TfCore.cpp
Go to the documentation of this file.
00001 /***
00002  The core code for robot control including path generation, topology branch selection, tensor field update, obastacle avoidance
00003  ***/
00004 #include"tensor_field_nav_core/TfCore.h"
00005 
00006 TfCore::TfCore(ros::NodeHandle private_nh_ ):nh_(),m_it(nh_)
00007 {
00008     //tensor field
00009         major_iframe = 0;
00010         quadmesh = NULL;
00011         ntenelems = 0;
00012         nten_regelems = 0;
00013         ndegpts = 0;
00014         ten_regularelems=NULL;
00015         degpts = NULL;
00016         curMaxNumTenRegElems =100;
00017         MaxNumDegeneratePts = 200;
00018         ten_tmax   = NPIX/(SCALE*NPN);
00019     ten_dmax   = SCALE/NPIX;
00020         iframe = 0; 
00021         Npat   = 32;
00022         alpha  = (0.12*255);
00023         tmax   = NPIX/(SCALE*NPN);
00024         dmax   = SCALE/NPIX;
00025         ten_designelems = NULL;
00026         curMaxNumTenDesignElems = 100;
00027         ndegenerate_tris = 0;
00028         degenerate_tris = NULL;
00029         major_path=NULL;
00030     NUM_Slices = 0;
00031     keyframes = NULL;
00032     enRelaxKeyframeOn=false;
00033     InterpScheme=1;
00034     curSliceID=0;
00035     showGridOn=false;
00036     showIBFVOn=true;
00037     showRegularElemOn=false;
00038     showSingularitiesOn=false;
00039     showMajorTenLine=true;
00040     interFrameNum=3;
00041     interFrameTime=0.2;
00042     //
00043     isReceiveNewMap=false;
00044     ifReachTrisector=false;
00045     targetTrisectorIndex=-1;
00046     safeDistance=0.3;
00047     realWorld_to_field_scale=25;
00048     realWorld_to_field_offset_x=0.5;
00049     realWorld_to_field_offset_y=0.5;
00050     rgb_im = (unsigned char *)malloc(NPIX * NPIX*3* sizeof(unsigned char));
00051     //
00052     //ros
00053     robotInitialPos_x=0.5;
00054     robotInitialPos_y=0.5;
00055     rgbTopicName="/tf_image";
00056     gridMapTopicName="/projected_map";
00057     worldFrameId="odom";
00058     baseFrameId="base_footprint";
00059     ifCancelPath=false;
00060     ifFinish_goTri=false;
00061     reGenPath=false;
00062 
00063     //
00064     ros::NodeHandle private_nh(private_nh_);
00065     private_nh.param("world_to_field_scale", realWorld_to_field_scale, realWorld_to_field_scale);
00066     private_nh.param("world_to_field_offset_x", realWorld_to_field_offset_x, realWorld_to_field_offset_x);
00067     private_nh.param("world_to_field_offset_y", realWorld_to_field_offset_y, realWorld_to_field_offset_y);
00068     private_nh.param("robot_initial_pos_x", robotInitialPos_x, robotInitialPos_x);
00069     private_nh.param("robot_initial_pos_y", robotInitialPos_y, robotInitialPos_y);
00070     private_nh.param("rgb_pub_topic_name", rgbTopicName, rgbTopicName);
00071     private_nh.param("gridMap_topic_name", gridMapTopicName, gridMapTopicName);
00072     private_nh.param("world_frame_id", worldFrameId, worldFrameId);
00073     private_nh.param("base_frame_id", baseFrameId, baseFrameId);
00074     private_nh.param("safe_disance", safeDistance, safeDistance);
00075     private_nh.param("inter_frame_num", interFrameNum, interFrameNum);
00076     private_nh.param("inter_frame_time", interFrameTime, interFrameTime);
00077 
00078     rgb_pub = m_it.advertise(rgbTopicName, 1);
00079     gridmap_sub=nh_.subscribe(gridMapTopicName,1,&TfCore::gridMap_callback,this);
00080     frontierPoints_sub=nh_.subscribe("frontier_points",1,&TfCore::frontier_point_callback,this);
00081     goTriExecuteclient=nh_.serviceClient<pure_pursuit_controller::executePath>("execute_goTri");
00082     pathExecuteClient=nh_.serviceClient<pure_pursuit_controller::executePath>("execute_path");
00083     pathCancelClient=nh_.serviceClient<pure_pursuit_controller::cancelPath>("cancel_path");
00084     pathCutClient=nh_.serviceClient<pure_pursuit_controller::cutPath>("cut_path");
00085     finishGoTri=nh_.subscribe("/pure_pursuit_controller/finish_go_tri",1,&TfCore::goTri_callback,this);
00086     //
00087     robot_loc=new Seed();
00088     robot_loc->pos[0]=robotInitialPos_x;
00089     robot_loc->pos[1]=robotInitialPos_y;
00090     robot_loc->triangle=0;
00091     realWorld_to_field_scale=realWorld_to_field_scale;
00092     realWorld_to_field_offset_x=realWorld_to_field_offset_x;
00093     realWorld_to_field_offset_y=realWorld_to_field_offset_y;
00094         //
00095 }
00096 
00097 TfCore::~TfCore(){
00098     for(int i=0;i<m_myThreads.size();i++)
00099         delete m_myThreads[i];
00100     delete quadmesh;
00101     delete major_path;
00102     delete separatrices;
00103     delete keyframes;
00104     delete vecsTime;
00105     delete vertTimeList;
00106 }
00107 
00108 void TfCore::TfCoreInit(){
00109     quadmesh = new QuadMesh(NMESH, NMESH, -0.01, 1.01, -0.01, 1.01);
00110     init_majorPath();
00111     init_separatrices();
00112         init_ten_designelems();
00113         init_degpts();
00114         zoom_factor = 1;
00115         trans_x=trans_y=0;
00116         cal_inverse_transform();
00117         InitGL();       
00118 
00119         make_tens_Patterns();
00120         tensor_init_tex();
00121 
00122     init_keyframeList();
00123     create_paraThread();
00124 
00125 }
00126 
00127 // for image based flow visualization
00128 void TfCore::makePatterns(void)
00129 {
00130     int lut[256];
00131     int phase[NPN][NPN];
00132     GLubyte pat[NPN][NPN][4];
00133     int i, j, k, t;
00134 
00135     for (i = 0; i < 256; i++) lut[i] = i < 127 ? 0 : 255;
00136     for (i = 0; i < NPN; i++)
00137         for (j = 0; j < NPN; j++) phase[i][j] = rand() % 256;
00138 
00139     for (k = 0; k < Npat; k++) {
00140         t = k*256/Npat;
00141         for (i = 0; i < NPN; i++)
00142             for (j = 0; j < NPN; j++) {
00143                 pat[i][j][0] =
00144                     pat[i][j][1] =
00145                     pat[i][j][2] = lut[(t + phase[i][j]) % 255];
00146                 pat[i][j][3] = alpha;
00147             }
00148             glNewList(k + 1, GL_COMPILE);
00149             glTexImage2D(GL_TEXTURE_2D, 0, 4, NPN, NPN, 0,
00150                 GL_RGBA, GL_UNSIGNED_BYTE, pat);
00151             glEndList();
00152     }
00153 }
00154 
00155 // for image based flow visualization
00156 void TfCore::make_tens_Patterns(void)
00157 {
00158         int lut[256];
00159         int phase[NPN][NPN];
00160         GLubyte pat[NPN][NPN][4];
00161         GLubyte spat[NPN][NPN][4];
00162         int i, j, k, t;
00163 
00164         for (i = 0; i < 256; i++) lut[i] = i < 127 ? 0 : 255;
00165         for (i = 0; i < NPN; i++)
00166                 for (j = 0; j < NPN; j++) phase[i][j] = rand() % 256; 
00167 
00168         for (k = 200; k < Npat+200; k++) {
00169                 //t = k*256/Npat;                           //t is used to control the animation of the image
00170                 for (i = 0; i < NPN; i++) 
00171                         for (j = 0; j < NPN; j++) {
00172                                 pat[i][j][0] = 
00173                                         pat[i][j][1] = 
00174                                         pat[i][j][2] = (GLubyte)lut[ phase[i][j] % 255];
00175                                 pat[i][j][3] = alpha+5;
00176 
00177                                 spat[i][j][0] = 
00178                                         spat[i][j][1] = 
00179                     spat[i][j][2] = (GLubyte)lut[ phase[i][j] % 255];
00180                                 spat[i][j][3] = alpha+5;
00181                         }
00182 
00183                         glNewList(k + 1, GL_COMPILE);  //major texture
00184                         glTexImage2D(GL_TEXTURE_2D, 0, 4, NPN, NPN, 0, 
00185                                 GL_RGBA, GL_UNSIGNED_BYTE, pat);
00186                         glEndList();
00187 
00188 
00189                         glNewList(k + 1 + 100, GL_COMPILE);       //This is for minor image
00190                         glTexImage2D(GL_TEXTURE_2D, 0, 4, NPN, NPN, 0, 
00191                                 GL_RGBA, GL_UNSIGNED_BYTE, spat);
00192                         glEndList();   
00193         }
00194 }
00195 
00196 int TfCore::InitGL()                                                            // All Setup For OpenGL Goes Here
00197 {
00198     glViewport(0, 0, (GLsizei)REALWINSIZE, (GLsizei)REALWINSIZE);
00199         glMatrixMode(GL_PROJECTION);
00200         glLoadIdentity(); 
00201         gluOrtho2D(0, 1, 0, 1);
00202         glTexParameteri(GL_TEXTURE_2D, 
00203                 GL_TEXTURE_WRAP_S, GL_REPEAT); 
00204         glTexParameteri(GL_TEXTURE_2D, 
00205                 GL_TEXTURE_WRAP_T, GL_REPEAT); 
00206         glTexParameteri(GL_TEXTURE_2D, 
00207                 GL_TEXTURE_MAG_FILTER, GL_LINEAR);
00208         glTexParameteri(GL_TEXTURE_2D, 
00209                 GL_TEXTURE_MIN_FILTER, GL_LINEAR);
00210         glTexEnvf(GL_TEXTURE_ENV, 
00211                 GL_TEXTURE_ENV_MODE, GL_REPLACE);
00212         glEnable(GL_TEXTURE_2D);
00213         glShadeModel(GL_FLAT);
00214         glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
00215         glClear(GL_COLOR_BUFFER_BIT);
00216 
00217         glDisable(GL_STENCIL_TEST);
00218 
00219         return true;                                                                            // Initialization Went OK
00220 }
00221 void TfCore::init_regular_ten_designelems()
00222 {
00223         /*initialize regular design element*/
00224         if(ten_regularelems == NULL)
00225         {
00226         ten_regularelems=(TenRegularElem *)malloc(sizeof(TenRegularElem)*curMaxNumTenRegElems);
00227                 if(ten_regularelems == NULL)
00228                         exit(-1);
00229         }
00230         nten_regelems = 0;
00231 }
00232 
00233 void TfCore::init_degpts()
00234 {
00235     /*initialize degerate design element*/
00236     if(degpts!=NULL) {free(degpts); degpts=NULL;}
00237     if(degpts == NULL)
00238         {
00239                 degpts = (DegeneratePt*)malloc(sizeof(DegeneratePt)*MaxNumDegeneratePts);
00240                 if(degpts == NULL)
00241                         exit(-1);
00242         }
00243         ndegpts = 0;
00244 
00245     int i;
00246     for(i=0; i<quadmesh->nfaces; i++)
00247     {
00248                 quadmesh->quadcells[i]->degpt_index = -1;
00249     }
00250 }
00251 
00252 
00253 /*initialize the textures*/
00254 void TfCore::tensor_init_tex()
00255 {
00256         glDrawBuffer(GL_BACK);
00257 
00258         glCallList(201);
00259 
00260         glBegin(GL_QUAD_STRIP);
00261         glTexCoord2f(0.0,  0.0);  glVertex2f(0.0, 0.0);
00262         glTexCoord2f(0.0,  ten_dmax); glVertex2f(0.0, 1.0);
00263         glTexCoord2f(ten_dmax, 0.0);  glVertex2f(1.0, 0.0);
00264         glTexCoord2f(ten_dmax, ten_dmax); glVertex2f(1.0, 1.0);
00265         glEnd();
00266 
00267         glReadBuffer(GL_BACK);
00268         glReadPixels(0, 0, NPIX, NPIX, GL_RGB, GL_UNSIGNED_BYTE, major_tex1);
00269 
00270         glReadBuffer(GL_BACK);
00271         glReadPixels(0, 0, NPIX, NPIX, GL_RGB, GL_UNSIGNED_BYTE, major_tex2);
00272 
00273         glReadBuffer(GL_BACK);
00274         glReadPixels(0, 0, NPIX, NPIX, GL_RGB, GL_UNSIGNED_BYTE, major_tex);
00275 }
00276 
00277 void TfCore::init_majorPath(){
00278     major_path=new EvenStreamlinePlace(1);
00279     major_path->setTfCore(this);
00280     major_path->init();
00281     major_path->set_default_parameters();
00282     major_path->init_major_line_info();
00283 }
00284 
00285 void TfCore::init_separatrices(){
00286     separatrices=new EvenStreamlinePlace(50);
00287     separatrices->setTfCore(this);
00288     separatrices->init();
00289     separatrices->set_default_parameters();
00290     separatrices->init_major_line_info();
00291 }
00292 
00293 void TfCore::cal_inverse_transform()
00294 {
00295         glMatrixMode(GL_MODELVIEW_MATRIX);
00296         glPushMatrix();
00297         glLoadIdentity();
00298         glTranslatef(-trans_x, -trans_y, 0);
00299         glTranslatef(0.5, 0.5, 0);
00300         glScalef(1./zoom_factor, 1./zoom_factor, 1./zoom_factor);
00301         glTranslatef(-.5,-.5, 0);
00302 
00303         glGetFloatv(GL_MODELVIEW_MATRIX, inverse_tran);
00304 
00305         glPopMatrix();
00306 }
00307 
00308 void TfCore::transform_fun(){
00309     glTranslatef(trans_x, trans_y, 0);
00310     glTranslatef(0.5, 0.5, 0);
00311     glScalef(zoom_factor, zoom_factor, zoom_factor);
00312     glTranslatef(-.5,-.5, 0);
00313 }
00314 
00315 
00316 int TfCore::without_anti_aliasing(GLenum mode)
00317 {
00318         glClearColor(0.93, 0.93, 0.87, 1);
00319         glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
00320         glPushMatrix ();
00321         transform_fun();
00322         if(showIBFVOn) /*visualize tensor field*/
00323         {
00324                 glEnable(GL_TEXTURE_2D);
00325                 glShadeModel(GL_FLAT);
00326         /*using quad mesh */
00327         render_majorfield_quad();  /*  showing major field only  */
00328 
00329         }
00330         else
00331         {
00332                 glClearColor(1, 1, 1, 1);
00333                 glClear(GL_COLOR_BUFFER_BIT);
00334                 glDisable(GL_TEXTURE_2D);
00335         }                                       
00336         glDisable(GL_TEXTURE_2D);
00337         glEnable(GL_COLOR_MATERIAL);
00338         glLineWidth(2.0);
00339 
00340 
00341         if(showRegularElemOn)
00342                 display_tenRegElem(mode);
00343 
00344         if(showGridOn)
00345                 display_design_grid();
00346 
00347         if(showSingularitiesOn)
00348                 display_degenerate_pts(mode);
00349 
00350     if (showMajorTenLine)
00351         display_major_tenlines(mode);
00352 
00353     display_valid_trisectors(mode);
00354     display_valid_degenerate_pts(mode);
00355     display_bresenham_line();
00356 
00357     display_separatrices(mode);
00358     display_trisectorVec(mode);
00359 
00360         glPopMatrix ();
00361         glDisable(GL_COLOR_MATERIAL);
00362         glEnable(GL_TEXTURE_2D);
00363     //glutSwapBuffers();
00364     glFlush();
00365         return true;    
00366 }
00367 
00368 void TfCore::render_majorfield_quad()
00369 {
00370 
00371         glMatrixMode(GL_PROJECTION);
00372         glPushMatrix();
00373         glLoadIdentity(); 
00374         gluOrtho2D(0, 1, 0, 1);
00375 
00376         major_vis_quad();
00377 
00378         glPopMatrix();
00379 
00380     render_tensor_final();
00381 
00382         glDisable(GL_TEXTURE_2D);
00383 }
00384 
00385 
00386 
00387 void TfCore::render_tensor_final()
00388 {
00389     /*use the mesh to display the texture instead */
00390         glClearColor(1, 1, 1, 1);
00391         glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
00392 
00393     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, NPIX, NPIX, 0,
00394         GL_RGB, GL_UNSIGNED_BYTE, major_tex);
00395 
00396         glBegin(GL_QUAD_STRIP);
00397         glTexCoord2f(0.0, 0.0);  glVertex2f(0.0, 0.0);
00398         glTexCoord2f(0.0, 1.0);  glVertex2f(0.0, 1.0);
00399         glTexCoord2f(1.0, 0.0);  glVertex2f(1.0, 0.0);
00400         glTexCoord2f(1.0, 1.0);  glVertex2f(1.0, 1.0);
00401         glEnd();
00402 }
00403 
00404 void TfCore::major_vis_quad()
00405 {
00406     /*reset the view point here */
00407     glViewport(0, 0, (GLsizei)NPIX, (GLsizei)NPIX);
00408 
00409         /*rendering the positive x direction*/
00410         glBindTexture(GL_TEXTURE_2D, tentextnames[0]);
00411         glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, NPIX, NPIX, 0,
00412                 GL_RGB, GL_UNSIGNED_BYTE, major_tex1);
00413 
00414     render_ibfv_tens_quad(false);
00415 
00416         /*save image*/
00417         glDisable(GL_BLEND);
00418         glReadBuffer(GL_BACK);
00419         glReadPixels(0, 0, NPIX, NPIX, GL_RGB, GL_UNSIGNED_BYTE, major_tex1);
00420 
00421         /***************************************************************/
00422 
00423         /*rendering the positive y direction*/
00424         major_iframe--;
00425         glBindTexture(GL_TEXTURE_2D, tentextnames[1]);
00426         glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, NPIX, NPIX, 0,
00427                 GL_RGB, GL_UNSIGNED_BYTE, major_tex2);
00428 
00429     render_ibfv_tens_quad(true);
00430 
00431         glDisable(GL_BLEND);
00432         glReadBuffer(GL_BACK);
00433         glReadPixels(0, 0, NPIX, NPIX, GL_RGB, GL_UNSIGNED_BYTE, major_tex2);
00434         /***************************************************************/
00435 
00436         /*blend them*/
00437 
00438         int i, j;
00439         for(i=0; i<NPIX; i++) /*y direction*/
00440                 for(j=0; j<NPIX; j++)
00441                 {
00442                         major_temp[i][j][0] = major_tex1[i][j][0];
00443                         major_temp[i][j][1] = major_tex1[i][j][1];
00444                         major_temp[i][j][2] = major_tex1[i][j][2];
00445                         major_temp[i][j][3] = major_alpha_map[i][j][0];
00446                 }
00447 
00448     for(i=0; i<NPIX; i++) /*x direction*/
00449         for(j=0; j<NPIX; j++)
00450         {
00451             minor_temp[i][j][0] = major_tex2[i][j][0];
00452             minor_temp[i][j][1] = major_tex2[i][j][1];
00453             minor_temp[i][j][2] = major_tex2[i][j][2];
00454             minor_temp[i][j][3] = 255-major_alpha_map[i][j][0];
00455         }
00456     glEnable(GL_BLEND);
00457     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, NPIX, NPIX, 0,
00458         GL_RGBA, GL_UNSIGNED_BYTE, major_temp);
00459     render_tensor_blend();
00460     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, NPIX, NPIX, 0,
00461         GL_RGBA, GL_UNSIGNED_BYTE, minor_temp);
00462     render_tensor_blend();
00463 
00465 
00466     glReadBuffer(GL_BACK);
00467     glReadPixels(0, 0, NPIX, NPIX, GL_RGB, GL_UNSIGNED_BYTE, major_tex);
00468 
00469     glClearColor(1, 1, 1, 1);
00470     glClear(GL_COLOR_BUFFER_BIT);
00471     glReadPixels(0, 0, NPIX, NPIX, GL_RGBA, GL_UNSIGNED_BYTE, major_temp);
00472     glReadPixels(0, 0, NPIX, NPIX, GL_RGBA, GL_UNSIGNED_BYTE, minor_temp);
00473 
00474     glViewport(0, 0, (GLsizei)REALWINSIZE, (GLsizei)REALWINSIZE);
00475 }
00476 void TfCore::render_ibfv_tens_quad(bool x_y)
00477 {
00478         int i, j;
00479         QuadCell *face;
00480         QuadVertex *vert;
00481         double px, py;
00482 
00483         glMatrixMode(GL_PROJECTION);
00484         glPushMatrix();
00485         glLoadIdentity(); 
00486         gluOrtho2D(0, 1, 0, 1);
00487     if(!x_y) /*positive x*/
00488     {
00489         for (i=0; i<quadmesh->nfaces; i++) {
00490             face = quadmesh->quadcells[i];
00491             glBegin(GL_POLYGON);
00492             for (j=0; j<face->nverts; j++) {
00493                 vert = quadmesh->quad_verts[face->verts[j]];
00494                 glTexCoord2f(vert->x, vert->y);
00495 
00496                 if(vert->major_cos)
00497                 {
00498                     px = vert->x - vert->major.entry[0];
00499                     py = vert->y - vert->major.entry[1];
00500                 }
00501                 else
00502                 {
00503                     px = vert->x + vert->major.entry[0];
00504                     py = vert->y + vert->major.entry[1];
00505                 }
00506 
00507                 glVertex2f(px, py);
00508             }
00509             glEnd();
00510         }
00511     }
00512     else  /*positive y*/
00513     {
00514         for (i=0; i<quadmesh->nfaces; i++) {
00515             face = quadmesh->quadcells[i];
00516             glBegin(GL_POLYGON);
00517             for (j=0; j<face->nverts; j++) {
00518                 vert = quadmesh->quad_verts[face->verts[j]];
00519                 glTexCoord2f(vert->x, vert->y);
00520                 if(vert->major_sin)
00521                 {
00522                     px = vert->x - vert->major.entry[0];
00523                     py = vert->y - vert->major.entry[1];
00524                 }
00525                 else
00526                 {
00527                     px = vert->x + vert->major.entry[0];
00528                     py = vert->y + vert->major.entry[1];
00529                 }
00530                 glVertex2f(px, py);
00531             }
00532             glEnd();
00533         }
00534     }
00535     major_iframe ++;
00536 
00537         glEnable(GL_BLEND); 
00538 
00539         /*double check the following codes*/
00540     glCallList(major_iframe % Npat + 200+ 1);
00541 
00542         glBegin(GL_QUAD_STRIP);
00543         glTexCoord2f(0.0,  0.0);  glVertex2f(0.0, 0.0);
00544         glTexCoord2f(0.0,  ten_tmax); glVertex2f(0.0, 1.0);
00545         glTexCoord2f(ten_tmax, 0.0);  glVertex2f(1.0, 0.0);
00546         glTexCoord2f(ten_tmax, ten_tmax); glVertex2f(1.0, 1.0);
00547         glEnd();
00548 
00549         glPopMatrix();
00550 
00551 }
00552 void TfCore::render_tensor_blend()
00553 {
00554         glBegin(GL_QUAD_STRIP);
00555         glTexCoord2f(0.0, 0.0);  glVertex2f(0.0, 0.0);
00556         glTexCoord2f(0.0, 1.0);  glVertex2f(0.0, 1.0);
00557         glTexCoord2f(1.0, 0.0);  glVertex2f(1.0, 0.0);
00558         glTexCoord2f(1.0, 1.0);  glVertex2f(1.0, 1.0);
00559         glEnd();
00560 }
00561 void TfCore::drawSolidRect_size(double cx, double cy, double R)
00562 {
00563         glBegin(GL_POLYGON);
00564         glVertex2f(cx-R, cy-R);
00565         glVertex2f(cx-R, cy+R);
00566         glVertex2f(cx+R, cy+R);
00567         glVertex2f(cx+R, cy-R);
00568         glEnd();
00569 }
00570 void TfCore::drawSolidCircle_size(double cx, double cy, double R)
00571 {
00572         int i;
00573         double theta, deta ;
00574         deta = 2 * M_PI/49.;
00575         double x, y;
00576         theta = 0.;
00577         glBegin(GL_POLYGON);
00578         for(i = 0; i < 50; i++, theta += deta)
00579         {
00580                 x =  cx + R * cos(theta);
00581                 y =  cy + R * sin(theta);
00582 
00583                 glVertex2f(x, y);
00584         }
00585         glEnd();
00586 }
00587 
00589 void TfCore::display_tenRegElem(GLenum mode)
00590 {
00591     glLineWidth(1.);
00592         for(int i = 0; i < nten_regelems; i++)
00593         {
00594                 if(ten_regularelems[i].ID>0)
00595                 {
00597                         if(mode == GL_SELECT)
00598                                 glLoadName(ten_regularelems[i].ID);
00599 
00600                         if(ten_regularelems[i].deleted)
00601                                 continue;
00602 
00604 
00605                         if(ten_regularelems[i].type == 0) 
00606                                 glColor3f(0, 1, 1);
00607                         else if(ten_regularelems[i].type == 1) 
00608                                 glColor3f(1, 0.5, 0);
00609                         else                         
00610                                 glColor3f(0, 1, 0.5);
00611 
00612                         /*we draw two line segments*/
00613                         glBegin(GL_LINES);
00614                         glVertex2f(ten_regularelems[i].base[0], ten_regularelems[i].base[1]);
00615                         glVertex2f(ten_regularelems[i].end[0], ten_regularelems[i].end[1]);
00616                         glEnd();
00617 
00618                         glBegin(GL_LINES);
00619                         glVertex2f(ten_regularelems[i].base[0], ten_regularelems[i].base[1]);
00620                         glVertex2f(ten_regularelems[i].base[0]-ten_regularelems[i].Direct.entry[0], 
00621                                 ten_regularelems[i].base[1]-ten_regularelems[i].Direct.entry[1]);
00622                         glEnd();
00623 
00624                 }
00625         }
00626 }
00627 
00628 void TfCore::display_trisectorVec(GLenum mode)
00629 {
00630     glLineWidth(1.5);
00631     for(int i = 0; i < validDegpts.size(); i++)
00632     {
00633         if(validDegpts[i].type==1)
00634         {
00635             for(int j=0;j<validDegpts[i].nseps;j++){
00636                 if(j == 0)
00637                     glColor3f(1, 0, 0);
00638                 else if(j == 1)
00639                     glColor3f(204.0/255, 102.0/255, 0);
00640                 else                         
00641                     glColor3f(0, 0, 1);
00642                 /*we draw two line segments*/
00643                 glBegin(GL_LINES);
00644                 glVertex2f(validDegpts[i].gcx, validDegpts[i].gcy);
00645                 glVertex2f(validDegpts[i].gcx+ validDegpts[i].s_vec[j].entry[0]*0.015, validDegpts[i].gcy+ validDegpts[i].s_vec[j].entry[1]*0.015);
00646                 glEnd();
00647 
00648             }
00649         }
00650     }
00651 }
00652 
00653 void TfCore::display_design_grid()
00654 {
00655         glColor3f(0.8, 0.8, 0.5);
00656         glLineWidth(1.);
00657 
00658         QuadCell* face;
00659         QuadVertex *v;
00660         int j;
00661         for(int i=0;i<quadmesh->nfaces;i++)
00662         {
00663                 face=quadmesh->quadcells[i];
00664 
00665                 glBegin(GL_LINE_LOOP);
00666                 for(j=0;j<face->nverts;j++)
00667                 {
00668                         v=quadmesh->quad_verts[face->verts[j]];
00669                         glVertex2f(v->x, v->y);
00670                 }
00671                 glEnd();
00672         }
00673 }
00674 
00675 void TfCore::display_degenerate_pts(GLenum mode)
00676 {
00677         int i, singular_id = 0;
00678 
00679         for(i = 0; i < ndegpts; i++)
00680         {
00681                 if(degpts[i].type == 0) /*wedge*/
00682                         glColor3f(1, 0, 0);
00683                 else if(degpts[i].type == 1) /*trisector*/
00684                         glColor3f(0, 1, 0);
00685                 else if(degpts[i].type == 2) /*node*/
00686                         glColor3f(1, 1, 0);
00687                 else if(degpts[i].type == 3) /*center*/
00688                         glColor3f(1, 0, 1);
00689                 else if(degpts[i].type == 4) /*saddle*/
00690                         glColor3f(0, 0, 1);
00691                 else
00692                         glColor3f(1, 1, 1);
00693 
00694                 drawSolidCircle_size(degpts[i].gcx, degpts[i].gcy, 0.006/zoom_factor);
00695 
00696                 glColor3f(0, 0, 0);
00697                 glLineWidth(1.4);
00698                 draw_hollow_circle_size(degpts[i].gcx, degpts[i].gcy, 0.0065/zoom_factor);
00699         }
00700     glFlush();
00701 }
00702 
00703 void TfCore::draw_hollow_circle_size(double cx, double cy, double R)
00704 {
00705         int i;
00706         double theta, deta ;
00707         deta = 2 * M_PI/49.;
00708         double x, y;
00709         theta = 0.;
00710         glBegin(GL_LINE_LOOP);
00711         for(i = 0; i < 50; i++, theta += deta)
00712         {
00713                 x =  cx + R * cos(theta);
00714                 y =  cy + R * sin(theta);
00715 
00716                 glVertex2f(x, y);
00717         }
00718         glEnd();
00719 }
00720 
00721 int TfCore::DrawGLScene(GLenum mode)                                    // Here's Where We Do All The Drawing
00722 {
00723         glEnable(GL_LINE_SMOOTH);
00724         glHint(GL_LINE_SMOOTH_HINT, GL_DONT_CARE);
00725         glDisable(GL_LIGHTING);
00726         without_anti_aliasing(mode);
00727     publish_image();
00728         return 1;
00729 }
00730 
00731 void TfCore::set_ten_regBasis(double x, double y, int type)
00732 {
00734         if(nten_regelems >= curMaxNumTenRegElems-1 )
00735         {
00736                 //Allocate new space for the element list
00737                 curMaxNumTenRegElems += 50;
00738                 ten_regularelems = (TenRegularElem*)realloc(ten_regularelems, sizeof(TenRegularElem) * curMaxNumTenRegElems);
00739                 if(ten_regularelems == NULL)
00740                         exit(-1);
00741 
00742         }
00743         ten_regularelems[nten_regelems].end[0] = ten_regularelems[nten_regelems].base[0] = x;
00744         ten_regularelems[nten_regelems].end[1] = ten_regularelems[nten_regelems].base[1] = y;
00745     ten_regularelems[nten_regelems].ID = nten_regelems+1;
00746         ten_regularelems[nten_regelems].type = type;
00747         ten_regularelems[nten_regelems].Direct.set(0, 0);
00748 
00750         ten_regularelems[nten_regelems].transform_matrix.setIdentity();
00751         //ten_regularelems[nten_regelems].transposeRot.setIdentity();
00752 
00753         ten_regularelems[nten_regelems].rotang = 0;
00754         ten_regularelems[nten_regelems].s = 1;
00755 
00756     ten_regularelems[nten_regelems].deleted=false;
00757 
00758     /*mark which region the design element belongs to*/
00759         ten_regularelems[nten_regelems].which_region=get_region_id(x, y);
00760 
00761         nten_regelems ++;
00762 }
00763 
00764 
00765 unsigned char TfCore::get_region_id(double x, double y)
00766 {
00767         int i=(x-quadmesh->xstart)/quadmesh->xinterval;
00768         int j=(y-quadmesh->ystart)/quadmesh->yinterval;
00769 
00770         if(i>=quadmesh->XDIM-1) i=quadmesh->XDIM-2;
00771         if(j>=quadmesh->YDIM-1) j=quadmesh->YDIM-2;
00772 
00773         int cellid=j*(quadmesh->XDIM-1)+i;
00774         return quadmesh->quadcells[cellid]->which_region;
00775 }
00776 
00777 void TfCore::set_ten_regDir(double x, double y)
00778 {
00780 
00781         ten_regularelems[nten_regelems - 1].end[0] = x ;
00782         ten_regularelems[nten_regelems - 1].end[1] = y ;
00783 
00784         ten_regularelems[nten_regelems - 1].Direct.entry[0] = x - ten_regularelems[nten_regelems - 1].base[0];
00785         ten_regularelems[nten_regelems - 1].Direct.entry[1] = y - ten_regularelems[nten_regelems - 1].base[1];
00786 
00787         ten_regularelems[nten_regelems - 1].rotang = 
00788                 atan2(ten_regularelems[nten_regelems - 1].Direct.entry[1],
00789                 ten_regularelems[nten_regelems - 1].Direct.entry[0]);
00790 }
00791 
00792 void TfCore::set_ten_regDir(double x, double y,icVector2 &vec)
00793 {
00795     ten_regularelems[nten_regelems - 1].end[0] = x+vec.entry[0];
00796     ten_regularelems[nten_regelems - 1].end[1] = y+vec.entry[1] ;
00797 
00798     ten_regularelems[nten_regelems - 1].Direct.entry[0] =vec.entry[0];
00799     ten_regularelems[nten_regelems - 1].Direct.entry[1] = vec.entry[1];
00800 
00801     ten_regularelems[nten_regelems - 1].rotang =
00802         atan2(ten_regularelems[nten_regelems - 1].Direct.entry[1],
00803         ten_regularelems[nten_regelems - 1].Direct.entry[0]);
00804 }
00805 
00806 
00807 void TfCore::cal_tensorvals_quad()
00808 {
00809         int i;
00810         QuadVertex *v;
00811         double t[4]={0.};
00812 
00813         for(i=0; i<quadmesh->nverts; i++)
00814         {
00815                 v = quadmesh->quad_verts[i];
00816 
00817                 if(!v->inland)
00818                         continue;
00819         get_tensor(v->x, v->y, t);
00820         v->Jacobian.entry[0][0] = t[0];
00821         v->Jacobian.entry[0][1] = t[1];
00822         v->Jacobian.entry[1][0] = t[2];
00823         v->Jacobian.entry[1][1] = t[3];
00824         }
00825 }
00826 
00827 
00828 void TfCore::get_tensor(double x, double y, double t[4])
00829 {
00830         int i;
00831         double  dx, dy, vx, vy, t00, t01, t10, t11, r=0.;
00832         double d;
00833 
00834         icMatrix3x3 tempJacobian, transposerot;
00835         double ang;
00836 
00837         vx = vy = 0.;
00838 
00839         t[0]=t[1]=t[2]=t[3]=0.;
00840 
00842         for(i = 0; i < ntenelems; i++)
00843         {
00844                 if(ten_designelems[i].ID >= 0 && !ten_designelems[i].deleted)
00845                 {
00846                         dx = x - ten_designelems[i].centerx;
00847                         dy = y - ten_designelems[i].centery;
00848 
00849                         r  = dx*dx + dy*dy; 
00850                         d = exp(-1000*r);
00851 
00852                         if (r < DistanceThreshold)   r = DistanceThreshold;
00853 
00854                         tempJacobian.set(ten_designelems[i].transform_matrix);
00855 
00856                         ang = ten_designelems[i].rotang;
00857 
00858                         transposerot.set(cos(ang), sin(ang), 0,
00859                                 -sin(ang),  cos(ang), 0,
00860                                 0,0,1);
00861 
00862                         tempJacobian.rightMultiply(transposerot);
00863 
00864                         if(ten_designelems[i].type == 0) /*wedge*/
00865                         {
00866                                 t00 = (dx * tempJacobian.entry[0][0] + dy * tempJacobian.entry[0][1])/r;  
00867                                 t01 = (dy * tempJacobian.entry[0][0] - dx * tempJacobian.entry[0][1])/r;
00868                                 t10 = (dx * tempJacobian.entry[1][0] + dy * tempJacobian.entry[1][1])/r;
00869                                 t11 = (dy * tempJacobian.entry[1][0] - dx * tempJacobian.entry[1][1])/r;
00870                         }
00871                         else if(ten_designelems[i].type == 1) /*trisector*/
00872                         {
00873                                 t00 = (dx * tempJacobian.entry[0][0] - dy * tempJacobian.entry[0][1])/r;  
00874                                 t01 = (-dy * tempJacobian.entry[0][0] - dx * tempJacobian.entry[0][1])/r;
00875                                 t10 = (dx * tempJacobian.entry[1][0] - dy * tempJacobian.entry[1][1])/r;
00876                                 t11 = (-dy * tempJacobian.entry[1][0] - dx * tempJacobian.entry[1][1])/r;
00877                         }
00878                         else if(ten_designelems[i].type == 2) /*node*/
00879                         {
00880                                 t00 = ((dx*dx-dy*dy)*tempJacobian.entry[0][0]+2*dx*dy*tempJacobian.entry[0][1])/(r*sqrt(r));
00881                                 t01 = (2*dx*dy*tempJacobian.entry[0][0]-(dx*dx-dy*dy)*tempJacobian.entry[0][1])/(r*sqrt(r));
00882                                 t10 = ((dx*dx-dy*dy)*tempJacobian.entry[1][0]+2*dx*dy*tempJacobian.entry[1][1])/(r*sqrt(r));
00883                                 t11 = (2*dx*dy*tempJacobian.entry[1][0]-(dx*dx-dy*dy)*tempJacobian.entry[1][1])/(r*sqrt(r));
00884 
00885                         }
00886                         else if(ten_designelems[i].type == 3) /*center*/
00887                         {
00888                                 t00 = ((dy*dy-dx*dx)*tempJacobian.entry[0][0]-2*dx*dy*tempJacobian.entry[0][1])/(r*sqrt(r));
00889                                 t01 = (-2*dx*dy*tempJacobian.entry[0][0]+(dx*dx-dy*dy)*tempJacobian.entry[0][1])/(r*sqrt(r));
00890                                 t10 = ((dy*dy-dx*dx)*tempJacobian.entry[1][0]-2*dx*dy*tempJacobian.entry[1][1])/(r*sqrt(r));
00891                                 t11 = (-2*dx*dy*tempJacobian.entry[1][0]+(dx*dx-dy*dy)*tempJacobian.entry[1][1])/(r*sqrt(r));
00892                         }
00893                         else if(ten_designelems[i].type == 4) /*saddle*/
00894                         {
00895                                 t00 = ((dx*dx-dy*dy)*tempJacobian.entry[0][0]-2*dx*dy*tempJacobian.entry[0][1])/(r*sqrt(r));
00896                                 t01 = (-2*dx*dy*tempJacobian.entry[0][0]-(dx*dx-dy*dy)*tempJacobian.entry[0][1])/(r*sqrt(r));
00897                                 t10 = ((dx*dx-dy*dy)*tempJacobian.entry[1][0]-2*dx*dy*tempJacobian.entry[1][1])/(r*sqrt(r));
00898                                 t11 = (-2*dx*dy*tempJacobian.entry[1][0]-(dx*dx-dy*dy)*tempJacobian.entry[1][1])/(r*sqrt(r));
00899                         }
00900 
00901                         /*you may also need to multiply the transpose of the transformation matrix*/
00902 
00903 
00904                         t[0] += t00/sqrt(r)*LOWER;
00905                         t[1] += t01/sqrt(r)*LOWER;
00906                         t[2] += t10/sqrt(r)*LOWER;
00907                         t[3] += t11/sqrt(r)*LOWER;
00908 
00909                 }
00910 
00911         }
00912 
00913         /*the following we combine the regular element*/
00914     //icMatrix3x3 regten, temp;
00915         for(i = 0; i < nten_regelems; i++)
00916         {
00917                 if(ten_regularelems[i].ID > 0 && !ten_regularelems[i].deleted)
00918                 {
00919                         dx = x - ten_regularelems[i].base[0];
00920                         dy = y - ten_regularelems[i].base[1];
00921 
00922                         r  = dx*dx + dy*dy; 
00923 
00924                         if (r < DistanceThreshold)   r = DistanceThreshold;
00925 
00926                         if(ten_regularelems[i].type == 0) 
00927                         {
00928                 /*the creation of regular element before */
00929                                 double strength = length(ten_regularelems[i].Direct);
00930 
00931                                 t[0] += strength*cos(2*ten_regularelems[i].rotang)/(r*sqrt(r));
00932                                 t[1] += strength*sin(2*ten_regularelems[i].rotang)/(r*sqrt(r));
00933                                 t[2] += strength*sin(2*ten_regularelems[i].rotang)/(r*sqrt(r));
00934                                 t[3] += -strength*cos(2*ten_regularelems[i].rotang)/(r*sqrt(r));
00935 
00936                         }
00937 
00938                 }
00939 
00940                 else if(ten_regularelems[i].ID > 0 && 
00941                         !ten_regularelems[i].deleted && ten_regularelems[i].which_region == 0)
00942                 {
00943                         dx = x - ten_regularelems[i].base[0];
00944                         dy = y - ten_regularelems[i].base[1];
00945 
00946                         r  = dx*dx + dy*dy; 
00947 
00948                         if (r < DistanceThreshold)   r = DistanceThreshold;
00949 
00950                         if(ten_regularelems[i].type == 0) 
00951                         {
00952                 /*the creation of regular element before */
00953                                 double strength = length(ten_regularelems[i].Direct);
00954 
00955                                 t[0] += strength*cos(2*ten_regularelems[i].rotang)/(r*sqrt(r));
00956                                 t[1] += strength*sin(2*ten_regularelems[i].rotang)/(r*sqrt(r));
00957                                 t[2] += strength*sin(2*ten_regularelems[i].rotang)/(r*sqrt(r));
00958                                 t[3] += -strength*cos(2*ten_regularelems[i].rotang)/(r*sqrt(r));
00959 
00960                         }
00961                 }
00962         }
00963 
00964 }
00965 
00966 void TfCore::init_ten_designelems()
00967 {
00968     /*initialize degenerate design element*/
00969         if(ten_designelems == NULL)
00970         {
00971                 ten_designelems=(Degenerate_Design *)malloc(sizeof(Degenerate_Design)*curMaxNumTenDesignElems);
00972                 if(ten_designelems == NULL)
00973                         exit(-1);
00974         }
00975         ntenelems = 0;
00976 
00977         init_regular_ten_designelems();
00978 }
00979 
00980 void TfCore::cal_all_eigenvecs_quad()
00981 {
00982     int i;
00983 
00984     for(i=0; i<quadmesh->nverts; i++)
00985     {
00986         if(quadmesh->quad_verts[i]->inland)
00987             cal_eigenvecs_onevert_quad(i);
00988     }
00989 
00990         /*normalize the major and minor field*/
00991         normalized_tensorfield_quad();
00992 }
00993 
00994 void TfCore::cal_eigenvecs_onevert_quad(int ver)
00995 {
00996         QuadVertex *v=quadmesh->quad_verts[ver];
00997         icVector2 ev[2];
00998 
00999         if(fabs(v->Jacobian.entry[0][0])<=1.e-7
01000                 &&fabs(v->Jacobian.entry[0][1])<=1.e-7
01001                 &&fabs(v->Jacobian.entry[1][0])<=1.e-7
01002                 &&fabs(v->Jacobian.entry[1][1])<=1.e-7)
01003         {
01004                 v->major.set(0,0);
01005                 v->minor.set(0,0);
01006                 v->major_ang=0;
01007                 v->minor_ang=0;
01008                 return;
01009         }
01010 
01011         cal_eigen_vector_sym(v->Jacobian, ev);
01012 
01013         v->major = ev[0];
01014         v->minor = ev[1];
01015 
01016         /*compute the angle*/
01017         v->major_ang = atan2(v->major.entry[1], v->major.entry[0]);
01018         v->minor_ang = atan2(v->minor.entry[1], v->minor.entry[0]);
01019 
01020         /*save the angle of major field for degenerate points/singularity detection*/
01021     v->tensor_major_ang = v->major_ang;
01022                 
01023         /*obtain the multiplied vector, we will use this obtained
01024         vector field to extract singularities*/
01025         v->tran_vec.set(cos(2*v->tensor_major_ang), sin(2*v->tensor_major_ang));
01026 
01027 
01028         /*transfer to cos^2*/
01029         double major_ang_cos = cos(v->major_ang);
01030         double major_ang_sin = sin(v->major_ang);
01031 
01032         v->major_ang = major_ang_cos*major_ang_cos;
01033         if(major_ang_cos<0)
01034                 v->major_cos = true;
01035         else
01036                 v->major_cos = false;
01037         if(major_ang_sin<0)
01038                 v->major_sin = true;
01039         else
01040                 v->major_sin = false;
01041 
01042         double minor_ang_cos = cos(v->minor_ang);
01043         double minor_ang_sin = sin(v->minor_ang);
01044 
01045         v->minor_ang = minor_ang_cos*minor_ang_cos;
01046         //v->minor_ang = minor_ang_sin*minor_ang_sin;
01047         if(minor_ang_cos<0)
01048                 v->minor_cos = true;
01049         else
01050                 v->minor_cos = false;
01051         if(minor_ang_sin<0)
01052                 v->minor_sin = true;
01053         else
01054                 v->minor_sin = false;
01055 
01056 }
01057 
01058 void TfCore::cal_eigen_vector_sym(icMatrix2x2 m, icVector2 ev[2])
01059 {
01060         /*first get the deviator of m*/
01061         icMatrix2x2 dev;
01062         double half_trace = 0.5*(m.entry[0][0]+m.entry[1][1]);
01063         dev.entry[0][0] = m.entry[0][0]-half_trace;
01064         dev.entry[1][1] = m.entry[1][1]-half_trace;
01065         dev.entry[0][1] = m.entry[0][1];
01066         dev.entry[1][0] = m.entry[1][0];
01067 
01068         /*compute the eigen vectors*/
01069         double theta = atan2(dev.entry[0][1], dev.entry[0][0]);
01070 
01071         //if(theta < 0) theta += 2*M_PI;
01072 
01073         /*major eigen vector*/
01074         ev[0].entry[0] = cos(theta/2.);
01075         ev[0].entry[1] = sin(theta/2.);
01076 
01077         //ev[0] = half_trace*ev[0];
01078 
01079         /*minor eigen vector*/
01080         ev[1].entry[0] = cos((theta+M_PI)/2.);
01081         ev[1].entry[1] = sin((theta+M_PI)/2.);
01082 
01083         //ev[1] = half_trace*ev[1];
01084 }
01085 
01086 void TfCore::normalized_tensorfield_quad()
01087 {
01088         /*normalize the major and minor field*/
01089         int i;
01090         double r;
01091         QuadVertex *cur_v;
01092 
01093         for(i = 0; i < quadmesh->nverts; i++)
01094         {
01095                 cur_v = quadmesh->quad_verts[i];
01096 
01097                 /*normalize major field*/
01098                 r = length(cur_v->major);
01099                 r *= r;
01100                 if (r < DistanceThreshold) 
01101                 {
01102                         r = DistanceThreshold;
01103                         cur_v->major *= ten_dmax/r; 
01104                 }
01105                 r = length(cur_v->major);
01106                 r *= r;
01107                 if (r > ten_dmax*ten_dmax) { 
01108                         r  = sqrt(r); 
01109                         cur_v->major *= ten_dmax/r; 
01110                 }
01111 
01112                 /*normalize minor field*/
01113                 r = length(cur_v->minor);
01114                 r *= r;
01115                 if (r < DistanceThreshold) 
01116                 {
01117                         r = DistanceThreshold;
01118                         cur_v->minor *= ten_dmax/r; 
01119                 }
01120                 r = length(cur_v->minor);
01121                 r *= r;
01122                 if (r > ten_dmax*ten_dmax) { 
01123                         r  = sqrt(r); 
01124                         cur_v->minor *= ten_dmax/r; 
01125                 }
01126         }
01127 }
01128 
01129 void TfCore::render_alpha_map_quad()
01130 {
01131         
01132         int i, j;
01133         QuadCell *face;
01134         QuadVertex *vert;
01135 
01136         glViewport(0, 0, (GLsizei)NPIX, (GLsizei)NPIX);
01137         glDisable(GL_TEXTURE_2D);
01138         glDisable(GL_BLEND);
01139         glShadeModel(GL_SMOOTH);
01140     for (i=0; i<quadmesh->nfaces; i++) {
01141         face = quadmesh->quadcells[i];
01142         glBegin(GL_POLYGON);
01143         for (j=0; j<face->nverts; j++) {
01144             vert = quadmesh->quad_verts[face->verts[j]];
01145             glColor3f(vert->major_ang,
01146                 vert->major_ang,
01147                 vert->major_ang);
01148 
01149             glVertex2f(vert->x, vert->y);
01150         }
01151         glEnd();
01152     }
01153 
01154     /*copy to the major_alpha_map*/
01155     glReadBuffer(GL_BACK);
01156     glReadPixels(0, 0, NPIX, NPIX, GL_RGB, GL_UNSIGNED_BYTE, major_alpha_map);
01157         glDisable(GL_BLEND);
01158     glViewport(0, 0, (GLsizei)REALWINSIZE, (GLsizei)REALWINSIZE);
01159 }
01160 
01161 /*we use quad mesh to locate the degenerate points*/
01162 void TfCore::locate_degpts_cells_tranvec_quad(void)
01163 {
01164     //std::cout<<"befor locate degpts points, num is :"<<ndegpts<<std::endl;
01165     unsigned int i, j;
01166     QuadCell *face;
01167     QuadVertex *v;
01168     icVector2 vec[4];      //vectors at four vertices
01169     double  theta[4];      //for storing the angles between two vector for Gauss circle judgement
01170 
01171     double  vec_ang[4];  //the angle for each vector under the polar frame of current triangle
01172     double  ang_sum;
01173 
01175     ndegenerate_tris = 0;
01176 
01177     if(degenerate_tris == NULL)
01178         degenerate_tris = (int*) malloc(sizeof(int) * MaxNumDegeneratePts); //default range is 200
01179 
01180 
01182     for (i = 0; i < quadmesh->nfaces; i++) {
01183         face = quadmesh->quadcells[i];
01184 
01185         ang_sum = 0;
01186 
01187         for(j=0; j<face->nverts; j++)
01188         {
01189             v = quadmesh->quad_verts[face->verts[j]];
01190             vec_ang[j] = atan2(v->tran_vec.entry[1], v->tran_vec.entry[0]);
01191             if(vec_ang[j] < 0) vec_ang[j] += 2 * M_PI;
01192         }
01193 
01194         for(j = 0; j < face->nverts; j++)
01195         {
01196             theta[j] = vec_ang[(j+1)%face->nverts] - vec_ang[j];
01197 
01198             if( theta[j] < -M_PI)
01199                 theta[j] += 2 * M_PI;
01200 
01201             if( theta[j] > M_PI)
01202                 theta[j] -= 2 * M_PI;
01203 
01204             ang_sum += theta[j];
01205         }
01206 
01207         double index = ang_sum/(2*M_PI);
01208 
01209 
01210         /*here we need to allow some numerical errors 09/26/2007*/
01211         if(fabs(index) >= 1.- 1.e-1)
01212         {
01213             //The triangle must have singularities inside, mark it as yellow color
01214             //Still need to judge whether it is one of current singularities or not
01215             degenerate_tris[ndegenerate_tris] = i;
01216             ndegenerate_tris ++;
01217 
01218             if(fabs(index-1)<1e-2)  /*it is a wedge*/
01219                 quadmesh->quadcells[i]->degenerate_type = 0;
01220             else if(fabs(index+1)<1e-2)  /*it is a trisector*/
01221                 quadmesh->quadcells[i]->degenerate_type = 1;
01222             else if(fabs(index-2)<1e-2)    /*it is a node/center*/
01223                 quadmesh->quadcells[i]->degenerate_type = 2;
01224             else if(fabs(index+2)<1e-2)    /*it is a saddle*/
01225                 quadmesh->quadcells[i]->degenerate_type = 3;
01226 
01227             if(ndegenerate_tris >= MaxNumDegeneratePts - 1)
01228             {
01229                 MaxNumDegeneratePts += 50;
01230                 degenerate_tris = (int*) realloc(degenerate_tris, sizeof(int) * MaxNumDegeneratePts);
01231                 degpts = (DegeneratePt*)realloc(degpts, sizeof(DegeneratePt)*MaxNumDegeneratePts);
01232             }
01233         }
01234     }
01235 
01236     if(ndegenerate_tris>0) /*we find some degenerate triangles*/
01237         compute_degpts_pos_tranvec_quad();
01238 }
01239 
01240 
01241 void TfCore::compute_degpts_pos_tranvec_quad()
01242 {
01243     int i;
01244     double x_cp, y_cp;
01245     ndegpts = 0;
01246 
01247     for(i=0; i<ndegenerate_tris; i++)
01248     {
01249         compute_onedegpt_pos_tranvec_quad(degenerate_tris[i], x_cp, y_cp);
01250 
01251         /*save the information to the degenerate point list*/
01252         degpts[ndegpts].gcx = x_cp;
01253         degpts[ndegpts].gcy = y_cp;
01254         degpts[ndegpts].degpt_index = ndegpts;
01255         degpts[ndegpts].type = quadmesh->quadcells[degenerate_tris[i]]->degenerate_type;
01256         degpts[ndegpts].Triangle_ID = degenerate_tris[i];
01257         quadmesh->quadcells[degenerate_tris[i]]->degpt_index = ndegpts;
01258 
01259         /*compute the separatrices*/
01260         degpts[ndegpts].nseps = 0;
01261         degpts[ndegpts].nlinks = 0;
01262         ndegpts++;
01263     }
01264 
01265 }
01266 void TfCore::compute_onedegpt_pos_tranvec_quad(int cellid, double &x, double &y)
01267 {
01268         /*first, we find an a along x direction, such that with this coefficient
01269         the interpolated vectors between v0v1 and v2v3 have opposite direction*/
01270 
01271         /*second, on this a, we find an b along y direction, such that the
01272         magnitude of v0v1 equal the magnitude of v2v3*/
01273         QuadCell *qc = quadmesh->quadcells[cellid];
01274 
01275 
01276         QuadVertex *v00 = quadmesh->quad_verts[qc->verts[0]];
01277         QuadVertex *v01 = quadmesh->quad_verts[qc->verts[3]];
01278         QuadVertex *v10 = quadmesh->quad_verts[qc->verts[1]];
01279         QuadVertex *v11 = quadmesh->quad_verts[qc->verts[2]];
01280 
01281         icVector2 v0v1, v2v3;
01282         double a, b;
01283 
01284         /*get a: the most difficult step*/
01285         compute_a_alongx_degptlocate(a, v00->tran_vec, v10->tran_vec, v11->tran_vec, v01->tran_vec,
01286                 v0v1, v2v3);
01287 
01288         /*get b. after first step, v0v1 and v2v3 are opposite to each other*/
01289         if(fabs(v0v1.entry[0])>1e-8) /*use x direction*/
01290         {
01291                 b = (v0v1.entry[0])/(v0v1.entry[0]-v2v3.entry[0]);
01292         }
01293         else /*use y direction*/
01294         {
01295                 b = (v0v1.entry[1])/(v0v1.entry[1]-v2v3.entry[1]);
01296         }
01297     if(a<0||a>1) a=0.5;
01298     if(b<0 ||b>1)b=0.5;
01299         /*obtain the position*/
01300     x = bilinear_interpolate(a, b, v00->x, v01->x, v10->x, v11->x);
01301     y = bilinear_interpolate(a, b, v00->y, v01->y, v10->y, v11->y);
01302 }
01303 
01304 
01305 void TfCore::compute_a_alongx_degptlocate(double &a, icVector2 v0, icVector2 v1, icVector2 v2, icVector2 v3,
01306                                                                   icVector2 &v0v1, icVector2 &v2v3)
01307 {
01308         /*use binary search*/
01309         /*initialization*/
01310         double a0, a1;
01311         bool orient = false;  //false -- CCW, true -- CW
01312         a0=0.; a1=1.;
01313         a = 0.5;
01314         v0v1 = 0.5*(v0+v1);
01315         v2v3 = 0.5*(v3+v2);
01316         double theta1, theta2, theta;
01317         double theta_v0, theta_v1, theta_v2, theta_v3, theta_v03;
01318         theta_v0 = atan2(v0.entry[1], v0.entry[0]);
01319         //if(theta_v0<0) theta_v0 += 2*M_PI;
01320         //theta_v1 = atan2(v1.entry[1], v1.entry[0]);
01321         //if(theta_v1<0) theta_v1 += 2*M_PI;
01322         //theta_v2 = atan2(v2.entry[1], v2.entry[0]);
01323         //if(theta_v2<0) theta_v2 += 2*M_PI;
01324         theta_v3 = atan2(v3.entry[1], v3.entry[0]);
01325         //if(theta_v3<0) theta_v3 += 2*M_PI;
01326 
01327         theta_v03 = theta_v3-theta_v0;
01328         if(theta_v03>=0)
01329                 orient = false; //CCW
01330         else
01331                 orient = true;
01332         if(theta_v03<-M_PI) orient = false; //CCW
01333         if(theta_v03>M_PI) orient = true;   //CW
01334 
01335         /*NOTE: we interpolate from v0 to v1
01336                                from v3 to v2 */
01337         //normalize(v0v1);
01338         //normalize(v2v3);
01339         theta1 = atan2(v0v1.entry[1], v0v1.entry[0]); //obtain angle for v0v1;
01340         //if(theta1<0) theta1 += 2*M_PI;
01341         theta2 = atan2(v2v3.entry[1], v2v3.entry[0]); //obtain angle for v2v3;
01342         //if(theta2<0) theta2 += 2*M_PI;
01343         /*subtract the two angles*/
01344         theta = theta1-theta2;
01345 
01346         bool s_orient = false;
01347         while(fabs(fabs(theta)-M_PI)>1e-8 && fabs(a0-a1)>1e-9) /*if they are not opposite to each other*/
01348         {
01349                 if(theta>=0)
01350                         s_orient = false;                   //CCW
01351                 else
01352                         s_orient = true;                    //CW
01353 
01354                 if(theta>M_PI) s_orient = true;         //CW
01355                 if(theta<-M_PI) s_orient = false;       //CCW
01356 
01357                 /*if they have the same orientation*/
01358                 if((orient&&s_orient) || (!orient&&!s_orient))
01359                 {
01360                         /*we need to increase a*/
01361                         a1 = a;
01362                         a = (a0+a1)/2.;
01363                 }
01364                 else
01365                 {
01366                         /*we need to decrease a*/
01367                         a0 = a;
01368                         a = (a0+a1)/2.;
01369                 }
01370 
01371                 /*recalculate v0v1 and v2v3*/
01372                 v0v1 = (1-a)*v0+a*v1;
01373                 v2v3 = (1-a)*v3+a*v2;
01374 
01375                 /*recompute the angles of v0v1 and v2v3*/
01376                 theta1 = atan2(v0v1.entry[1], v0v1.entry[0]); //obtain angle for v0v1;
01377                 if(theta1<0) theta1 += 2*M_PI;
01378                 theta2 = atan2(v2v3.entry[1], v2v3.entry[0]); //obtain angle for v2v3;
01379                 if(theta2<0) theta2 += 2*M_PI;
01380                 /*subtract the two angles*/
01381                 theta = theta1-theta2;
01382 
01383         }
01384         
01385         v0v1 = (1-a)*v0+a*v1;
01386         v2v3 = (1-a)*v3+a*v2;
01387 }
01388 
01389 void TfCore::compute_separatrixVec_degpt_quad(int degpt_index)
01390 {
01391     QuadCell *face = quadmesh->quadcells[validDegpts[degpt_index].Triangle_ID];
01392     QuadVertex *v;
01393     icMatrix2x2 dv[3]; // the deviators of the tensors at the three vertices
01394 
01395     int i,start;
01396     icVector3 point0(quadmesh->quad_verts[face->verts[0]]->x,quadmesh->quad_verts[face->verts[0]]->y,0);
01397     icVector3 point1(quadmesh->quad_verts[face->verts[1]]->x,quadmesh->quad_verts[face->verts[1]]->y,0);
01398     icVector3 point2(quadmesh->quad_verts[face->verts[2]]->x,quadmesh->quad_verts[face->verts[2]]->y,0);
01399     icVector3 degpt_point(validDegpts[degpt_index].gcx,validDegpts[degpt_index].gcy,0);
01400     if (PointInTriangle(point0,point1,point2,degpt_point)) start=0;
01401     else start=1;
01402     /*obtain the deviators*/
01403     for(i=start; i<3+start; i++)
01404     {
01405         dv[i-start].set(0.);
01406         v=quadmesh->quad_verts[face->verts[i]];
01407         double half_trace = 0.5*(v->Jacobian.entry[0][0]+v->Jacobian.entry[1][1]);
01408         dv[i-start].entry[0][0] = v->Jacobian.entry[0][0]-half_trace;
01409         dv[i-start].entry[1][1] = v->Jacobian.entry[1][1]-half_trace;
01410         dv[i-start].entry[0][1] = v->Jacobian.entry[0][1];
01411         dv[i-start].entry[1][0] = v->Jacobian.entry[1][0];
01412     }
01413 
01414     /*translate the tensor system according to the center of the degenerate point*/
01415     //for(i=0; i<3; i++)
01416     //{
01417     //}
01418 
01419     double a, b, c, d, e, f; //
01420     double x[3], y[3]; //
01421     double vx[3], vy[3];//
01422 
01423     for (i=start; i<3+start; i++) {
01424         v=quadmesh->quad_verts[face->verts[i]];
01425         x[i-start] = v->x;
01426         y[i-start] = v->y;
01427 
01429 
01430         /* Use normalized vector field*/
01431         vx[i-start] = dv[i-start].entry[0][0];
01432         vy[i-start] = dv[i-start].entry[0][1];
01433 
01434     }
01435 
01437     double coord[3][3],  *inver_coord ;  //inver_coord[3][3];
01438     for(int k = 0; k < 3; k++)
01439     {
01440         coord[0][k] = x[k];
01441         coord[1][k] = y[k];
01442         coord[2][k] = 1.;
01443     }
01444 
01445     inver_coord = MatrixOpp((double*)coord, 3, 3);
01446 
01447     icMatrix3x3 result, rightM;
01448     result.set(vx[0],vx[1],vx[2],  vy[0],vy[1],vy[2],  1,1,1);
01449     rightM.set(inver_coord[0], inver_coord[1], inver_coord[2],
01450         inver_coord[3], inver_coord[4], inver_coord[5],
01451         inver_coord[6], inver_coord[7], inver_coord[8]);
01452 
01453 
01454     result.rightMultiply(rightM);
01455 
01456     a = result.entry[0][0];
01457     b = result.entry[0][1];
01458     c = result.entry[0][2];
01459     d = result.entry[1][0];
01460     e = result.entry[1][1];
01461     f = result.entry[1][2];
01462 
01463     /*compute the solution for a cubic equations*/
01464     double solutions[4] = {0.};
01465     //int nroots = solve_ten_cubic(e, (d+2*b), (2*a-e), -d, solutions);
01466     int nroots = solve_ten_cubic_3(e, (d+2*b), (2*a-e), -d, solutions);
01467     //std::cout<<"degpt type is: "<<degpts[degpt_index].type<<";  nroots value is: "<<nroots<<std::endl;
01468     if(nroots == 0)
01469         return;
01470     else if(nroots == 1 /*|| nroots == 4*/)
01471     {
01472         /*it is the separatrix of a wedge*/
01473         validDegpts[degpt_index].nseps = 1;
01474         validDegpts[degpt_index].s1_ang = atan(solutions[0]);
01475         validDegpts[degpt_index].s[0].entry[0] = cos(validDegpts[degpt_index].s1_ang);
01476         validDegpts[degpt_index].s[0].entry[1] = sin(validDegpts[degpt_index].s1_ang);
01477     }
01478     else if(nroots == 2|| nroots == 4)
01479     {
01480         /*they are the separatrices of a wedge*/
01481         validDegpts[degpt_index].nseps = 2;
01482         validDegpts[degpt_index].s1_ang = atan(solutions[0]);
01483         validDegpts[degpt_index].s[0].entry[0] = cos(validDegpts[degpt_index].s1_ang);
01484         validDegpts[degpt_index].s[0].entry[1] = sin(validDegpts[degpt_index].s1_ang);
01485        // validDegpts[degpt_index].s_ifLinks[0]=true;
01486 
01487         validDegpts[degpt_index].s2_ang = atan(solutions[1]);
01488         validDegpts[degpt_index].s[1].entry[0] = cos(validDegpts[degpt_index].s2_ang);
01489         validDegpts[degpt_index].s[1].entry[1] = sin(validDegpts[degpt_index].s2_ang);
01490     }
01491     else if(nroots == 3) /*they are the separatrices of a trisector*/
01492     {
01493         validDegpts[degpt_index].nseps = 3;
01494         validDegpts[degpt_index].s1_ang = atan(solutions[0]);
01495         validDegpts[degpt_index].s[0].entry[0] = cos(validDegpts[degpt_index].s1_ang);
01496         validDegpts[degpt_index].s[0].entry[1] = sin(validDegpts[degpt_index].s1_ang);
01497        // validDegpts[degpt_index].s_ifLinks[0]=true;
01498 
01499         validDegpts[degpt_index].s2_ang = atan(solutions[1]);
01500         validDegpts[degpt_index].s[1].entry[0] = cos(validDegpts[degpt_index].s2_ang);
01501         validDegpts[degpt_index].s[1].entry[1] = sin(validDegpts[degpt_index].s2_ang);
01502        // validDegpts[degpt_index].s_ifLinks[1]=true;
01503 
01504         validDegpts[degpt_index].s3_ang = atan(solutions[2]);
01505         validDegpts[degpt_index].s[2].entry[0] = cos(validDegpts[degpt_index].s3_ang);
01506         validDegpts[degpt_index].s[2].entry[1] = sin(validDegpts[degpt_index].s3_ang);
01507        // validDegpts[degpt_index].s_ifLinks[2]=true;
01508 
01509         if(validDegpts[degpt_index].type==0){
01510             int target1=0,target2=1;
01511             float cosAngle1= fabs(dot(validDegpts[degpt_index].s[0],validDegpts[degpt_index].s[1]));
01512             float cosAngle2= fabs(dot(validDegpts[degpt_index].s[0],validDegpts[degpt_index].s[2]));
01513             float cosAngle3= fabs(dot(validDegpts[degpt_index].s[1],validDegpts[degpt_index].s[2]));
01514             if(cosAngle1>cosAngle2){
01515                 target1=0;
01516                 target2=2;
01517                 if(cosAngle2>cosAngle3)
01518                    target1=1;target2=2;
01519             }else{
01520                if(cosAngle1>cosAngle3)
01521                    target1=1;target2=2;
01522             }
01523              validDegpts[degpt_index].nseps = 2;
01524              validDegpts[degpt_index].s[0]=validDegpts[degpt_index].s[target1];
01525              validDegpts[degpt_index].s[1]=validDegpts[degpt_index].s[target2];
01526         }
01527     }
01528     for(int i=0;i<3;i++)
01529         validDegpts[degpt_index].s_ifLink[i]=true;
01530 }
01531 
01532 //calculating the integral direction for every separatrix
01533 void TfCore::cal_separatrix_vec(){
01534     Seed *seed1=new Seed;
01535     Seed *seed2=new Seed;
01536     float factor=0.5*1e-2;
01537     for(int i=0; i<validDegpts.size(); i++){
01538         bool ifTriSepSim=false;
01539         int target1,target2,target3;
01540         double degpt_loc[2];
01541         degpt_loc[0]=validDegpts[i].gcx;
01542         degpt_loc[1]=validDegpts[i].gcy;
01543         // if vector of two separatrices are close, then use a simple way to separate.
01544         if(validDegpts[i].type==1){
01545             if(fabs(dot(validDegpts[i].s[0],validDegpts[i].s[1]))>0.7){ifTriSepSim=true;target1=0;target2=1;target3=2;}
01546             else if(fabs(dot(validDegpts[i].s[0],validDegpts[i].s[2]))>0.7){ifTriSepSim=true;target1=0;target2=2;target3=1;}
01547             else if(fabs(dot(validDegpts[i].s[1],validDegpts[i].s[2]))>0.7){ifTriSepSim=true;target1=1;target2=2;target3=0;}
01548         }
01549         if(ifTriSepSim){
01550             seed1->pos[0]=validDegpts[i].gcx+ validDegpts[i].s[target3].entry[0]*factor;
01551             seed1->pos[1]=validDegpts[i].gcy+ validDegpts[i].s[target3].entry[1]*factor;
01552             seed1->triangle=separatrices->get_cellID_givencoords(seed1->pos[0],seed1->pos[1]);
01553 
01554             seed2->pos[0]=validDegpts[i].gcx - validDegpts[i].s[target3].entry[0]*factor;
01555             seed2->pos[1]=validDegpts[i].gcy - validDegpts[i].s[target3].entry[1]*factor;
01556             seed2->triangle=separatrices->get_cellID_givencoords(seed2->pos[0],seed2->pos[1]);
01557 
01558             icMatrix2x2 ten1,ten2;
01559             separatrices->compute_tensor_at_quad(seed1->triangle,seed1->pos[0], seed1->pos[1], ten1);
01560             separatrices->compute_tensor_at_quad(seed2->triangle,seed2->pos[0], seed2->pos[1], ten2);
01561             icVector2 ev1[2],ev2[2];
01562             cal_eigen_vector_sym(ten1, ev1);
01563             cal_eigen_vector_sym(ten2, ev2);
01564             double deta1=fabs(dot(ev1[0],validDegpts[i].s[target3]));
01565             double deta2=fabs(dot(ev2[0],validDegpts[i].s[target3]));
01566             if(deta1>deta2){
01567                 validDegpts[i].s_vec[target3]=validDegpts[i].s[target3];
01568             }else{
01569                 validDegpts[i].s_vec[target3]=-validDegpts[i].s[target3];
01570             }
01571 
01572             seed1->pos[0]=validDegpts[i].gcx+ validDegpts[i].s[target1].entry[0]*factor;
01573             seed1->pos[1]=validDegpts[i].gcy+ validDegpts[i].s[target1].entry[1]*factor;
01574             seed1->triangle=separatrices->get_cellID_givencoords(seed1->pos[0],seed1->pos[1]);
01575 
01576             seed2->pos[0]=validDegpts[i].gcx - validDegpts[i].s[target1].entry[0]*factor;
01577             seed2->pos[1]=validDegpts[i].gcy - validDegpts[i].s[target1].entry[1]*factor;
01578             seed2->triangle=separatrices->get_cellID_givencoords(seed2->pos[0],seed2->pos[1]);
01579 
01580             separatrices->compute_tensor_at_quad(seed1->triangle,seed1->pos[0], seed1->pos[1], ten1);
01581             separatrices->compute_tensor_at_quad(seed2->triangle,seed2->pos[0], seed2->pos[1], ten2);
01582             cal_eigen_vector_sym(ten1, ev1);
01583             cal_eigen_vector_sym(ten2, ev2);
01584             deta1=fabs(dot(ev1[0],validDegpts[i].s[target1]));
01585             deta2=fabs(dot(ev2[0],validDegpts[i].s[target1]));
01586 
01587             if(deta1>deta2){
01588                 validDegpts[i].s_vec[target1]=validDegpts[i].s[target1];
01589                 if(dot(validDegpts[i].s[target1],validDegpts[i].s[target2])>0)
01590                     validDegpts[i].s_vec[target2]=-validDegpts[i].s[target2];
01591                 else
01592                     validDegpts[i].s_vec[target2]=validDegpts[i].s[target2];
01593             }else{
01594                 validDegpts[i].s_vec[target1]=-validDegpts[i].s[target1];
01595                 if(dot(validDegpts[i].s[target1],validDegpts[i].s[target2])>0)
01596                     validDegpts[i].s_vec[target2]=validDegpts[i].s[target2];
01597                 else
01598                     validDegpts[i].s_vec[target2]=-validDegpts[i].s[target2];
01599             }
01600         }else{
01601             for(int j=0; j<validDegpts[i].nseps;j++)
01602             {
01603                 seed1->pos[0]=validDegpts[i].gcx+ validDegpts[i].s[j].entry[0]*factor;
01604                 seed1->pos[1]=validDegpts[i].gcy+ validDegpts[i].s[j].entry[1]*factor;
01605                 seed1->triangle=separatrices->get_cellID_givencoords(seed1->pos[0],seed1->pos[1]);
01606 
01607                 seed2->pos[0]=validDegpts[i].gcx - validDegpts[i].s[j].entry[0]*factor;
01608                 seed2->pos[1]=validDegpts[i].gcy - validDegpts[i].s[j].entry[1]*factor;
01609                 seed2->triangle=separatrices->get_cellID_givencoords(seed2->pos[0],seed2->pos[1]);
01610                 icMatrix2x2 ten1,ten2;
01611                 separatrices->compute_tensor_at_quad(seed1->triangle,seed1->pos[0], seed1->pos[1], ten1);
01612                 separatrices->compute_tensor_at_quad(seed2->triangle,seed2->pos[0], seed2->pos[1], ten2);
01613                 icVector2 ev1[2],ev2[2];
01614                 cal_eigen_vector_sym(ten1, ev1);
01615                 cal_eigen_vector_sym(ten2, ev2);
01616                 double deta1=fabs(dot(ev1[0],validDegpts[i].s[j]));
01617                 double deta2=fabs(dot(ev2[0],validDegpts[i].s[j]));
01618                 if(deta1>deta2){
01619                     validDegpts[i].s_vec[j]=validDegpts[i].s[j];
01620                 }else{
01621                      validDegpts[i].s_vec[j]=-validDegpts[i].s[j];
01622                 }
01623             }
01624         }
01625     }
01626 }
01627 
01628 
01629 
01630 
01631 //generate separatrix for trisector
01632 void TfCore::gen_separatrix(){
01633     reset_separatrices();
01634     double degpt_loc[2];
01635     double startpt[2];
01636     int startcell;
01637     int fieldtype;
01638     fieldtype=0;        /*major direction*/
01639     float factor=1e-2;
01640     for(int i=0; i<validDegpts.size(); i++)
01641     {
01642         if(validDegpts[i].type==1){
01643             for(int j=0; j<validDegpts[i].nseps;j++)
01644             {
01645                 degpt_loc[0]=validDegpts[i].gcx;
01646                 degpt_loc[1]=validDegpts[i].gcy;
01647                 startpt[0]=validDegpts[i].gcx+ validDegpts[i].s_vec[j].entry[0]*factor;
01648                 startpt[1]=validDegpts[i].gcy+ validDegpts[i].s_vec[j].entry[1]*factor;
01649                 startcell=separatrices->get_cellID_givencoords(startpt[0],startpt[1]);
01650                 separatrices->grow_a_separatrix(degpt_loc,startpt, startcell, separatrices->percentage_dsep*separatrices->dsep,
01651                     separatrices->discsize, separatrices->sample_interval, separatrices->loopdsep, separatrices->dist2sing,
01652                     separatrices->streamlinelength, fieldtype,validDegpts[i].s_vec[j],i,j);
01653             }
01654         }
01655     }
01656 
01657 }
01658 
01659 void TfCore::display_major_tenlines(GLenum mode)
01660 {
01661     if(major_path == NULL)
01662         return;
01663     int i, j, k;
01664     Trajectory *cur_traj;
01665     glColor3f(1, 0, 0);
01666     glLineWidth(1.5);
01667     cur_traj = major_path->evenstreamlines->trajs[0];
01668 
01669     for(k=0; k<cur_traj->nlinesegs; k++)
01670     {
01671         glBegin(GL_LINES);
01672         glVertex2f(cur_traj->linesegs[k].gstart[0], cur_traj->linesegs[k].gstart[1]);
01673         glVertex2f(cur_traj->linesegs[k].gend[0], cur_traj->linesegs[k].gend[1]);
01674         glEnd();
01675     }
01676     glFlush();
01677 }
01678 
01679 void TfCore::display_separatrices(GLenum mode){
01680     if(separatrices == NULL)
01681         return;
01682     int i, j, k;
01683     Trajectory *cur_traj;
01684     glColor3f(0, 1, 0);
01685     glLineWidth(1.5);
01686     glShadeModel(GL_SMOOTH);
01687     for(j=0; j<separatrices->evenstreamlines->ntrajs; j++)
01688     {
01689         cur_traj = separatrices->evenstreamlines->trajs[j];
01690          glColor3f(1, 1, 0);
01691          drawSolidCircle_size(cur_traj->linesegs[0].gend[0], cur_traj->linesegs[0].gend[1], 0.003/zoom_factor);
01692          glColor3f(0, 1, 0);
01693         for(k=0; k<cur_traj->nlinesegs; k++)
01694         {
01695             glBegin(GL_LINES);
01696             glVertex2f(cur_traj->linesegs[k].gstart[0], cur_traj->linesegs[k].gstart[1]);
01697             glVertex2f(cur_traj->linesegs[k].gend[0], cur_traj->linesegs[k].gend[1]);
01698             glEnd();
01699         }
01700     }
01701     glFlush();
01702 }
01703 
01704 void TfCore::reset_major_path(){
01705     free(major_path);
01706     init_majorPath();
01707 }
01708 
01709 void TfCore::reset_separatrices(){
01710     free(separatrices);
01711     init_separatrices();
01712 }
01713 
01714 void TfCore::set_robot_loc(double x,double y){
01715     robot_loc->pos[0]=x;
01716     robot_loc->pos[1]=y;
01717 }
01718 
01719 void TfCore::gen_major_path(){
01720     listen_to_robot_loc();
01721     double startpt[2];
01722     int startcell;
01723     robot_loc->triangle=major_path->get_cellID_givencoords(robot_loc->pos[0],robot_loc->pos[1]);
01724     startcell=robot_loc->triangle;
01725     startpt[0]=robot_loc->pos[0];
01726     startpt[1]=robot_loc->pos[1];
01727     major_path->grow_a_majRoad(startpt, startcell, major_path->percentage_dsep*major_path->dsep,
01728         major_path->discsize, major_path->sample_interval, major_path->loopdsep, major_path->dist2sing,
01729         major_path->streamlinelength, 0,m_robotDirect);
01730 }
01731 
01732 //get the location of robot at this time
01733 void TfCore::listen_to_robot_loc(){
01734     tf::StampedTransform transform;
01735     try{
01736       ros::Time now = ros::Time::now();
01737       listener.waitForTransform(worldFrameId, baseFrameId,
01738                                   now, ros::Duration(3.0));
01739       listener.lookupTransform(worldFrameId, baseFrameId,
01740                                now, transform);
01741     }
01742     catch (tf::TransformException ex){
01743       ROS_ERROR("%s",ex.what());
01744     }
01745     robot_world_pos[0]=transform.getOrigin().x();
01746     robot_world_pos[1]=transform.getOrigin().y();
01747 
01748     double loc_x=transform.getOrigin().x()/realWorld_to_field_scale+realWorld_to_field_offset_x;
01749     double loc_y=transform.getOrigin().y()/realWorld_to_field_scale+realWorld_to_field_offset_y;
01750     set_robot_loc(loc_x,loc_y);
01751 
01752     double x = transform.getRotation().getX();
01753     double y = transform.getRotation().getY();
01754     double z = transform.getRotation().getZ();
01755     double w = transform.getRotation().getW();
01756     double robot_angel = atan2(2 * (w * z + x * y), 1 - 2 * (y * y + z * z));
01757     m_robotDirect.entry[0]=cos(robot_angel);
01758     m_robotDirect.entry[1]=sin(robot_angel);
01759 }
01761 //send points of a branch of trisector to pursuit controller when select one.
01762 void TfCore::add_separatrix_points_toRobot(Trajectory * target_traj){
01763     nav_msgs::Path path;
01764     path.header.frame_id=worldFrameId;
01765     Trajectory *cur_traj=target_traj;
01766     for (int i=0;i<cur_traj->nlinesegs;i++)
01767     {
01768          geometry_msgs::PoseStamped pose;
01769          pose.header.stamp = ros::Time::now();
01770          double x=(cur_traj->linesegs[i].gend[0]-realWorld_to_field_offset_x)*realWorld_to_field_scale;
01771          double y=(cur_traj->linesegs[i].gend[1]-realWorld_to_field_offset_y)*realWorld_to_field_scale;
01772          pose.pose.position.x=x;
01773          pose.pose.position.y=y;
01774          pose.header.frame_id=worldFrameId;
01775          pose.pose.position.z=0;
01776          pose.pose.orientation.x=0;
01777          pose.pose.orientation.y=0;
01778          pose.pose.orientation.z=0;
01779          pose.pose.orientation.w=1;
01780          path.poses.push_back(pose);
01781     }
01782     pure_pursuit_controller::executePath srv;
01783     srv.request.curPath=path;
01784     srv.request.ifFirstPoint=true;
01785     if(pathExecuteClient.call(srv)){
01786         ROS_INFO("Reach a trisector, request execute a branch");
01787         sleep(3);
01788     }
01789     else{
01790         ROS_ERROR("Failed to call service execute_path");
01791     }
01792 }
01793 
01794 //send points of path advection to pursuit controller.
01795 void TfCore::add_robot_wayPoints()
01796 {
01797     Trajectory *cur_traj=major_path->evenstreamlines->trajs[0];
01798     icVector2 tmp_path_dir(cur_traj->linesegs[6].gend[0]-cur_traj->linesegs[6].gstart[0],cur_traj->linesegs[6].gend[1]-cur_traj->linesegs[6].gstart[1]);
01799     normalize(tmp_path_dir);
01800     nav_msgs::Path path;
01801     path.header.frame_id=worldFrameId;
01802     for (int i=0;i<cur_traj->nlinesegs;i++)
01803     {
01804          geometry_msgs::PoseStamped pose;
01805          pose.header.stamp = ros::Time::now();
01806          double x=(cur_traj->linesegs[i].gend[0]-realWorld_to_field_offset_x)*realWorld_to_field_scale;
01807          double y=(cur_traj->linesegs[i].gend[1]-realWorld_to_field_offset_y)*realWorld_to_field_scale;
01808          pose.pose.position.x=x;
01809          pose.pose.position.y=y;
01810          pose.header.frame_id=worldFrameId;
01811          pose.pose.position.z=0;
01812          pose.pose.orientation.x=0;
01813          pose.pose.orientation.y=0;
01814          pose.pose.orientation.z=0;
01815          pose.pose.orientation.w=1;
01816          path.poses.push_back(pose);
01817     }
01818     pure_pursuit_controller::executePath srv;
01819     srv.request.curPath=path;
01820     normalize(m_robotDirect);
01821     if(dot(m_robotDirect,tmp_path_dir)<0.34)
01822         srv.request.ifFirstPoint=true;
01823     else
01824         srv.request.ifFirstPoint=false;
01825     if(pathExecuteClient.call(srv)){
01826         ROS_INFO("Request execute path");
01827     }
01828     else{
01829         ROS_ERROR("Failed to call service execute_path");
01830     }
01831 }
01832 
01833 void TfCore::cancelPath(){
01834     pure_pursuit_controller::cancelPath srv;
01835     srv.request.req="cancel";
01836     if(pathCancelClient.call(srv)){
01837         ROS_INFO("Request cancel path");
01838     }
01839     else{
01840         ROS_ERROR("Failed to call service cancel_path");
01841     }
01842 }
01843 
01844 // set regular constraints for tensor field calculatiion
01845 void TfCore::setRegularElems(){
01846     constraints_vecs.clear();
01847     //get regular elements from obstacle contours.
01848     for(int i=0;i<contours2Field.size();i++)
01849     {
01850         if (contours2Field[i].size()<10)
01851             continue;
01852         std::vector<icVector2> cur_vecs;
01853         for (int j=0;j<contours2Field[i].size();j++)
01854         {
01855            if(j<contours2Field[i].size()-1){
01856                std::vector<cv::Point2f> points;
01857                icVector2 tmp_dir(contours2Field[i][j+1].x-contours2Field[i][j].x,contours2Field[i][j+1].y-contours2Field[i][j].y);
01858                float cur_strength=length(tmp_dir);
01859                if(j<3){
01860                    for(int k=0;k<5;k++)
01861                        points.push_back(cv::Point2f(contours2Field[i][k].x,contours2Field[i][k].y));
01862                }else if(j>contours2Field[i].size()-6){
01863                    for(int k=contours2Field[i].size()-5;k<contours2Field[i].size();k++)
01864                        points.push_back(cv::Point2f(contours2Field[i][k].x,contours2Field[i][k].y));
01865                }else{
01866                    for(int k=j-2;k<j+3;k++)
01867                        points.push_back(cv::Point2f(contours2Field[i][k].x,contours2Field[i][k].y));
01868                }
01869                cv::Vec4f line;
01870                cv::fitLine(cv::Mat(points), line, CV_DIST_L2, 0, 0.01, 0.01);
01871                icVector2 tmp_vec(line[0],line[1]);
01872                if(dot(tmp_vec,tmp_dir)<0) tmp_vec=-tmp_vec;
01873                tmp_vec=tmp_vec*cur_strength;
01874                cur_vecs.push_back(tmp_vec);
01875            }else
01876            {
01877                std::vector<cv::Point2f> points;
01878                icVector2 testEnd2start=(contours2Field[i][0].x-contours2Field[i][j].x,contours2Field[i][0].y-contours2Field[i][j].y);
01879                icVector2 tmp_dir;
01880                float cur_strength;
01881                if(length(testEnd2start)<0.015)
01882                {
01883                    tmp_dir=testEnd2start;
01884                    cur_strength=length(tmp_dir);
01885                    points.push_back(cv::Point2f(contours2Field[i][0].x,contours2Field[i][0].y));
01886                    points.push_back(cv::Point2f(contours2Field[i][j].x,contours2Field[i][j].y));
01887                    points.push_back(cv::Point2f(contours2Field[i][j-1].x,contours2Field[i][j-1].y));
01888                }else{
01889                   tmp_dir=(contours2Field[i][j].x-contours2Field[i][j-1].x,contours2Field[i][j].y-contours2Field[i][j-1].y);
01890                   cur_strength=length(tmp_dir);
01891                   points.push_back(cv::Point2f(contours2Field[i][j].x,contours2Field[i][j].y));
01892                   points.push_back(cv::Point2f(contours2Field[i][j-1].x,contours2Field[i][j-1].y));
01893                   points.push_back(cv::Point2f(contours2Field[i][j-2].x,contours2Field[i][j-2].y));
01894                }
01895                cv::Vec4f line;
01896                cv::fitLine(cv::Mat(points), line, CV_DIST_L2, 0, 0.01, 0.01);
01897                icVector2 tmp_vec(line[0],line[1]);
01898                if(dot(tmp_vec,tmp_dir)<0) tmp_vec=-tmp_vec;
01899                tmp_vec=tmp_vec*cur_strength;
01900                cur_vecs.push_back(tmp_vec);
01901 
01902            }
01903 
01904 
01905         }
01906         constraints_vecs.push_back(cur_vecs);
01907     }
01908 
01909     int count=0;
01910     for(int i=0;i<contours2Field.size();i++)
01911     {
01912         if (contours2Field[i].size()<10)
01913             continue;
01914         for (int j=0;j<contours2Field[i].size()-1;j++)
01915         {
01916             set_ten_regBasis(contours2Field[i][j].x, contours2Field[i][j].y,0);
01917             set_ten_regDir(contours2Field[i][j].x,contours2Field[i][j].y,constraints_vecs[count][j]);
01918         }
01919         count++;
01920     }
01921 
01922 }
01923 
01924 
01925 void TfCore::goTri_callback(const std_msgs::String &msg){
01926     ifFinish_goTri=true;
01927 }
01928 
01929 //get 3d obstacle information from octomap
01930 void TfCore::gridMap_callback(const nav_msgs::OccupancyGrid &msg){
01931     if(!isReceiveNewMap)
01932         isReceiveNewMap=true;
01933     dirMap.info=msg.info;
01934     dirMap.info.width=dirMap.info.width+2;
01935     dirMap.info.height=dirMap.info.height+2;
01936     dirMap.info.origin.position.x=dirMap.info.origin.position.x-dirMap.info.resolution*0.5;
01937     dirMap.info.origin.position.y=dirMap.info.origin.position.y-dirMap.info.resolution*0.5;
01938     dirMap.data.clear();
01939     for(int i=dirMap.info.height-1;i>=0;i--)
01940         for(int j=0; j<dirMap.info.width;j++){
01941             if(i>0 && i<dirMap.info.height-1 && j>0 && j<dirMap.info.width-1){
01942                 if (msg.data[msg.info.width*(i-1)+j-1]>50)
01943                     dirMap.data.push_back(100);
01944                 else
01945                     dirMap.data.push_back(0);
01946             }else
01947                 dirMap.data.push_back(0);
01948         }
01949     for(int i=0;i<dirMap.info.height;i++){
01950         for(int j=0;j<dirMap.info.width;j++){
01951             if(dirMap.data[i*dirMap.info.width+j]==100)
01952             {
01953                 int x_min=max(j-2,0); int x_max=min(dirMap.info.width-1,j+2);
01954                 int y_min=max(i-2,0); int y_max=min(dirMap.info.height-1,i+2);
01955                 for(int l=y_min;l<=y_max;l++){
01956                     for(int n=x_min;n<=x_max;n++)
01957                         dirMap.data[l*dirMap.info.width+n]==100;
01958                 }
01959             }
01960         }
01961     }
01962     get_obstacles_contour();//calculate obstacle contours
01963     ensure_robot_safety(); // avoid path rushing into obstacles.
01964 }
01965 
01966 void TfCore::frontier_point_callback(const std_msgs::Float64MultiArray &msg){
01967     frontierPoints=msg;
01968 }
01969 
01970 //core constrol function
01971 void TfCore::set_obstacles(){
01972     //reset regular elements
01973     reset_regular_and_degenrateElem();
01974     bresenham_line_points.clear();
01975     validTriDegpts.clear();
01976     ifCancelPath=false;
01977     //calculate tensor field for current frame (after each periodic scanning)
01978     setRegularElems();
01979     parallel_update_tensorField();
01980     init_degpts();
01981     render_alpha_map_quad();
01982     locate_degpts_cells_tranvec_quad();
01983     //set keyframe and get current location of robot
01984     NUM_Slices+=interFrameNum;
01985     set_cur_as_keyframe(NUM_Slices);
01986     listen_to_robot_loc();
01987     //
01988     if(enRelaxKeyframeOn)
01989       Laplace_relax_timeDep();
01990 
01991     //check for whether the robot is at a trisector and ready to select a branch for scanning
01992     if(major_path->evenstreamlines->ntrajs!=0 && ifReachTrisector && check_reach_trisector()){ // reach a trisector
01993         reset_major_path();
01994         gen_separatrix();
01995         cal_sep_infoGain();
01996         select_target_trisector_branch_move();
01997     }else{  //no reach a trisector
01998         reset_separatrices();
01999         ifReachTrisector=false;
02000         reset_major_path();
02001         gen_major_path();
02002         cut_robot_path();
02003         if(reGenPath) //if too close to obstacles
02004         {
02005             reset_major_path();
02006             gen_major_path();
02007             cut_robot_path();
02008         }
02009         reGenPath=false;
02010 //        if( major_path->evenstreamlines->trajs[0]->nlinesegs<10 || major_path->evenstreamlines->trajs[0]->get_length()*realWorld_to_field_scale<THRESHOLD_LENGTH)
02011 //        {
02012 
02013 //            curSliceID=keyframes->keyframes[keyframes->nkeyframes-1]->keyFrameID;
02014 //            update_tensor_field();
02015 //            if(check_reach_wedge())
02016 //                req_turn_service();
02017 //            else
02018 //                recoverMode=true;
02019 //            return;
02020 //        }
02021         add_robot_wayPoints();
02022     }
02023     curSliceID=keyframes->keyframes[keyframes->nkeyframes-2]->keyFrameID+1;
02024     play_all_frames();// time-varying tensor field updating
02025 }
02026 
02027 // time-varying tensor field updating
02028 void TfCore::play_all_frames()
02029 {
02030     int t=0;
02031     while(t<interFrameNum)
02032     {
02033         ros::spinOnce();
02034         ifFinish_goTri=false;
02035         update_tensor_field();
02036         filterDegpts();
02037         cal_separatrix_vec();
02038         if(!ifReachTrisector)
02039         {
02040             if(check_bypass_trisector())
02041                 return;
02042         }
02043         if(ifReachTrisector)
02044         {
02045             gen_separatrix();
02046             cal_sep_infoGain();
02047             //usleep(0.2*1000000);
02048         }
02049         DrawGLScene(GL_RENDER);
02050         usleep(interFrameTime*1000000);
02051 //        std::cout<<"t: "<<t<<std::endl;
02052         t++;
02053     }
02054 }
02055 
02056 //a mechanism to detect whether the robot is passing by a trisector
02057 //examine whether the robot path first approaches and the leaves away a trisector,with the minimal
02058 //distance to the trisector less than a given threshold.
02059 bool TfCore::check_bypass_trisector(){
02060     validTriDegpts.clear();
02061     std::vector<DegeneratePt> tmp_validTriDegpts;
02062     bresenham_line_points.clear();
02063     std::vector<float> all_min_dists;
02064     std::vector<int > all_indexes;
02065     if(major_path->evenstreamlines->ntrajs==0) return false;
02066     Trajectory *cur_traj= major_path->evenstreamlines->trajs[0];
02067     for(int i=0;i<validDegpts.size();i++){ // examine every trisector to see if it conform the condition
02068         if(validDegpts[i].type==1 && validDegpts[i].nseps==3){
02069             float cur_min_dist=std::numeric_limits<float>::max();
02070             int target_min_index=-1;
02071             for(int j=0;j<cur_traj->nlinesegs;j++){
02072                 float deta_x=cur_traj->linesegs[j].gstart[0]-validDegpts[i].gcx;
02073                 float deta_y=cur_traj->linesegs[j].gstart[1]-validDegpts[i].gcy;
02074                 float dist=sqrt(pow(deta_x,2)+pow(deta_y,2));
02075                 if(dist<cur_min_dist)
02076                 {
02077                     target_min_index=j;
02078                     cur_min_dist=dist;
02079                 }
02080             }
02081             if(target_min_index>6 && target_min_index<cur_traj->nlinesegs-6){
02082                 //check sep_vec
02083                 std::vector<cv::Point2f> in_points;
02084                 for(int k=target_min_index-6;k<=target_min_index-4;k++)
02085                     in_points.push_back(cv::Point2f(cur_traj->linesegs[k].gstart[0],cur_traj->linesegs[k].gstart[1]));
02086                 cv::Vec4f in_line;
02087                 cv::fitLine(cv::Mat(in_points),in_line,CV_DIST_L2,0,0.01,0.01);
02088                 icVector2 in_dir(in_line[0],in_line[1]);
02089                 icVector2 tmp_in_dir(cur_traj->linesegs[target_min_index-6].gend[0]-cur_traj->linesegs[target_min_index-6].gstart[0],cur_traj->linesegs[target_min_index-6].gend[1]-cur_traj->linesegs[target_min_index-6].gstart[1]);
02090                 if(dot(in_dir,tmp_in_dir)<0) in_dir=-in_dir;
02091                 normalize(in_dir);
02092 
02093                 std::vector<cv::Point2f> out_points;
02094                 for(int k=target_min_index+4;k<=target_min_index+6;k++)
02095                     out_points.push_back(cv::Point2f(cur_traj->linesegs[k].gstart[0],cur_traj->linesegs[k].gstart[1]));
02096                 cv::Vec4f out_line;
02097                 cv::fitLine(cv::Mat(out_points),out_line,CV_DIST_L2,0,0.01,0.01);
02098                 icVector2 out_dir(out_line[0],out_line[1]);
02099                 icVector2 tmp_out_dir(cur_traj->linesegs[target_min_index+6].gend[0]-cur_traj->linesegs[target_min_index+6].gstart[0],cur_traj->linesegs[target_min_index+6].gend[1]-cur_traj->linesegs[target_min_index+6].gstart[1]);
02100                 if(dot(out_dir,tmp_out_dir)<0) out_dir=-out_dir;
02101                 normalize(out_dir);
02102 
02103                 int target_in_sep=-1;
02104                 int target_out_sep=-1;
02105                 float cur_in_dir_dot_min=std::numeric_limits<float>::max();
02106                 float cur_out_dir_dot_max=std::numeric_limits<float>::min();
02107                 for(int k=0;k<validDegpts[i].nseps;k++){
02108                     if(dot(validDegpts[i].s_vec[k],in_dir)<cur_in_dir_dot_min){
02109                         cur_in_dir_dot_min=dot(validDegpts[i].s_vec[k],in_dir);
02110                         target_in_sep=k;
02111                     }
02112                     if(dot(validDegpts[i].s_vec[k],out_dir)>cur_out_dir_dot_max) {
02113                         cur_out_dir_dot_max=dot(validDegpts[i].s_vec[k],out_dir);
02114                         target_out_sep=k;
02115                     }
02116                 }
02117                 if(cur_out_dir_dot_max>0.7 && cur_in_dir_dot_min<-0.7 && target_in_sep!=target_out_sep && cur_min_dist*realWorld_to_field_scale<0.8){
02118                     tmp_validTriDegpts.push_back(validDegpts[i]);
02119                     all_min_dists.push_back(cur_min_dist);
02120                     all_indexes.push_back(i);
02121                 }
02122             }
02123         }
02124     }
02125     if(tmp_validTriDegpts.size()>=1){ // if more than one trisector satisfy the condition, then select the nearest one.
02126         auto smallest = std::min_element(std::begin(all_min_dists), std::end(all_min_dists));
02127         int smallest_index=std::distance(std::begin(all_min_dists),smallest);
02128         int target_tri_index=all_indexes[smallest_index];
02129         //check line insection with obstacles
02130         //construct line between robot loc and target triscector
02131         cv::Point2i target_tri_loc, robot_cur_loc;
02132         double target_tri_pos[2],robot_cur_pos[2];
02133         target_tri_pos[0]=validDegpts[target_tri_index].gcx;
02134         target_tri_pos[1]=validDegpts[target_tri_index].gcy;
02135         selected_target_tri=target_tri_index;
02136         locat_point_inMap(target_tri_pos,target_tri_loc);
02137         listen_to_robot_loc();
02138         robot_cur_pos[0]=robot_loc->pos[0];
02139         robot_cur_pos[1]=robot_loc->pos[1];
02140         //send the path between location of robot and the trisector to puresuit controller(reaching to the trisector)
02141         locat_point_inMap(robot_cur_pos,robot_cur_loc);
02142         bresenham_line_points.clear();
02143         CalcBresenhamLocs(Location(target_tri_loc.x,target_tri_loc.y),Location(robot_cur_loc.x,robot_cur_loc.y),bresenham_line_points);
02144         if(check_line_insect_obstacle())
02145             bresenham_line_points.clear();
02146         else{
02147             validTriDegpts.push_back(validDegpts[target_tri_index]);
02148             nav_msgs::Path path;
02149             path.header.frame_id=worldFrameId;
02150             geometry_msgs::PoseStamped pose;
02151             pose.header.stamp = ros::Time::now();
02152             if( bresenham_line_points[0].x<robot_cur_loc.x+2 && bresenham_line_points[0].x>robot_cur_loc.x-2&& bresenham_line_points[0].y<robot_cur_loc.y+2 && bresenham_line_points[0].y>robot_cur_loc.y-2)
02153             {
02154                 std::vector<Location>::iterator cur_iter;
02155                 for(cur_iter=bresenham_line_points.begin();cur_iter!=bresenham_line_points.end();cur_iter++){
02156                     geometry_msgs::PoseStamped pose;
02157                     pose.header.stamp = ros::Time::now();
02158                     double x=dirMap.info.resolution*((*cur_iter).y+0.5)+dirMap.info.origin.position.x;
02159                     double y=dirMap.info.resolution*(dirMap.info.height-1-(*cur_iter).x+0.5)+dirMap.info.origin.position.y;
02160                     pose.pose.position.x=x;
02161                     pose.pose.position.y=y;
02162                     pose.header.frame_id=worldFrameId;
02163                     pose.pose.position.z=0;
02164                     pose.pose.orientation.x=0;
02165                     pose.pose.orientation.y=0;
02166                     pose.pose.orientation.z=0;
02167                     pose.pose.orientation.w=1;
02168                     path.poses.push_back(pose);
02169                 }
02170 
02171             }else{
02172                 std::vector<Location>::reverse_iterator cur_iter;
02173                 for(cur_iter=bresenham_line_points.rbegin();cur_iter!=bresenham_line_points.rend();cur_iter++){
02174                     geometry_msgs::PoseStamped pose;
02175                     pose.header.stamp = ros::Time::now();
02176                     double x=dirMap.info.resolution*((*cur_iter).y+0.5)+dirMap.info.origin.position.x;
02177                     double y=dirMap.info.resolution*(dirMap.info.height-1-(*cur_iter).x+0.5)+dirMap.info.origin.position.y;
02178                     pose.pose.position.x=x;
02179                     pose.pose.position.y=y;
02180                     pose.header.frame_id=worldFrameId;
02181                     pose.pose.position.z=0;
02182                     pose.pose.orientation.x=0;
02183                     pose.pose.orientation.y=0;
02184                     pose.pose.orientation.z=0;
02185                     pose.pose.orientation.w=1;
02186                     path.poses.push_back(pose);
02187                 }
02188 
02189             }
02190 
02191             pure_pursuit_controller::executePath srv;
02192             srv.request.curPath=path;
02193             srv.request.ifFirstPoint=true;
02194             if(goTriExecuteclient.call(srv)){
02195                 DrawGLScene(GL_RENDER);
02196                 ROS_INFO("Request go to the trisectror");
02197                 while(!ifFinish_goTri){
02198                     sleep(2);
02199                     ros::spinOnce();
02200                     if(ifCancelPath)
02201                         break;
02202                     //wait for go to trisector
02203                 }
02204                 ROS_INFO("go to the trisectror finish");
02205                 bresenham_line_points.clear();
02206                 ifFinish_goTri=false;
02207                 ifReachTrisector=true;
02208                 return true;
02209             }
02210             else{
02211                 ROS_ERROR("Failed to call service go to the trisectror");
02212             }
02213          }
02214     }
02215     return false;
02216            // ifReachTrisector
02217 
02218 }
02219 
02220 void TfCore::draw_map_contour(){
02221     glColor3f(1, 0, 0);
02222     glLineWidth(1);
02223     for(int i=0;i<contours2Field.size();i++)
02224     {
02225         for (int j=0;j<contours2Field[i].size()-1;j++)
02226         {
02227             glBegin(GL_LINES);
02228             glVertex2f(contours2Field[i][j].x, contours2Field[i][j].y);
02229             glVertex2f(contours2Field[i][j+1].x, contours2Field[i][j+1].y);
02230             glEnd();
02231         }
02232     }
02233 
02234 }
02235 
02236 //calulate the obstacle contours by using opencv
02237 void TfCore::get_obstacles_contour(){
02238       cv::Mat img = cv::Mat::zeros(dirMap.info.height, dirMap.info.width, CV_8UC1);
02239       dirMap2Field.clear();
02240       dirMapInWorld.clear();
02241       for (unsigned i=0;i<dirMap.info.height;i++)
02242       {
02243           std::vector<cv::Point2f> tmp_world,tmp_field;
02244           for(unsigned j=0;j<dirMap.info.width;j++)
02245           {
02246               cv::Point2f tmp_world_point,tmp_field_point;
02247               tmp_world_point.x=dirMap.info.resolution*(j+0.5)+dirMap.info.origin.position.x;
02248               tmp_world_point.y=dirMap.info.resolution*(dirMap.info.height-1-i+0.5)+dirMap.info.origin.position.y;
02249               tmp_world.push_back(tmp_world_point);
02250               tmp_field_point.x=tmp_world_point.x/realWorld_to_field_scale+realWorld_to_field_offset_x;
02251               tmp_field_point.y=tmp_world_point.y/realWorld_to_field_scale+realWorld_to_field_offset_y;
02252               if(i==0 && j==dirMap.info.width-1){
02253                   rightTop[0]=tmp_field_point.x;
02254                   rightTop[1]=tmp_field_point.y;
02255               }
02256               tmp_field.push_back(tmp_field_point);
02257               if(dirMap.data[dirMap.info.width*i+j]==100)
02258                  img.at<uchar>(i,j)=255;
02259               else
02260                  img.at<uchar>(i,j)=0;
02261           }
02262           dirMapInWorld.push_back(tmp_world);
02263           dirMap2Field.push_back(tmp_field);
02264       }
02265       leftBottom[0]=dirMap.info.origin.position.x/realWorld_to_field_scale+realWorld_to_field_offset_x;
02266       leftBottom[1]=dirMap.info.origin.position.y/realWorld_to_field_scale+realWorld_to_field_offset_y;
02267 
02268       contours.clear();
02269       std::vector<cv::Vec4i> hierarchy;
02270       cv::findContours(img, contours, hierarchy, CV_RETR_LIST, cv::CHAIN_APPROX_NONE);
02271       contours2Field.clear();
02272       contoursInWorld.clear();
02273       for( size_t k = 0; k < contours.size(); k++ )
02274       {
02275           std::vector<cv::Point2f> tmp_contour_to_field,tmp_contour_in_world;
02276           for(size_t i=0;i< contours[k].size();i++){
02277               tmp_contour_to_field.push_back(dirMap2Field[contours[k][i].y][contours[k][i].x]);
02278               tmp_contour_in_world.push_back(dirMapInWorld[contours[k][i].y][contours[k][i].x]);
02279           }
02280           contours2Field.push_back(tmp_contour_to_field);
02281           contoursInWorld.push_back(tmp_contour_in_world);
02282       }
02283 }
02284 
02285 //avoiding the path rushing into obstacles
02286 void TfCore::cut_robot_path(){
02287     if(major_path->evenstreamlines->ntrajs==0) return;
02288     Trajectory *cur_traj = major_path->evenstreamlines->trajs[0];
02289     int Num=500;
02290     int maxNum=Num;
02291     if(maxNum>cur_traj->nlinesegs)
02292         maxNum=cur_traj->nlinesegs;
02293     bool is_turn_sharp=false;
02294     for (int k=0;k<maxNum;k++){
02295         for(int i=0;i<contours2Field.size();i++)
02296         {
02297             for (int j=0;j<contours2Field[i].size();j++)
02298             {
02299                 double x_dist=cur_traj->linesegs[k].gstart[0]-contours2Field[i][j].x;
02300                 double y_dist=cur_traj->linesegs[k].gstart[1]-contours2Field[i][j].y;
02301                 if(!is_turn_sharp && k>1){
02302                     icVector2 now(cur_traj->linesegs[k].gend[0]-cur_traj->linesegs[k].gstart[0],cur_traj->linesegs[k].gend[1]-cur_traj->linesegs[k].gstart[1]);
02303                     icVector2 pre(cur_traj->linesegs[k-1].gend[0]-cur_traj->linesegs[k-1].gstart[0],cur_traj->linesegs[k-1].gend[1]-cur_traj->linesegs[k-1].gstart[1]);
02304                     normalize(now);
02305                     normalize(pre);
02306                     if(dot(now,pre)<0.10)
02307                     {
02308                         is_turn_sharp=true;
02309                         cur_traj->nlinesegs=k-1;
02310                     }
02311                 }
02312                 double cur_dist=sqrt(x_dist*x_dist+y_dist*y_dist);
02313                 cur_dist=cur_dist*realWorld_to_field_scale;
02314                 if (cur_dist<DANGERDIST)
02315                 {
02316                     reGenPath=true;
02317 //                    icVector2 tmp_dir(x_dist,y_dist);
02318 //                    //
02319 //                    std::vector<cv::Point2f> points;
02320 //                    if(j<3){
02321 //                       for(int k=0;k<5;k++)
02322 //                           points.push_back(cv::Point2f(contours2Field[i][k].x,contours2Field[i][k].y));
02323 //                    }else if(j>contours2Field[i].size()-6){
02324 //                       for(int k=contours2Field[i].size()-5;k<contours2Field[i].size();k++)
02325 //                           points.push_back(cv::Point2f(contours2Field[i][k].x,contours2Field[i][k].y));
02326 //                    }else{
02327 //                       for(int k=j-2;k<j+3;k++)
02328 //                           points.push_back(cv::Point2f(contours2Field[i][k].x,contours2Field[i][k].y));
02329 //                    }
02330 //                    cv::Vec4f line;
02331 //                    cv::fitLine(cv::Mat(points), line, CV_DIST_L2, 0, 0.01, 0.01);
02332 //                    icVector2 tmp_vec(-line[1],line[0]);
02333 //                    if(dot(tmp_vec,tmp_dir)<0) tmp_vec=-tmp_vec;
02334 //                    outside_push=tmp_vec;
02335 //                    //
02336 //                    cur_traj->nlinesegs=k;
02337 //                    pure_pursuit_controller::cutPath srv;
02338 //                    srv.request.safeWayPoint=k;
02339 //                    if(pathCutClient.call(srv))
02340 //                    {
02341 //                        ROS_INFO("Request cut path");
02342 //                    }else{
02343 //                        ROS_ERROR("Failed to call service cut_path");
02344 //                    }
02345                     return;
02346                 }
02347             }
02348         }
02349     }
02350 }
02351 
02352 //calculate information gain for each separatrix
02353 void TfCore::cal_sep_infoGain(){
02354     degptsPathsInfoGain.clear();
02355     float *pointCollection=new float[frontierPoints.data.size()];
02356     for(int i=0;i<frontierPoints.data.size();i++)
02357         pointCollection[i]=frontierPoints.data[i];
02358     for(int i=0;i<separatrices->evenstreamlines->ntrajs;i++){
02359         Trajectory *cur_traj = separatrices->evenstreamlines->trajs[i];
02360         float *curPathPoints=new float[cur_traj->nlinesegs*2];
02361         for(int j=0;j<cur_traj->nlinesegs;j++){
02362             curPathPoints[2*j]=(cur_traj->linesegs[j].start[0]-realWorld_to_field_offset_x)*realWorld_to_field_scale;
02363             curPathPoints[2*j+1]=(cur_traj->linesegs[j].start[1]-realWorld_to_field_offset_x)*realWorld_to_field_scale;
02364         }
02365         int *curPathInfoGain_cu=new int[cur_traj->nlinesegs];
02366         calPathInfoGain(pointCollection, curPathPoints, curPathInfoGain_cu,frontierPoints.data.size()/3,cur_traj->nlinesegs);
02367         std::vector<int> curPathInfoGain;
02368         float averageInfoGain=0;
02369         int maxInfoGain= 0;
02370         int minInfoGain=std::numeric_limits<int>::max();
02371         for(int k=0;k<cur_traj->nlinesegs;k++){
02372             curPathInfoGain.push_back(curPathInfoGain_cu[k]);
02373             if(maxInfoGain< curPathInfoGain_cu[k])
02374                 maxInfoGain=curPathInfoGain_cu[k];
02375             if(minInfoGain>curPathInfoGain_cu[k])
02376                 minInfoGain=curPathInfoGain_cu[k];
02377             averageInfoGain+=curPathInfoGain_cu[k];
02378         }
02379         averageInfoGain/=cur_traj->nlinesegs;
02380         cur_traj->infoGain=maxInfoGain;
02381         degptsPathsInfoGain.push_back(curPathInfoGain);
02382         delete curPathPoints;
02383         delete curPathInfoGain_cu;
02384     }
02385     delete pointCollection;
02386 }
02387 
02388 //check whether the robot is at a trisector
02389 bool TfCore::check_reach_trisector(){
02390     listen_to_robot_loc();
02391     if(validDegpts.size()==0) return false;
02392     float min_dist=std::numeric_limits<float>::max();
02393     for(int i=0;i<validDegpts.size();i++){
02394         if(validDegpts[i].type == 1){
02395             float deta_x=validDegpts[i].gcx-robot_loc->pos[0];
02396             float deta_y=validDegpts[i].gcy-robot_loc->pos[1];
02397             float dist=sqrt(deta_x*deta_x+deta_y*deta_y);
02398             if(dist<min_dist){
02399                 targetTrisectorIndex=i;
02400                 min_dist=dist;
02401             }
02402         }
02403     }
02404     if(min_dist<TRISECTOR_REACH_THRESHOLD){
02405         return true;
02406     }else{
02407         return false;
02408     }
02409 }
02410 
02411 void TfCore::ensure_robot_safety(){
02412     if(ifCancelPath) return;
02413     listen_to_robot_loc();
02414     double min_dist=std::numeric_limits<double>::max();
02415     for(int i=0;i<contours2Field.size();i++)
02416     {
02417         for (int j=0;j<contours2Field[i].size();j++)
02418         {
02419             double x_dist=robot_loc->pos[0]-contours2Field[i][j].x;
02420             double y_dist=robot_loc->pos[1]-contours2Field[i][j].y;
02421             double cur_dist=sqrt(x_dist*x_dist+y_dist*y_dist);
02422             cur_dist=cur_dist*realWorld_to_field_scale;
02423             if(min_dist>cur_dist)
02424                 min_dist=cur_dist;
02425             if (cur_dist<safeDistance)
02426             {
02427                 cancelPath();
02428                 ifCancelPath=true;
02429                 return;
02430             }
02431         }
02432     }
02433 }
02434 
02435 //reset tensor field
02436 void TfCore::reset_regular_and_degenrateElem(){
02437     /*initialize regular design element*/
02438     free(ten_regularelems);
02439     ten_regularelems=NULL;
02440     if(ten_regularelems == NULL)
02441     {
02442         ten_regularelems=(TenRegularElem *)malloc(sizeof(TenRegularElem)*curMaxNumTenRegElems);
02443         if(ten_regularelems == NULL)
02444             exit(-1);
02445     }
02446     nten_regelems = 0;
02447     /*initialize singular design element*/
02448     free(ten_designelems);
02449     ten_designelems = NULL;
02450     if(ten_designelems == NULL)
02451     {
02452         ten_designelems=(Degenerate_Design *)malloc(sizeof(Degenerate_Design)*curMaxNumTenDesignElems);
02453         if(ten_designelems == NULL)
02454             exit(-1);
02455     }
02456     ntenelems = 0;
02457 }
02458 
02459 //topo connection
02460 
02461 void TfCore::locat_point_inMap(double pos[2],cv::Point2i &mapLoc){
02462     //translate opengl point to real world point
02463     double x=(pos[0]-realWorld_to_field_offset_x)*realWorld_to_field_scale;
02464     double y=(pos[1]-realWorld_to_field_offset_y)*realWorld_to_field_scale;
02465 
02466     int lowerX = 0;
02467     int upperX = dirMap.info.width;
02468     do
02469     {
02470         int delim = (lowerX + upperX)/2;//change to shift later
02471         double tmp_x = dirMapInWorld[0][delim].x-dirMap.info.resolution*0.5;
02472 
02473         if(x < tmp_x)
02474             upperX = delim;
02475         else
02476             lowerX = delim;
02477     }
02478     while(upperX - lowerX > 1);
02479     mapLoc.y=lowerX;
02480 
02481     // for y-direction
02482     int lowerY = 0;
02483     int upperY = dirMap.info.height;
02484 
02485     do
02486     {
02487         int delim = (lowerY + upperY)/2;
02488         double tmp_y=dirMapInWorld[delim][0].y-dirMap.info.resolution*0.5;
02489 
02490         if(y>tmp_y)
02491             upperY = delim;
02492 
02493         else
02494             lowerY = delim;
02495     }
02496     while(upperY - lowerY > 1);
02497     mapLoc.x=lowerY;
02498 }
02499 
02500 // filter degenerate points which are in obstacles
02501 void TfCore::filterDegpts(){
02502     if(ndegpts==0) return;
02503     validDegpts.clear();
02504     std::vector<DegeneratePt> tmp_validDegpts;
02505     for (int i=0;i<ndegpts; i++){
02506         double x=(degpts[i].gcx-realWorld_to_field_offset_x)*realWorld_to_field_scale;
02507         double y=(degpts[i].gcy-realWorld_to_field_offset_y)*realWorld_to_field_scale;
02508         if(x>=dirMapInWorld[0][dirMap.info.width-1].x-dirMap.info.resolution*0.5 || x<=dirMapInWorld[0][0].x-dirMap.info.resolution*0.5 ||
02509               y>=dirMapInWorld[0][0].y-dirMap.info.resolution*0.5 ||  y<=dirMapInWorld[dirMap.info.height-1][0].y-dirMap.info.resolution*0.5 ){
02510             continue;
02511         }
02512         cv::Point2i mapLoc;
02513         int region_num=8;
02514         double pos[2];
02515         pos[0]=degpts[i].gcx;
02516         pos[1]=degpts[i].gcy;
02517         locat_point_inMap(pos,mapLoc);
02518         int region_x_min,region_x_max,region_y_min,region_y_max;
02519         if(mapLoc.x-region_num>-1) region_y_min=mapLoc.x-region_num; else region_y_min=0;
02520         if(mapLoc.x+region_num<dirMap.info.height) region_y_max=mapLoc.x+region_num; else region_y_max=dirMap.info.height-1;
02521         if(mapLoc.y-region_num>-1) region_x_min=mapLoc.y-region_num; else region_x_min=0;
02522         if(mapLoc.y+region_num<dirMap.info.width) region_x_max=mapLoc.y+region_num; else region_x_max=dirMap.info.width-1;
02523         bool if_valid=true;
02524         for(int l=region_x_min;l<=region_x_max;l++)
02525             for(int m=region_y_min; m<=region_y_max; m++)
02526             {
02527                 if(dirMap.data[l+dirMap.info.width*m]!=0)
02528                 {
02529                     if_valid=false;
02530                     break;
02531                 }
02532 
02533             }
02534          if(if_valid)
02535             tmp_validDegpts.push_back(degpts[i]);
02536    }
02537    std::set<int> deleteIndex;
02538    if(tmp_validDegpts.size()>1){
02539        for(int i=0;i<tmp_validDegpts.size();i++){
02540             for(int j=i+1;j<tmp_validDegpts.size();j++){
02541                 if(deleteIndex.find(j)!=deleteIndex.end()) continue;
02542                 float deta_x=tmp_validDegpts[i].gcx-tmp_validDegpts[j].gcx;
02543                 float deta_y=tmp_validDegpts[i].gcy-tmp_validDegpts[j].gcy;
02544                 if(sqrt(deta_x*deta_x+deta_y*deta_y)<2*1e-2){
02545                     if(fabs(tmp_validDegpts[i].type-tmp_validDegpts[j].type)!=1)continue;
02546                     deleteIndex.insert(i);
02547                     deleteIndex.insert(j);
02548                     break;
02549                 }
02550             }
02551        }
02552    }
02553    for(int i=0;i<tmp_validDegpts.size();i++){
02554        if(deleteIndex.find(i)==deleteIndex.end())
02555            validDegpts.push_back(tmp_validDegpts[i]);
02556    }
02557    for(int i=0;i<validDegpts.size();i++){
02558       validDegpts[i].valid_index=i;
02559       compute_separatrixVec_degpt_quad(i);
02560    }
02561 }
02562 
02563 
02564 void TfCore::display_valid_trisectors(GLenum mode)
02565 {
02566     if (validTriDegpts.size()==0) return;
02567     for(int i = 0; i < validTriDegpts.size(); i++)
02568     {
02569         glColor3f(0, 1, 0);
02570 
02571         drawSolidCircle_size(validTriDegpts[i].gcx, validTriDegpts[i].gcy, 0.008/zoom_factor);
02572 
02573         glColor3f(0, 0, 1);
02574         glLineWidth(1.4);
02575         draw_hollow_circle_size(validTriDegpts[i].gcx, validTriDegpts[i].gcy, 0.0085/zoom_factor);
02576     }
02577     glFlush();
02578 }
02579 
02580 void TfCore::display_valid_degenerate_pts(GLenum mode)
02581 {
02582     if (validDegpts.size()==0) return;
02583     for(int i = 0; i < validDegpts.size(); i++)
02584     {
02585         //if (validDegpts[i].type==1) continue;
02586         if(validDegpts[i].type == 0) /*wedge*/
02587             glColor3f(1, 0, 0);
02588         else if(validDegpts[i].type == 1) /*trisector*/
02589             glColor3f(0, 1, 0);
02590         else
02591             glColor3f(1, 1, 1);
02592 
02593         drawSolidCircle_size(validDegpts[i].gcx, validDegpts[i].gcy, 0.0045/zoom_factor);
02594 
02595         glColor3f(0, 0, 0);
02596         glLineWidth(1.4);
02597         draw_hollow_circle_size(validDegpts[i].gcx, validDegpts[i].gcy, 0.005/zoom_factor);
02598     }
02599     glFlush();
02600 }
02601 
02602 
02603 //laplace system for time-varying tensor field
02604 
02605 void TfCore::get_laplace_TVTF(int which_slice){
02606     /*  We now save the read file into the vec variable of the mesh  */
02607     int curStep=which_slice-keyframes->keyframes[keyframes->nkeyframes-2]->keyFrameID;
02608     int cur_vertID;
02609     int variableID;
02610     for(int j=0; j<quadmesh->nverts; j++)
02611     {
02612         cur_vertID = curStep*quadmesh->nverts+j;
02613         QuadVertex *v=quadmesh->quad_verts[j];
02614         if(vertTimeList->vertsTime[cur_vertID]->isConstraint)
02615         {
02616             OneKeyFrame *thekeyframe = keyframes->get_frame_pointer(which_slice);
02617             v->Jacobian.entry[0][0] = thekeyframe->jacobian_vals[j].entry[0][0];
02618             v->Jacobian.entry[0][1] = thekeyframe->jacobian_vals[j].entry[0][1];
02619         }
02620         else
02621         {
02622             variableID=(curStep-1)*quadmesh->nverts+j;
02623             v->Jacobian.entry[0][0]  = vecsTime[variableID].entry[0];
02624             v->Jacobian.entry[0][1]  = vecsTime[variableID].entry[1];
02625         }
02626         double theta = atan2( v->Jacobian.entry[0][1], v->Jacobian.entry[0][0]);
02627         /*major eigen vector*/
02628         v->major.entry[0] = cos(theta/2.);
02629         v->major.entry[1] = sin(theta/2.);
02630 
02631         /*minor eigen vector*/
02632         v->minor.entry[0] = cos((theta+M_PI)/2.);
02633         v->minor.entry[1] = sin((theta+M_PI)/2.);
02634 
02635         v->major_ang = atan2(v->major.entry[1],v->major.entry[0]);
02636         v->minor_ang = atan2(v->minor.entry[1], v->minor.entry[0]);
02637 
02638         v->minor.entry[0]=cos(v->minor_ang);
02639         v->minor.entry[1]=sin(v->minor_ang);
02640 
02641         v->tensor_major_ang = v->major_ang;
02642 
02643         v->tran_vec.set(cos(2*v->tensor_major_ang), sin(2*v->tensor_major_ang));
02644         /*transfer to cos^2*/
02645         double major_ang_cos = cos(v->major_ang);
02646         double major_ang_sin = sin(v->major_ang);
02647 
02648         v->major_ang = major_ang_cos*major_ang_cos;
02649         if(major_ang_cos<0)
02650             v->major_cos = true;
02651         else
02652             v->major_cos = false;
02653         if(major_ang_sin<0)
02654             v->major_sin = true;
02655         else
02656             v->major_sin = false;
02657 
02658         double minor_ang_cos = cos(v->minor_ang);
02659         double minor_ang_sin = sin(v->minor_ang);
02660 
02661         v->minor_ang = minor_ang_cos*minor_ang_cos;
02662         //v->minor_ang = minor_ang_sin*minor_ang_sin;
02663         if(minor_ang_cos<0)
02664             v->minor_cos = true;
02665         else
02666             v->minor_cos = false;
02667         if(minor_ang_sin<0)
02668             v->minor_sin = true;
02669         else
02670             v->minor_sin = false;
02671     }
02672 }
02673 
02674 void TfCore::update_cur_TF_keyframe()
02675 {
02676     if(keyframes == NULL) return;
02677     /*  if interpolation scheme is used to obtain the in-between slices  */
02678     if(!enRelaxKeyframeOn)
02679     {
02680         cal_TF_at_slice_keyframe_interp(curSliceID);
02681         cal_all_eigenvecs_quad();
02682     }
02683     else
02684     {
02685         //read_timeDep_TF_oneSlice_bin("keyframe_tempOut.bin", curSliceID);
02686         get_laplace_TVTF(curSliceID);
02687         normalized_tensorfield_quad();
02688     }
02689     curSliceID ++;
02690 
02691 }
02692 
02693 void TfCore::cal_TF_at_slice_keyframe_interp(int which_slice)
02694 {
02695     /*   first, we need to judge which two neighboring key frames in the list containting this slice   */
02696     int i;
02697     bool is_keyframe = false;
02698     int keyframeID1, keyframeID2;
02699     double ratio = 0;
02700 
02701     keyframeID1 = keyframeID2 = -1;
02702 
02703     for(i=0; i<keyframes->nkeyframes; i++)
02704     {
02705         if(which_slice < keyframes->keyframes[i]->keyFrameID)
02706         {
02707             keyframeID1 = i-1;
02708             keyframeID2 = i;
02709             ratio = (double)(which_slice-keyframes->keyframes[i-1]->keyFrameID)/
02710                 (double)(keyframes->keyframes[i]->keyFrameID-keyframes->keyframes[i-1]->keyFrameID);
02711             break;
02712         }
02713         else if(which_slice == keyframes->keyframes[i]->keyFrameID)
02714         {
02715             keyframeID1 = i;
02716             is_keyframe = true;
02717             break;
02718         }
02719     }
02720 
02721     if(i==keyframes->nkeyframes-1 && keyframeID1<0)
02722         keyframeID1 = keyframes->nkeyframes-1;
02723 
02724     /*  current computed frame is a key frame  */
02725     if(is_keyframe)
02726     {
02727         copy_from_keyframe(keyframeID1);
02728     }
02729 
02730     else
02731     {
02732         if(keyframeID2 < 0)
02733         {
02734             //ROS_ERROR("out of range, cur slice id is %d",which_slice);
02735             /*   we may have to use relaxation to obtain the slices after the last key frame slice   */
02736         }
02737 
02738         else
02739         {
02740             cal_TF_at_inbetween_slice_keyframe_interp(ratio, keyframeID1, keyframeID2);
02741         }
02742     }
02743 }
02744 
02745 void TfCore::copy_from_keyframe(int keyframelistPos)
02746 {
02747     int i;
02748 
02749     for(i=0; i<quadmesh->nverts; i++)
02750     {
02751         quadmesh->quad_verts[i]->Jacobian = keyframes->keyframes[keyframelistPos]->jacobian_vals[i];
02752     }
02753 
02754     /*  maybe normalize the field?  */
02755 }
02756 
02757 void TfCore::cal_TF_at_inbetween_slice_keyframe_interp(double ratio, int start, int end)
02758 {
02759     /*
02760         We now assume only two keyframes available
02761     */
02762     int i;
02763     icMatrix2x2 vect, vec1, vec2;
02764 
02765     double ang0, ang1, ang2;  /*  for angle-based interpolation  */
02766 
02767     for(i=0; i<quadmesh->nverts; i++)
02768     {
02769         vec1 = keyframes->keyframes[start]->jacobian_vals[i];
02770         vec2 = keyframes->keyframes[end]->jacobian_vals[i];
02771 
02772         if(InterpScheme == 1)
02773         {
02774             vect = vec1+ratio*(vec2-vec1);
02775         }
02776 
02777         else if (InterpScheme == 2)  // Bezier
02778         {
02779             /*  make a quick test with #keyframes = 3  */
02780             icMatrix2x2 vec0;
02781             vec0 = keyframes->keyframes[0]->jacobian_vals[i];
02782             vec1 = keyframes->keyframes[1]->jacobian_vals[i];
02783             vec2 = keyframes->keyframes[2]->jacobian_vals[i];
02784 
02785             vect = (1-ratio)*((1-ratio)*vec0+ratio*vec1)
02786                 +ratio*((1-ratio)*vec1+ratio*vec2);
02787         }
02788 
02789         else if (InterpScheme == 3)  // Try Hermite
02790         {
02791             icMatrix2x2 pseudo_vec1 = 0.5*(vec2-vec1);  //Catmull-Rom splines
02792             icMatrix2x2 pseudo_vec2;
02793             float s = ratio;    // scale s to go from 0 to 1
02794             float h1 =  2*s*s*s - 3*s*s*s + 1;          // calculate basis function 1
02795             float h2 = -2*s*s*s + 3*s*s;              // calculate basis function 2
02796             float h3 =   s*s*s - 2*s*s + s;         // calculate basis function 3
02797             float h4 =   s*s*s -  s*s;
02798 
02799             if (end+1 >= keyframes->nkeyframes)
02800                 pseudo_vec2 = pseudo_vec1;
02801             else
02802             {
02803                 pseudo_vec2 = 0.5*(keyframes->keyframes[end+1]->jacobian_vals[i]-vec2); //Catmull-Rom splines
02804             }
02805             vect = h1*vec1 +                    // multiply and sum all funtions
02806                      h2*vec2 +                    // together to build the interpolated
02807                      h3*pseudo_vec1 +                    // point along the curve.
02808                      h4*pseudo_vec2;
02809         }
02810 
02811         QuadVertex *v=quadmesh->quad_verts[i];
02812         v->Jacobian = vect;
02813     }
02814 }
02815 
02816 
02817 void TfCore::update_tensor_field(){
02818     update_cur_TF_keyframe();
02819     init_degpts();
02820     /*calculate the alpha map here*/
02821     render_alpha_map_quad();
02822     locate_degpts_cells_tranvec_quad();
02823 }
02824 
02825 void TfCore::init_keyframeList(int size){
02826     if(keyframes == NULL)
02827         keyframes = new KeyFrameList(size);
02828 }
02829 
02830 void TfCore::set_cur_as_keyframe(int frameID)
02831 {
02832     keyframes->save_cur_field(frameID, quadmesh);
02833 }
02834 
02835 void TfCore::publish_image(){
02836     glReadBuffer(GL_BACK);
02837     glReadPixels(0, 0,NPIX,NPIX, GL_RGB, GL_UNSIGNED_BYTE, rgb_im);
02838     cv_bridge::CvImage img_ptr_rgb;//=new cv_bridge::CvImage ;
02839     img_ptr_rgb.image=cv::Mat(NPIX,NPIX, CV_8UC3);
02840     cv::Mat& mat_rgb = img_ptr_rgb.image;
02841 
02842     cv::MatIterator_<cv::Vec3b> it=mat_rgb.begin<cv::Vec3b>();
02843     for (int i = NPIX-1;i >-1; i--)
02844     {
02845         for (int j = 0; j <  NPIX; j++)
02846         {
02847             (*it)[2]=rgb_im[i * NPIX*3 + j*3+0];  (*it)[1]=rgb_im[i * NPIX*3 + j*3+1]; (*it)[0]=rgb_im[i * NPIX*3 + j*3+2];
02848             ++it;
02849         }
02850     }
02851     sensor_msgs::ImagePtr msg_rgb=cv_bridge::CvImage(std_msgs::Header(), "bgr8", mat_rgb).toImageMsg();
02852     int count=0;
02853     while(count<3){
02854         rgb_pub.publish(msg_rgb);
02855         count++;
02856     }
02857 
02858 }
02859 //parallel
02860 void TfCore::create_paraThread(){
02861     for (int i = 0; i < EXTRA_THREAD_NUM; i++)
02862     {
02863         ParaThread *myThread = new ParaThread();
02864         myThread->setID(i+1);
02865         myThread->connectTensorField(this);
02866         m_myThreads.push_back(myThread);
02867     }
02868 }
02869 void TfCore::parallel_update_tensorField(){
02870     int x1 = 0, x2 = 0;
02871     for (int i = 0; i < EXTRA_THREAD_NUM; i++)
02872     {
02873         split_tensorField(i+1, EXTRA_THREAD_NUM+1, x1, x2);
02874         m_myThreads[i]->setUpdateTensorFieldMission(x1, x2);
02875         m_myThreads[i]->start();
02876     }
02877     split_tensorField(0, EXTRA_THREAD_NUM+1, x1, x2);
02878     parallel_cal_tensorvals_quad(x1,x2);
02879     for (int i = 0; i < EXTRA_THREAD_NUM; i++)
02880         m_myThreads[i]->wait(); //
02881 
02882     normalized_tensorfield_quad();
02883 
02884 }
02885 void TfCore::split_tensorField( int i, int threadNum, int &x1, int &x2){
02886     int width = quadmesh->nverts/ threadNum;
02887     int last_remainder = quadmesh->nverts % width;
02888     x1 = i * width + (i<last_remainder%threadNum? i: last_remainder%threadNum);  //last_remainder < threadNum
02889     x2 = (i+1) * width + (i+1<last_remainder%threadNum? i+1: last_remainder%threadNum);
02890 }
02891 void TfCore::parallel_cal_tensorvals_quad(int &x1, int &x2){
02892     QuadVertex *v;
02893     double t[4]={0.};
02894     for(int i=x1; i<x2; i++)
02895     {
02896         v = quadmesh->quad_verts[i];
02897         get_tensor(v->x, v->y, t);
02898         v->Jacobian.entry[0][0] = t[0];
02899         v->Jacobian.entry[0][1] = t[1];
02900         v->Jacobian.entry[1][0] = t[2];
02901         v->Jacobian.entry[1][1] = t[3];
02902         cal_eigenvecs_onevert_quad(i);
02903     }
02904 }
02905 //
02906 void TfCore::Laplace_relax_timeDep(){
02907     /*  initialize the list  */
02908     init_vertTimeList();
02909     add_verts_to_vertTimeList();
02910     set_constraints_keyframes();
02911     count_nonconstrained_verts();
02912 
02913     int num_nonconstrained_verts = vertTimeList->total_notconstraint_verts;
02914 
02915     if(num_nonconstrained_verts < 2)
02916     {
02917         fprintf(stderr, "Can not find enough inner vertices. \n");
02918         return;
02919     }
02920 
02921     int i;
02922     Vertex *cur_v;
02923     int NMAX=10*num_nonconstrained_verts;
02924 
02925     Vec_INT tempija(NMAX);
02926     Vec_DP tempsa(NMAX);
02927 
02928     DP err;
02929     Vec_DP b(num_nonconstrained_verts),/*bcmp(num_nonconstrained_verts),*/x(num_nonconstrained_verts);
02930 
02931     Mat_DP bound_vert(0.0, num_nonconstrained_verts, 2);  
02932 
02933     const int ITOL=1,ITMAX=500;
02934     const DP TOL=ERROR_LAPLACE;
02935     int iter;
02936 
02937     con_linear_Sys_spatioTemp(tempsa, tempija, bound_vert);
02938 
02939     Vec_INT ija(tempija[num_nonconstrained_verts]);
02940     Vec_DP sa(tempija[num_nonconstrained_verts]);
02941 
02942     for(i = 0; i < tempija[num_nonconstrained_verts]; i++)
02943     {
02944         ija[i] = tempija[i];
02945         sa[i] = tempsa[i];
02946     }
02947 
02948     ija_p = &ija;
02949     sa_p = &sa;
02950 
02951     /*   allocate temporary space to store the computed vector values   */
02952    vecsTime=new icVector2[num_nonconstrained_verts];
02953 
02954 
02956     for (i = 0; i < vertTimeList->total_notconstraint_verts; i++)
02957     {
02958         x[i]=0.0;
02959         b[i]= bound_vert[i][0];
02960     }
02961     linbcg(b,x,ija_p,sa_p,ITOL,TOL,ITMAX,iter,err);
02962 
02964     for (i = 0; i < num_nonconstrained_verts; i++)
02965     {
02966         vecsTime[i].entry[0] = x[i];
02967     }
02968 
02970     for (i = 0; i < vertTimeList->total_notconstraint_verts; i++)
02971     {
02972         x[i]=0.0;
02973         b[i]= bound_vert[i][1];
02974     }
02975     linbcg(b,x,ija_p,sa_p,ITOL,TOL,ITMAX,iter,err);
02976 
02978     for (i = 0; i < num_nonconstrained_verts; i++)
02979     {
02980         vecsTime[i].entry[1] = x[i];
02981     }
02982 }
02983 
02984 void TfCore::init_vertTimeList(){
02985     if(vertTimeList != NULL){
02986         delete vertTimeList;
02987         vertTimeList=NULL;
02988         if(vecsTime!= NULL){
02989             delete vecsTime;
02990             vecsTime=NULL;
02991         }
02992     }
02993     vertTimeList = new VertTimeList(quadmesh->nverts,quadmesh->nverts*(interFrameNum+1));
02994 }
02995 void TfCore::add_verts_to_vertTimeList(){
02996     int i, j;
02997 
02998     if(vertTimeList == NULL)
02999         init_vertTimeList();
03000 
03001     for(i=0; i<interFrameNum+1; i++)
03002     {
03003         for(j=0; j<quadmesh->nverts; j++)
03004             vertTimeList->add_new(i, j);
03005     }
03006 }
03007 void TfCore::set_constraints_keyframes(){
03008     int i, j;
03009     int cur_step;
03010     for(i=0; i<2;i++){
03011         if (i==0)
03012             cur_step=0;
03013         else
03014             cur_step=interFrameNum;
03015         for(j=0; j<quadmesh->nverts; j++)
03016             vertTimeList->set_constraint_at_vert(cur_step,j);
03017     }
03018 }
03019 void TfCore::count_nonconstrained_verts(){
03020     int i;
03021     vertTimeList->total_notconstraint_verts = 0;
03022     for(i=0; i<vertTimeList->nvertsTime; i++)
03023     {
03024         if(!vertTimeList->vertsTime[i]->isConstraint)
03025         {
03026             /*  assign the variable index to the non-constrained vertex  */
03027             vertTimeList->vertsTime[i]->variableID = vertTimeList->total_notconstraint_verts;
03028             /*  increase the number of the non-constrained vertices  */
03029             vertTimeList->total_notconstraint_verts ++;
03030         }
03031     }
03032 }
03033 
03034 void TfCore::con_linear_Sys_spatioTemp(Vec_DP &tsa, Vec_INT &tija, Mat_DP &bound_v){
03035     if(vertTimeList == NULL) return;
03036 
03037     int i, j;
03038     QuadVertex *adj_v, *cur_v = NULL;
03039     QuadEdge *adj_e;
03040     int *RegionIndex;
03041     int num_nonzeroarow = 0;
03042     int num_elements = 0;
03043     int cur_variableID = 0;
03044     unsigned char type = -1;
03045     double time_axis_weight = /*0.1*/30;
03046 
03047     /*    fill the diagnal elements first   */
03048     for(i = 0; i < vertTimeList->total_notconstraint_verts; i++)
03049         tsa[i] = 1. + time_axis_weight*2.;
03050 
03051     num_elements = vertTimeList->total_notconstraint_verts+1;
03052 
03053     /*   store other the remaining off-diagnal non-zero elements  */
03054 
03055     for(i = 0; i < quadmesh->nverts*(interFrameNum+1)/*vertTimeList->total_notconstraint_verts*/; i++)
03056     {
03057         if(vertTimeList->vertsTime[i]->isConstraint)  /* consider non-constrained verts only  */
03058             continue;
03059 
03060         cur_variableID = vertTimeList->vertsTime[i]->variableID;
03061         cur_v = quadmesh->quad_verts[vertTimeList->vertsTime[i]->which_vert];
03062         RegionIndex = new int[cur_v->Num_edge+2]; /*  we consider two more neighbors along time axis 09/19/2008  */
03063 
03064         int cur_time = vertTimeList->vertsTime[i]->time_step;
03065 
03066         num_nonzeroarow = 0;
03067 
03068         type = -1;
03069 
03070         for(j = 0; j < cur_v->Num_edge; j++)
03071         {
03072             adj_e = cur_v->edges[j];
03073 
03075             if( quadmesh->quad_verts[adj_e->verts[0]] != cur_v)
03076                 adj_v = quadmesh->quad_verts[adj_e->verts[0]];
03077             else
03078                 adj_v = quadmesh->quad_verts[adj_e->verts[1]];
03079 
03080             if(vertTimeList->vertsTime[cur_time*quadmesh->nverts+adj_v->index]->isConstraint)
03081             {
03082                 RegionIndex[j] = -1;
03083 
03084                 OneKeyFrame *thekeyframe = keyframes->get_frame_pointer(cur_time+keyframes->keyframes[keyframes->nkeyframes-2]->keyFrameID);
03085 
03086                 /*  need to obtain the key frame vector values  */
03087                 if(thekeyframe != NULL)
03088                 {
03089                     bound_v[cur_variableID][0] += (1./cur_v->Num_edge)*thekeyframe->jacobian_vals[adj_v->index].entry[0][0];
03090                     bound_v[cur_variableID][1] += (1./cur_v->Num_edge)*thekeyframe->jacobian_vals[adj_v->index].entry[0][1];
03091                 }
03092             }
03093             else
03094             {
03095                 RegionIndex[j] = vertTimeList->vertsTime[cur_time*quadmesh->nverts+adj_v->index]->variableID;
03096                 num_nonzeroarow++;
03097             }
03098         }
03099 
03100         /*   consider the two neighbors along the time axis   */
03101         if(cur_time == 0)
03102         {
03103             RegionIndex[cur_v->Num_edge] = -1;
03104 
03105             if(vertTimeList->vertsTime[i+quadmesh->nverts]->isConstraint)
03106             {
03107                 RegionIndex[cur_v->Num_edge+1] = -1;
03108                 OneKeyFrame *thekeyframe = keyframes->get_frame_pointer(cur_time+1+keyframes->keyframes[keyframes->nkeyframes-2]->keyFrameID);
03109                 bound_v[cur_variableID][0] += /*(1./(cur_v->Num_edge+2))*/time_axis_weight*thekeyframe->jacobian_vals[cur_v->index].entry[0][0];
03110                 bound_v[cur_variableID][1] += /*(1./(cur_v->Num_edge+2))*/time_axis_weight*thekeyframe->jacobian_vals[cur_v->index].entry[0][1];
03111             }
03112             else
03113             {
03114                 RegionIndex[cur_v->Num_edge+1] = vertTimeList->vertsTime[i+quadmesh->nverts]->variableID;
03115                 num_nonzeroarow++;
03116                 type = 0;
03117             }
03118         }
03119         else if(cur_time == interFrameNum+1-1)
03120         {
03121             RegionIndex[cur_v->Num_edge+1] = -1;
03122 
03123             if(vertTimeList->vertsTime[i-quadmesh->nverts]->isConstraint)
03124             {
03125                 RegionIndex[cur_v->Num_edge] = -1;
03126                 OneKeyFrame *thekeyframe = keyframes->get_frame_pointer(cur_time-1+keyframes->keyframes[keyframes->nkeyframes-2]->keyFrameID);
03127                 bound_v[cur_variableID][0] += /*(1./(cur_v->Num_edge+2))*/time_axis_weight*thekeyframe->jacobian_vals[cur_v->index].entry[0][0];
03128                 bound_v[cur_variableID][1] += /*(1./(cur_v->Num_edge+2))*/time_axis_weight*thekeyframe->jacobian_vals[cur_v->index].entry[0][1];
03129             }
03130             else
03131             {
03132                 RegionIndex[cur_v->Num_edge] = vertTimeList->vertsTime[i-quadmesh->nverts]->variableID;
03133                 num_nonzeroarow++;
03134                 type = 1;
03135             }
03136         }
03137         else
03138         {
03139 
03140             if(vertTimeList->vertsTime[i-quadmesh->nverts]->isConstraint)
03141             {
03142                 RegionIndex[cur_v->Num_edge] = -1;
03143                 OneKeyFrame *thekeyframe = keyframes->get_frame_pointer(cur_time-1+keyframes->keyframes[keyframes->nkeyframes-2]->keyFrameID);
03144                 bound_v[cur_variableID][0] += /*(1./(cur_v->Num_edge+2))*/time_axis_weight*thekeyframe->jacobian_vals[cur_v->index].entry[0][0];
03145                 bound_v[cur_variableID][1] += /*(1./(cur_v->Num_edge+2))*/time_axis_weight*thekeyframe->jacobian_vals[cur_v->index].entry[0][1];
03146             }
03147             else
03148             {
03149                 RegionIndex[cur_v->Num_edge] = vertTimeList->vertsTime[i-quadmesh->nverts]->variableID;
03150                 num_nonzeroarow++;
03151                 type = 0;
03152             }
03153 
03154             if(vertTimeList->vertsTime[i+quadmesh->nverts]->isConstraint)
03155             {
03156                 RegionIndex[cur_v->Num_edge+1] = -1;
03157                 OneKeyFrame *thekeyframe = keyframes->get_frame_pointer(cur_time+1+keyframes->keyframes[keyframes->nkeyframes-2]->keyFrameID);
03158                 bound_v[cur_variableID][0] += /*(1./(cur_v->Num_edge+2))*/time_axis_weight*thekeyframe->jacobian_vals[cur_v->index].entry[0][0];
03159                 bound_v[cur_variableID][1] += /*(1./(cur_v->Num_edge+2))*/time_axis_weight*thekeyframe->jacobian_vals[cur_v->index].entry[0][1];
03160             }
03161             else
03162             {
03163                 RegionIndex[cur_v->Num_edge+1] = vertTimeList->vertsTime[i+quadmesh->nverts]->variableID;
03164                 num_nonzeroarow++;
03165 
03166                 if(type == 0)
03167                     type = 2;
03168                 else
03169                     type = 1;
03170             }
03171         }
03172 
03174         BubbleSorting(RegionIndex, cur_v->Num_edge+2);
03175 
03177         if(num_nonzeroarow < cur_v->Num_edge+2)
03178         {
03179             int firstnonfuyielement = cur_v->Num_edge+2 - num_nonzeroarow;
03180 
03181             for(j = 0; j < num_nonzeroarow; j++)
03182             {
03183                 RegionIndex[j] = RegionIndex[firstnonfuyielement + j];
03184             }
03185         }
03186 
03188         tija[cur_variableID] = num_elements;
03189         for(j = 0; j < num_nonzeroarow; j++)
03190         {
03191             if(type < 0)
03192                 tsa[num_elements + j] = -1./cur_v->Num_edge;  //tsa[num_elements + j] = -SMOOTHSTEP/cur_v->Num_edge;
03193             else if(type == 0)   // the last element is the constraint along the time axis
03194             {
03195                 if(j == 0)
03196                     tsa[num_elements+j] = -time_axis_weight;
03197                 else
03198                     tsa[num_elements+j] = -1./cur_v->Num_edge;
03199             }
03200             else if(type == 1)
03201             {
03202                 if(j == num_nonzeroarow - 1)    //  the first element is the constraint along the time axis
03203                     tsa[num_elements+j] = -time_axis_weight;
03204                 else
03205                     tsa[num_elements+j] = -1./cur_v->Num_edge;
03206             }
03207             else if(type == 2)  // the first and last elements are both the constraints along the time axis
03208             {
03209                 if(j == 0 || j == num_nonzeroarow - 1)    //  no constraint along the time axis
03210                     tsa[num_elements+j] = -time_axis_weight;
03211                 else
03212                     tsa[num_elements+j] = -1./cur_v->Num_edge;
03213             }
03214 
03215             /*   we have to consider the weights for the neighbors along the time axis   */
03216             tija[num_elements + j] = RegionIndex[j];
03217         }
03218 
03219         num_elements += num_nonzeroarow;
03220 
03221         delete [] RegionIndex;
03222     }
03223 
03224     tsa[vertTimeList->total_notconstraint_verts] = 0.;
03225     tija[vertTimeList->total_notconstraint_verts] = num_elements-1;
03226 }
03227 
03228 void TfCore::display_bresenham_line(){
03229     if(bresenham_line_points.size()<2) return;
03230     glColor3f(0,0,1);
03231     for(int i=0;i<bresenham_line_points.size()-1;i++){
03232         glBegin(GL_LINES);
03233         double point1_x=(dirMap.info.resolution*(bresenham_line_points[i].y+0.5)+dirMap.info.origin.position.x)/realWorld_to_field_scale+realWorld_to_field_offset_x;
03234         double point1_y=(dirMap.info.resolution*(dirMap.info.height-1-bresenham_line_points[i].x+0.5)+dirMap.info.origin.position.y)/realWorld_to_field_scale+realWorld_to_field_offset_y;
03235         double point2_x=(dirMap.info.resolution*(bresenham_line_points[i+1].y+0.5)+dirMap.info.origin.position.x)/realWorld_to_field_scale+realWorld_to_field_offset_x;
03236         double point2_y=(dirMap.info.resolution*(dirMap.info.height-1-bresenham_line_points[i+1].x+0.5)+dirMap.info.origin.position.y)/realWorld_to_field_scale+realWorld_to_field_offset_y;
03237         glVertex2f(point1_x,point1_y);
03238         glVertex2f(point2_x,point2_y);
03239         glEnd();
03240     }
03241 
03242 }
03243  bool TfCore::check_line_insect_obstacle(){
03244     for(int i=0; i<bresenham_line_points.size();i++){
03245         int region_num=5;
03246         int region_x_min,region_x_max,region_y_min,region_y_max;
03247         if(bresenham_line_points[i].x-region_num>-1) region_y_min=bresenham_line_points[i].x-region_num; else region_y_min=0;
03248         if(bresenham_line_points[i].x+region_num<dirMap.info.height) region_y_max=bresenham_line_points[i].x+region_num; else region_y_max=dirMap.info.height-1;
03249         if(bresenham_line_points[i].y-region_num>-1) region_x_min=bresenham_line_points[i].y-region_num; else region_x_min=0;
03250         if(bresenham_line_points[i].y+region_num<dirMap.info.width) region_x_max=bresenham_line_points[i].y+region_num; else region_x_max=dirMap.info.width-1;
03251         for(int l=region_x_min;l<=region_x_max;l++)
03252             for(int m=region_y_min; m<=region_y_max; m++)
03253             {
03254                 if(dirMap.data[l+dirMap.info.width*m]!=0)
03255                     return true;
03256             }
03257     }
03258 
03259     return false;
03260  }
03261 
03262 bool TfCore::insertLinks(int i, int j){
03263     pair<int,int> tmp_pair;
03264     set<pair<int,int>>::iterator tmp_iter;
03265     if(i<j){
03266         tmp_pair=make_pair(i,j);
03267         if(degptsLinks.find(tmp_pair)==degptsLinks.end())
03268         {
03269             degptsLinks.insert(tmp_pair);
03270             return true;
03271         }else
03272             return false;
03273 
03274     }else{
03275         tmp_pair=make_pair(j,i);
03276         if(degptsLinks.find(tmp_pair)==degptsLinks.end()){
03277             degptsLinks.insert(tmp_pair);
03278             return true;
03279         }else
03280             return false;
03281     }
03282 }
03283 
03284 std::map<pair<int ,int>,float>  TfCore::search_degpts_mst(std::set<int> connect_degpts,int target_tri_index){
03285     std::map<pair<int ,int>,float> cur_mst;
03286     if(connect_degpts.size()==1) return cur_mst;
03287     degptsLinks.clear();
03288     int num_seps=separatrices->evenstreamlines->ntrajs;
03289     std::map<pair<int,int>,float> linkValues;
03290     for(int i=0;i<num_seps;i++){
03291         Trajectory *cur_traj=separatrices->evenstreamlines->trajs[i];
03292         int degpt_id=cur_traj->degpt_id;
03293         int linked_degpt_id=cur_traj->linked_degpt_id;
03294         pair<int,int> tmp_pair;
03295         if(degpt_id==target_tri_index && connect_degpts.find(linked_degpt_id)!=connect_degpts.end()){
03296             if(degpt_id<linked_degpt_id){
03297                 if(insertLinks(degpt_id,linked_degpt_id)){
03298                     tmp_pair=make_pair(degpt_id,linked_degpt_id);
03299                     linkValues.insert(pair<pair<int,int>,float>(tmp_pair,cur_traj->infoGain));
03300                 }
03301             }else{
03302                 if(insertLinks(linked_degpt_id,degpt_id)){
03303                     tmp_pair=make_pair(linked_degpt_id,degpt_id);
03304                     linkValues.insert(pair<pair<int,int>,float>(tmp_pair,cur_traj->infoGain));
03305                 }
03306             }
03307         }
03308     }
03309 
03310     for(int i=0;i<num_seps;i++){
03311         Trajectory *cur_traj=separatrices->evenstreamlines->trajs[i];
03312         int degpt_id=cur_traj->degpt_id;
03313         if(degpt_id==target_tri_index) continue;
03314         int linked_degpt_id=cur_traj->linked_degpt_id;
03315         pair<int,int> tmp_pair;
03316         if(connect_degpts.find(degpt_id)!=connect_degpts.end() && connect_degpts.find(linked_degpt_id)!=connect_degpts.end()){
03317             if(degpt_id<linked_degpt_id){
03318                 if(insertLinks(degpt_id,linked_degpt_id)){
03319                     tmp_pair=make_pair(degpt_id,linked_degpt_id);
03320                     linkValues.insert(pair<pair<int,int>,float>(tmp_pair,cur_traj->infoGain));
03321                 }
03322             }else{
03323                 if(insertLinks(linked_degpt_id,degpt_id)){
03324                     tmp_pair=make_pair(linked_degpt_id,degpt_id);
03325                     linkValues.insert(pair<pair<int,int>,float>(tmp_pair,cur_traj->infoGain));
03326                 }
03327             }
03328 
03329         }
03330     }
03331     graph g_graph(connect_degpts.size());
03332     std::map<int,int> connect_degpts_index_map_forward;
03333     std::map<int,int> connect_degpts_index_map_backward;
03334     std::set<int>::iterator iter_set;
03335     int count=0;
03336     for(iter_set=connect_degpts.begin();iter_set!=connect_degpts.end();iter_set++){
03337         connect_degpts_index_map_forward.insert(pair<int,int>(*iter_set,count));
03338         connect_degpts_index_map_backward.insert(pair<int,int>(count,*iter_set));
03339         count++;
03340     }
03341     std::map<pair<int,int>,float>::iterator iter;
03342     for(iter=linkValues.begin();iter!=linkValues.end();iter++){
03343         g_graph.addEdge(connect_degpts_index_map_forward[(*iter).first.first],connect_degpts_index_map_forward[(*iter).first.second],(*iter).second);
03344         g_graph.addEdge(connect_degpts_index_map_forward[(*iter).first.second],connect_degpts_index_map_forward[(*iter).first.first],(*iter).second);
03345     }
03346     //std::unique_ptr<MSTStrategy> s_mst = std::make_unique<PrimeMST>();
03347     MSTStrategy *s_mst =new PrimeMST();
03348     std::vector<graph::Vertex> parent=s_mst->mst(g_graph);
03349     delete s_mst;
03350 
03351     for(int i=1;i<g_graph.vertexCount();i++){
03352         int link1=connect_degpts_index_map_backward[i];
03353         int link2=connect_degpts_index_map_backward[parent[i]];
03354         pair<int,int> tmp_pair;
03355         if(link1<link2)
03356         {
03357            tmp_pair=make_pair(link1,link2);
03358            cur_mst.insert(pair<pair<int,int>,float>(tmp_pair,g_graph[i][parent[i]]));
03359         }
03360         else
03361         {
03362            tmp_pair=make_pair(link2,link1);
03363            cur_mst.insert(pair<pair<int,int>,float>(tmp_pair,g_graph[i][parent[i]]));
03364         }
03365      }
03366     return cur_mst;
03367     //
03368     //
03369 }
03370 
03371 std::set<int> TfCore::find_connect_degpts(int target_tri_index){
03372     std::set<int> connect_degpts;
03373     connect_degpts.insert(target_tri_index);
03374     int num_seps=separatrices->evenstreamlines->ntrajs;
03375     for(int i=0;i<num_seps;i++){
03376         Trajectory *cur_traj=separatrices->evenstreamlines->trajs[i];
03377         if(cur_traj->linked_degpt_id=-1) continue;
03378         if(cur_traj->degpt_id==target_tri_index)
03379         {
03380             if(connect_degpts.find(cur_traj->linked_degpt_id)==connect_degpts.end())
03381                 connect_degpts.insert(cur_traj->linked_degpt_id);
03382         }
03383     }
03384     if(connect_degpts.size()==1) return connect_degpts;
03385 
03386     while(true){
03387         int cur_connect_degpts_num=connect_degpts.size();
03388         for(int i=0;i<num_seps;i++){
03389             Trajectory *cur_traj=separatrices->evenstreamlines->trajs[i];
03390             if(cur_traj->linked_degpt_id==-1) continue;
03391             if(connect_degpts.find(cur_traj->degpt_id)!=connect_degpts.end()){
03392                 if(connect_degpts.find(cur_traj->linked_degpt_id)==connect_degpts.end())
03393                 {
03394                     connect_degpts.insert(cur_traj->linked_degpt_id);
03395                     break;
03396                 }
03397             }
03398             if(connect_degpts.find(cur_traj->linked_degpt_id)!=connect_degpts.end()){
03399                 if(connect_degpts.find(cur_traj->degpt_id)==connect_degpts.end()){
03400                     connect_degpts.insert(cur_traj->degpt_id);
03401                     break;
03402                 }
03403             }
03404         }
03405         if(connect_degpts.size()==cur_connect_degpts_num)
03406             break;
03407     }
03408     return connect_degpts;
03409 }
03410 
03411 
03412 Trajectory * TfCore::select_a_branch(std::map<pair<int,int>,float> cur_mst, int target_tri_index){
03413     std::vector<Trajectory *> cur_trajs;
03414     std::vector<Trajectory *> tmp_cur_trajs;
03415     std::vector<float> info_gains;
03416     int num_seps=separatrices->evenstreamlines->ntrajs;
03417     bool reach_unkown=false;
03418     for(int i=0;i<num_seps;i++){
03419         Trajectory *cur_traj=separatrices->evenstreamlines->trajs[i];
03420         if(cur_traj->degpt_id==target_tri_index)
03421         {
03422             tmp_cur_trajs.push_back(cur_traj);
03423             if(cur_traj->is_reach_unknown)  reach_unkown=true;
03424         }
03425     }
03426     if(reach_unkown){
03427         for(int i=0;i<tmp_cur_trajs.size();i++){
03428             if(tmp_cur_trajs[i]->is_reach_unknown)
03429             {
03430                cur_trajs.push_back(tmp_cur_trajs[i]);
03431                info_gains.push_back(1.0/tmp_cur_trajs[i]->get_length());
03432             }
03433 
03434         }
03435     }else{
03436         for(int i=0;i<tmp_cur_trajs.size();i++)
03437             cur_trajs.push_back(tmp_cur_trajs[i]);
03438         if(cur_mst.size()==0){
03439             for(int i=0;i<cur_trajs.size();i++){
03440                 info_gains.push_back(cur_trajs[i]->infoGain);
03441             }
03442         }else{
03443             for(int i=0;i<cur_trajs.size();i++){
03444                 if(cur_trajs[i]->linked_degpt_id==-1)
03445                 {
03446                     info_gains.push_back(cur_trajs[i]->infoGain);
03447                 }
03448                 else
03449                 {
03450 
03451                     bool flag=false;
03452                     std::map<pair<int,int>,float>::iterator iter;
03453                     for(iter=cur_mst.begin();iter!=cur_mst.end();iter++)
03454                     {
03455                         if(((*iter).first.first==target_tri_index && (*iter).first.second==cur_trajs[i]->linked_degpt_id) || ((*iter).first.second==target_tri_index && (*iter).first.first==cur_trajs[i]->linked_degpt_id))
03456                             flag=true;
03457                     }
03458                     if(!flag){
03459                        info_gains.push_back(cur_trajs[i]->infoGain);
03460                     }else{
03461                         float cur_infoGain=cur_trajs[i]->infoGain;
03462                         int cur_count=1;
03463                         std::set<int> cur_tri_link_set;
03464                         cur_tri_link_set.insert(cur_trajs[i]->linked_degpt_id);
03465                         for(iter=cur_mst.begin();iter!=cur_mst.end();iter++){
03466                             if((*iter).first.first==cur_trajs[i]->linked_degpt_id && (*iter).first.second!=target_tri_index)
03467                                 cur_tri_link_set.insert((*iter).first.second);
03468                             if((*iter).first.second==cur_trajs[i]->linked_degpt_id && (*iter).first.first!=target_tri_index)
03469                                 cur_tri_link_set.insert((*iter).first.first);
03470                         }
03471                         std::set<int>::iterator iter_link=cur_tri_link_set.find(cur_trajs[i]->linked_degpt_id);
03472                         cur_tri_link_set.erase(iter_link);
03473 
03474                         while(true){
03475                             int cur_size=cur_tri_link_set.size();
03476                             for(iter=cur_mst.begin();iter!=cur_mst.end();iter++){
03477                                 int first=(*iter).first.first;
03478                                 int second=(*iter).first.second;
03479                                 if(cur_tri_link_set.find(first)!=cur_tri_link_set.end() && cur_tri_link_set.find(second)==cur_tri_link_set.end())
03480                                 {
03481                                     cur_tri_link_set.insert(second);
03482                                     break;
03483                                 }
03484                                 if(cur_tri_link_set.find(second)!=cur_tri_link_set.end() && cur_tri_link_set.find(first)==cur_tri_link_set.end())
03485                                 {
03486                                     cur_tri_link_set.insert(first);
03487                                     break;
03488                                 }
03489                             }
03490                             if(cur_size==cur_tri_link_set.size()) break;
03491                         }
03492                         iter_link=cur_tri_link_set.find(cur_trajs[i]->linked_degpt_id);
03493                         cur_tri_link_set.erase(iter_link);
03494                         for(iter=cur_mst.begin();iter!=cur_mst.end();iter++){
03495                             int first=(*iter).first.first;
03496                             int second=(*iter).first.second;
03497                             if(cur_tri_link_set.find(first)!=cur_tri_link_set.end() || cur_tri_link_set.find(second)!=cur_tri_link_set.end())
03498                             {
03499                                 if(cur_infoGain<(*iter).second){
03500                                     cur_infoGain=(*iter).second;
03501                                 }
03502                                 //sum_infoGain+=(*iter).second;
03503                                 cur_count++;
03504                             }
03505                         }
03506                         info_gains.push_back(cur_infoGain);
03507                     }
03508                 }
03509             }
03510         }
03511 
03512     }
03513 
03514 
03515      auto biggest = std::max_element(std::begin(info_gains), std::end(info_gains));
03516      int target_branch=std::distance(std::begin(info_gains), biggest);
03517      return cur_trajs[target_branch];
03518 }
03519 
03520 void TfCore::select_target_trisector_branch_move(){
03521     std::set<int> connect_degpts=find_connect_degpts(selected_target_tri);
03522     std::map<pair<int ,int>,float> cur_mst=search_degpts_mst(connect_degpts,selected_target_tri);
03523     Trajectory *target_branch=select_a_branch(cur_mst,selected_target_tri);
03524     add_separatrix_points_toRobot(target_branch);
03525 }
03526 
03527 bool TfCore::check_reach_wedge(){
03528     if(major_path==NULL || major_path->evenstreamlines->ntrajs==0) return false;
03529     Trajectory *cur_traj= major_path->evenstreamlines->trajs[0];
03530     int index=cur_traj->nlinesegs-1;
03531     double loc_x=cur_traj->linesegs[index].gend[0];
03532     double loc_y=cur_traj->linesegs[index].gend[1];
03533     if(validDegpts.size()==0) return false;
03534     float min_dist=std::numeric_limits<float>::max();
03535     for(int i=0;i<validDegpts.size();i++){
03536         if(validDegpts[i].type == 0){
03537             float deta_x=validDegpts[i].gcx-loc_x;
03538             float deta_y=validDegpts[i].gcy-loc_y;
03539             float dist=sqrt(deta_x*deta_x+deta_y*deta_y);
03540             if(dist<min_dist){
03541                 min_dist=dist;
03542             }
03543         }
03544     }
03545     if(min_dist<0.01){
03546         return true;
03547     }else{
03548         return false;
03549     }
03550 }


tensor_field_nav_core
Author(s): Lintao Zheng, Kai Xu
autogenerated on Thu Jun 6 2019 19:50:56