Commit ebb721c7e4788ddc420c63fc3292664ef83ac89e

Authored by David Mayerich
0 parents

new repository for STIM lab

00_GT.obj 0 โ†’ 100644
  1 +++ a/00_GT.obj
  1 +v 99 677 0
  2 +v 229 510 0
  3 +v 57 347 0
  4 +v 344 724 0
  5 +v 581 361 0
  6 +v 341 199 0
  7 +v 757 377 0
  8 +v 981 152 0
  9 +v 793 508 0
  10 +v 941 600 0
  11 +v 647 738 0
  12 +v 88 563 0
  13 +v 181 372 0
  14 +v 316 596 0
  15 +v 385 425 0
  16 +v 481 165 0
  17 +v 574 223 0
  18 +v 818 229 0
  19 +v 679 601 0
  20 +l 1 12 2
  21 +l 3 13 2
  22 +l 2 14 4
  23 +l 2 15 5
  24 +l 6 16 17 5
  25 +l 5 7
  26 +l 8 18 7
  27 +l 7 9
  28 +l 9 10
  29 +l 9 19 11
... ...
00_T.obj 0 โ†’ 100644
  1 +++ a/00_T.obj
  1 +v 119 675 0
  2 +v 343 730 0
  3 +v 59 346 0
  4 +v 577 361 0
  5 +v 347 199 0
  6 +v 756 375 0
  7 +v 588 483 0
  8 +v 789 514 0
  9 +v 676 603 0
  10 +v 652 744 0
  11 +v 933 598 0
  12 +v 105 611 0
  13 +v 126 537 0
  14 +v 227 519 0
  15 +v 294 580 0
  16 +v 319 677 0
  17 +v 165 366 0
  18 +v 192 438 0
  19 +v 234 473 0
  20 +v 294 463 0
  21 +v 375 428 0
  22 +v 441 404 0
  23 +v 510 388 0
  24 +v 419 188 0
  25 +v 492 174 0
  26 +v 551 205 0
  27 +v 567 273 0
  28 +v 572 334 0
  29 +v 645 365 0
  30 +v 695 410 0
  31 +v 633 438 0
  32 +v 776 424 0
  33 +v 788 467 0
  34 +v 742 552 0
  35 +v 702 584 0
  36 +v 663 659 0
  37 +v 649 720 0
  38 +v 839 539 0
  39 +v 882 557 0
  40 +v 804 606 0
  41 +l 1 12 13 14 15 16 2
  42 +l 3 17 18 19 20 21 22 23 4
  43 +l 5 24 25 26 27 28 4
  44 +l 4 29 6
  45 +l 6 30 31 7
  46 +l 6 32 33 8
  47 +l 8 34 35 9
  48 +l 9 36 37 10
  49 +l 8 38 39 11
  50 +l 9 40 11
... ...
01_GT.obj 0 โ†’ 100644
  1 +++ a/01_GT.obj
  1 +v 291 412 0
  2 +v 464 251 0
  3 +v 635 405 0
  4 +v 463 602 0
  5 +v 635 405 0
  6 +l 1 2
  7 +l 2 3
  8 +l 3 5 1
  9 +l 3 4
... ...
01_T.obj 0 โ†’ 100644
  1 +++ a/01_T.obj
  1 +v 292 411 0
  2 +v 464 252 0
  3 +v 531 312 0
  4 +v 637 404 0
  5 +v 537 405 0
  6 +v 442 408 0
  7 +v 368 409 0
  8 +v 464 603 0
  9 +v 531 312 0
  10 +v 442 408 0
  11 +l 1 2
  12 +l 2 3
  13 +l 3 4
  14 +l 4 5
  15 +l 3 9 5
  16 +l 6 10 5
  17 +l 1 7
  18 +l 4 8
... ...
02_GT.obj 0 โ†’ 100644
  1 +++ a/02_GT.obj
  1 +v 485 172 0
  2 +v 681 360 0
  3 +v 548 544 0
  4 +v 300 356 0
  5 +v 372 545 0
  6 +v 481 378 0
  7 +v 372 545 0
  8 +v 481 378 0
  9 +v 481 378 0
  10 +v 481 378 0
  11 +v 481 378 0
  12 +l 1 2
  13 +l 2 3
  14 +l 1 4
  15 +l 4 5
  16 +l 5 7 3
  17 +l 1 6
  18 +l 6 8 3
  19 +l 6 9 2
  20 +l 6 10 5
  21 +l 6 11 4
... ...
02_T.obj 0 โ†’ 100644
  1 +++ a/02_T.obj
  1 +v 334 445 0
  2 +v 370 544 0
  3 +v 549 545 0
  4 +v 681 360 0
  5 +v 484 172 0
  6 +v 469 477 0
  7 +v 484 172 0
  8 +v 469 477 0
  9 +v 370 544 0
  10 +v 549 545 0
  11 +v 469 477 0
  12 +v 484 172 0
  13 +l 1 2
  14 +l 2 3
  15 +l 3 4
  16 +l 4 5
  17 +l 5 7 1
  18 +l 6 8 1
  19 +l 2 9 6
  20 +l 3 10 6
  21 +l 6 11 4
  22 +l 5 12 6
... ...
03_GT.obj 0 โ†’ 100644
  1 +++ a/03_GT.obj
  1 +v 212 603 0
  2 +v 365 427 0
  3 +v 125 308 0
  4 +v 457 253 0
  5 +v 654 335 0
  6 +v 578 630 0
  7 +v 565 118 0
  8 +v 813 145 0
  9 +v 801 451 0
  10 +v 949 54 0
  11 +v 276 494 0
  12 +v 208 348 0
  13 +v 284 382 0
  14 +v 404 352 0
  15 +v 381 408 0
  16 +v 414 444 0
  17 +v 492 452 0
  18 +v 554 451 0
  19 +v 602 403 0
  20 +v 662 429 0
  21 +v 648 487 0
  22 +v 617 570 0
  23 +v 633 266 0
  24 +v 614 219 0
  25 +v 594 172 0
  26 +v 705 322 0
  27 +v 747 299 0
  28 +v 796 243 0
  29 +v 855 233 0
  30 +v 825 359 0
  31 +v 884 89 0
  32 +l 1 11 2
  33 +l 3 12 13 2
  34 +l 4 14 15 2
  35 +l 2 16 17 18 19 5
  36 +l 5 20 21 22 6
  37 +l 5 23 24 25 7
  38 +l 5 26 27 28 8
  39 +l 8 29 30 9
  40 +l 8 31 10
... ...
03_T.obj 0 โ†’ 100644
  1 +++ a/03_T.obj
  1 +v 212 604 0
  2 +v 123 310 0
  3 +v 365 427 0
  4 +v 576 631 0
  5 +v 457 253 0
  6 +v 563 116 0
  7 +v 813 144 0
  8 +v 800 450 0
  9 +v 951 57 0
  10 +v 800 450 0
  11 +l 1 2
  12 +l 3 4
  13 +l 5 6
  14 +l 6 7
  15 +l 8 10 4
  16 +l 8 9
... ...
CMakeLists.txt 0 โ†’ 100644
  1 +++ a/CMakeLists.txt
  1 +#Specify the version being used aswell as the language
  2 +cmake_minimum_required(VERSION 2.8)
  3 +#Name your project here
  4 +project(netmets)
  5 +
  6 +#set the module directory
  7 +set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}")
  8 +
  9 +#find OpenGL
  10 +find_package(OpenGL REQUIRED)
  11 +
  12 +#find GLUT
  13 +set(GLUT_ROOT_PATH $ENV{GLUT_ROOT_PATH})
  14 +find_package(GLUT REQUIRED)
  15 +
  16 +#find GLEW
  17 +find_package(GLEW REQUIRED)
  18 +
  19 +#find BOOST
  20 +find_package(Boost REQUIRED)
  21 +
  22 +#find the Approximate Nearest Neighbor Library
  23 +find_package(ANN REQUIRED)
  24 +
  25 +#set the include directories
  26 +include_directories(
  27 + ${CMAKE_CURRENT_BINARY_DIR}
  28 + ${OPENGL_INCLUDE_DIR}
  29 + ${GLEW_INCLUDE_PATH}
  30 + ${GLUT_INCLUDE_DIR}
  31 + ${ANN_INCLUDE_DIR}
  32 + ${Boost_INCLUDE_DIR}
  33 +)
  34 +
  35 +#Assign source files to the appropriate variables
  36 +file(GLOB SRC_CPP "*.cpp")
  37 +file(GLOB SRC_H "*.h")
  38 +
  39 +#set up copying data files
  40 +configure_file(00_GT.obj ${CMAKE_CURRENT_BINARY_DIR}/00_GT.obj @ONLY)
  41 +configure_file(00_T.obj ${CMAKE_CURRENT_BINARY_DIR}/00_T.obj @ONLY)
  42 +configure_file(01_GT.obj ${CMAKE_CURRENT_BINARY_DIR}/01_GT.obj @ONLY)
  43 +configure_file(01_T.obj ${CMAKE_CURRENT_BINARY_DIR}/01_T.obj @ONLY)
  44 +configure_file(02_GT.obj ${CMAKE_CURRENT_BINARY_DIR}/02_GT.obj @ONLY)
  45 +configure_file(02_T.obj ${CMAKE_CURRENT_BINARY_DIR}/02_T.obj @ONLY)
  46 +configure_file(03_GT.obj ${CMAKE_CURRENT_BINARY_DIR}/03_GT.obj @ONLY)
  47 +configure_file(03_T.obj ${CMAKE_CURRENT_BINARY_DIR}/03_T.obj @ONLY)
  48 +configure_file(SmoothShader_Vertex.glsl ${CMAKE_CURRENT_BINARY_DIR}/SmoothShader_Vertex.glsl @ONLY)
  49 +configure_file(SmoothShader_Fragment.glsl ${CMAKE_CURRENT_BINARY_DIR}/SmoothShader_Fragment.glsl @ONLY)
  50 +configure_file(ErrorMap_Fragment.glsl ${CMAKE_CURRENT_BINARY_DIR}/ErrorMap_Fragment.glsl @ONLY)
  51 +
  52 +#create an executable
  53 +add_executable(netmets ${SRC_CPP} ${SRC_H})
  54 +
  55 +#set the link libraries
  56 +target_link_libraries(netmets ${ANN_LIBRARY} ${OPENGL_gl_LIBRARY} ${OPENGL_glu_LIBRARY} ${GLEW_LIBRARY} ${GLUT_glut_LIBRARY})
  57 +
  58 +
  59 +
... ...
DrawingFunctions.h 0 โ†’ 100644
  1 +++ a/DrawingFunctions.h
  1 +#include "rtsFiberNetwork.h"
  2 +#include "rts/rts_glShaderProgram.h"
  3 +#include "GL/glut.h"
  4 +#include "rts/rts_glutRenderWindow.h"
  5 +#include <time.h>
  6 +
  7 +extern void ComputeNetMets();
  8 +extern rtsFiberNetwork* goldNetwork;
  9 +extern rtsFiberNetwork* testNetwork;
  10 +extern float sigmaG, sigmaC;
  11 +float network_span;
  12 +CoreGraphList coreGraph;
  13 +vector<point3D<float> > sequenceColors;
  14 +int current_sequence = 0;
  15 +
  16 +//shader variables
  17 +rts_glShaderProgram Edge_ErrorShader;
  18 +rts_glShaderProgram Node_ErrorShader;
  19 +rts_glShaderProgram Smooth_Shader;
  20 +
  21 +//display lists
  22 +GLuint GT_FibersList=0;
  23 +GLuint T_FibersList=0;
  24 +GLuint GT_EndCaps=0;
  25 +GLuint T_EndCaps=0;
  26 +GLuint GT_NodesList=0;
  27 +GLuint T_NodesList=0;
  28 +GLuint T_PathList=0;
  29 +GLuint GT_PathList=0;
  30 +
  31 +//drawing variables
  32 +int tube_subdivisions = 20;
  33 +float node_radius_factor = 0.7;
  34 +float fiber_radius_factor = 0.5;
  35 +float cull_test_case_threshold = 1.0;
  36 +
  37 +#define DISPLAY_GT_NETWORK 1
  38 +#define DISPLAY_T_NETWORK 2
  39 +#define DISPLAY_GT_GRAPH 3
  40 +#define DISPLAY_T_GRAPH 4
  41 +#define DISPLAY_GT_SELECTED 5
  42 +#define DISPLAY_T_SELECTED 6
  43 +
  44 +//menu options
  45 +#define NETCOMP_EXIT 0
  46 +#define DISPLAY_NETWORK 1
  47 +#define DISPLAY_GRAPH 2
  48 +#define DISPLAY_CONNECTED 3
  49 +#define DISPLAY_SELECTED 4
  50 +#define COLORMAP_ISOLUMINANT 5
  51 +#define COLORMAP_BLACKBODY 6
  52 +#define COLORMAP_BREWER 7
  53 +#define COLORMAP_POLAR_CIELAB 8
  54 +#define COLORMAP_RAINBOW 9
  55 +#define CULL_TEST_CASE 10
  56 +#define RECOMPUTE_METRIC 11
  57 +
  58 +
  59 +//fibers to render in Graph Mode
  60 +//list<int> T_DisplayEdges;
  61 +//list<int> GT_DisplayEdges;
  62 +
  63 +int DisplayMode = DISPLAY_NETWORK;
  64 +float L0_pos[3];
  65 +float L1_pos[3];
  66 +//GLuint texColorMap=0;
  67 +rts_glTextureMap texColorMap;
  68 +
  69 +
  70 +
  71 +
  72 +void makeColormap(int ColorMapType = COLORMAP_BREWER)
  73 +{
  74 + //if(texColorMap != 0)
  75 + // glDeleteTextures(1, &texColorMap);
  76 +
  77 + point3D<float>* ctrlPts;
  78 + int num_points = 0;
  79 + if(ColorMapType == COLORMAP_ISOLUMINANT)
  80 + {
  81 + //allocate memory for the colormap
  82 + num_points = 2;
  83 + ctrlPts = new point3D<float>[num_points];
  84 + //memset(ctrlPts, 0, num_points*sizeof(point3D<float>));
  85 +
  86 + ctrlPts[0] = point3D<float>(0.0, 1.0, 0.0);
  87 + ctrlPts[1] = point3D<float>(1.0, 0.0, 0.0);
  88 + }
  89 + else if(ColorMapType == COLORMAP_RAINBOW)
  90 + {
  91 + //allocate memory for the colormap
  92 + num_points = 5;
  93 + ctrlPts = new point3D<float>[num_points];
  94 + //memset(ctrlPts, 0, num_points*sizeof(point3D<float>));
  95 +
  96 + //ctrlPts[0] = point3D<float>(0.7, 0, 0.7);
  97 + ctrlPts[0] = point3D<float>(0, 0, 1);
  98 + ctrlPts[1] = point3D<float>(0, 0.7, 0.7);
  99 + ctrlPts[2] = point3D<float>(0, 1, 0);
  100 + ctrlPts[3] = point3D<float>(0.7, 0.7, 0);
  101 + ctrlPts[4] = point3D<float>(1, 0, 0);
  102 + }
  103 + else if(ColorMapType == COLORMAP_BLACKBODY)
  104 + {
  105 + //allocate memory for the colormap
  106 + num_points = 4;
  107 + ctrlPts = new point3D<float>[num_points];
  108 + //memset(ctrlPts, 0, num_points*sizeof(point3D<float>));
  109 +
  110 + ctrlPts[0] = point3D<float>(0.0, 0.0, 0.0);
  111 + ctrlPts[1] = point3D<float>(1.0, 0.0, 0.0);
  112 + ctrlPts[2] = point3D<float>(1.0, 1.0, 0.0);
  113 + ctrlPts[3] = point3D<float>(1.0, 1.0, 1.0);
  114 + }
  115 + else if(ColorMapType == COLORMAP_BREWER)
  116 + {
  117 + //allocate memory for the colormap
  118 + num_points = 11;
  119 + ctrlPts = new point3D<float>[num_points];
  120 + //memset(ctrlPts, 0, num_points*sizeof(point3D<float>));
  121 +
  122 + ctrlPts[0] = point3D<float>(0.192157, 0.211765, 0.584314);
  123 + ctrlPts[1] = point3D<float>(0.270588, 0.458824, 0.705882);
  124 + ctrlPts[2] = point3D<float>(0.454902, 0.678431, 0.819608);
  125 + ctrlPts[3] = point3D<float>(0.670588, 0.85098, 0.913725);
  126 + ctrlPts[4] = point3D<float>(0.878431, 0.952941, 0.972549);
  127 + ctrlPts[5] = point3D<float>(1, 1, 0.74902);
  128 + ctrlPts[6] = point3D<float>(0.996078, 0.878431, 0.564706);
  129 + ctrlPts[7] = point3D<float>(0.992157, 0.682353, 0.380392);
  130 + ctrlPts[8] = point3D<float>(0.956863, 0.427451, 0.262745);
  131 + ctrlPts[9] = point3D<float>(0.843137, 0.188235, 0.152941);
  132 + ctrlPts[10] = point3D<float>(0.647059, 0, 0.14902);
  133 +
  134 + }
  135 + else if(ColorMapType == COLORMAP_POLAR_CIELAB)
  136 + {
  137 + //allocate memory for the colormap
  138 + num_points = 33;
  139 + ctrlPts = new point3D<float>[num_points];
  140 + //memset(ctrlPts, 0, num_points*sizeof(point3D<float>));
  141 +
  142 + ctrlPts[0] = point3D<float>(0.07514311, 0.468049805,1);
  143 + ctrlPts[1] = point3D<float>(0.247872569, 0.498782363,1);
  144 + ctrlPts[2] = point3D<float>(0.339526309, 0.528909511,1);
  145 + ctrlPts[3] = point3D<float>(0.409505078, 0.558608486,1);
  146 + ctrlPts[4] = point3D<float>(0.468487184, 0.588057293,1);
  147 + ctrlPts[5] = point3D<float>(0.520796675, 0.617435078,1);
  148 + ctrlPts[6] = point3D<float>(0.568724526, 0.646924167,1);
  149 + ctrlPts[7] = point3D<float>(0.613686735, 0.676713218,1);
  150 + ctrlPts[8] = point3D<float>(0.656658579, 0.707001303,1);
  151 + ctrlPts[9] = point3D<float>(0.698372844, 0.738002964,1);
  152 + ctrlPts[10] = point3D<float>(0.739424025, 0.769954435,1);
  153 + ctrlPts[11] = point3D<float>(0.780330104, 0.803121429,1);
  154 + ctrlPts[12] = point3D<float>(0.821573924, 0.837809045,1);
  155 + ctrlPts[13] = point3D<float>(0.863634967, 0.874374691,1);
  156 + ctrlPts[14] = point3D<float>(0.907017747, 0.913245283,1);
  157 + ctrlPts[15] = point3D<float>(0.936129275, 0.938743558, 0.983038586);
  158 + ctrlPts[16] = point3D<float>(0.943467973, 0.943498599, 0.943398095);
  159 + ctrlPts[17] = point3D<float>(0.990146732, 0.928791426, 0.917447482);
  160 + ctrlPts[18] = point3D<float>(1, 0.88332677, 0.861943246);
  161 + ctrlPts[19] = point3D<float>(1, 0.833985467, 0.803839606);
  162 + ctrlPts[20] = point3D<float>(1, 0.788626485, 0.750707739);
  163 + ctrlPts[21] = point3D<float>(1, 0.746206642, 0.701389973);
  164 + ctrlPts[22] = point3D<float>(1, 0.70590052, 0.654994046);
  165 + ctrlPts[23] = point3D<float>(1, 0.667019783, 0.610806959);
  166 + ctrlPts[24] = point3D<float>(1, 0.6289553, 0.568237474);
  167 + ctrlPts[25] = point3D<float>(1, 0.591130233, 0.526775617);
  168 + ctrlPts[26] = point3D<float>(1, 0.552955184, 0.485962266);
  169 + ctrlPts[27] = point3D<float>(1, 0.513776083, 0.445364274);
  170 + ctrlPts[28] = point3D<float>(1, 0.472800903, 0.404551679);
  171 + ctrlPts[29] = point3D<float>(1, 0.428977855, 0.363073592);
  172 + ctrlPts[30] = point3D<float>(1, 0.380759558, 0.320428137);
  173 + ctrlPts[31] = point3D<float>(0.961891484, 0.313155629, 0.265499262);
  174 + ctrlPts[32] = point3D<float>(0.916482116, 0.236630659, 0.209939162);
  175 +
  176 + }
  177 +
  178 + texColorMap.Init(ctrlPts, GL_TEXTURE_1D, num_points, 0, 0, GL_RGB, GL_RGB, GL_FLOAT);
  179 +
  180 + //glGenTextures(1, &texColorMap);
  181 + //glBindTexture(GL_TEXTURE_1D, texColorMap);
  182 + //glTexImage1D(GL_TEXTURE_1D, 0, GL_RGB, num_points, 0, GL_RGB, GL_FLOAT, ctrlPts);
  183 +}
  184 +
  185 +
  186 +
  187 +point3D<float> HSLtoRGB(point3D<float> HSL)
  188 +{
  189 + float H = HSL.x;
  190 + float S = HSL.y;
  191 + float L = HSL.z;
  192 +
  193 + float temp2;
  194 + if(L < 0.5)
  195 + temp2 = L*(1.0+S);
  196 + else
  197 + temp2 = L+S - L*S;
  198 +
  199 + float temp1 = 2.0*L - temp2;
  200 +
  201 + point3D<float> temp3(H+1.0/3.0, H, H-1.0/3.0);
  202 + if(temp3.x < 0.0) temp3.x = temp3.x+1.0;
  203 + if(temp3.y < 0.0) temp3.y = temp3.y+1.0;
  204 + if(temp3.z < 0.0) temp3.z = temp3.z+1.0;
  205 +
  206 + if(temp3.x > 1.0) temp3.x = temp3.x - 1.0;
  207 + if(temp3.y > 1.0) temp3.y = temp3.y - 1.0;
  208 + if(temp3.z > 1.0) temp3.z = temp3.z - 1.0;
  209 +
  210 + point3D<float> result;
  211 + if(6.0*temp3.x < 1.0) result.x = temp1 +(temp2 - temp1)*6.0*temp3.x;
  212 + else if(2.0*temp3.x < 1.0) result.x = temp2;
  213 + else if(3.0*temp3.x < 2.0) result.x = temp1+(temp2-temp1)*((2.0/3.0) - temp3.x)*6.0;
  214 + else result.x = temp1;
  215 +
  216 + if(6.0*temp3.y < 1.0) result.y = temp1 +(temp2 - temp1)*6.0*temp3.y;
  217 + else if(2.0*temp3.y < 1.0) result.y = temp2;
  218 + else if(3.0*temp3.y < 2.0) result.y = temp1+(temp2-temp1)*((2.0/3.0) - temp3.y)*6.0;
  219 + else result.y = temp1;
  220 +
  221 + if(6.0*temp3.z < 1.0) result.z = temp1 +(temp2 - temp1)*6.0*temp3.z;
  222 + else if(2.0*temp3.z < 1.0) result.z = temp2;
  223 + else if(3.0*temp3.z < 2.0) result.z = temp1+(temp2-temp1)*((2.0/3.0) - temp3.z)*6.0;
  224 + else result.z = temp1;
  225 +
  226 + //result.a = 0.0;
  227 + return result;
  228 +}
  229 +void ColorFibers()
  230 +{
  231 + //srand(time(NULL));
  232 + sequenceColors.clear();
  233 + //for each fiber
  234 + for(CoreGraphList::iterator i = coreGraph.begin(); i!=coreGraph.end(); i++)
  235 + {
  236 + float random_hue = (double)rand()/(double)RAND_MAX;
  237 + //cout<<"Random Hue: "<<random_hue<<endl;
  238 + float random_saturation = 1.0;//(double)rand()/(double)RAND_MAX;
  239 + point3D<float> rgb = HSLtoRGB(point3D<float>(random_hue, random_saturation, 0.5));
  240 + //point3D<float> rgb((double)rand()/(double)RAND_MAX, (double)rand()/(double)RAND_MAX, (double)rand()/(double)RAND_MAX);
  241 + sequenceColors.push_back(rgb);
  242 + }
  243 +
  244 +
  245 +}
  246 +void CenterCameraToSelected()
  247 +{
  248 + if(coreGraph.size() == 0)
  249 + return;
  250 +
  251 + //center the fiber in both networks
  252 + point3D<float> min_pt(9999, 9999, 9999);
  253 + point3D<float> max_pt(-9999, -9999, -9999);
  254 +
  255 + //iterate through the first edge sequence
  256 + EdgeSequence::iterator i;
  257 + int node;
  258 + point3D<float> test;
  259 + for(i=coreGraph[current_sequence].first.begin(); i!=coreGraph[current_sequence].first.end(); i++)
  260 + {
  261 + node = testNetwork->FiberList[*i].n0;
  262 + test = testNetwork->NodeList[node].p;
  263 + min_pt.x = min(test.x, min_pt.x);
  264 + min_pt.y = min(test.y, min_pt.y);
  265 + min_pt.z = min(test.z, min_pt.z);
  266 + max_pt.x = max(test.x, max_pt.x);
  267 + max_pt.y = max(test.y, max_pt.y);
  268 + max_pt.z = max(test.z, max_pt.z);
  269 +
  270 + node = testNetwork->FiberList[*i].n1;
  271 + test = testNetwork->NodeList[node].p;
  272 + min_pt.x = min(test.x, min_pt.x);
  273 + min_pt.y = min(test.y, min_pt.y);
  274 + min_pt.z = min(test.z, min_pt.z);
  275 + max_pt.x = max(test.x, max_pt.x);
  276 + max_pt.y = max(test.y, max_pt.y);
  277 + max_pt.z = max(test.z, max_pt.z);
  278 + }
  279 + point3D<float> middle = min_pt+0.5*(max_pt - min_pt);
  280 +
  281 + rts_glut_camera.LookAt(middle);
  282 +
  283 +}
  284 +void IncrementSelectedFiber(int i)
  285 +{
  286 + //get the currently selected fiber id
  287 + if(coreGraph.size() <= 0)
  288 + return;
  289 +
  290 + //get the number of fibers
  291 + int end_id = coreGraph.size();
  292 +
  293 + current_sequence+=i;
  294 + if(current_sequence >= end_id)
  295 + current_sequence = 0;
  296 + if(current_sequence < 0)
  297 + current_sequence = coreGraph.size()-1;
  298 +
  299 + //print the selected edges
  300 + EdgeSequence::iterator EdgeI;
  301 +
  302 + for(EdgeI = coreGraph[current_sequence].first.begin(); EdgeI != coreGraph[current_sequence].first.end(); EdgeI++)
  303 + cout<<*EdgeI<<" ";
  304 + cout<<"--->";
  305 + for(EdgeI = coreGraph[current_sequence].second.begin(); EdgeI != coreGraph[current_sequence].second.end(); EdgeI++)
  306 + cout<<*EdgeI<<" ";
  307 + cout<<endl;
  308 +
  309 +
  310 + CenterCameraToSelected();
  311 +
  312 +}
  313 +void DrawNodeSphere(rtsFiberNetwork* network, int n, float radius)
  314 +{
  315 + GLUquadricObj* quadric = gluNewQuadric();
  316 + gluQuadricNormals(quadric, GLU_SMOOTH);
  317 +
  318 + glMatrixMode(GL_MODELVIEW);
  319 +
  320 + glPushMatrix();
  321 +
  322 + point3D<float> p;
  323 + //glColor3f(network->NodeList[n].error, 0.0, 0.0);
  324 + p = network->NodeList[n].p;
  325 +
  326 + glTranslatef(p.x, p.y, p.z);
  327 + //glutSolidSphere(node_radius*standard_deviation, 20, 20);
  328 + glTexCoord1f(network->NodeList[n].error);
  329 + if(network->NodeList[n].color < 0)
  330 + glColor3f(1.0, 0.0, 0.0);
  331 + else
  332 + glColor3f(1.0, 1.0, 1.0);
  333 + gluSphere(quadric,radius,32,32);
  334 +
  335 + glPopMatrix();
  336 +
  337 +}
  338 +void DrawNodeSpheres(rtsFiberNetwork* network, float radius)
  339 +{
  340 +
  341 +
  342 + unsigned int n;
  343 + for(n=0; n != network->FiberList.size(); n++)
  344 + {
  345 + if(!network->isCulled(n))
  346 + {
  347 + DrawNodeSphere(network, network->FiberList[n].n0,radius);
  348 + DrawNodeSphere(network, network->FiberList[n].n1,radius);
  349 + }
  350 + }
  351 +}
  352 +
  353 +void FrenetFrame(vector3D<float> &x, vector3D<float> &y, vector3D<float> &z)
  354 +{
  355 + x = vector3D<float>(0.0, 0.0, 1.0);
  356 + y = x.X(z);
  357 + x = z.X(y);
  358 + x.Normalize();
  359 + y.Normalize();
  360 + z.Normalize();
  361 +}
  362 +
  363 +vector3D<float> GetColor(float error)
  364 +{
  365 + //This function converts an error value to a color
  366 + //The conversion is done by creating an HSV color from the error value and converting that HSV color to RGB
  367 + float H = (240.0/60.0)*(1.0 - error);
  368 + float S = 1.0;
  369 + float V = 1.0;
  370 +
  371 + int i = floor(H);
  372 + float f = H - i;
  373 + if(i%2 == 0)
  374 + f = 1-f;
  375 + float m = V*(1 - S);
  376 + float n = V*(1-S*f);
  377 + switch(i)
  378 + {
  379 + case 0:
  380 + return vector3D<float>(V, n, m);
  381 + case 1:
  382 + return vector3D<float>(n, V, m);
  383 + case 2:
  384 + return vector3D<float>(m, V, n);
  385 + case 3:
  386 + return vector3D<float>(m, n, V);
  387 + case 4:
  388 + return vector3D<float>(n, m, V);
  389 + case 5:
  390 + return vector3D<float>(V, m, n);
  391 + default:
  392 + return vector3D<float>(0, 0, 0);
  393 + }
  394 +
  395 +}
  396 +
  397 +void DrawTube(point3D<float> p0, vector3D<float> d0, point3D<float> p1, vector3D<float> d1, float error0, float error1, float radius, int subdiv)
  398 +{
  399 +
  400 + //draw the first circle
  401 + vector3D<float> x0, y0, z0, x1, y1, z1;
  402 + z0 = d0;
  403 + FrenetFrame(x0, y0, z0);
  404 +
  405 + z1 = d1;
  406 + FrenetFrame(x1, y1, z1);
  407 +
  408 + float t_step = (2*3.14159)/subdiv;
  409 +
  410 +
  411 + float u, v;
  412 +
  413 + //get the RGB color
  414 + point3D<float> circle0, circle1;
  415 + vector3D<float> RGB0, RGB1;
  416 + vector3D<float> normal;
  417 +
  418 + //RGB0 = GetColor(color0);
  419 + //RGB1 = GetColor(color1);
  420 +
  421 + glBegin(GL_TRIANGLE_STRIP);
  422 + for(int t=0; t<=subdiv; t++)
  423 + {
  424 + u = radius * cos(t*t_step);
  425 + v = radius * sin(t*t_step);
  426 + normal = u*x0 + v*y0;
  427 + circle0 = p0 + normal;
  428 + normal.Normalize();
  429 +
  430 + glTexCoord1f(error0);
  431 + //glColor4f(error0, 0.0, 0.0, 1.0);
  432 + glNormal3f(normal.x, normal.y, normal.z);
  433 + glVertex3f(circle0.x, circle0.y, circle0.z);
  434 +
  435 + normal = u*x1 + v*y1;
  436 + circle1 = p1 + normal;
  437 + normal.Normalize();
  438 +
  439 + glTexCoord1f(error1);
  440 + //glColor4f(error1, 0.0, 0.0, 1.0);
  441 + glNormal3f(normal.x, normal.y, normal.z);
  442 + glVertex3f(circle1.x, circle1.y, circle1.z);
  443 +
  444 + }
  445 + glEnd();
  446 + CHECK_OPENGL_ERROR
  447 +}
  448 +
  449 +void ExtrudeFiber(rtsFiberNetwork* network, int fiber, float radius)
  450 +{
  451 + vector3D<float> x, y, z;
  452 + point3D<float> p0, p1, p2, p3;
  453 + vector3D<float> d1, d2;
  454 + float e1, e2;
  455 +
  456 + //get the first point
  457 + int node = network->FiberList[fiber].n0;
  458 + p1 = network->NodeList[node].p;
  459 + e1 = network->NodeList[node].error;
  460 +
  461 + //for each vertex in the fiber
  462 + int num_points = (int)network->FiberList[fiber].pointList.size();
  463 + for(int v=0; v<num_points; v++)
  464 + {
  465 + //get the next point
  466 + p2 = network->FiberList[fiber].pointList[v];
  467 + e2 = network->FiberList[fiber].errorList[v];
  468 +
  469 + if(v<num_points-1)
  470 + p3 = network->FiberList[fiber].pointList[v+1];
  471 + else
  472 + {
  473 + node = network->FiberList[fiber].n1;
  474 + p3 = network->NodeList[node].p;
  475 + }
  476 +
  477 + d2 = p3-p1;
  478 +
  479 + //compute the fiber derivatives at p1 and p2
  480 + if(v==0) //if this is the first fiber
  481 + d1 = p2 - p1;
  482 + else
  483 + {
  484 + d1 = p2 - p0;
  485 + }
  486 +
  487 + DrawTube(p1, d1, p2, d2, e1, e2, radius, tube_subdivisions);
  488 +
  489 + //shift
  490 + p0 = p1;
  491 + p1 = p2;
  492 + e1 = e2;
  493 + }
  494 + //make the last tube
  495 +
  496 + //if there were any points in the pointlist
  497 + if(num_points > 0)
  498 + {
  499 + p2 = p3;
  500 + node = network->FiberList[fiber].n1;
  501 + e2 = network->NodeList[node].error;
  502 + d1 = p2-p0;
  503 + d2 = p2-p1;
  504 + DrawTube(p1, d1, p2, d2, e1, e2, radius, tube_subdivisions);
  505 + }
  506 + //if there are only the two node points
  507 + else
  508 + {
  509 + node = network->FiberList[fiber].n1;
  510 + p2 = network->NodeList[node].p;
  511 + e2 = network->NodeList[node].error;
  512 + d1 = p2 - p1;
  513 + d2 = p2 - p1;
  514 + DrawTube(p1, d1, p2, d2, e1, e2, radius, tube_subdivisions);
  515 + }
  516 +}
  517 +
  518 +void DrawLineFiber(rtsFiberNetwork* network, int f)
  519 +{
  520 + point3D<float> p;
  521 + int node = network->FiberList[f].n0;
  522 + p = network->NodeList[node].p;
  523 +
  524 + glBegin(GL_LINE_STRIP);
  525 + glVertex3f(p.x, p.y, p.z);
  526 + for(int v=0; v!=network->FiberList[f].pointList.size(); v++)
  527 + {
  528 + p = network->FiberList[f].pointList[v];
  529 + glVertex3f(p.x, p.y, p.z);
  530 + }
  531 + node = network->FiberList[f].n1;
  532 + p = network->NodeList[node].p;
  533 + glVertex3f(p.x, p.y, p.z);
  534 + glEnd();
  535 +
  536 +}
  537 +void DrawLineNetwork(rtsFiberNetwork* network)
  538 +{
  539 +
  540 + int num_fibers = network->FiberList.size();
  541 + for(int f = 0; f < num_fibers; f++)
  542 + {
  543 + /*if(network->FiberList[f].mapped_to == -1)
  544 + glColor3f(0.0,0.0, 0.0);
  545 + else
  546 + glColor3f(1.0, 0.0, 0.0);
  547 + */
  548 + DrawLineFiber(network, f);
  549 + CHECK_OPENGL_ERROR
  550 + }
  551 +
  552 +
  553 +}
  554 +void DrawGraphNodes(rtsFiberNetwork* network)
  555 +{
  556 + //renders graph nodes, colored based on their node color
  557 + glMatrixMode(GL_MODELVIEW);
  558 +
  559 + unsigned int n;
  560 + for(n=0; n != network->NodeList.size(); n++)
  561 + {
  562 + glPushMatrix();
  563 +
  564 + point3D<float> p;
  565 + /*if(network->NodeList[n].color < 0)
  566 + glColor3f(1.0, 0.0, 0.0);
  567 + else
  568 + glColor3f(0.0, 1.0, 0.0);
  569 + */
  570 + //glColor3f(network->NodeList[n].error, 0.0, 0.0);
  571 + p = network->NodeList[n].p;
  572 +
  573 + glTranslatef(p.x, p.y, p.z);
  574 + glutSolidSphere(node_radius_factor*sigmaC, 20, 20);
  575 +
  576 + glPopMatrix();
  577 + }
  578 +}
  579 +void DrawFiberSequence(rtsFiberNetwork* network, EdgeSequence sequence, float fiber_radius, float node_radius)
  580 +{
  581 + //glClear(GL_DEPTH_BUFFER_BIT);
  582 + for(EdgeSequence::iterator i = sequence.begin(); i != sequence.end(); i++)
  583 + {
  584 + ExtrudeFiber(network, *i, fiber_radius);
  585 + glPushAttrib(GL_CURRENT_BIT);
  586 + DrawNodeSphere(network, network->FiberList[*i].n0, node_radius);
  587 + DrawNodeSphere(network, network->FiberList[*i].n1, node_radius);
  588 + glPopAttrib();
  589 + }
  590 +
  591 +
  592 +}
  593 +GLuint CreateFiberDisplayList(rtsFiberNetwork* network, float radius)
  594 +{
  595 + GLuint result = glGenLists(1);
  596 + glNewList(result, GL_COMPILE);
  597 +
  598 + int num_fibers = network->FiberList.size();
  599 + for(int f = 0; f < num_fibers; f++)
  600 + {
  601 + if(!network->isCulled(f))
  602 + {
  603 + ExtrudeFiber(network, f, radius);
  604 + CHECK_OPENGL_ERROR
  605 + }
  606 + }
  607 + glEndList();
  608 + return result;
  609 +}
  610 +
  611 +GLuint CreateNodeDisplayList(rtsFiberNetwork* network, float radius)
  612 +{
  613 + GLuint result = glGenLists(1);
  614 + glNewList(result, GL_COMPILE);
  615 + DrawNodeSpheres(network, radius);
  616 + glEndList();
  617 + return result;
  618 +}
  619 +
  620 +
  621 +void CreateFiberPathLists(float fiber_radius, float node_radius)
  622 +{
  623 + GT_PathList = glGenLists(1);
  624 + glNewList(GT_PathList, GL_COMPILE);
  625 +
  626 + if(coreGraph.size() > 0)
  627 + {
  628 + for(unsigned int i=0; i<sequenceColors.size(); i++)
  629 + {
  630 + point3D<float> rgb = sequenceColors[i];
  631 + glColor3f(rgb.x, rgb.y, rgb.z);
  632 + DrawFiberSequence(goldNetwork, coreGraph[i].second, fiber_radius, node_radius);
  633 + }
  634 + }
  635 + glEndList();
  636 +
  637 + T_PathList = glGenLists(1);
  638 + glNewList(T_PathList, GL_COMPILE);
  639 +
  640 + if(coreGraph.size() > 0)
  641 + {
  642 + for(unsigned int i=0; i<sequenceColors.size(); i++)
  643 + {
  644 + point3D<float> rgb = sequenceColors[i];
  645 + glColor3f(rgb.x, rgb.y, rgb.z);
  646 + DrawFiberSequence(testNetwork, coreGraph[i].first, fiber_radius, node_radius);
  647 + }
  648 + }
  649 + glEndList();
  650 +
  651 +}
  652 +void CreateDisplayLists()
  653 +{
  654 + if(GT_FibersList != 0)
  655 + glDeleteLists(GT_FibersList, 1);
  656 + if(T_FibersList != 0)
  657 + glDeleteLists(T_FibersList, 1);
  658 + if(GT_NodesList != 0)
  659 + glDeleteLists(GT_NodesList, 1);
  660 + if(T_NodesList != 0)
  661 + glDeleteLists(T_NodesList, 1);
  662 + if(GT_EndCaps != 0)
  663 + glDeleteLists(GT_EndCaps, 1);
  664 + if(T_EndCaps != 0)
  665 + glDeleteLists(T_EndCaps, 1);
  666 +
  667 + //create the display lists
  668 + GT_FibersList = CreateFiberDisplayList(goldNetwork, sigmaG*fiber_radius_factor);
  669 + T_FibersList = CreateFiberDisplayList(testNetwork, sigmaG*fiber_radius_factor);
  670 + GT_NodesList = CreateNodeDisplayList(goldNetwork, sigmaG*node_radius_factor);
  671 + T_NodesList = CreateNodeDisplayList(testNetwork, sigmaG*node_radius_factor);
  672 + GT_EndCaps = CreateNodeDisplayList(goldNetwork, sigmaG*fiber_radius_factor);
  673 + T_EndCaps = CreateNodeDisplayList(testNetwork, sigmaG*fiber_radius_factor);
  674 +
  675 + if(GT_PathList != 0)
  676 + glDeleteLists(GT_PathList,1);
  677 + if(T_PathList != 0)
  678 + glDeleteLists(T_PathList,1);
  679 + CreateFiberPathLists(fiber_radius_factor*sigmaG, node_radius_factor*sigmaG);
  680 +}
  681 +void RenderViewCamera()
  682 +{
  683 + glMatrixMode(GL_PROJECTION);
  684 + glLoadIdentity();
  685 + //compute the aspect ratio
  686 + float aspect_ratio = (float)glutGet(GLUT_WINDOW_WIDTH)/2.0/(float)glutGet(GLUT_WINDOW_HEIGHT);
  687 + gluPerspective(rts_glut_camera.getFOV(), aspect_ratio, network_span/10, network_span*10);
  688 +
  689 + //render the camera
  690 + glMatrixMode(GL_MODELVIEW);
  691 + glLoadIdentity();
  692 +
  693 + point3D<float> camera_position = rts_glut_camera.getPosition();
  694 + vector3D<float> camera_up = rts_glut_camera.getUp();
  695 + point3D<float> camera_lookat = rts_glut_camera.getLookAt();
  696 + gluLookAt(camera_position.x,
  697 + camera_position.y,
  698 + camera_position.z,
  699 + camera_lookat.x,
  700 + camera_lookat.y,
  701 + camera_lookat.z,
  702 + camera_up.x,
  703 + camera_up.y,
  704 + camera_up.z);
  705 +
  706 +
  707 + //get the light positions (lights move with the camera)
  708 + vector3D<float> up = rts_glut_camera.getUp();
  709 + vector3D<float> dir = rts_glut_camera.getDirection();
  710 + vector3D<float> side = dir.X(up);
  711 + L0_pos[0] = side.x;
  712 + L0_pos[1] = side.y;
  713 + L0_pos[2] = side.z;
  714 +
  715 + L1_pos[0] = -dir.x;
  716 + L1_pos[1] = -dir.y;
  717 + L1_pos[2] = -dir.z;
  718 +
  719 + //scale the viewport to the network
  720 + /*vector3D<float> span = max_point - min_point;
  721 + float scale = 1.0/span.Length();
  722 + //compute center point
  723 + point3D<float> center = min_point + 0.5*span;
  724 + glScalef(scale, scale, scale);
  725 + glTranslatef(-center.x, -center.y, -center.z);*/
  726 +
  727 +
  728 +}
  729 +void RecenterCamera()
  730 +{
  731 + point3D<float> min_point0 = goldNetwork->min_pos;
  732 + point3D<float> min_point1 = testNetwork->min_pos;
  733 +
  734 + point3D<float> max_point0 = goldNetwork->max_pos;
  735 + point3D<float> max_point1 = testNetwork->max_pos;
  736 +
  737 + point3D<float> min_point(min(min_point0.x, min_point1.x), min(min_point0.y, min_point1.y), min(min_point0.z, min_point1.z));
  738 + point3D<float> max_point(max(max_point0.x, max_point1.x), max(max_point0.y, max_point1.y), max(max_point0.z, max_point1.z));
  739 + point3D<float> center_point = min_point + 0.5*(max_point - min_point);
  740 +
  741 +
  742 + network_span = (max_point - point3D<float>(0, 0, 0)).Length();
  743 + rts_glut_camera.setPosition(0, 0, 3*network_span);
  744 + rts_glut_camera.LookAt(center_point, vector3D<float>(0.0, 1.0, 0.0));
  745 +
  746 +}
  747 +void DrawNetwork(int Display)
  748 +{
  749 + //draw the network fibers
  750 + switch(Display)
  751 + {
  752 + case DISPLAY_GT_NETWORK:
  753 + Edge_ErrorShader.UpdateGlobalUniforms();
  754 + Edge_ErrorShader.BeginProgram();
  755 + glCallList(GT_FibersList);
  756 + Edge_ErrorShader.EndProgram();
  757 +
  758 + Node_ErrorShader.UpdateGlobalUniforms();
  759 + Node_ErrorShader.BeginProgram();
  760 + glCallList(GT_EndCaps);
  761 + Node_ErrorShader.EndProgram();
  762 + break;
  763 + case DISPLAY_T_NETWORK:
  764 + Edge_ErrorShader.UpdateGlobalUniforms();
  765 + Edge_ErrorShader.BeginProgram();
  766 + glCallList(T_FibersList);
  767 + Edge_ErrorShader.EndProgram();
  768 +
  769 + Node_ErrorShader.UpdateGlobalUniforms();
  770 + Node_ErrorShader.BeginProgram();
  771 + glCallList(T_EndCaps);
  772 + Node_ErrorShader.EndProgram();
  773 + break;
  774 + case DISPLAY_GT_GRAPH:
  775 + glColor3f(1.0, 1.0, 1.0);
  776 + Smooth_Shader.UpdateGlobalUniforms();
  777 + Smooth_Shader.BeginProgram();
  778 + glCallList(GT_PathList);
  779 + glColor3f(1.0, 1.0, 1.0);
  780 + glCallList(GT_FibersList);
  781 + glCallList(GT_NodesList);
  782 + Smooth_Shader.EndProgram();
  783 + break;
  784 + case DISPLAY_T_GRAPH:
  785 + glColor3f(1.0, 1.0, 1.0);
  786 + Smooth_Shader.UpdateGlobalUniforms();
  787 + Smooth_Shader.BeginProgram();
  788 + glCallList(T_PathList);
  789 + glColor3f(1.0, 1.0, 1.0);
  790 + glCallList(T_FibersList);
  791 + glCallList(T_NodesList);
  792 + Smooth_Shader.EndProgram();
  793 + break;
  794 + case DISPLAY_GT_SELECTED:
  795 + glColor3f(1.0, 1.0, 1.0);
  796 + Smooth_Shader.UpdateGlobalUniforms();
  797 + Smooth_Shader.BeginProgram();
  798 + glCallList(GT_FibersList);
  799 + glCallList(GT_NodesList);
  800 +
  801 + glClear(GL_DEPTH_BUFFER_BIT);
  802 + glColor3f(1.0, 0.0, 1.0);
  803 + DrawFiberSequence(goldNetwork, coreGraph[current_sequence].second, fiber_radius_factor*sigmaG, node_radius_factor*sigmaG);
  804 + Smooth_Shader.EndProgram();
  805 + break;
  806 + case DISPLAY_T_SELECTED:
  807 + glColor3f(1.0, 1.0, 1.0);
  808 + Smooth_Shader.UpdateGlobalUniforms();
  809 + Smooth_Shader.BeginProgram();
  810 + glCallList(T_FibersList);
  811 + glCallList(T_NodesList);
  812 +
  813 + glClear(GL_DEPTH_BUFFER_BIT);
  814 + glColor3f(1.0, 0.0, 1.0);
  815 + DrawFiberSequence(testNetwork, coreGraph[current_sequence].first, fiber_radius_factor*sigmaG, node_radius_factor*sigmaG);
  816 + Smooth_Shader.EndProgram();
  817 + break;
  818 + default:
  819 + break;
  820 + }
  821 +
  822 +}
  823 +
  824 +
  825 +
  826 +
  827 +void MyDisplayFunction()
  828 +{
  829 + //glClearColor(0.95, 1.0, 0.95, 1.0);
  830 + glClearColor(1.0, 1.0, 1.0, 1.0);
  831 + glClear(GL_COLOR_BUFFER_BIT);
  832 + glClear(GL_DEPTH_BUFFER_BIT);
  833 +
  834 + //set left viewport
  835 + glMatrixMode(GL_PROJECTION);
  836 + glLoadIdentity();
  837 + glViewport(0, 0, glutGet(GLUT_WINDOW_WIDTH)/2, glutGet(GLUT_WINDOW_HEIGHT));
  838 +
  839 + RenderViewCamera();
  840 +
  841 +
  842 + if(DisplayMode == DISPLAY_NETWORK)
  843 + DrawNetwork(DISPLAY_GT_NETWORK);
  844 + else if(DisplayMode == DISPLAY_GRAPH)
  845 + DrawNetwork(DISPLAY_GT_GRAPH);
  846 + else if(DisplayMode == DISPLAY_SELECTED)
  847 + DrawNetwork(DISPLAY_GT_SELECTED);
  848 +
  849 + //set right viewport
  850 + glMatrixMode(GL_PROJECTION);
  851 + glLoadIdentity();
  852 + glViewport(glutGet(GLUT_WINDOW_WIDTH)/2, 0, glutGet(GLUT_WINDOW_WIDTH)/2, glutGet(GLUT_WINDOW_HEIGHT));
  853 +
  854 + RenderViewCamera();
  855 + //glClear(GL_COLOR_BUFFER_BIT);
  856 + //glClear(GL_DEPTH_BUFFER_BIT);
  857 +
  858 + if(DisplayMode == DISPLAY_NETWORK)
  859 + DrawNetwork(DISPLAY_T_NETWORK);
  860 + else if(DisplayMode == DISPLAY_GRAPH)
  861 + DrawNetwork(DISPLAY_T_GRAPH);
  862 + else if(DisplayMode == DISPLAY_SELECTED)
  863 + DrawNetwork(DISPLAY_T_SELECTED);
  864 +
  865 +
  866 +
  867 + //glutSwapBuffers();
  868 +}
  869 +
  870 +void GlutMenuCallback(int option)
  871 +{
  872 + if(option == NETCOMP_EXIT)
  873 + exit(1);
  874 + if(option >= DISPLAY_NETWORK && option <= DISPLAY_SELECTED)
  875 + DisplayMode = option;
  876 + if(option >= COLORMAP_ISOLUMINANT && option <= COLORMAP_RAINBOW)
  877 + makeColormap(option);
  878 + if(option == CULL_TEST_CASE)
  879 + {
  880 + //get the new threshold
  881 + cout<<"Enter new test case fiber threshold [0 1]: ";
  882 + float cull_value;
  883 + cin>>cull_value;
  884 + testNetwork->setCullValue(cull_value);
  885 +
  886 + //re-create the display lists
  887 + ComputeNetMets();
  888 + CreateDisplayLists();
  889 +
  890 + }
  891 + if(option == RECOMPUTE_METRIC)
  892 + {
  893 + cout<<"Please enter a sigma value: ";
  894 + cin>>sigmaG;
  895 + sigmaC = sigmaG;
  896 +
  897 + ComputeNetMets();
  898 + CreateDisplayLists();
  899 + }
  900 +
  901 +
  902 +
  903 + /*
  904 + switch(option)
  905 + {
  906 + case NETCOMP_EXIT:
  907 + exit(1);
  908 + break;
  909 + case NETCOMP_VIEW_GT:
  910 + DisplayMode = DISPLAY_GT_NETWORK;
  911 + break;
  912 + case NETCOMP_VIEW_T:
  913 + DisplayMode = DISPLAY_T_NETWORK;
  914 + break;
  915 + default:
  916 + break;
  917 + }*/
  918 +
  919 +}
0 920 \ No newline at end of file
... ...
ErrorMap_Fragment.glsl 0 โ†’ 100644
  1 +++ a/ErrorMap_Fragment.glsl
  1 +#extension GL_EXT_gpu_shader4 : enable
  2 +
  3 +varying vec3 fragment_normal;
  4 +//uniform vec3 L0_pos;
  5 +uniform vec3 L1_pos;
  6 +uniform sampler1D colorMap;
  7 +
  8 +vec4 HSLtoRGB(vec4 HSL)
  9 +{
  10 + float H = HSL.x;
  11 + float S = HSL.y;
  12 + float L = HSL.z;
  13 +
  14 + float temp2;
  15 + if(L < 0.5)
  16 + temp2 = L*(1.0+S);
  17 + else
  18 + temp2 = L+S - L*S;
  19 +
  20 + float temp1 = 2.0*L - temp2;
  21 +
  22 + vec3 temp3 = vec3(H+1.0/3.0, H, H-1.0/3.0);
  23 + if(temp3.r < 0.0) temp3.r = temp3.r+1.0;
  24 + if(temp3.g < 0.0) temp3.g = temp3.g+1.0;
  25 + if(temp3.b < 0.0) temp3.b = temp3.b+1.0;
  26 +
  27 + if(temp3.r > 1.0) temp3.r = temp3.r - 1.0;
  28 + if(temp3.g > 1.0) temp3.g = temp3.g - 1.0;
  29 + if(temp3.b > 1.0) temp3.b = temp3.b - 1.0;
  30 +
  31 + vec4 result;
  32 + if(6.0*temp3.r < 1.0) result.r = temp1 +(temp2 - temp1)*6.0*temp3.r;
  33 + else if(2.0*temp3.r < 1.0) result.r = temp2;
  34 + else if(3.0*temp3.r < 2.0) result.r = temp1+(temp2-temp1)*((2.0/3.0) - temp3.r)*6.0;
  35 + else result.r = temp1;
  36 +
  37 + if(6.0*temp3.g < 1.0) result.g = temp1 +(temp2 - temp1)*6.0*temp3.g;
  38 + else if(2.0*temp3.g < 1.0) result.g = temp2;
  39 + else if(3.0*temp3.g < 2.0) result.g = temp1+(temp2-temp1)*((2.0/3.0) - temp3.g)*6.0;
  40 + else result.g = temp1;
  41 +
  42 + if(6.0*temp3.b < 1.0) result.b = temp1 +(temp2 - temp1)*6.0*temp3.b;
  43 + else if(2.0*temp3.b < 1.0) result.b = temp2;
  44 + else if(3.0*temp3.b < 2.0) result.b = temp1+(temp2-temp1)*((2.0/3.0) - temp3.b)*6.0;
  45 + else result.b = temp1;
  46 +
  47 + result.a = 0.0;
  48 + return result;
  49 +}
  50 +
  51 +float LightIntensity()
  52 +{
  53 + //vec3 L0_pos = vec3(1.0, 0.0, 0.0);
  54 + //vec3 L1_pos = vec3(0.0, 0.0, 1.0);
  55 + //float L0 = max(dot(fragment_normal, L0_pos), 0.0);
  56 + float L1 = max(dot(fragment_normal, L1_pos), 0.0);
  57 +
  58 + //float total = L0 + L1;
  59 + //if(total > 1.0)
  60 + // total = 1.0;
  61 +
  62 + return L1;
  63 + //return 0.5;
  64 +
  65 +}
  66 +
  67 +void main(void)
  68 +{
  69 + float error = gl_TexCoord[0].x;
  70 +
  71 + float light = LightIntensity();
  72 +
  73 + gl_FragColor = texture1D(colorMap, error)*light;
  74 +}
... ...
ErrorShader_Fragment.glsl 0 โ†’ 100644
  1 +++ a/ErrorShader_Fragment.glsl
  1 +#extension GL_EXT_gpu_shader4 : enable
  2 +
  3 +varying vec3 fragment_normal;
  4 +uniform vec3 L0_pos;
  5 +uniform vec3 L1_pos;
  6 +
  7 +vec4 HSLtoRGB(vec4 HSL)
  8 +{
  9 + float H = HSL.x;
  10 + float S = HSL.y;
  11 + float L = HSL.z;
  12 +
  13 + float temp2;
  14 + if(L < 0.5)
  15 + temp2 = L*(1.0+S);
  16 + else
  17 + temp2 = L+S - L*S;
  18 +
  19 + float temp1 = 2.0*L - temp2;
  20 +
  21 + vec3 temp3 = vec3(H+1.0/3.0, H, H-1.0/3.0);
  22 + if(temp3.r < 0.0) temp3.r = temp3.r+1.0;
  23 + if(temp3.g < 0.0) temp3.g = temp3.g+1.0;
  24 + if(temp3.b < 0.0) temp3.b = temp3.b+1.0;
  25 +
  26 + if(temp3.r > 1.0) temp3.r = temp3.r - 1.0;
  27 + if(temp3.g > 1.0) temp3.g = temp3.g - 1.0;
  28 + if(temp3.b > 1.0) temp3.b = temp3.b - 1.0;
  29 +
  30 + vec4 result;
  31 + if(6.0*temp3.r < 1.0) result.r = temp1 +(temp2 - temp1)*6.0*temp3.r;
  32 + else if(2.0*temp3.r < 1.0) result.r = temp2;
  33 + else if(3.0*temp3.r < 2.0) result.r = temp1+(temp2-temp1)*((2.0/3.0) - temp3.r)*6.0;
  34 + else result.r = temp1;
  35 +
  36 + if(6.0*temp3.g < 1.0) result.g = temp1 +(temp2 - temp1)*6.0*temp3.g;
  37 + else if(2.0*temp3.g < 1.0) result.g = temp2;
  38 + else if(3.0*temp3.g < 2.0) result.g = temp1+(temp2-temp1)*((2.0/3.0) - temp3.g)*6.0;
  39 + else result.g = temp1;
  40 +
  41 + if(6.0*temp3.b < 1.0) result.b = temp1 +(temp2 - temp1)*6.0*temp3.b;
  42 + else if(2.0*temp3.b < 1.0) result.b = temp2;
  43 + else if(3.0*temp3.b < 2.0) result.b = temp1+(temp2-temp1)*((2.0/3.0) - temp3.b)*6.0;
  44 + else result.b = temp1;
  45 +
  46 + result.a = 0.0;
  47 + return result;
  48 +}
  49 +
  50 +float LightIntensity()
  51 +{
  52 + //vec3 L0_pos = vec3(1.0, 0.0, 0.0);
  53 + //vec3 L1_pos = vec3(0.0, 0.0, 1.0);
  54 + float L0 = 0.3*max(dot(fragment_normal, L0_pos), 0.0);
  55 + float L1 = 0.3*max(dot(fragment_normal, L1_pos), 0.0);
  56 +
  57 + return L0 + L1;
  58 + //return 0.5;
  59 +
  60 +}
  61 +
  62 +void main(void)
  63 +{
  64 + float error = (1.0 - gl_TexCoord[0].x)*(240.0/360.0);
  65 + float light = LightIntensity();
  66 +
  67 + //convert from HSL to RGB
  68 + vec4 HSL = vec4(error, 1.0, light, 1.0);
  69 + vec4 RGB = HSLtoRGB(HSL);
  70 +
  71 + gl_FragColor = vec4(RGB.r, RGB.g, RGB.b, 1.0);
  72 +}
0 73 \ No newline at end of file
... ...
FindANN.cmake 0 โ†’ 100644
  1 +++ a/FindANN.cmake
  1 +# - Try to find ANN
  2 +# Once done this will define
  3 +#
  4 +# ANN_FOUND - system has ANN
  5 +# ANN_INCLUDE_DIR - the ANN include directory
  6 +# ANN_LIBRARY - Link these to use ANN
  7 +#
  8 +
  9 +IF (ANN_INCLUDE_DIRS)
  10 + # Already in cache, be silent
  11 + SET(ANN_FIND_QUIETLY TRUE)
  12 +ENDIF (ANN_INCLUDE_DIRS)
  13 +
  14 +FIND_PATH( ANN_INCLUDE_DIR ANN/ANN.h
  15 + PATHS "/usr/include" "C:/libs/ANN/include")
  16 +
  17 +if( WIN32 )
  18 +
  19 + set(ANN_LIBRARY $ENV{ANN_PATH}\\ANN.lib)
  20 + set(ANN_INCLUDE_DIR $ENV{ANN_PATH})
  21 +
  22 +
  23 + # Store the library dir. May be used for linking to dll!
  24 + # GET_FILENAME_COMPONENT( ANN_LIBRARY_DIR ${ANN_LIBRARY} PATH )
  25 +
  26 + find_package_handle_standard_args(ANN DEFAULT_MSG ANN_INCLUDE_DIR)
  27 +
  28 +else (WIN32)
  29 +
  30 + FIND_LIBRARY( ANN_LIBRARY
  31 + NAMES ann ANN
  32 + PATHS /lib /usr/lib /usr/lib64 /usr/local/lib )
  33 +
  34 +endif( WIN32)
  35 +
  36 +
  37 +IF (ANN_INCLUDE_DIR AND ANN_LIBRARY)
  38 + SET(ANN_FOUND TRUE)
  39 +ELSE (ANN_INCLUDE_DIR AND ANN_LIBRARY)
  40 + SET( ANN_FOUND FALSE )
  41 +ENDIF (ANN_INCLUDE_DIR AND ANN_LIBRARY)
  42 +
... ...
FindGLEW.cmake 0 โ†’ 100644
  1 +++ a/FindGLEW.cmake
  1 +#
  2 +# Try to find GLEW library and include path.
  3 +# Once done this will define
  4 +#
  5 +# GLEW_FOUND
  6 +# GLEW_INCLUDE_PATH
  7 +# GLEW_LIBRARY
  8 +#
  9 +
  10 +IF (WIN32)
  11 + FIND_PATH( GLEW_INCLUDE_PATH GL/glew.h
  12 + $ENV{PROGRAMFILES}/GLEW/include
  13 + $ENV{GLEW_PATH}/include
  14 + DOC "The directory where GL/glew.h resides")
  15 + FIND_LIBRARY( GLEW_LIBRARY
  16 + NAMES glew GLEW glew32 glew32s
  17 + PATHS
  18 + $ENV{GLEW_PATH}/lib/Release/Win32
  19 + DOC "The GLEW library")
  20 +ELSE (WIN32)
  21 + FIND_PATH( GLEW_INCLUDE_PATH GL/glew.h
  22 + /usr/include
  23 + /usr/local/include
  24 + /sw/include
  25 + /opt/local/include
  26 + DOC "The directory where GL/glew.h resides")
  27 + FIND_LIBRARY( GLEW_LIBRARY
  28 + NAMES GLEW glew
  29 + PATHS
  30 + /usr/lib64
  31 + /usr/lib
  32 + /usr/local/lib64
  33 + /usr/local/lib
  34 + /sw/lib
  35 + /opt/local/lib
  36 + DOC "The GLEW library")
  37 +ENDIF (WIN32)
  38 +
  39 +IF (GLEW_INCLUDE_PATH)
  40 + SET( GLEW_FOUND 1 CACHE STRING "Set to 1 if GLEW is found, 0 otherwise")
  41 +ELSE (GLEW_INCLUDE_PATH)
  42 + SET( GLEW_FOUND 0 CACHE STRING "Set to 1 if GLEW is found, 0 otherwise")
  43 +ENDIF (GLEW_INCLUDE_PATH)
  44 +
  45 +MARK_AS_ADVANCED(
  46 + GLEW_FOUND
  47 + GLEW_INCLUDE_PATH
  48 + GLEW_LIBRARY
  49 +)
... ...
FindGLUT.cmake 0 โ†’ 100644
  1 +++ a/FindGLUT.cmake
  1 +# - Try to find ANN
  2 +# Once done this will define
  3 +#
  4 +# ANN_FOUND - system has ANN
  5 +# ANN_INCLUDE_DIR - the ANN include directory
  6 +# ANN_LIBRARY - Link these to use ANN
  7 +#
  8 +
  9 +IF (ANN_INCLUDE_DIRS)
  10 + # Already in cache, be silent
  11 + SET(ANN_FIND_QUIETLY TRUE)
  12 +ENDIF (ANN_INCLUDE_DIRS)
  13 +
  14 +FIND_PATH( ANN_INCLUDE_DIR ANN/ANN.h
  15 + PATHS "/usr/include" "C:/libs/ANN/include")
  16 +
  17 +if( WIN32 )
  18 +
  19 + set(ANN_LIBRARY $ENV{ANN_PATH}\\ANN.lib)
  20 + set(ANN_INCLUDE_DIR $ENV{ANN_PATH})
  21 +
  22 +
  23 + # Store the library dir. May be used for linking to dll!
  24 + # GET_FILENAME_COMPONENT( ANN_LIBRARY_DIR ${ANN_LIBRARY} PATH )
  25 +
  26 + find_package_handle_standard_args(ANN DEFAULT_MSG ANN_INCLUDE_DIR)
  27 +
  28 +else (WIN32)
  29 +
  30 + FIND_LIBRARY( ANN_LIBRARY
  31 + NAMES ann ANN
  32 + PATHS /lib /usr/lib /usr/lib64 /usr/local/lib )
  33 +
  34 +endif( WIN32)
  35 +
  36 +
  37 +IF (ANN_INCLUDE_DIR AND ANN_LIBRARY)
  38 + SET(ANN_FOUND TRUE)
  39 +ELSE (ANN_INCLUDE_DIR AND ANN_LIBRARY)
  40 + SET( ANN_FOUND FALSE )
  41 +ENDIF (ANN_INCLUDE_DIR AND ANN_LIBRARY)
  42 +
... ...
GroundTruth.swc 0 โ†’ 100644
  1 +++ a/GroundTruth.swc
  1 +# Original neuron tracing performed in Neuromantic
  2 +# which was programmed by Darren Myatt (d.r.myatt@reading.ac.uk)
  3 +# See homepage at http://www.rdg.ac.uk/Neuromantic
  4 +#
  5 +# NEUROMANTIC V1.6.3 (1/15/2012 5:22:06 PM): Saved to GroundTruth.swc
  6 +1 1 1342.5 1069.5 0 6 -1
  7 +2 1 1351.5 1063.5 0 6 1
  8 +3 1 1361.5 1058.5 0 6 2
  9 +4 1 1369.5 1052.5 0 4 3
  10 +5 1 1378.5 1047.5 0 3.5 4
  11 +6 1 1386.5 1041.5 0 3 5
  12 +7 1 1394.5 1034.5 0 3 6
  13 +8 1 1402.5 1027.5 0 3.5 7
  14 +9 1 1412.5 1026.5 0 4 8
  15 +10 1 1420.5 1018.5 0 4 9
  16 +11 1 1428.5 1011.5 0 4 10
  17 +12 1 1437.5 1005.5 0 4.5 11
  18 +13 1 1447.5 1001.5 0 4.5 12
  19 +14 1 1456.5 995.5 0 3 13
  20 +15 1 1465.5 990.5 0 3 14
  21 +16 1 1474.5 985.5 0 2.5 15
  22 +17 1 1482.5 979.5 0 2.5 16
  23 +18 1 1492.5 979.5 0 2.5 17
  24 +19 1 1501.5 974.5 0 2 18
  25 +20 1 1510.5 969.5 0 2 19
  26 +21 1 1520.5 969.5 0 2 20
  27 +22 1 1530.5 969.5 0 2.5 21
  28 +23 1 1538.5 962.5 0 2.5 22
  29 +24 1 1548.5 959.5 0 2.5 23
  30 +25 1 1558.5 959.5 0 2 24
  31 +26 1 1568.5 959.5 0 2 25
  32 +27 1 1578.5 958.5 0 2 26
  33 +28 1 1588.5 954.5 0 2.5 27
  34 +29 1 1598.5 952.5 0 3.5 28
  35 +30 1 1618.5 943.5 0 2 29
  36 +31 1 1628.5 941.5 0 2 30
  37 +32 1 1636.5 935.5 0 2 31
  38 +33 1 1645.5 930.5 0 2 32
  39 +34 1 1655.5 926.5 0 2 33
  40 +35 1 1665.5 922.5 0 2 34
  41 +36 1 1675.5 918.5 0 2 35
  42 +37 1 1685.5 913.5 0 2 36
  43 +38 1 1695.5 909.5 0 2 37
  44 +39 1 1705.5 907.5 0 2 38
  45 +40 1 1714.5 902.5 0 2 39
  46 +41 1 1722.5 896.5 0 2 40
  47 +42 1 1730.5 888.5 0 2 41
  48 +43 1 1735.5 878.5 0 2 42
  49 +44 1 1742.5 870.5 0 2 43
  50 +45 1 1748.5 862.5 0 2 44
  51 +46 1 1753.5 853.5 0 2 45
  52 +47 1 1761.5 845.5 0 2 46
  53 +48 1 1769.5 837.5 0 2.5 47
  54 +49 1 1777.5 829.5 0 2.5 48
  55 +50 1 1786.5 824.5 0 2.5 49
  56 +51 1 1796.5 822.5 0 2.5 50
  57 +52 1 1809.5 826.5 0 2 51
  58 +53 1 1819.5 828.5 0 2 52
  59 +54 1 1829.5 831.5 0 1.5 53
  60 +55 1 1837.5 838.5 0 1.5 54
  61 +56 1 1839.5 848.5 0 2.5 55
  62 +57 1 1749.5 882.5 0 2 42
  63 +58 1 1758.5 876.5 0 2 57
  64 +59 1 1766.5 870.5 0 2 58
  65 +60 1 1774.5 862.5 0 2.5 59
  66 +61 1 1784.5 861.5 0 2.5 60
  67 +62 1 1794.5 861.5 0 3 61
  68 +63 1 1803.5 866.5 0 2 62
  69 +64 1 1813.5 870.5 0 2 63
  70 +65 1 1608.5 957.5 0 2 28
  71 +66 1 1618.5 959.5 0 1.5 65
  72 +67 1 1628.5 960.5 0 1.5 66
  73 +68 1 1638.5 960.5 0 1.5 67
  74 +69 1 1648.5 960.5 0 2 68
  75 +70 1 1658.5 960.5 0 2.5 69
  76 +71 1 1668.5 960.5 0 2.5 70
  77 +72 1 1678.5 958.5 0 2 71
  78 +73 1 1687.5 952.5 0 2 72
  79 +74 1 1696.5 947.5 0 2 73
  80 +75 1 1706.5 944.5 0 2 74
  81 +76 1 1714.5 938.5 0 2.5 75
  82 +77 1 1723.5 933.5 0 3 76
  83 +78 1 1733.5 929.5 0 3 77
  84 +79 1 1743.5 928.5 0 2.5 78
  85 +80 1 1753.5 926.5 0 2.5 79
  86 +81 1 1763.5 923.5 0 2.5 80
  87 +82 1 1772.5 917.5 0 2.5 81
  88 +83 1 1781.5 912.5 0 2 82
  89 +84 1 1349.5 1054.5 0 4 1
  90 +85 1 1358.5 1049.5 0 4 84
  91 +86 1 1366.5 1041.5 0 3 85
  92 +87 1 1371.5 1032.5 0 3 86
  93 +88 1 1379.5 1024.5 0 3 87
  94 +89 1 1387.5 1016.5 0 2.5 88
  95 +90 1 1395.5 1008.5 0 2.5 89
  96 +91 1 1403.5 1000.5 0 2.5 90
  97 +92 1 1410.5 992.5 0 2.5 91
  98 +93 1 1417.5 984.5 0 2 92
  99 +94 1 1425.5 976.5 0 2.5 93
  100 +95 1 1433.5 968.5 0 3 94
  101 +96 1 1441.5 960.5 0 3 95
  102 +97 1 1449.5 952.5 0 3 96
  103 +98 1 1458.5 947.5 0 2.5 97
  104 +99 1 1468.5 944.5 0 1.5 98
  105 +100 1 1476.5 938.5 0 1.5 99
  106 +101 1 1486.5 934.5 0 2 100
  107 +102 1 1494.5 927.5 0 2 101
  108 +103 1 1502.5 919.5 0 2 102
  109 +104 1 1511.5 914.5 0 2 103
  110 +105 1 1519.5 908.5 0 2 104
  111 +106 1 1527.5 901.5 0 2 105
  112 +107 1 1535.5 895.5 0 2 106
  113 +108 1 1543.5 887.5 0 2.5 107
  114 +109 1 1551.5 880.5 0 2.5 108
  115 +110 1 1559.5 872.5 0 2.5 109
  116 +111 1 1566.5 864.5 0 2 110
  117 +112 1 1573.5 856.5 0 2 111
  118 +113 1 1581.5 848.5 0 2.5 112
  119 +114 1 1590.5 843.5 0 3.5 113
  120 +115 1 1459.5 931.5 0 3 97
  121 +116 1 1467.5 923.5 0 2 115
  122 +117 1 1475.5 915.5 0 2 116
  123 +118 1 1479.5 905.5 0 2 117
  124 +119 1 1485.5 897.5 0 2.5 118
  125 +120 1 1491.5 888.5 0 2.5 119
  126 +121 1 1499.5 880.5 0 2.5 120
  127 +122 1 1507.5 872.5 0 2.5 121
  128 +123 1 1515.5 864.5 0 2.5 122
  129 +124 1 1521.5 856.5 0 2 123
  130 +125 1 1527.5 847.5 0 2.5 124
  131 +126 1 1529.5 837.5 0 2.5 125
  132 +127 1 1530.5 827.5 0 2.5 126
  133 +128 1 1534.5 817.5 0 2.5 127
  134 +129 1 1538.5 807.5 0 3 128
  135 +130 1 1545.5 799.5 0 3 129
  136 +131 1 1553.5 791.5 0 2.5 130
  137 +132 1 1561.5 785.5 0 2.5 131
  138 +133 1 1571.5 781.5 0 2 132
  139 +134 1 1581.5 778.5 0 2 133
  140 +135 1 1591.5 776.5 0 2 134
  141 +136 1 1601.5 773.5 0 2 135
  142 +137 1 1611.5 769.5 0 2 136
  143 +138 1 1621.5 769.5 0 2.5 137
  144 +139 1 1635.5 762.5 0 2 138
  145 +140 1 1645.5 759.5 0 2 139
  146 +141 1 1654.5 754.5 0 2.5 140
  147 +142 1 1662.5 747.5 0 2 141
  148 +143 1 1671.5 741.5 0 2 142
  149 +144 1 1680.5 735.5 0 2 143
  150 +145 1 1688.5 728.5 0 2 144
  151 +146 1 1697.5 723.5 0 2 145
  152 +147 1 1707.5 720.5 0 2 146
  153 +148 1 1716.5 715.5 0 1.5 147
  154 +149 1 1726.5 711.5 0 2 148
  155 +150 1 1736.5 709.5 0 1.5 149
  156 +151 1 1746.5 708.5 0 2 150
  157 +152 1 1756.5 705.5 0 3 151
  158 +153 1 1765.5 700.5 0 12 152
  159 +154 1 1636.5 753.5 0 6 138
  160 +155 1 1646.5 748.5 0 5.5 154
  161 +156 1 1656.5 743.5 0 5.5 155
  162 +157 1 1666.5 736.5 0 2 156
  163 +158 1 1672.5 728.5 0 2 157
  164 +159 1 1677.5 718.5 0 2 158
  165 +160 1 1683.5 709.5 0 2 159
  166 +161 1 1689.5 701.5 0 2 160
  167 +162 1 1695.5 692.5 0 2 161
  168 +163 1 1701.5 683.5 0 1.5 162
  169 +164 1 1704.5 673.5 0 1.5 163
  170 +165 1 1708.5 663.5 0 1.5 164
  171 +166 1 1711.5 653.5 0 1.5 165
  172 +167 1 1342.5 1038.5 0 3.5 1
  173 +168 1 1339.5 1028.5 0 4 167
  174 +169 1 1339.5 1018.5 0 4 168
  175 +170 1 1339.5 1008.5 0 4 169
  176 +171 1 1339.5 998.5 0 3 170
  177 +172 1 1339.5 988.5 0 3 171
  178 +173 1 1339.5 978.5 0 2.5 172
  179 +174 1 1339.5 968.5 0 2.5 173
  180 +175 1 1319.5 1084.5 0 4 1
  181 +176 1 1310.5 1090.5 0 4 175
  182 +177 1 1302.5 1098.5 0 4 176
  183 +178 1 1294.5 1106.5 0 4 177
  184 +179 1 1286.5 1114.5 0 4 178
  185 +180 1 1278.5 1121.5 0 4 179
  186 +181 1 1270.5 1128.5 0 4.5 180
  187 +182 1 1262.5 1136.5 0 4 181
  188 +183 1 1254.5 1144.5 0 4.5 182
  189 +184 1 1246.5 1152.5 0 4.5 183
  190 +185 1 1238.5 1160.5 0 4.5 184
  191 +186 1 1231.5 1168.5 0 3.5 185
  192 +187 1 1225.5 1176.5 0 3.5 186
  193 +188 1 1221.5 1186.5 0 3.5 187
  194 +189 1 1216.5 1196.5 0 3.5 188
  195 +190 1 1210.5 1204.5 0 5 189
  196 +191 1 1202.5 1212.5 0 5 190
  197 +192 1 1197.5 1222.5 0 2.5 191
  198 +193 1 1193.5 1232.5 0 2.5 192
  199 +194 1 1188.5 1241.5 0 2.5 193
  200 +195 1 1183.5 1251.5 0 2.5 194
  201 +196 1 1177.5 1259.5 0 2.5 195
  202 +197 1 1171.5 1268.5 0 2.5 196
  203 +198 1 1165.5 1276.5 0 2.5 197
  204 +199 1 1157.5 1284.5 0 2 198
  205 +200 1 1149.5 1292.5 0 2 199
  206 +201 1 1144.5 1302.5 0 2 200
  207 +202 1 1133.5 1317.5 0 2 201
  208 +203 1 1127.5 1326.5 0 2 202
  209 +204 1 1122.5 1335.5 0 2.5 203
  210 +205 1 1118.5 1345.5 0 2.5 204
  211 +206 1 1115.5 1355.5 0 2 205
  212 +207 1 1114.5 1365.5 0 2 206
  213 +208 1 1114.5 1375.5 0 2 207
  214 +209 1 1162.5 1298.5 0 2 197
  215 +210 1 1158.5 1308.5 0 2 209
  216 +211 1 1155.5 1318.5 0 2 210
  217 +212 1 1153.5 1328.5 0 2 211
  218 +213 1 1152.5 1338.5 0 2 212
  219 +214 1 1151.5 1348.5 0 2 213
  220 +215 1 1150.5 1358.5 0 2 214
  221 +216 1 1149.5 1368.5 0 2 215
  222 +217 1 1147.5 1378.5 0 2 216
  223 +218 1 1144.5 1388.5 0 2 217
  224 +219 1 1178.5 1232.5 0 2.5 191
  225 +220 1 1172.5 1240.5 0 2.5 219
  226 +221 1 1166.5 1248.5 0 2.5 220
  227 +222 1 1159.5 1256.5 0 2.5 221
  228 +223 1 1151.5 1264.5 0 2.5 222
  229 +224 1 1142.5 1269.5 0 2.5 223
  230 +225 1 1133.5 1274.5 0 2 224
  231 +226 1 1125.5 1281.5 0 2 225
  232 +227 1 1117.5 1289.5 0 2 226
  233 +228 1 1109.5 1297.5 0 2 227
  234 +229 1 1101.5 1303.5 0 2 228
  235 +230 1 1093.5 1310.5 0 2 229
  236 +231 1 1084.5 1315.5 0 2 230
  237 +232 1 1076.5 1322.5 0 2 231
  238 +233 1 1067.5 1327.5 0 2.5 232
  239 +234 1 1059.5 1334.5 0 2.5 233
  240 +235 1 1051.5 1342.5 0 2.5 234
  241 +236 1 1043.5 1350.5 0 2 235
  242 +237 1 1037.5 1359.5 0 2.5 236
  243 +238 1 1031.5 1368.5 0 4.5 237
... ...
GroundTruthCopy.swc 0 โ†’ 100644
  1 +++ a/GroundTruthCopy.swc
  1 +# Original neuron tracing performed in Neuromantic
  2 +# which was programmed by Darren Myatt (d.r.myatt@reading.ac.uk)
  3 +# See homepage at http://www.rdg.ac.uk/Neuromantic
  4 +#
  5 +# NEUROMANTIC V1.6.3 (1/15/2012 5:22:06 PM): Saved to GroundTruth.swc
  6 +1 1 1342.5 1069.5 0 6 -1
  7 +2 1 1351.5 1063.5 0 6 1
  8 +3 1 1361.5 1058.5 0 6 2
  9 +4 1 1369.5 1052.5 0 4 3
  10 +5 1 1378.5 1047.5 0 3.5 4
  11 +6 1 1386.5 1041.5 0 3 5
  12 +7 1 1394.5 1034.5 0 3 6
  13 +8 1 1402.5 1027.5 0 3.5 7
  14 +9 1 1412.5 1026.5 0 4 8
  15 +10 1 1420.5 1018.5 0 4 9
  16 +11 1 1428.5 1011.5 0 4 10
  17 +12 1 1437.5 1005.5 0 4.5 11
  18 +13 1 1447.5 1001.5 0 4.5 12
  19 +14 1 1456.5 995.5 0 3 13
  20 +15 1 1465.5 990.5 0 3 14
  21 +16 1 1474.5 985.5 0 2.5 15
  22 +17 1 1482.5 979.5 0 2.5 16
  23 +18 1 1492.5 979.5 0 2.5 17
  24 +19 1 1501.5 974.5 0 2 18
  25 +20 1 1510.5 969.5 0 2 19
  26 +21 1 1520.5 969.5 0 2 20
  27 +22 1 1530.5 969.5 0 2.5 21
  28 +23 1 1538.5 962.5 0 2.5 22
  29 +24 1 1548.5 959.5 0 2.5 23
  30 +25 1 1558.5 959.5 0 2 24
  31 +26 1 1568.5 959.5 0 2 25
  32 +27 1 1578.5 958.5 0 2 26
  33 +28 1 1588.5 954.5 0 2.5 27
  34 +29 1 1598.5 952.5 0 3.5 28
  35 +30 1 1618.5 943.5 0 2 29
  36 +31 1 1628.5 941.5 0 2 30
  37 +32 1 1636.5 935.5 0 2 31
  38 +33 1 1645.5 930.5 0 2 32
  39 +34 1 1655.5 926.5 0 2 33
  40 +35 1 1665.5 922.5 0 2 34
  41 +36 1 1675.5 918.5 0 2 35
  42 +37 1 1685.5 913.5 0 2 36
  43 +38 1 1695.5 909.5 0 2 37
  44 +39 1 1705.5 907.5 0 2 38
  45 +40 1 1714.5 902.5 0 2 39
  46 +41 1 1722.5 896.5 0 2 40
  47 +42 1 1730.5 888.5 0 2 41
  48 +43 1 1735.5 878.5 0 2 42
  49 +44 1 1742.5 870.5 0 2 43
  50 +45 1 1748.5 862.5 0 2 44
  51 +46 1 1753.5 853.5 0 2 45
  52 +47 1 1761.5 845.5 0 2 46
  53 +48 1 1769.5 837.5 0 2.5 47
  54 +49 1 1777.5 829.5 0 2.5 48
  55 +50 1 1786.5 824.5 0 2.5 49
  56 +51 1 1796.5 822.5 0 2.5 50
  57 +52 1 1809.5 826.5 0 2 51
  58 +53 1 1819.5 828.5 0 2 52
  59 +54 1 1829.5 831.5 0 1.5 53
  60 +55 1 1837.5 838.5 0 1.5 54
  61 +56 1 1839.5 848.5 0 2.5 55
  62 +57 1 1749.5 882.5 0 2 42
  63 +58 1 1758.5 876.5 0 2 57
  64 +59 1 1766.5 870.5 0 2 58
  65 +60 1 1774.5 862.5 0 2.5 59
  66 +61 1 1784.5 861.5 0 2.5 60
  67 +62 1 1794.5 861.5 0 3 61
  68 +63 1 1803.5 866.5 0 2 62
  69 +64 1 1813.5 870.5 0 2 63
  70 +65 1 1608.5 957.5 0 2 28
  71 +66 1 1618.5 959.5 0 1.5 65
  72 +67 1 1628.5 960.5 0 1.5 66
  73 +68 1 1638.5 960.5 0 1.5 67
  74 +69 1 1648.5 960.5 0 2 68
  75 +70 1 1658.5 960.5 0 2.5 69
  76 +71 1 1668.5 960.5 0 2.5 70
  77 +72 1 1678.5 958.5 0 2 71
  78 +73 1 1687.5 952.5 0 2 72
  79 +74 1 1696.5 947.5 0 2 73
  80 +75 1 1706.5 944.5 0 2 74
  81 +76 1 1714.5 938.5 0 2.5 75
  82 +77 1 1723.5 933.5 0 3 76
  83 +78 1 1733.5 929.5 0 3 77
  84 +79 1 1743.5 928.5 0 2.5 78
  85 +80 1 1753.5 926.5 0 2.5 79
  86 +81 1 1763.5 923.5 0 2.5 80
  87 +82 1 1772.5 917.5 0 2.5 81
  88 +83 1 1781.5 912.5 0 2 82
  89 +84 1 1349.5 1054.5 0 4 1
  90 +85 1 1358.5 1049.5 0 4 84
  91 +86 1 1366.5 1041.5 0 3 85
  92 +87 1 1371.5 1032.5 0 3 86
  93 +88 1 1379.5 1024.5 0 3 87
  94 +89 1 1387.5 1016.5 0 2.5 88
  95 +90 1 1395.5 1008.5 0 2.5 89
  96 +91 1 1403.5 1000.5 0 2.5 90
  97 +92 1 1410.5 992.5 0 2.5 91
  98 +93 1 1417.5 984.5 0 2 92
  99 +94 1 1425.5 976.5 0 2.5 93
  100 +95 1 1433.5 968.5 0 3 94
  101 +96 1 1441.5 960.5 0 3 95
  102 +97 1 1449.5 952.5 0 3 96
  103 +98 1 1458.5 947.5 0 2.5 97
  104 +99 1 1468.5 944.5 0 1.5 98
  105 +100 1 1476.5 938.5 0 1.5 99
  106 +101 1 1486.5 934.5 0 2 100
  107 +102 1 1494.5 927.5 0 2 101
  108 +103 1 1502.5 919.5 0 2 102
  109 +104 1 1511.5 914.5 0 2 103
  110 +105 1 1519.5 908.5 0 2 104
  111 +106 1 1527.5 901.5 0 2 105
  112 +107 1 1535.5 895.5 0 2 106
  113 +108 1 1543.5 887.5 0 2.5 107
  114 +109 1 1551.5 880.5 0 2.5 108
  115 +110 1 1559.5 872.5 0 2.5 109
  116 +111 1 1566.5 864.5 0 2 110
  117 +112 1 1573.5 856.5 0 2 111
  118 +113 1 1581.5 848.5 0 2.5 112
  119 +114 1 1590.5 843.5 0 3.5 113
  120 +115 1 1459.5 931.5 0 3 97
  121 +116 1 1467.5 923.5 0 2 115
  122 +117 1 1475.5 915.5 0 2 116
  123 +118 1 1479.5 905.5 0 2 117
  124 +119 1 1485.5 897.5 0 2.5 118
  125 +120 1 1491.5 888.5 0 2.5 119
  126 +121 1 1499.5 880.5 0 2.5 120
  127 +122 1 1507.5 872.5 0 2.5 121
  128 +123 1 1515.5 864.5 0 2.5 122
  129 +124 1 1521.5 856.5 0 2 123
  130 +125 1 1527.5 847.5 0 2.5 124
  131 +126 1 1529.5 837.5 0 2.5 125
  132 +127 1 1530.5 827.5 0 2.5 126
  133 +128 1 1534.5 817.5 0 2.5 127
  134 +129 1 1538.5 807.5 0 3 128
  135 +130 1 1545.5 799.5 0 3 129
  136 +131 1 1553.5 791.5 0 2.5 130
  137 +132 1 1561.5 785.5 0 2.5 131
  138 +133 1 1571.5 781.5 0 2 132
  139 +134 1 1581.5 778.5 0 2 133
  140 +135 1 1591.5 776.5 0 2 134
  141 +136 1 1601.5 773.5 0 2 135
  142 +137 1 1611.5 769.5 0 2 136
  143 +138 1 1621.5 769.5 0 2.5 137
  144 +139 1 1635.5 762.5 0 2 138
  145 +140 1 1645.5 759.5 0 2 139
  146 +141 1 1654.5 754.5 0 2.5 140
  147 +142 1 1662.5 747.5 0 2 141
  148 +143 1 1671.5 741.5 0 2 142
  149 +144 1 1680.5 735.5 0 2 143
  150 +145 1 1688.5 728.5 0 2 144
  151 +146 1 1697.5 723.5 0 2 145
  152 +147 1 1707.5 720.5 0 2 146
  153 +148 1 1716.5 715.5 0 1.5 147
  154 +149 1 1726.5 711.5 0 2 148
  155 +150 1 1736.5 709.5 0 1.5 149
  156 +151 1 1746.5 708.5 0 2 150
  157 +152 1 1756.5 705.5 0 3 151
  158 +153 1 1765.5 700.5 0 12 152
  159 +154 1 1636.5 753.5 0 6 138
  160 +155 1 1646.5 748.5 0 5.5 154
  161 +156 1 1656.5 743.5 0 5.5 155
  162 +157 1 1666.5 736.5 0 2 156
  163 +158 1 1672.5 728.5 0 2 157
  164 +159 1 1677.5 718.5 0 2 158
  165 +160 1 1683.5 709.5 0 2 159
  166 +161 1 1689.5 701.5 0 2 160
  167 +162 1 1695.5 692.5 0 2 161
  168 +163 1 1701.5 683.5 0 1.5 162
  169 +164 1 1704.5 673.5 0 1.5 163
  170 +165 1 1708.5 663.5 0 1.5 164
  171 +166 1 1711.5 653.5 0 1.5 165
  172 +167 1 1342.5 1038.5 0 3.5 1
  173 +168 1 1339.5 1028.5 0 4 167
  174 +169 1 1339.5 1018.5 0 4 168
  175 +170 1 1339.5 1008.5 0 4 169
  176 +171 1 1339.5 998.5 0 3 170
  177 +172 1 1339.5 988.5 0 3 171
  178 +173 1 1339.5 978.5 0 2.5 172
  179 +174 1 1339.5 968.5 0 2.5 173
  180 +175 1 1319.5 1084.5 0 4 1
  181 +176 1 1310.5 1090.5 0 4 175
  182 +177 1 1302.5 1098.5 0 4 176
  183 +178 1 1294.5 1106.5 0 4 177
  184 +179 1 1286.5 1114.5 0 4 178
  185 +180 1 1278.5 1121.5 0 4 179
  186 +181 1 1270.5 1128.5 0 4.5 180
  187 +182 1 1262.5 1136.5 0 4 181
  188 +183 1 1254.5 1144.5 0 4.5 182
  189 +184 1 1246.5 1152.5 0 4.5 183
  190 +185 1 1238.5 1160.5 0 4.5 184
  191 +186 1 1231.5 1168.5 0 3.5 185
  192 +187 1 1225.5 1176.5 0 3.5 186
  193 +188 1 1221.5 1186.5 0 3.5 187
  194 +189 1 1216.5 1196.5 0 3.5 188
  195 +190 1 1210.5 1204.5 0 5 189
  196 +191 1 1202.5 1212.5 0 5 190
  197 +192 1 1197.5 1222.5 0 2.5 191
  198 +193 1 1193.5 1232.5 0 2.5 192
  199 +194 1 1188.5 1241.5 0 2.5 193
  200 +195 1 1183.5 1251.5 0 2.5 194
  201 +196 1 1177.5 1259.5 0 2.5 195
  202 +197 1 1171.5 1268.5 0 2.5 196
  203 +198 1 1165.5 1276.5 0 2.5 197
  204 +199 1 1157.5 1284.5 0 2 198
  205 +200 1 1149.5 1292.5 0 2 199
  206 +201 1 1144.5 1302.5 0 2 200
  207 +202 1 1133.5 1317.5 0 2 201
  208 +203 1 1127.5 1326.5 0 2 202
  209 +204 1 1122.5 1335.5 0 2.5 203
  210 +205 1 1118.5 1345.5 0 2.5 204
  211 +206 1 1115.5 1355.5 0 2 205
  212 +207 1 1114.5 1365.5 0 2 206
  213 +208 1 1114.5 1375.5 0 2 207
  214 +209 1 1162.5 1298.5 0 2 197
  215 +210 1 1158.5 1308.5 0 2 209
  216 +211 1 1155.5 1318.5 0 2 210
  217 +212 1 1153.5 1328.5 0 2 211
  218 +213 1 1152.5 1338.5 0 2 212
  219 +214 1 1151.5 1348.5 0 2 213
  220 +215 1 1150.5 1358.5 0 2 214
  221 +216 1 1149.5 1368.5 0 2 215
  222 +217 1 1147.5 1378.5 0 2 216
  223 +218 1 1144.5 1388.5 0 2 217
  224 +219 1 1178.5 1232.5 0 2.5 191
  225 +220 1 1172.5 1240.5 0 2.5 219
  226 +221 1 1166.5 1248.5 0 2.5 220
  227 +222 1 1159.5 1256.5 0 2.5 221
  228 +223 1 1151.5 1264.5 0 2.5 222
  229 +224 1 1142.5 1269.5 0 2.5 223
  230 +225 1 1133.5 1274.5 0 2 224
  231 +226 1 1125.5 1281.5 0 2 225
  232 +227 1 1117.5 1289.5 0 2 226
  233 +228 1 1109.5 1297.5 0 2 227
  234 +229 1 1101.5 1303.5 0 2 228
  235 +230 1 1093.5 1310.5 0 2 229
  236 +231 1 1084.5 1315.5 0 2 230
  237 +232 1 1076.5 1322.5 0 2 231
  238 +233 1 1067.5 1327.5 0 2.5 232
  239 +234 1 1059.5 1334.5 0 2.5 233
  240 +235 1 1051.5 1342.5 0 2.5 234
  241 +236 1 1043.5 1350.5 0 2 235
  242 +237 1 1037.5 1359.5 0 2.5 236
  243 +238 1 1031.5 1368.5 0 4.5 237
... ...
ImplicitCalculations.h 0 โ†’ 100644
  1 +++ a/ImplicitCalculations.h
  1 +#include <itkImage.h>
  2 +#include <itkImageFileWriter.h>
  3 +#include <rtsLinearAlgebra.h>
  4 +//#include "DrawingFunctions.h"
  5 +#include "rtsFiberNetwork.h"
  6 +#include <octree\octree.h>
  7 +#include <rts_itkVolume.h>
  8 +#include <rtsDTGrid3D.h>
  9 +#include <rtsDTGridFastSweeping.h>
  10 +#include <algorithm>
  11 +
  12 +/***************************************************
  13 +New Stuff
  14 +***************************************************/
  15 +//networks for analysis
  16 +rtsFiberNetwork* goldNetwork;
  17 +rtsFiberNetwork* testNetwork;
  18 +rtsFiberNetwork* focusNetwork;
  19 +
  20 +
  21 +//Implicit network representations
  22 +rtsDTGrid3D<float>* goldGrid;
  23 +rtsDTGrid3D<float>* testGrid;
  24 +rtsDTGrid3D<float>* focusGrid;
  25 +
  26 +//lexicographic lists, contains LexIDs for each sampled point as well as identifiers to the associated fiber
  27 +struct LexID
  28 +{
  29 + unsigned long ID;
  30 + unsigned int fiber;
  31 +
  32 + bool operator<(LexID &rhs)
  33 + {
  34 + if(ID < rhs.ID)
  35 + return true;
  36 + return false;
  37 + }
  38 + bool operator==(LexID &rhs)
  39 + {
  40 + if(ID == rhs.ID)
  41 + return true;
  42 + return false;
  43 + }
  44 +};
  45 +list<LexID> goldLexList;
  46 +list<LexID> testLexList;
  47 +
  48 +//standard deviation of the implicit envelope
  49 +float STD;
  50 +
  51 +//Size of each grid voxel. This value is defined in Network Space.
  52 +float VOXEL_SIZE;
  53 +
  54 +//Theoretical size of the grid. Used to compute the lexicographic identifiers.
  55 +vector3D<int> GRID_DIM;
  56 +
  57 +//Transformation matrix that converts Network Space coordinates into Grid Space coordinates.
  58 +matrix4x4<float> toGRID;
  59 +
  60 +//Dilation parameter describes the radius of the envelope around the network (in voxels)
  61 +int DILATION;
  62 +
  63 +void ComputeGridProperties()
  64 +{
  65 + /*Computes the following grid properties:
  66 + VOXEL_SIZE = the size (along one side) of each voxel "bin"
  67 + GRID_DIM = the theoretical dimensions of the grid used to represent the network
  68 + toGRID = transformation used to convert a point on the network into "grid space"
  69 + */
  70 +
  71 + //pick a voxel size based on the standard daviation of the envelope that captures the shape of the Gaussian
  72 + //lets say that a voxel is 1 standard-deviation wide
  73 + VOXEL_SIZE = STD*1.0;
  74 + //dilate the DT Grid to 3 standard deviations
  75 + DILATION = (3.0*STD)/VOXEL_SIZE;
  76 +
  77 +
  78 + //find the minimum and maximum points in both networks to get the theoretical grid size
  79 + //find the bounding box for both networks
  80 + point3D<float> net_min;
  81 + net_min.x = min(goldNetwork->min_pos.x, testNetwork->min_pos.x);
  82 + net_min.y = min(goldNetwork->min_pos.y, testNetwork->min_pos.y);
  83 + net_min.z = min(goldNetwork->min_pos.z, testNetwork->min_pos.z);
  84 +
  85 + point3D<float> net_max;
  86 + net_max.x = max(goldNetwork->max_pos.x, testNetwork->max_pos.x);
  87 + net_max.y = max(goldNetwork->max_pos.y, testNetwork->max_pos.y);
  88 + net_max.z = max(goldNetwork->max_pos.z, testNetwork->max_pos.z);
  89 +
  90 + //compute the spatial size of the network
  91 + vector3D<float> net_size = net_max - net_min;
  92 +
  93 + //compute the theoretical size of the grid
  94 + GRID_DIM.x = ceil(net_size.x / VOXEL_SIZE);
  95 + GRID_DIM.y = ceil(net_size.y / VOXEL_SIZE);
  96 + GRID_DIM.z = ceil(net_size.z / VOXEL_SIZE);
  97 +
  98 + //compute the transformation from Network Space to Grid Space
  99 + matrix4x4<float> scale;
  100 + scale. SetIdentity();
  101 + scale.SetScale(1.0/VOXEL_SIZE, 1.0/VOXEL_SIZE, 1.0/VOXEL_SIZE);
  102 +
  103 + matrix4x4<float> trans;
  104 + trans.SetIdentity();
  105 + trans.SetTranslation(-net_min.x, -net_min.y, -net_min.z);
  106 +
  107 + toGRID.SetIdentity();
  108 + toGRID = scale*trans;
  109 +
  110 + cout<<"Voxel Size: "<<VOXEL_SIZE<<endl;
  111 + cout<<"Grid Dimensions: "<<GRID_DIM.x<<","<<GRID_DIM.y<<","<<GRID_DIM.z<<endl;
  112 +}
  113 +
  114 +void RasterizeSegmentLex(int f, point3D<float> p0, point3D<float> p1, list<LexID>* destList)
  115 +{
  116 + /*Resamples a segment and stores the resulting points as
  117 + lexicographic values in LexicographicList.
  118 + */
  119 +
  120 + //transform the Network Space coordinates to Grid Space
  121 + point3D<float> grid_p0 = toGRID*p0;
  122 + point3D<float> grid_p1 = toGRID*p1;
  123 +
  124 + //find the direction of travel
  125 + vector3D<float> v = grid_p1 - grid_p0;
  126 +
  127 + //set the step size to the voxel size
  128 + int length = (int)v.Length();
  129 + v.Normalize();
  130 +
  131 + //start at p0, continue until p1
  132 + point3D<float> p = grid_p0;
  133 +
  134 + int l;
  135 + LexID lex;
  136 +
  137 +
  138 + for(l=0; l<=length; l++)
  139 + {
  140 + lex.ID = (unsigned long)p.x*GRID_DIM.y*GRID_DIM.z + (unsigned long)p.y*GRID_DIM.z + (unsigned long)p.z;
  141 + lex.fiber = f;
  142 + destList->push_back(lex);
  143 +
  144 + p = p + v;
  145 + }
  146 +}
  147 +
  148 +void RasterizeFiberLex(rtsFiberNetwork* sourceNet, int f, list<LexID>* destList)
  149 +{
  150 + /*resamples a fiber f and stores the resulting points as
  151 + lexicographic values in LexicographicList.
  152 + */
  153 +
  154 + int num_points = sourceNet->FiberList[f].pointList.size();
  155 + int p;
  156 +
  157 + point3D<float> pos = sourceNet->getNodeCoord(f, 0);
  158 +
  159 + point3D<float> coord;
  160 + for(p=0; p<num_points; p++)
  161 + {
  162 + coord = sourceNet->getFiberPoint(f, p);
  163 + RasterizeSegmentLex(f, pos, coord, destList);
  164 + pos = coord;
  165 + }
  166 + RasterizeSegmentLex(f, pos, sourceNet->getNodeCoord(f, 1), destList);
  167 +}
  168 +
  169 +list<LexID> RasterizeNetworkLex(rtsFiberNetwork* sourceNet, rtsDTGrid3D<float>* destGrid)
  170 +{
  171 + /*This function creates a list of points on the focus network
  172 + and stores them in a list as a lexicographic point:
  173 + lp = z*sx*sy + y*sx + x
  174 + */
  175 +
  176 + //create a list that stores Lexicographic identifiers
  177 + list<LexID> LexicographicList;
  178 +
  179 + int num_fibers = sourceNet->FiberList.size();
  180 + int f;
  181 + for(f=0; f<num_fibers; f++)
  182 + RasterizeFiberLex(sourceNet, f, &LexicographicList);
  183 +
  184 + LexicographicList.sort();
  185 + LexicographicList.unique();
  186 + //LexicographicList.reverse();
  187 +
  188 + //nonLexVolume.SaveVOL("nonlexico.vol");
  189 +
  190 + //save the points in the focus field
  191 + point3D<unsigned long> p;
  192 + list<LexID>::iterator i;
  193 + unsigned long lexID;
  194 + for(i=LexicographicList.begin(); i!=LexicographicList.end(); i++)
  195 + {
  196 + lexID = (*i).ID;
  197 + p.x = (lexID)/(GRID_DIM.y*GRID_DIM.z);
  198 + p.y = (lexID - p.x*GRID_DIM.y*GRID_DIM.z)/GRID_DIM.z;
  199 + p.z = (lexID - p.x*GRID_DIM.y*GRID_DIM.z - p.y*GRID_DIM.z);
  200 + //cout<<"Pushing ";
  201 + //p.print();
  202 + //focusField->set(p.x, p.y, p.z, 255);
  203 + destGrid->push(p.x, p.y, p.z, 255);
  204 + //p.print();
  205 +
  206 + }
  207 + return LexicographicList;
  208 +}
  209 +
  210 +void EvaluateDistanceField(rtsDTGrid3D<float>* initialField)
  211 +{
  212 +
  213 + initialField->background = 255;
  214 + (*initialField) = 0;
  215 + FastSweeping3D(initialField, DILATION, VOXEL_SIZE);
  216 +
  217 +}
  218 +
  219 +float Gaussian(float x, float std)
  220 +{
  221 + float prefix = 1.0/sqrt(2.0*3.14159*std*std);
  222 + float suffix = exp(-(x*x)/(2.0*std*std));
  223 + return prefix*suffix;
  224 +}
  225 +
  226 +void EvaluateGaussianEnvelope(rtsDTGrid3D<float>* distanceField)
  227 +{
  228 +
  229 + rtsDTGrid3D<float>::iterator i;
  230 + float G;
  231 + float zero_value = Gaussian(0.0, STD);
  232 + for(i=distanceField->begin(); i!=distanceField->after(); i++)
  233 + {
  234 + G = Gaussian(i.Value(), STD);
  235 + //normalize the gaussian
  236 + G /= zero_value;
  237 + //cout<<G<<endl;
  238 + i.SetValue(G);
  239 + }
  240 + distanceField->background = 0.0;
  241 +
  242 +}
  243 +
  244 +rtsDTGrid3D<float> CalculateDifference(rtsDTGrid3D<float>* grid0, rtsDTGrid3D<float>* grid1)
  245 +{
  246 + rtsDTGrid3D<float> result;
  247 + result = (*grid0) - (*grid1);
  248 +
  249 +
  250 + rts_itkVolume<float> testVolume;
  251 + testVolume.InsertDTGrid(&result);
  252 + testVolume.SaveVOL("rasterized.vol");
  253 + cout<<"Size: "<<testVolume.DimX()<<","<<testVolume.DimY()<<","<<testVolume.DimZ()<<endl;
  254 + cout<<"Raw Size: "<<testVolume.DimX()*testVolume.DimY()*testVolume.DimZ()<<endl;
  255 +
  256 +
  257 + return result;
  258 +}
  259 +
  260 +
  261 +float ComparePoints(float gold_val, float test_val, float std_1)
  262 +{
  263 + /*if(gold_val > std_1)
  264 + test_val = 0.0;
  265 + if(test_val > std_1)
  266 + gold_val = 0.0;
  267 + */
  268 + if(test_val > std_1 && gold_val > std_1)
  269 + return 0.0;
  270 + return gold_val - test_val;
  271 +
  272 +}
  273 +
  274 +rtsDTGrid3D<float> CompareGrids(rtsDTGrid3D<float>* goldGrid, rtsDTGrid3D<float>* testGrid)
  275 +{
  276 + rtsDTGrid3D<float> result;
  277 + //create an iterator for each DT Grid
  278 + rtsDTGrid3D<float>::iterator gold_i = goldGrid->begin();
  279 + rtsDTGrid3D<float>::iterator test_i = testGrid->begin();
  280 +
  281 + //compute the value at one standard deviation
  282 + float std_1 = Gaussian(STD, STD);
  283 + cout<<"Value at 1 STD: "<<std_1<<endl;
  284 + //create a variable to store the result value
  285 + float result_value;
  286 +
  287 + //iterate both until one iterator has hit after()
  288 + while(gold_i != goldGrid->after() && test_i != testGrid->after())
  289 + {
  290 + //if the iterators are at the same coordinate
  291 + if(gold_i.Coord() == test_i.Coord())
  292 + {
  293 + //insert result of the comparison into the new grid
  294 + result_value = ComparePoints(gold_i.Value(), test_i.Value(), std_1);
  295 + result.push(gold_i.X1(), gold_i.X2(), gold_i.X3(), result_value);
  296 + //increment both
  297 + gold_i++; test_i++;
  298 + }
  299 + //add the lowest (lexicographically) value to the background, insert the result, and increment
  300 + else if( (gold_i.Coord() < test_i.Coord()) )
  301 + {
  302 + result_value = ComparePoints(gold_i.Value(), testGrid->background, std_1);
  303 + result.push(gold_i.X1(), gold_i.X2(), gold_i.X3(), result_value);
  304 + gold_i++;
  305 + }
  306 + else if( (test_i.Coord() < gold_i.Coord()) )
  307 + {
  308 + result_value = ComparePoints(goldGrid->background, test_i.Value(), std_1);
  309 + result.push(test_i.X1(), test_i.X2(), test_i.X3(), result_value);
  310 + test_i++;
  311 + }
  312 + }
  313 +
  314 + cout<<"here"<<endl;
  315 +
  316 + //if the left iterator hasn't finished, iterate to finish it off
  317 + while(gold_i != goldGrid->after())
  318 + {
  319 + result_value = ComparePoints(gold_i.Value(), testGrid->background, std_1);
  320 + result.push(gold_i.X1(), gold_i.X2(), gold_i.X3(), result_value);
  321 + gold_i++;
  322 + }
  323 +
  324 + while(test_i != testGrid->after())
  325 + {
  326 + result_value = ComparePoints(goldGrid->background, test_i.Value(), std_1);
  327 + result.push(test_i.X1(), test_i.X2(), test_i.X3(), result_value);
  328 + test_i++;
  329 + }
  330 +
  331 +
  332 + return result;
  333 +
  334 +
  335 + rts_itkVolume<float> testVolume;
  336 + testVolume.InsertDTGrid(&result);
  337 + testVolume.SaveVOL("rasterized.vol");
  338 + cout<<"Size: "<<testVolume.DimX()<<","<<testVolume.DimY()<<","<<testVolume.DimZ()<<endl;
  339 + cout<<"Raw Size: "<<testVolume.DimX()*testVolume.DimY()*testVolume.DimZ()<<endl;
  340 +
  341 +
  342 + return result;
  343 +}
  344 +
  345 +void IntegrateResult(rtsDTGrid3D<float>* inputGrid, float &total_positive, float &total_negative)
  346 +{
  347 + total_positive = total_negative = 0.0;
  348 + rtsDTGrid3D<float>::iterator i;
  349 + float value;
  350 + for(i = inputGrid->begin(); i != inputGrid->after(); i++)
  351 + {
  352 + value = i.Value();
  353 + if(value > 0.0)
  354 + total_positive += value;
  355 + if(value < 0.0)
  356 + total_negative += -value;
  357 + }
  358 +}
  359 +
  360 +float SumGrid(rtsDTGrid3D<float>* inputGrid)
  361 +{
  362 + rtsDTGrid3D<float>::iterator i;
  363 + float result = 0.0;
  364 + for(i = inputGrid->begin(); i != inputGrid->after(); i++)
  365 + {
  366 + result += i.Value();
  367 + }
  368 + return result;
  369 +}
  370 +
  371 +void StoreInFiber(rtsFiberNetwork* network, int fiber, float value)
  372 +{
  373 + if(network->FiberList[fiber].FiberData == NULL)
  374 + {
  375 + network->FiberList[fiber].FiberData = (void*)(new float[2]);
  376 + ((float*)network->FiberList[fiber].FiberData)[0] = 0.0;
  377 + ((float*)network->FiberList[fiber].FiberData)[1] = 0.0;
  378 + }
  379 +
  380 + ((float*)network->FiberList[fiber].FiberData)[0] += value;
  381 + ((float*)network->FiberList[fiber].FiberData)[1] += 1.0;
  382 +
  383 +}
  384 +void MapToExplicit(int radius, rtsDTGrid3D<float>* inGrid, list<LexID>* inLexList, rtsFiberNetwork* inNetwork)
  385 +{
  386 + //create a template iterator to move over the input grid
  387 + rtsMultiDirectionStencil3D<float> i;
  388 +
  389 + //create an iterator to move through the lexicographic list
  390 + list<LexID>::iterator L = inLexList->begin();
  391 +
  392 + //set the stencil positions
  393 + int x, y, z;
  394 + for(x=-radius; x<=radius; x++)
  395 + for(y=-radius; y<=radius; y++)
  396 + for(z=-radius; z<=radius; z++)
  397 + {
  398 + i.addPosition(x, y, z);
  399 + }
  400 +
  401 + i.Initialize(inGrid);
  402 + unsigned long lex_id;
  403 + float positives;
  404 + int f;
  405 + int p;
  406 + for(i.StartPPP(); L != inLexList->end(); i.PPP())
  407 + {
  408 + //convert the iterator position to a Lexicographic ID
  409 + lex_id = (unsigned long)i.X1()*GRID_DIM.y*GRID_DIM.z + (unsigned long)i.X2()*GRID_DIM.z + (unsigned long)i.X3();
  410 + if(lex_id == (*L).ID)
  411 + {
  412 + //get the fiber ID associated with the point
  413 + f = (*L).fiber;
  414 +
  415 + //get the positive value
  416 + positives = 0.0;
  417 + for(p = 0; p<i.numValues(); p++)
  418 + {
  419 + if(i.getValue(p) > 0)
  420 + positives += i.getValue(p);
  421 + }
  422 + //if(positives > 0)
  423 + // cout<<positives<<endl;
  424 +
  425 + //store the value in the network
  426 + StoreInFiber(inNetwork, f, positives);
  427 + L++;
  428 +
  429 + }
  430 +
  431 +
  432 + }
  433 +
  434 +
  435 +
  436 +}
... ...
NetworkComparison.cpp 0 โ†’ 100644
  1 +++ a/NetworkComparison.cpp
  1 +#include "rts/rtsPoint3d.h"
  2 +#include <vector>
  3 +#include <string>
  4 +
  5 +//AnyOption library for parsing command-line options:
  6 +//http://www.hackorama.com/anyoption/
  7 +#include "anyoption.h"
  8 +
  9 +//#include "ImplicitCalculations.h"
  10 +#include "rts/objJedi.h"
  11 +#include "DrawingFunctions.h"
  12 +#include "rts/rtsGraph.h"
  13 +#include "rts/rtsFilename.h"
  14 +
  15 +#define PRINT_LOG 1
  16 +
  17 +
  18 +using namespace std;
  19 +
  20 +bool displayGui = false;
  21 +bool displayVerbose = false;
  22 +
  23 +rtsFiberNetwork* goldNetwork;
  24 +GLint goldNodeDL;
  25 +
  26 +rtsFiberNetwork* testNetwork;
  27 +
  28 +//standard deviation of the gaussian envelope surrounding the networks
  29 +float sigmaG, sigmaC;
  30 +
  31 +int glutwindow_id;
  32 +
  33 +void GlutMenuCallback(int option);
  34 +
  35 +void LoadNetworks(string gold_filename, string test_filename)
  36 +{
  37 +
  38 + goldNetwork = new rtsFiberNetwork();
  39 + testNetwork = new rtsFiberNetwork();
  40 +
  41 + cout<<endl;
  42 + cout<<"Gold Standard:"<<endl;
  43 + goldNetwork->LoadSWC(gold_filename);
  44 + cout<<"Nodes: "<<goldNetwork->NodeList.size()<<endl;
  45 + cout<<"Fibers: "<<goldNetwork->FiberList.size()<<endl;
  46 + cout<<"Total Length: "<<goldNetwork->getTotalLength()<<endl;
  47 +
  48 + cout<<endl;
  49 +
  50 + cout<<"Test Network:"<<endl;
  51 + testNetwork->LoadSWC(test_filename);
  52 + cout<<"Nodes: "<<testNetwork->NodeList.size()<<endl;
  53 + cout<<"Fibers: "<<testNetwork->FiberList.size()<<endl;
  54 + cout<<"Total Length: "<<testNetwork->getTotalLength()<<endl;
  55 +
  56 + cout<<endl;
  57 +
  58 + //focusNetwork = testNetwork;
  59 +}
  60 +
  61 +void SpecialKeys(int key, int x, int y)
  62 +{
  63 + if(key == GLUT_KEY_LEFT)
  64 + IncrementSelectedFiber(-1);
  65 + if(key == GLUT_KEY_RIGHT)
  66 + IncrementSelectedFiber(1);
  67 +}
  68 +
  69 +void PrintHelp()
  70 +{
  71 + cout<<"'.' = Center Camera"<<endl;
  72 + cout<<"'z' = Reduce Radius"<<endl;
  73 + cout<<"'x' = Increase Radius"<<endl;
  74 + cout<<"'c' = Color Segments"<<endl;
  75 +}
  76 +
  77 +void KeyboardFunction(unsigned char key, int x, int y)
  78 +{
  79 + if(key == '.')
  80 + RecenterCamera();
  81 + if(key == '?')
  82 + PrintHelp();
  83 + if(key == 'z')
  84 + {
  85 + fiber_radius_factor += 0.1;
  86 + node_radius_factor += 0.1;
  87 + CreateDisplayLists();
  88 + }
  89 + if(key == 'x')
  90 + {
  91 + fiber_radius_factor -= 0.1;
  92 + node_radius_factor -= 0.1;
  93 + CreateDisplayLists();
  94 + }
  95 + if(key == 'c')
  96 + {
  97 + ColorFibers();
  98 + CreateDisplayLists();
  99 + }
  100 + if(key == 'q')
  101 + {
  102 + exit(1);
  103 + }
  104 +
  105 +}
  106 +
  107 +void InitializeOpenGL()
  108 +{
  109 + //GLUT stuff
  110 + //menus
  111 + rts_glutInitialize("Network Comparison", 1000, 500);
  112 +
  113 + int mnuMain = glutCreateMenu(GlutMenuCallback);
  114 + int mnuColormap = glutCreateMenu(GlutMenuCallback);
  115 +
  116 + glutSetMenu(mnuMain);
  117 + glutAddMenuEntry("Network", DISPLAY_NETWORK);
  118 + glutAddMenuEntry("Graph", DISPLAY_GRAPH);
  119 + glutAddMenuEntry("Connected", DISPLAY_CONNECTED);
  120 + glutAddMenuEntry("Selected", DISPLAY_SELECTED);
  121 +
  122 + //create the colormap menu
  123 + glutAddSubMenu("Colormap", mnuColormap);
  124 + glutSetMenu(mnuColormap);
  125 + glutAddMenuEntry("Isoluminant", COLORMAP_ISOLUMINANT);
  126 + glutAddMenuEntry("Black Body", COLORMAP_BLACKBODY);
  127 + glutAddMenuEntry("Brewer", COLORMAP_BREWER);
  128 + glutAddMenuEntry("Rainbow", COLORMAP_RAINBOW);
  129 +
  130 + glutSetMenu(mnuMain);
  131 + glutAddMenuEntry("Exit", NETCOMP_EXIT);
  132 + glutAddMenuEntry("Cull Test-Case", CULL_TEST_CASE);
  133 + glutAddMenuEntry("Recompute NetMets", RECOMPUTE_METRIC);
  134 + glutAttachMenu(GLUT_RIGHT_BUTTON);
  135 +
  136 + //keyboard stuff
  137 + glutSpecialFunc(SpecialKeys);
  138 + glutKeyboardFunc(KeyboardFunction);
  139 +
  140 + //camera
  141 + point3D<float> min_point0 = goldNetwork->min_pos;
  142 + point3D<float> min_point1 = testNetwork->min_pos;
  143 +
  144 + point3D<float> max_point0 = goldNetwork->max_pos;
  145 + point3D<float> max_point1 = testNetwork->max_pos;
  146 +
  147 + point3D<float> min_point(min(min_point0.x, min_point1.x), min(min_point0.y, min_point1.y), min(min_point0.z, min_point1.z));
  148 + point3D<float> max_point(max(max_point0.x, max_point1.x), max(max_point0.y, max_point1.y), max(max_point0.z, max_point1.z));
  149 + point3D<float> center_point = min_point + 0.5*(max_point - min_point);
  150 + network_span = (max_point - point3D<float>(0, 0, 0)).Length();
  151 + rts_glut_camera.setPosition(0, 0, 3*network_span);
  152 + rts_glut_camera.LookAt(center_point, vector3D<float>(0.0, 1.0, 0.0));
  153 +
  154 +
  155 + //load the shaders
  156 + makeColormap();
  157 + //create strings for all of the shader filenames
  158 + string SmoothShaderVertexFilename = "";
  159 + SmoothShaderVertexFilename += "SmoothShader_Vertex.glsl";
  160 + string SmoothShaderFragmentFilename = "";
  161 + SmoothShaderFragmentFilename += "SmoothShader_Fragment.glsl";
  162 + string ErrorMapFragmentFilename = "";
  163 + ErrorMapFragmentFilename += "ErrorMap_Fragment.glsl";
  164 +
  165 + //Edge_ErrorShader.Init();
  166 + //ErrorShader.Clean();
  167 +
  168 + Edge_ErrorShader.AttachShader(GL_VERTEX_SHADER, SmoothShaderVertexFilename.c_str());
  169 +
  170 + //Edge_ErrorShader.AttachShader(GL_FRAGMENT_SHADER, "ErrorShader_Fragment.glsl");
  171 + Edge_ErrorShader.AttachShader(GL_FRAGMENT_SHADER, ErrorMapFragmentFilename.c_str());
  172 + Edge_ErrorShader.Compile();
  173 +
  174 + //cout<<"Edge Error Shader Log-------------------------"<<endl;
  175 + Edge_ErrorShader.PrintLog();
  176 + Edge_ErrorShader.Link();
  177 + Edge_ErrorShader.PrintLog();
  178 + Edge_ErrorShader.AttachGlobalUniform("L1_pos", L1_pos);
  179 + Edge_ErrorShader.AttachTextureMap("colorMap", texColorMap);
  180 +
  181 +
  182 + Node_ErrorShader.AttachShader(GL_VERTEX_SHADER, SmoothShaderVertexFilename.c_str());
  183 + Node_ErrorShader.AttachShader(GL_FRAGMENT_SHADER, ErrorMapFragmentFilename.c_str());
  184 + Node_ErrorShader.Compile();
  185 + Node_ErrorShader.PrintLog();
  186 + Node_ErrorShader.Link();
  187 + Node_ErrorShader.PrintLog();
  188 + Node_ErrorShader.AttachGlobalUniform("L1_pos", L1_pos);
  189 + Node_ErrorShader.AttachTextureMap("colorMap", texColorMap);
  190 +
  191 + Smooth_Shader.AttachShader(GL_VERTEX_SHADER, SmoothShaderVertexFilename.c_str());
  192 + Smooth_Shader.AttachShader(GL_FRAGMENT_SHADER, SmoothShaderFragmentFilename.c_str());
  193 + Smooth_Shader.Compile();
  194 + Smooth_Shader.PrintLog();
  195 + Smooth_Shader.Link();
  196 + Smooth_Shader.PrintLog();
  197 + Smooth_Shader.AttachGlobalUniform("L0_pos", L0_pos);
  198 + Smooth_Shader.AttachGlobalUniform("L1_pos", L1_pos);
  199 +
  200 +}
  201 +
  202 +void ComputeNetMets()
  203 +{
  204 +
  205 + testNetwork->Resample(sigmaG);
  206 + testNetwork->SubdivideNetwork(sigmaG);
  207 +
  208 + goldNetwork->Resample(sigmaG);
  209 + goldNetwork->SubdivideNetwork(sigmaG);
  210 +
  211 +
  212 + //compare the two networks and get the core graph
  213 + float gFPR, gFNR, cFPR, cFNR;
  214 + coreGraph = goldNetwork->CompareNetworks(testNetwork, sigmaG, sigmaC, gFPR, gFNR, cFPR, cFNR);
  215 +
  216 + //output error metrics
  217 + if(displayVerbose)
  218 + {
  219 + cout<<"GEOMETRY++++++++++++"<<endl;
  220 + cout<<"False Positive Rate: "<<gFPR<<endl;
  221 + cout<<"False Negative Rate: "<<gFNR<<endl;
  222 + cout<<"CONNECTIVITY++++++++"<<endl;
  223 + cout<<"False Positive Rate: "<<cFPR<<endl;
  224 + cout<<"False Negative Rate: "<<cFNR<<endl;
  225 + }
  226 + else
  227 + {
  228 + cout<<gFPR<<'\t'<<gFNR<<'\t'<<cFPR<<'\t'<<cFNR<<endl;
  229 + }
  230 +
  231 + //color each of the core graph fiber sequences
  232 + ColorFibers();
  233 +
  234 +}
  235 +
  236 +#include <stdio.h>
  237 +#include <errno.h>
  238 +int main(int argc, char* argv[])
  239 +{
  240 + //Create an AnyOption object
  241 + AnyOption* opt = new AnyOption();
  242 + opt->addUsage( "" );
  243 + opt->addUsage( "Usage: NetMets [OPTION]... [GROUND TRUTH FILE] [TEST CASE FILE]" );
  244 + opt->addUsage( "" );
  245 + opt->addUsage( " -h --help Prints this help " );
  246 + opt->addUsage( " -s --sigma Input sigma value (default = 25)");
  247 + opt->addUsage( " -g --gui Display NetMets GUI " );
  248 + opt->addUsage( " -v --verbose Verbose output " );
  249 + opt->addUsage( "" );
  250 +
  251 + opt->setFlag( "help", 'h' ); /* a flag (takes no argument), supporting long and short form */
  252 + opt->setFlag( "gui", 'g' );
  253 + opt->setOption("sigma", 's');
  254 + opt->setFlag( "verbose", 'v');
  255 +
  256 + /* go through the command line and get the options */
  257 + opt->processCommandArgs( argc, argv );
  258 +
  259 + //display the help
  260 + if( opt->getFlag( "help" ) || opt->getFlag( 'h' ) )
  261 + {
  262 + opt->printUsage();
  263 + return 0;
  264 + }
  265 +
  266 + //set a flag to display the GUI if requested
  267 + if( opt->getFlag( "gui" ) || opt->getFlag( 'g' ) )
  268 + displayGui = true;
  269 + if( opt->getFlag("verbose") || opt->getFlag('v'))
  270 + displayVerbose = true;
  271 +
  272 + //set the sigma value based on user input
  273 + sigmaG = 25;
  274 + sigmaC = 25;
  275 +
  276 + if( opt->getValue( 's' ) != NULL || opt->getValue( "sigma" ) != NULL )
  277 + {
  278 + sigmaG = atof(opt->getValue("sigma"));
  279 + sigmaC = sigmaG;
  280 +
  281 + }
  282 + //cout << "size = " << atof(opt->getValue("sigma")) << endl ;
  283 +
  284 + //get the filename arguments
  285 + int nArgs = opt->getArgc();
  286 + char** sArgs = (char**)malloc(nArgs);
  287 + for(int a=0; a<nArgs; a++)
  288 + sArgs[a] = opt->getArgv(a);
  289 +
  290 +
  291 + string gold_filename;
  292 + string test_filename;
  293 +
  294 + int resolution = 512;
  295 + float epsilon = 0.1;
  296 + if(nArgs < 2)
  297 + {
  298 + gold_filename = "00_GT.obj"; test_filename = "00_T.obj"; sigmaG = sigmaC = 25.0;
  299 + //sigmaG = 25; sigmaC = 25.0;
  300 +
  301 + }
  302 + else
  303 + {
  304 + gold_filename = sArgs[0];
  305 + test_filename = sArgs[1];
  306 + }
  307 +
  308 +
  309 + //load the network files
  310 + testNetwork = new rtsFiberNetwork();
  311 + testNetwork->LoadFile(test_filename);
  312 +
  313 + goldNetwork = new rtsFiberNetwork();
  314 + goldNetwork->LoadFile(gold_filename);
  315 +
  316 +
  317 +
  318 +
  319 +
  320 +
  321 + //compute the metric
  322 + ComputeNetMets();
  323 +
  324 +
  325 +
  326 + //if the user does not want the GUI displayed, just return
  327 + if(!displayGui) return 0;
  328 +
  329 + //initialize OpenGL
  330 + InitializeOpenGL();
  331 +
  332 + //create display lists
  333 + CreateDisplayLists();
  334 +
  335 +
  336 + //set up GLUT and start
  337 + rts_glutStart(MyDisplayFunction);
  338 +
  339 + return 0;
  340 +
  341 +}
... ...
Node_SmoothError_Vertex.glsl 0 โ†’ 100644
  1 +++ a/Node_SmoothError_Vertex.glsl
  1 +varying vec3 fragment_normal;
  2 +
  3 +void main(void)
  4 +{
  5 + //fragment_normal = normalize(gl_NormalMatrix * gl_Normal);
  6 + //fragment_normal = vec3(0.0, 0.0, 0.5);
  7 + fragment_normal = gl_Normal;
  8 + gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
  9 + //gl_TexCoord[0] = gl_Color;
  10 + gl_FrontColor = gl_Color;
  11 +}
... ...
PerformanceData.h 0 โ†’ 100644
  1 +++ a/PerformanceData.h
  1 +// add the following to a cpp file:
  2 +// PerformanceData PD;
  3 +
  4 +#pragma once
  5 +
  6 +enum PerformanceDataType
  7 +{
  8 + PD_DISPLAY=0,
  9 + PD_SPS,
  10 + PD_UNUSED0,
  11 +
  12 + //my stuff
  13 + SUBDIVIDE_NETWORKS,
  14 + BRUTE_FORCE_DISTANCE,
  15 + LOG_N_DIST_BUILD0,
  16 + LOG_N_DIST_SEARCH0,
  17 + LOG_N_DIST_BUILD1,
  18 + LOG_N_DIST_SEARCH1,
  19 + LOG_N_DISTANCE,
  20 + MY_TOPOLOGY,
  21 + BOOST_TOPOLOGY,
  22 +
  23 +
  24 + //end my stuff
  25 + PERFORMANCE_DATA_TYPE_COUNT
  26 +};
  27 +
  28 +static char PDTypeNames[][255] = {
  29 + "Display ",
  30 + "Simulation Total ",
  31 + " ----------------- ",
  32 + //my stuff
  33 + "Network Subdivision",
  34 + "Brute Force Dist.--",
  35 + " Build 0 ",
  36 + " Search 0 ",
  37 + " Build 1 ",
  38 + " Search 1 ",
  39 + "ANN Dist.----------",
  40 + "MY Topology--------",
  41 + "BOOST Topology-----",
  42 + //end my stuff
  43 +
  44 +};
  45 +
  46 +//-------------------------------------------------------------------------------
  47 +
  48 +//#ifdef DISPLAY
  49 +// #define PERFORMANCE_DATA_MEASUE_ENABLE
  50 +//#endif
  51 +
  52 +//#ifdef PERFORMANCE_DATA_MEASUE_ENABLE
  53 +
  54 +//-------------------------------------------------------------------------------
  55 +
  56 +#include <stdio.h>
  57 +#include <windows.h>
  58 +#include <float.h>
  59 +
  60 +#include <iostream>
  61 +#include <iomanip>
  62 +
  63 +//-------------------------------------------------------------------------------
  64 +
  65 +class PerformanceData
  66 +{
  67 +public:
  68 + PerformanceData() { ClearAll(); QueryPerformanceFrequency(&cps); }
  69 + ~PerformanceData(){}
  70 +
  71 + void ClearAll()
  72 + {
  73 + for ( int i=0; i<PERFORMANCE_DATA_TYPE_COUNT; i++ ) {
  74 + for ( int j=0; j<256; j++ ) times[i][j] = 0;
  75 + pos[i] = 0;
  76 + minTime[i] = 0xFFFFFFFF;
  77 + maxTime[i] = 0;
  78 + totalTime[i] = 0;
  79 + dataReady[i] = false;
  80 + }
  81 + }
  82 +
  83 + void StartTimer( int type ) { QueryPerformanceCounter( &startTime[type] ); /*startTime[type] = GetTickCount();*/ }
  84 + void EndTimer( int type ) {
  85 + LARGE_INTEGER endTime;
  86 + QueryPerformanceCounter( &endTime );
  87 + double t = endTime.QuadPart - startTime[type].QuadPart;
  88 + //unsigned int t = GetTickCount() - startTime[type];
  89 + if ( t < minTime[type] ) minTime[type] = t;
  90 + if ( t > maxTime[type] ) maxTime[type] = t;
  91 + totalTime[type] -= times[type][ pos[type] ];
  92 + times[type][ pos[type] ] = t;
  93 + totalTime[type] += t;
  94 + pos[type]++;
  95 + if ( pos[type] == 0 ) dataReady[type] = true;
  96 + }
  97 +
  98 + void PrintResult( ostream &os,int i=PERFORMANCE_DATA_TYPE_COUNT)
  99 + {
  100 + os.setf(ios::fixed);
  101 + if ((i<PERFORMANCE_DATA_TYPE_COUNT)&&(i>=0)){
  102 + double a = GetAvrgTime(i);
  103 + if ( a )
  104 + os<< PDTypeNames[i]<<" : avrg="<<setw(8)<<setprecision(3)<<a<<"\tmin="<<setw(8)<<setprecision(3)<< GetMinTime(i) <<"\tmax="<<setw(8)<<setprecision(3)<< GetMaxTime(i) <<endl ;
  105 + else
  106 + os<< PDTypeNames[i]<<" : avrg= -----\tmin= -----\tmax= -----"<<endl;
  107 + }
  108 + }
  109 +
  110 + void PrintResults( ostream &os)
  111 + {
  112 + for ( int i=0; i<PERFORMANCE_DATA_TYPE_COUNT; i++ )
  113 + PrintResult(os,i);
  114 + }
  115 +
  116 + double GetLastTime( int type ) { return times[type][pos[type]]; }
  117 + double GetAvrgTime( int type ) { double a = 1000.0 * totalTime[type] / (float)cps.QuadPart / ( (dataReady[type]) ? 256.0 : (double)pos[type] ); return (_finite(a))? a:0; }
  118 + double GetMinTime( int type ) { return 1000.0 * minTime[type] / (float)cps.LowPart; }
  119 + double GetMaxTime( int type ) { return 1000.0 * maxTime[type] / (float)cps.LowPart; }
  120 +
  121 +private:
  122 + double times[PERFORMANCE_DATA_TYPE_COUNT][256];
  123 + unsigned char pos[PERFORMANCE_DATA_TYPE_COUNT];
  124 + LARGE_INTEGER startTime[PERFORMANCE_DATA_TYPE_COUNT];
  125 + double minTime[ PERFORMANCE_DATA_TYPE_COUNT ];
  126 + double maxTime[ PERFORMANCE_DATA_TYPE_COUNT ];
  127 + double totalTime[ PERFORMANCE_DATA_TYPE_COUNT ];
  128 + bool dataReady[ PERFORMANCE_DATA_TYPE_COUNT ];
  129 + LARGE_INTEGER cps;
  130 +};
  131 +
  132 +//-------------------------------------------------------------------------------
  133 +/*#else
  134 +
  135 +class PerformanceData{
  136 +public:
  137 + PerformanceData() {;};
  138 + ~PerformanceData(){;};
  139 + void ClearAll(){;};
  140 + void StartTimer( int type ) {;};
  141 + void EndTimer( int type ) {;};
  142 + void PrintResults( ostream &os){;};
  143 + void PrintResult( ostream &os, int i=PERFORMANCE_DATA_TYPE_COUNT){;};
  144 + double GetLastTime( int type ) { return 0.0; };
  145 + double GetAvrgTime( int type ) { return 0.0; };
  146 + double GetMinTime( int type ) { return 0.0; };
  147 + double GetMaxTime( int type ) { return 0.0; };
  148 +};
  149 +
  150 +#endif
  151 +//-------------------------------------------------------------------------------
  152 +*/
  153 +extern PerformanceData PD;
  154 +
  155 +//-------------------------------------------------------------------------------
... ...
README 0 โ†’ 100644
  1 +++ a/README
  1 +NetMets requires the following libraries:
  2 +
  3 +GLUT (OpenGL Utility Toolkit) -- http://www.opengl.org/resources/libraries/glut/
  4 +GLEW (OpenGL Extension Wrangler) -- http://glew.sourceforge.net/
  5 +RTS (my personal codebase) -- https://github.com/dmayerich/RTS
  6 +BOOST Graph Library -- http://www.boost.org/doc/libs/1_52_0/libs/graph/doc/index.html
  7 +ANN (Approximate Nearest Neighbor Library) -- http://www.cs.umd.edu/~mount/ANN/
  8 +
  9 +If CMake is unable to find these, make sure to specify their locations.
0 10 \ No newline at end of file
... ...
SmoothShader_Fragment.glsl 0 โ†’ 100644
  1 +++ a/SmoothShader_Fragment.glsl
  1 +#extension GL_EXT_gpu_shader4 : enable
  2 +
  3 +varying vec3 fragment_normal;
  4 +uniform vec3 L0_pos;
  5 +uniform vec3 L1_pos;
  6 +
  7 +float LightIntensity()
  8 +{
  9 + //vec3 L0_pos = vec3(1.0, 0.0, 0.0);
  10 + //vec3 L1_pos = vec3(0.0, 0.0, 1.0);
  11 + float L0 = 0.5*max(dot(fragment_normal, L0_pos), 0.0);
  12 + float L1 = 0.5*max(dot(fragment_normal, L1_pos), 0.0);
  13 +
  14 + return L0 + L1;
  15 + //return 0.5;
  16 +
  17 +}
  18 +
  19 +void main(void)
  20 +{
  21 + //float error = (1.0 - gl_TexCoord[0].x)*(240.0/360.0);
  22 + float light = LightIntensity();
  23 + vec4 color = gl_Color;//vec4(1.0, 1.0, 1.0, 1.0);
  24 + gl_FragColor = color*light;
  25 +
  26 + //assume that the error is the H component of an HSV triple
  27 + //vec4 HSV = vec4((240.0/60.0)*(1.0 - error), 1.0, 0.5, 1.0);
  28 + //vec4 RGB = HSVtoRGB(HSV);
  29 +
  30 + //convert from HSL to RGB
  31 + //vec4 HSL = vec4(error, 1.0, light, 1.0);
  32 + //vec4 RGB = HSLtoRGB(HSL);
  33 +
  34 + //gl_FragColor = vec4(0.5, 0.5, 0.5, 1.0);
  35 +}
... ...
SmoothShader_Vertex.glsl 0 โ†’ 100644
  1 +++ a/SmoothShader_Vertex.glsl
  1 +varying vec3 fragment_normal;
  2 +
  3 +void main(void)
  4 +{
  5 + //fragment_normal = normalize(gl_NormalMatrix * gl_Normal);
  6 + //fragment_normal = vec3(0.0, 0.0, 0.5);
  7 + fragment_normal = gl_Normal;
  8 + gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
  9 + gl_TexCoord[0] = gl_MultiTexCoord0;
  10 + gl_FrontColor = gl_Color;
  11 +}
... ...
anyoption.cpp 0 โ†’ 100644
  1 +++ a/anyoption.cpp
  1 +/*
  2 + * AnyOption 1.3
  3 + *
  4 + * kishan at hackorama dot com www.hackorama.com JULY 2001
  5 + *
  6 + * + Acts as a common facade class for reading
  7 + * commandline options as well as options from
  8 + * an optionfile with delimited type value pairs
  9 + *
  10 + * + Handles the POSIX style single character options ( -w )
  11 + * as well as the newer GNU long options ( --width )
  12 + *
  13 + * + The option file assumes the traditional format of
  14 + * first character based comment lines and type value
  15 + * pairs with a delimiter , and flags which are not pairs
  16 + *
  17 + * # this is a coment
  18 + * # next line is an option value pair
  19 + * width : 100
  20 + * # next line is a flag
  21 + * noimages
  22 + *
  23 + * + Supports printing out Help and Usage
  24 + *
  25 + * + Why not just use getopt() ?
  26 + *
  27 + * getopt() Its a POSIX standard not part of ANSI-C.
  28 + * So it may not be available on platforms like Windows.
  29 + *
  30 + * + Why it is so long ?
  31 + *
  32 + * The actual code which does command line parsing
  33 + * and option file parsing are done in few methods.
  34 + * Most of the extra code are for providing a flexible
  35 + * common public interface to both a resourcefile and
  36 + * and command line supporting POSIX style and
  37 + * GNU long option as well as mixing of both.
  38 + *
  39 + * + Please see "anyoption.h" for public method descriptions
  40 + *
  41 + */
  42 +
  43 +/* Updated Auguest 2004
  44 + * Fix from Michael D Peters (mpeters at sandia.gov)
  45 + * to remove static local variables, allowing multiple instantiations
  46 + * of the reader (for using multiple configuration files). There is
  47 + * an error in the destructor when using multiple instances, so you
  48 + * cannot delete your objects (it will crash), but not calling the
  49 + * destructor only introduces a small memory leak, so I
  50 + * have not bothered tracking it down.
  51 + *
  52 + * Also updated to use modern C++ style headers, rather than
  53 + * depricated iostream.h (it was causing my compiler problems)
  54 +*/
  55 +
  56 +/*
  57 + * Updated September 2006
  58 + * Fix from Boyan Asenov for a bug in mixing up option indexes
  59 + * leading to exception when mixing different options types
  60 + */
  61 +
  62 +#include "anyoption.h"
  63 +
  64 +AnyOption::AnyOption()
  65 +{
  66 + init();
  67 +}
  68 +
  69 +AnyOption::AnyOption(int maxopt)
  70 +{
  71 + init( maxopt , maxopt );
  72 +}
  73 +
  74 +AnyOption::AnyOption(int maxopt, int maxcharopt)
  75 +{
  76 + init( maxopt , maxcharopt );
  77 +}
  78 +
  79 +AnyOption::~AnyOption()
  80 +{
  81 + if( mem_allocated )
  82 + cleanup();
  83 +}
  84 +
  85 +void
  86 +AnyOption::init()
  87 +{
  88 + init( DEFAULT_MAXOPTS , DEFAULT_MAXOPTS );
  89 +}
  90 +
  91 +void
  92 +AnyOption::init(int maxopt, int maxcharopt )
  93 +{
  94 +
  95 + max_options = maxopt;
  96 + max_char_options = maxcharopt;
  97 + max_usage_lines = DEFAULT_MAXUSAGE;
  98 + usage_lines = 0 ;
  99 + argc = 0;
  100 + argv = NULL;
  101 + posix_style = true;
  102 + verbose = false;
  103 + filename = NULL;
  104 + appname = NULL;
  105 + option_counter = 0;
  106 + optchar_counter = 0;
  107 + new_argv = NULL;
  108 + new_argc = 0 ;
  109 + max_legal_args = 0 ;
  110 + command_set = false;
  111 + file_set = false;
  112 + values = NULL;
  113 + g_value_counter = 0;
  114 + mem_allocated = false;
  115 + command_set = false;
  116 + file_set = false;
  117 + opt_prefix_char = '-';
  118 + file_delimiter_char = ':';
  119 + file_comment_char = '#';
  120 + equalsign = '=';
  121 + comment = '#' ;
  122 + delimiter = ':' ;
  123 + endofline = '\n';
  124 + whitespace = ' ' ;
  125 + nullterminate = '\0';
  126 + set = false;
  127 + once = true;
  128 + hasoptions = false;
  129 + autousage = false;
  130 +
  131 + strcpy( long_opt_prefix , "--" );
  132 +
  133 + if( alloc() == false ){
  134 + cout << endl << "OPTIONS ERROR : Failed allocating memory" ;
  135 + cout << endl ;
  136 + cout << "Exiting." << endl ;
  137 + exit (0);
  138 + }
  139 +}
  140 +
  141 +bool
  142 +AnyOption::alloc()
  143 +{
  144 + int i = 0 ;
  145 + int size = 0 ;
  146 +
  147 + if( mem_allocated )
  148 + return true;
  149 +
  150 + size = (max_options+1) * sizeof(const char*);
  151 + options = (const char**)malloc( size );
  152 + optiontype = (int*) malloc( (max_options+1)*sizeof(int) );
  153 + optionindex = (int*) malloc( (max_options+1)*sizeof(int) );
  154 + if( options == NULL || optiontype == NULL || optionindex == NULL )
  155 + return false;
  156 + else
  157 + mem_allocated = true;
  158 + for( i = 0 ; i < max_options ; i++ ){
  159 + options[i] = NULL;
  160 + optiontype[i] = 0 ;
  161 + optionindex[i] = -1 ;
  162 + }
  163 + optionchars = (char*) malloc( (max_char_options+1)*sizeof(char) );
  164 + optchartype = (int*) malloc( (max_char_options+1)*sizeof(int) );
  165 + optcharindex = (int*) malloc( (max_char_options+1)*sizeof(int) );
  166 + if( optionchars == NULL ||
  167 + optchartype == NULL ||
  168 + optcharindex == NULL )
  169 + {
  170 + mem_allocated = false;
  171 + return false;
  172 + }
  173 + for( i = 0 ; i < max_char_options ; i++ ){
  174 + optionchars[i] = '0';
  175 + optchartype[i] = 0 ;
  176 + optcharindex[i] = -1 ;
  177 + }
  178 +
  179 + size = (max_usage_lines+1) * sizeof(const char*) ;
  180 + usage = (const char**) malloc( size );
  181 +
  182 + if( usage == NULL ){
  183 + mem_allocated = false;
  184 + return false;
  185 + }
  186 + for( i = 0 ; i < max_usage_lines ; i++ )
  187 + usage[i] = NULL;
  188 +
  189 + return true;
  190 +}
  191 +
  192 +bool
  193 +AnyOption::doubleOptStorage()
  194 +{
  195 + options = (const char**)realloc( options,
  196 + ((2*max_options)+1) * sizeof( const char*) );
  197 + optiontype = (int*) realloc( optiontype ,
  198 + ((2 * max_options)+1)* sizeof(int) );
  199 + optionindex = (int*) realloc( optionindex,
  200 + ((2 * max_options)+1) * sizeof(int) );
  201 + if( options == NULL || optiontype == NULL || optionindex == NULL )
  202 + return false;
  203 + /* init new storage */
  204 + for( int i = max_options ; i < 2*max_options ; i++ ){
  205 + options[i] = NULL;
  206 + optiontype[i] = 0 ;
  207 + optionindex[i] = -1 ;
  208 + }
  209 + max_options = 2 * max_options ;
  210 + return true;
  211 +}
  212 +
  213 +bool
  214 +AnyOption::doubleCharStorage()
  215 +{
  216 + optionchars = (char*) realloc( optionchars,
  217 + ((2*max_char_options)+1)*sizeof(char) );
  218 + optchartype = (int*) realloc( optchartype,
  219 + ((2*max_char_options)+1)*sizeof(int) );
  220 + optcharindex = (int*) realloc( optcharindex,
  221 + ((2*max_char_options)+1)*sizeof(int) );
  222 + if( optionchars == NULL ||
  223 + optchartype == NULL ||
  224 + optcharindex == NULL )
  225 + return false;
  226 + /* init new storage */
  227 + for( int i = max_char_options ; i < 2*max_char_options ; i++ ){
  228 + optionchars[i] = '0';
  229 + optchartype[i] = 0 ;
  230 + optcharindex[i] = -1 ;
  231 + }
  232 + max_char_options = 2 * max_char_options;
  233 + return true;
  234 +}
  235 +
  236 +bool
  237 +AnyOption::doubleUsageStorage()
  238 +{
  239 + usage = (const char**)realloc( usage,
  240 + ((2*max_usage_lines)+1) * sizeof( const char*) );
  241 + if ( usage == NULL )
  242 + return false;
  243 + for( int i = max_usage_lines ; i < 2*max_usage_lines ; i++ )
  244 + usage[i] = NULL;
  245 + max_usage_lines = 2 * max_usage_lines ;
  246 + return true;
  247 +
  248 +}
  249 +
  250 +
  251 +void
  252 +AnyOption::cleanup()
  253 +{
  254 + free (options);
  255 + free (optiontype);
  256 + free (optionindex);
  257 + free (optionchars);
  258 + free (optchartype);
  259 + free (optcharindex);
  260 + free (usage);
  261 + if( values != NULL )
  262 + free (values);
  263 + if( new_argv != NULL )
  264 + free (new_argv);
  265 +}
  266 +
  267 +void
  268 +AnyOption::setCommandPrefixChar( char _prefix )
  269 +{
  270 + opt_prefix_char = _prefix;
  271 +}
  272 +
  273 +void
  274 +AnyOption::setCommandLongPrefix( char *_prefix )
  275 +{
  276 + if( strlen( _prefix ) > MAX_LONG_PREFIX_LENGTH ){
  277 + *( _prefix + MAX_LONG_PREFIX_LENGTH ) = '\0';
  278 + }
  279 +
  280 + strcpy (long_opt_prefix, _prefix);
  281 +}
  282 +
  283 +void
  284 +AnyOption::setFileCommentChar( char _comment )
  285 +{
  286 + file_delimiter_char = _comment;
  287 +}
  288 +
  289 +
  290 +void
  291 +AnyOption::setFileDelimiterChar( char _delimiter )
  292 +{
  293 + file_comment_char = _delimiter ;
  294 +}
  295 +
  296 +bool
  297 +AnyOption::CommandSet()
  298 +{
  299 + return( command_set );
  300 +}
  301 +
  302 +bool
  303 +AnyOption::FileSet()
  304 +{
  305 + return( file_set );
  306 +}
  307 +
  308 +void
  309 +AnyOption::noPOSIX()
  310 +{
  311 + posix_style = false;
  312 +}
  313 +
  314 +bool
  315 +AnyOption::POSIX()
  316 +{
  317 + return posix_style;
  318 +}
  319 +
  320 +
  321 +void
  322 +AnyOption::setVerbose()
  323 +{
  324 + verbose = true ;
  325 +}
  326 +
  327 +void
  328 +AnyOption::printVerbose()
  329 +{
  330 + if( verbose )
  331 + cout << endl ;
  332 +}
  333 +void
  334 +AnyOption::printVerbose( const char *msg )
  335 +{
  336 + if( verbose )
  337 + cout << msg ;
  338 +}
  339 +
  340 +void
  341 +AnyOption::printVerbose( char *msg )
  342 +{
  343 + if( verbose )
  344 + cout << msg ;
  345 +}
  346 +
  347 +void
  348 +AnyOption::printVerbose( char ch )
  349 +{
  350 + if( verbose )
  351 + cout << ch ;
  352 +}
  353 +
  354 +bool
  355 +AnyOption::hasOptions()
  356 +{
  357 + return hasoptions;
  358 +}
  359 +
  360 +void
  361 +AnyOption::autoUsagePrint(bool _autousage)
  362 +{
  363 + autousage = _autousage;
  364 +}
  365 +
  366 +void
  367 +AnyOption::useCommandArgs( int _argc, char **_argv )
  368 +{
  369 + argc = _argc;
  370 + argv = _argv;
  371 + command_set = true;
  372 + appname = argv[0];
  373 + if(argc > 1) hasoptions = true;
  374 +}
  375 +
  376 +void
  377 +AnyOption::useFiileName( const char *_filename )
  378 +{
  379 + filename = _filename;
  380 + file_set = true;
  381 +}
  382 +
  383 +/*
  384 + * set methods for options
  385 + */
  386 +
  387 +void
  388 +AnyOption::setCommandOption( const char *opt )
  389 +{
  390 + addOption( opt , COMMAND_OPT );
  391 + g_value_counter++;
  392 +}
  393 +
  394 +void
  395 +AnyOption::setCommandOption( char opt )
  396 +{
  397 + addOption( opt , COMMAND_OPT );
  398 + g_value_counter++;
  399 +}
  400 +
  401 +void
  402 +AnyOption::setCommandOption( const char *opt , char optchar )
  403 +{
  404 + addOption( opt , COMMAND_OPT );
  405 + addOption( optchar , COMMAND_OPT );
  406 + g_value_counter++;
  407 +}
  408 +
  409 +void
  410 +AnyOption::setCommandFlag( const char *opt )
  411 +{
  412 + addOption( opt , COMMAND_FLAG );
  413 + g_value_counter++;
  414 +}
  415 +
  416 +void
  417 +AnyOption::setCommandFlag( char opt )
  418 +{
  419 + addOption( opt , COMMAND_FLAG );
  420 + g_value_counter++;
  421 +}
  422 +
  423 +void
  424 +AnyOption::setCommandFlag( const char *opt , char optchar )
  425 +{
  426 + addOption( opt , COMMAND_FLAG );
  427 + addOption( optchar , COMMAND_FLAG );
  428 + g_value_counter++;
  429 +}
  430 +
  431 +void
  432 +AnyOption::setFileOption( const char *opt )
  433 +{
  434 + addOption( opt , FILE_OPT );
  435 + g_value_counter++;
  436 +}
  437 +
  438 +void
  439 +AnyOption::setFileOption( char opt )
  440 +{
  441 + addOption( opt , FILE_OPT );
  442 + g_value_counter++;
  443 +}
  444 +
  445 +void
  446 +AnyOption::setFileOption( const char *opt , char optchar )
  447 +{
  448 + addOption( opt , FILE_OPT );
  449 + addOption( optchar, FILE_OPT );
  450 + g_value_counter++;
  451 +}
  452 +
  453 +void
  454 +AnyOption::setFileFlag( const char *opt )
  455 +{
  456 + addOption( opt , FILE_FLAG );
  457 + g_value_counter++;
  458 +}
  459 +
  460 +void
  461 +AnyOption::setFileFlag( char opt )
  462 +{
  463 + addOption( opt , FILE_FLAG );
  464 + g_value_counter++;
  465 +}
  466 +
  467 +void
  468 +AnyOption::setFileFlag( const char *opt , char optchar )
  469 +{
  470 + addOption( opt , FILE_FLAG );
  471 + addOption( optchar , FILE_FLAG );
  472 + g_value_counter++;
  473 +}
  474 +
  475 +void
  476 +AnyOption::setOption( const char *opt )
  477 +{
  478 + addOption( opt , COMMON_OPT );
  479 + g_value_counter++;
  480 +}
  481 +
  482 +void
  483 +AnyOption::setOption( char opt )
  484 +{
  485 + addOption( opt , COMMON_OPT );
  486 + g_value_counter++;
  487 +}
  488 +
  489 +void
  490 +AnyOption::setOption( const char *opt , char optchar )
  491 +{
  492 + addOption( opt , COMMON_OPT );
  493 + addOption( optchar , COMMON_OPT );
  494 + g_value_counter++;
  495 +}
  496 +
  497 +void
  498 +AnyOption::setFlag( const char *opt )
  499 +{
  500 + addOption( opt , COMMON_FLAG );
  501 + g_value_counter++;
  502 +}
  503 +
  504 +void
  505 +AnyOption::setFlag( const char opt )
  506 +{
  507 + addOption( opt , COMMON_FLAG );
  508 + g_value_counter++;
  509 +}
  510 +
  511 +void
  512 +AnyOption::setFlag( const char *opt , char optchar )
  513 +{
  514 + addOption( opt , COMMON_FLAG );
  515 + addOption( optchar , COMMON_FLAG );
  516 + g_value_counter++;
  517 +}
  518 +
  519 +void
  520 +AnyOption::addOption( const char *opt, int type )
  521 +{
  522 + if( option_counter >= max_options ){
  523 + if( doubleOptStorage() == false ){
  524 + addOptionError( opt );
  525 + return;
  526 + }
  527 + }
  528 + options[ option_counter ] = opt ;
  529 + optiontype[ option_counter ] = type ;
  530 + optionindex[ option_counter ] = g_value_counter;
  531 + option_counter++;
  532 +}
  533 +
  534 +void
  535 +AnyOption::addOption( char opt, int type )
  536 +{
  537 + if( !POSIX() ){
  538 + printVerbose("Ignoring the option character \"");
  539 + printVerbose( opt );
  540 + printVerbose( "\" ( POSIX options are turned off )" );
  541 + printVerbose();
  542 + return;
  543 + }
  544 +
  545 +
  546 + if( optchar_counter >= max_char_options ){
  547 + if( doubleCharStorage() == false ){
  548 + addOptionError( opt );
  549 + return;
  550 + }
  551 + }
  552 + optionchars[ optchar_counter ] = opt ;
  553 + optchartype[ optchar_counter ] = type ;
  554 + optcharindex[ optchar_counter ] = g_value_counter;
  555 + optchar_counter++;
  556 +}
  557 +
  558 +void
  559 +AnyOption::addOptionError( const char *opt )
  560 +{
  561 + cout << endl ;
  562 + cout << "OPTIONS ERROR : Failed allocating extra memory " << endl ;
  563 + cout << "While adding the option : \""<< opt << "\"" << endl;
  564 + cout << "Exiting." << endl ;
  565 + cout << endl ;
  566 + exit(0);
  567 +}
  568 +
  569 +void
  570 +AnyOption::addOptionError( char opt )
  571 +{
  572 + cout << endl ;
  573 + cout << "OPTIONS ERROR : Failed allocating extra memory " << endl ;
  574 + cout << "While adding the option: \""<< opt << "\"" << endl;
  575 + cout << "Exiting." << endl ;
  576 + cout << endl ;
  577 + exit(0);
  578 +}
  579 +
  580 +void
  581 +AnyOption::processOptions()
  582 +{
  583 + if( ! valueStoreOK() )
  584 + return;
  585 +}
  586 +
  587 +void
  588 +AnyOption::processCommandArgs(int max_args)
  589 +{
  590 + max_legal_args = max_args;
  591 + processCommandArgs();
  592 +}
  593 +
  594 +void
  595 +AnyOption::processCommandArgs( int _argc, char **_argv, int max_args )
  596 +{
  597 + max_legal_args = max_args;
  598 + processCommandArgs( _argc, _argv );
  599 +}
  600 +
  601 +void
  602 +AnyOption::processCommandArgs( int _argc, char **_argv )
  603 +{
  604 + useCommandArgs( _argc, _argv );
  605 + processCommandArgs();
  606 +}
  607 +
  608 +void
  609 +AnyOption::processCommandArgs()
  610 +{
  611 + if( ! ( valueStoreOK() && CommandSet() ) )
  612 + return;
  613 +
  614 + if( max_legal_args == 0 )
  615 + max_legal_args = argc;
  616 + new_argv = (int*) malloc( (max_legal_args+1) * sizeof(int) );
  617 + for( int i = 1 ; i < argc ; i++ ){/* ignore first argv */
  618 + if( argv[i][0] == long_opt_prefix[0] &&
  619 + argv[i][1] == long_opt_prefix[1] ) { /* long GNU option */
  620 + int match_at = parseGNU( argv[i]+2 ); /* skip -- */
  621 + if( match_at >= 0 && i < argc-1 ) /* found match */
  622 + setValue( options[match_at] , argv[++i] );
  623 + }else if( argv[i][0] == opt_prefix_char ) { /* POSIX char */
  624 + if( POSIX() ){
  625 + char ch = parsePOSIX( argv[i]+1 );/* skip - */
  626 + if( ch != '0' && i < argc-1 ) /* matching char */
  627 + setValue( ch , argv[++i] );
  628 + } else { /* treat it as GNU option with a - */
  629 + int match_at = parseGNU( argv[i]+1 ); /* skip - */
  630 + if( match_at >= 0 && i < argc-1 ) /* found match */
  631 + setValue( options[match_at] , argv[++i] );
  632 + }
  633 + }else { /* not option but an argument keep index */
  634 + if( new_argc < max_legal_args ){
  635 + new_argv[ new_argc ] = i ;
  636 + new_argc++;
  637 + }else{ /* ignore extra arguments */
  638 + printVerbose( "Ignoring extra argument: " );
  639 + printVerbose( argv[i] );
  640 + printVerbose( );
  641 + printAutoUsage();
  642 + }
  643 + printVerbose( "Unknown command argument option : " );
  644 + printVerbose( argv[i] );
  645 + printVerbose( );
  646 + printAutoUsage();
  647 + }
  648 + }
  649 +}
  650 +
  651 +char
  652 +AnyOption::parsePOSIX( char* arg )
  653 +{
  654 +
  655 + for( unsigned int i = 0 ; i < strlen(arg) ; i++ ){
  656 + char ch = arg[i] ;
  657 + if( matchChar(ch) ) { /* keep matching flags till an option */
  658 + /*if last char argv[++i] is the value */
  659 + if( i == strlen(arg)-1 ){
  660 + return ch;
  661 + }else{/* else the rest of arg is the value */
  662 + i++; /* skip any '=' and ' ' */
  663 + while( arg[i] == whitespace
  664 + || arg[i] == equalsign )
  665 + i++;
  666 + setValue( ch , arg+i );
  667 + return '0';
  668 + }
  669 + }
  670 + }
  671 + printVerbose( "Unknown command argument option : " );
  672 + printVerbose( arg );
  673 + printVerbose( );
  674 + printAutoUsage();
  675 + return '0';
  676 +}
  677 +
  678 +int
  679 +AnyOption::parseGNU( char *arg )
  680 +{
  681 + int split_at = 0;
  682 + /* if has a '=' sign get value */
  683 + for( unsigned int i = 0 ; i < strlen(arg) ; i++ ){
  684 + if(arg[i] == equalsign ){
  685 + split_at = i ; /* store index */
  686 + i = strlen(arg); /* get out of loop */
  687 + }
  688 + }
  689 + if( split_at > 0 ){ /* it is an option value pair */
  690 + char* tmp = (char*) malloc( (split_at+1)*sizeof(char) );
  691 + for( int i = 0 ; i < split_at ; i++ )
  692 + tmp[i] = arg[i];
  693 + tmp[split_at] = '\0';
  694 +
  695 + if ( matchOpt( tmp ) >= 0 ){
  696 + setValue( options[matchOpt(tmp)] , arg+split_at+1 );
  697 + free (tmp);
  698 + }else{
  699 + printVerbose( "Unknown command argument option : " );
  700 + printVerbose( arg );
  701 + printVerbose( );
  702 + printAutoUsage();
  703 + free (tmp);
  704 + return -1;
  705 + }
  706 + }else{ /* regular options with no '=' sign */
  707 + return matchOpt(arg);
  708 + }
  709 + return -1;
  710 +}
  711 +
  712 +
  713 +int
  714 +AnyOption::matchOpt( char *opt )
  715 +{
  716 + for( int i = 0 ; i < option_counter ; i++ ){
  717 + if( strcmp( options[i], opt ) == 0 ){
  718 + if( optiontype[i] == COMMON_OPT ||
  719 + optiontype[i] == COMMAND_OPT )
  720 + { /* found option return index */
  721 + return i;
  722 + }else if( optiontype[i] == COMMON_FLAG ||
  723 + optiontype[i] == COMMAND_FLAG )
  724 + { /* found flag, set it */
  725 + setFlagOn( opt );
  726 + return -1;
  727 + }
  728 + }
  729 + }
  730 + printVerbose( "Unknown command argument option : " );
  731 + printVerbose( opt ) ;
  732 + printVerbose( );
  733 + printAutoUsage();
  734 + return -1;
  735 +}
  736 +bool
  737 +AnyOption::matchChar( char c )
  738 +{
  739 + for( int i = 0 ; i < optchar_counter ; i++ ){
  740 + if( optionchars[i] == c ) { /* found match */
  741 + if(optchartype[i] == COMMON_OPT ||
  742 + optchartype[i] == COMMAND_OPT )
  743 + { /* an option store and stop scanning */
  744 + return true;
  745 + }else if( optchartype[i] == COMMON_FLAG ||
  746 + optchartype[i] == COMMAND_FLAG ) { /* a flag store and keep scanning */
  747 + setFlagOn( c );
  748 + return false;
  749 + }
  750 + }
  751 + }
  752 + printVerbose( "Unknown command argument option : " );
  753 + printVerbose( c ) ;
  754 + printVerbose( );
  755 + printAutoUsage();
  756 + return false;
  757 +}
  758 +
  759 +bool
  760 +AnyOption::valueStoreOK( )
  761 +{
  762 + int size= 0;
  763 + if( !set ){
  764 + if( g_value_counter > 0 ){
  765 + size = g_value_counter * sizeof(char*);
  766 + values = (char**)malloc( size );
  767 + for( int i = 0 ; i < g_value_counter ; i++)
  768 + values[i] = NULL;
  769 + set = true;
  770 + }
  771 + }
  772 + return set;
  773 +}
  774 +
  775 +/*
  776 + * public get methods
  777 + */
  778 +char*
  779 +AnyOption::getValue( const char *option )
  780 +{
  781 + if( !valueStoreOK() )
  782 + return NULL;
  783 +
  784 + for( int i = 0 ; i < option_counter ; i++ ){
  785 + if( strcmp( options[i], option ) == 0 )
  786 + return values[ optionindex[i] ];
  787 + }
  788 + return NULL;
  789 +}
  790 +
  791 +bool
  792 +AnyOption::getFlag( const char *option )
  793 +{
  794 + if( !valueStoreOK() )
  795 + return false;
  796 + for( int i = 0 ; i < option_counter ; i++ ){
  797 + if( strcmp( options[i], option ) == 0 )
  798 + return findFlag( values[ optionindex[i] ] );
  799 + }
  800 + return false;
  801 +}
  802 +
  803 +char*
  804 +AnyOption::getValue( char option )
  805 +{
  806 + if( !valueStoreOK() )
  807 + return NULL;
  808 + for( int i = 0 ; i < optchar_counter ; i++ ){
  809 + if( optionchars[i] == option )
  810 + return values[ optcharindex[i] ];
  811 + }
  812 + return NULL;
  813 +}
  814 +
  815 +bool
  816 +AnyOption::getFlag( char option )
  817 +{
  818 + if( !valueStoreOK() )
  819 + return false;
  820 + for( int i = 0 ; i < optchar_counter ; i++ ){
  821 + if( optionchars[i] == option )
  822 + return findFlag( values[ optcharindex[i] ] ) ;
  823 + }
  824 + return false;
  825 +}
  826 +
  827 +bool
  828 +AnyOption::findFlag( char* val )
  829 +{
  830 + if( val == NULL )
  831 + return false;
  832 +
  833 + if( strcmp( TRUE_FLAG , val ) == 0 )
  834 + return true;
  835 +
  836 + return false;
  837 +}
  838 +
  839 +/*
  840 + * private set methods
  841 + */
  842 +bool
  843 +AnyOption::setValue( const char *option , char *value )
  844 +{
  845 + if( !valueStoreOK() )
  846 + return false;
  847 + for( int i = 0 ; i < option_counter ; i++ ){
  848 + if( strcmp( options[i], option ) == 0 ){
  849 + values[ optionindex[i] ] = (char*) malloc((strlen(value)+1)*sizeof(char));
  850 + strcpy( values[ optionindex[i] ], value );
  851 + return true;
  852 + }
  853 + }
  854 + return false;
  855 +}
  856 +
  857 +bool
  858 +AnyOption::setFlagOn( const char *option )
  859 +{
  860 + if( !valueStoreOK() )
  861 + return false;
  862 + for( int i = 0 ; i < option_counter ; i++ ){
  863 + if( strcmp( options[i], option ) == 0 ){
  864 + values[ optionindex[i] ] = (char*) malloc((strlen(TRUE_FLAG)+1)*sizeof(char));
  865 + strcpy( values[ optionindex[i] ] , TRUE_FLAG );
  866 + return true;
  867 + }
  868 + }
  869 + return false;
  870 +}
  871 +
  872 +bool
  873 +AnyOption::setValue( char option , char *value )
  874 +{
  875 + if( !valueStoreOK() )
  876 + return false;
  877 + for( int i = 0 ; i < optchar_counter ; i++ ){
  878 + if( optionchars[i] == option ){
  879 + values[ optcharindex[i] ] = (char*) malloc((strlen(value)+1)*sizeof(char));
  880 + strcpy( values[ optcharindex[i] ], value );
  881 + return true;
  882 + }
  883 + }
  884 + return false;
  885 +}
  886 +
  887 +bool
  888 +AnyOption::setFlagOn( char option )
  889 +{
  890 + if( !valueStoreOK() )
  891 + return false;
  892 + for( int i = 0 ; i < optchar_counter ; i++ ){
  893 + if( optionchars[i] == option ){
  894 + values[ optcharindex[i] ] = (char*) malloc((strlen(TRUE_FLAG)+1)*sizeof(char));
  895 + strcpy( values[ optcharindex[i] ] , TRUE_FLAG );
  896 + return true;
  897 + }
  898 + }
  899 + return false;
  900 +}
  901 +
  902 +
  903 +int
  904 +AnyOption::getArgc( )
  905 +{
  906 + return new_argc;
  907 +}
  908 +
  909 +char*
  910 +AnyOption::getArgv( int index )
  911 +{
  912 + if( index < new_argc ){
  913 + return ( argv[ new_argv[ index ] ] );
  914 + }
  915 + return NULL;
  916 +}
  917 +
  918 +/* dotfile sub routines */
  919 +
  920 +bool
  921 +AnyOption::processFile()
  922 +{
  923 + if( ! (valueStoreOK() && FileSet()) )
  924 + return false;
  925 + return ( consumeFile(readFile()) );
  926 +}
  927 +
  928 +bool
  929 +AnyOption::processFile( const char *filename )
  930 +{
  931 + useFiileName(filename );
  932 + return ( processFile() );
  933 +}
  934 +
  935 +char*
  936 +AnyOption::readFile()
  937 +{
  938 + return ( readFile(filename) );
  939 +}
  940 +
  941 +/*
  942 + * read the file contents to a character buffer
  943 + */
  944 +
  945 +char*
  946 +AnyOption::readFile( const char* fname )
  947 +{
  948 + int length;
  949 + char *buffer;
  950 + ifstream is;
  951 + is.open ( fname , ifstream::in );
  952 + if( ! is.good() ){
  953 + is.close();
  954 + return NULL;
  955 + }
  956 + is.seekg (0, ios::end);
  957 + length = is.tellg();
  958 + is.seekg (0, ios::beg);
  959 + buffer = (char*) malloc(length*sizeof(char));
  960 + is.read (buffer,length);
  961 + is.close();
  962 + return buffer;
  963 +}
  964 +
  965 +/*
  966 + * scans a char* buffer for lines that does not
  967 + * start with the specified comment character.
  968 + */
  969 +bool
  970 +AnyOption::consumeFile( char *buffer )
  971 +{
  972 +
  973 + if( buffer == NULL )
  974 + return false;
  975 +
  976 + char *cursor = buffer;/* preserve the ptr */
  977 + char *pline = NULL ;
  978 + int linelength = 0;
  979 + bool newline = true;
  980 + for( unsigned int i = 0 ; i < strlen( buffer ) ; i++ ){
  981 + if( *cursor == endofline ) { /* end of line */
  982 + if( pline != NULL ) /* valid line */
  983 + processLine( pline, linelength );
  984 + pline = NULL;
  985 + newline = true;
  986 + }else if( newline ){ /* start of line */
  987 + newline = false;
  988 + if( (*cursor != comment ) ){ /* not a comment */
  989 + pline = cursor ;
  990 + linelength = 0 ;
  991 + }
  992 + }
  993 + cursor++; /* keep moving */
  994 + linelength++;
  995 + }
  996 + free (buffer);
  997 + return true;
  998 +}
  999 +
  1000 +
  1001 +/*
  1002 + * find a valid type value pair separated by a delimiter
  1003 + * character and pass it to valuePairs()
  1004 + * any line which is not valid will be considered a value
  1005 + * and will get passed on to justValue()
  1006 + *
  1007 + * assuming delimiter is ':' the behaviour will be,
  1008 + *
  1009 + * width:10 - valid pair valuePairs( width, 10 );
  1010 + * width : 10 - valid pair valuepairs( width, 10 );
  1011 + *
  1012 + * :::: - not valid
  1013 + * width - not valid
  1014 + * :10 - not valid
  1015 + * width: - not valid
  1016 + * :: - not valid
  1017 + * : - not valid
  1018 + *
  1019 + */
  1020 +
  1021 +void
  1022 +AnyOption::processLine( char *theline, int length )
  1023 +{
  1024 + bool found = false;
  1025 + char *pline = (char*) malloc( (length+1)*sizeof(char) );
  1026 + for( int i = 0 ; i < length ; i ++ )
  1027 + pline[i]= *(theline++);
  1028 + pline[length] = nullterminate;
  1029 + char *cursor = pline ; /* preserve the ptr */
  1030 + if( *cursor == delimiter || *(cursor+length-1) == delimiter ){
  1031 + justValue( pline );/* line with start/end delimiter */
  1032 + }else{
  1033 + for( int i = 1 ; i < length-1 && !found ; i++){/* delimiter */
  1034 + if( *cursor == delimiter ){
  1035 + *(cursor-1) = nullterminate; /* two strings */
  1036 + found = true;
  1037 + valuePairs( pline , cursor+1 );
  1038 + }
  1039 + cursor++;
  1040 + }
  1041 + cursor++;
  1042 + if( !found ) /* not a pair */
  1043 + justValue( pline );
  1044 + }
  1045 + free (pline);
  1046 +}
  1047 +
  1048 +/*
  1049 + * removes trailing and preceeding whitespaces from a string
  1050 + */
  1051 +char*
  1052 +AnyOption::chomp( char *str )
  1053 +{
  1054 + while( *str == whitespace )
  1055 + str++;
  1056 + char *end = str+strlen(str)-1;
  1057 + while( *end == whitespace )
  1058 + end--;
  1059 + *(end+1) = nullterminate;
  1060 + return str;
  1061 +}
  1062 +
  1063 +void
  1064 +AnyOption::valuePairs( char *type, char *value )
  1065 +{
  1066 + if ( strlen(chomp(type)) == 1 ){ /* this is a char option */
  1067 + for( int i = 0 ; i < optchar_counter ; i++ ){
  1068 + if( optionchars[i] == type[0] ){ /* match */
  1069 + if( optchartype[i] == COMMON_OPT ||
  1070 + optchartype[i] == FILE_OPT )
  1071 + {
  1072 + setValue( type[0] , chomp(value) );
  1073 + return;
  1074 + }
  1075 + }
  1076 + }
  1077 + }
  1078 + /* if no char options matched */
  1079 + for( int i = 0 ; i < option_counter ; i++ ){
  1080 + if( strcmp( options[i], type ) == 0 ){ /* match */
  1081 + if( optiontype[i] == COMMON_OPT ||
  1082 + optiontype[i] == FILE_OPT )
  1083 + {
  1084 + setValue( type , chomp(value) );
  1085 + return;
  1086 + }
  1087 + }
  1088 + }
  1089 + printVerbose( "Unknown option in resourcefile : " );
  1090 + printVerbose( type );
  1091 + printVerbose( );
  1092 +}
  1093 +
  1094 +void
  1095 +AnyOption::justValue( char *type )
  1096 +{
  1097 +
  1098 + if ( strlen(chomp(type)) == 1 ){ /* this is a char option */
  1099 + for( int i = 0 ; i < optchar_counter ; i++ ){
  1100 + if( optionchars[i] == type[0] ){ /* match */
  1101 + if( optchartype[i] == COMMON_FLAG ||
  1102 + optchartype[i] == FILE_FLAG )
  1103 + {
  1104 + setFlagOn( type[0] );
  1105 + return;
  1106 + }
  1107 + }
  1108 + }
  1109 + }
  1110 + /* if no char options matched */
  1111 + for( int i = 0 ; i < option_counter ; i++ ){
  1112 + if( strcmp( options[i], type ) == 0 ){ /* match */
  1113 + if( optiontype[i] == COMMON_FLAG ||
  1114 + optiontype[i] == FILE_FLAG )
  1115 + {
  1116 + setFlagOn( type );
  1117 + return;
  1118 + }
  1119 + }
  1120 + }
  1121 + printVerbose( "Unknown option in resourcefile : " );
  1122 + printVerbose( type );
  1123 + printVerbose( );
  1124 +}
  1125 +
  1126 +/*
  1127 + * usage and help
  1128 + */
  1129 +
  1130 +
  1131 +void
  1132 +AnyOption::printAutoUsage()
  1133 +{
  1134 + if( autousage ) printUsage();
  1135 +}
  1136 +
  1137 +void
  1138 +AnyOption::printUsage()
  1139 +{
  1140 +
  1141 + if( once ) {
  1142 + once = false ;
  1143 + cout << endl ;
  1144 + for( int i = 0 ; i < usage_lines ; i++ )
  1145 + cout << usage[i] << endl ;
  1146 + cout << endl ;
  1147 + }
  1148 +}
  1149 +
  1150 +
  1151 +void
  1152 +AnyOption::addUsage( const char *line )
  1153 +{
  1154 + if( usage_lines >= max_usage_lines ){
  1155 + if( doubleUsageStorage() == false ){
  1156 + addUsageError( line );
  1157 + exit(1);
  1158 + }
  1159 + }
  1160 + usage[ usage_lines ] = line ;
  1161 + usage_lines++;
  1162 +}
  1163 +
  1164 +void
  1165 +AnyOption::addUsageError( const char *line )
  1166 +{
  1167 + cout << endl ;
  1168 + cout << "OPTIONS ERROR : Failed allocating extra memory " << endl ;
  1169 + cout << "While adding the usage/help : \""<< line << "\"" << endl;
  1170 + cout << "Exiting." << endl ;
  1171 + cout << endl ;
  1172 + exit(0);
  1173 +
  1174 +}
... ...
anyoption.h 0 โ†’ 100644
  1 +++ a/anyoption.h
  1 +#ifndef _ANYOPTION_H
  2 +#define _ANYOPTION_H
  3 +
  4 +#include <iostream>
  5 +#include <fstream>
  6 +#include <stdlib.h>
  7 +#include <cstring>
  8 +
  9 +#define COMMON_OPT 1
  10 +#define COMMAND_OPT 2
  11 +#define FILE_OPT 3
  12 +#define COMMON_FLAG 4
  13 +#define COMMAND_FLAG 5
  14 +#define FILE_FLAG 6
  15 +
  16 +#define COMMAND_OPTION_TYPE 1
  17 +#define COMMAND_FLAG_TYPE 2
  18 +#define FILE_OPTION_TYPE 3
  19 +#define FILE_FLAG_TYPE 4
  20 +#define UNKNOWN_TYPE 5
  21 +
  22 +#define DEFAULT_MAXOPTS 10
  23 +#define MAX_LONG_PREFIX_LENGTH 2
  24 +
  25 +#define DEFAULT_MAXUSAGE 3
  26 +#define DEFAULT_MAXHELP 10
  27 +
  28 +#define TRUE_FLAG "true"
  29 +
  30 +using namespace std;
  31 +
  32 +class AnyOption
  33 +{
  34 +
  35 +public: /* the public interface */
  36 + AnyOption();
  37 + AnyOption(int maxoptions );
  38 + AnyOption(int maxoptions , int maxcharoptions);
  39 + ~AnyOption();
  40 +
  41 + /*
  42 + * following set methods specifies the
  43 + * special characters and delimiters
  44 + * if not set traditional defaults will be used
  45 + */
  46 +
  47 + void setCommandPrefixChar( char _prefix ); /* '-' in "-w" */
  48 + void setCommandLongPrefix( char *_prefix ); /* '--' in "--width" */
  49 + void setFileCommentChar( char _comment ); /* '#' in shellscripts */
  50 + void setFileDelimiterChar( char _delimiter );/* ':' in "width : 100" */
  51 +
  52 + /*
  53 + * provide the input for the options
  54 + * like argv[] for commndline and the
  55 + * option file name to use;
  56 + */
  57 +
  58 + void useCommandArgs( int _argc, char **_argv );
  59 + void useFiileName( const char *_filename );
  60 +
  61 + /*
  62 + * turn off the POSIX style options
  63 + * this means anything starting with a '-' or "--"
  64 + * will be considered a valid option
  65 + * which alo means you cannot add a bunch of
  66 + * POIX options chars together like "-lr" for "-l -r"
  67 + *
  68 + */
  69 +
  70 + void noPOSIX();
  71 +
  72 + /*
  73 + * prints warning verbose if you set anything wrong
  74 + */
  75 + void setVerbose();
  76 +
  77 +
  78 + /*
  79 + * there are two types of options
  80 + *
  81 + * Option - has an associated value ( -w 100 )
  82 + * Flag - no value, just a boolean flag ( -nogui )
  83 + *
  84 + * the options can be either a string ( GNU style )
  85 + * or a character ( traditional POSIX style )
  86 + * or both ( --width, -w )
  87 + *
  88 + * the options can be common to the commandline and
  89 + * the optionfile, or can belong only to either of
  90 + * commandline and optionfile
  91 + *
  92 + * following set methods, handle all the aboove
  93 + * cases of options.
  94 + */
  95 +
  96 + /* options comman to command line and option file */
  97 + void setOption( const char *opt_string );
  98 + void setOption( char opt_char );
  99 + void setOption( const char *opt_string , char opt_char );
  100 + void setFlag( const char *opt_string );
  101 + void setFlag( char opt_char );
  102 + void setFlag( const char *opt_string , char opt_char );
  103 +
  104 + /* options read from commandline only */
  105 + void setCommandOption( const char *opt_string );
  106 + void setCommandOption( char opt_char );
  107 + void setCommandOption( const char *opt_string , char opt_char );
  108 + void setCommandFlag( const char *opt_string );
  109 + void setCommandFlag( char opt_char );
  110 + void setCommandFlag( const char *opt_string , char opt_char );
  111 +
  112 + /* options read from an option file only */
  113 + void setFileOption( const char *opt_string );
  114 + void setFileOption( char opt_char );
  115 + void setFileOption( const char *opt_string , char opt_char );
  116 + void setFileFlag( const char *opt_string );
  117 + void setFileFlag( char opt_char );
  118 + void setFileFlag( const char *opt_string , char opt_char );
  119 +
  120 + /*
  121 + * process the options, registerd using
  122 + * useCommandArgs() and useFileName();
  123 + */
  124 + void processOptions();
  125 + void processCommandArgs();
  126 + void processCommandArgs( int max_args );
  127 + bool processFile();
  128 +
  129 + /*
  130 + * process the specified options
  131 + */
  132 + void processCommandArgs( int _argc, char **_argv );
  133 + void processCommandArgs( int _argc, char **_argv, int max_args );
  134 + bool processFile( const char *_filename );
  135 +
  136 + /*
  137 + * get the value of the options
  138 + * will return NULL if no value is set
  139 + */
  140 + char *getValue( const char *_option );
  141 + bool getFlag( const char *_option );
  142 + char *getValue( char _optchar );
  143 + bool getFlag( char _optchar );
  144 +
  145 + /*
  146 + * Print Usage
  147 + */
  148 + void printUsage();
  149 + void printAutoUsage();
  150 + void addUsage( const char *line );
  151 + void printHelp();
  152 + /* print auto usage printing for unknown options or flag */
  153 + void autoUsagePrint(bool flag);
  154 +
  155 + /*
  156 + * get the argument count and arguments sans the options
  157 + */
  158 + int getArgc();
  159 + char* getArgv( int index );
  160 + bool hasOptions();
  161 +
  162 +private: /* the hidden data structure */
  163 + int argc; /* commandline arg count */
  164 + char **argv; /* commndline args */
  165 + const char* filename; /* the option file */
  166 + char* appname; /* the application name from argv[0] */
  167 +
  168 + int *new_argv; /* arguments sans options (index to argv) */
  169 + int new_argc; /* argument count sans the options */
  170 + int max_legal_args; /* ignore extra arguments */
  171 +
  172 +
  173 + /* option strings storage + indexing */
  174 + int max_options; /* maximum number of options */
  175 + const char **options; /* storage */
  176 + int *optiontype; /* type - common, command, file */
  177 + int *optionindex; /* index into value storage */
  178 + int option_counter; /* counter for added options */
  179 +
  180 + /* option chars storage + indexing */
  181 + int max_char_options; /* maximum number options */
  182 + char *optionchars; /* storage */
  183 + int *optchartype; /* type - common, command, file */
  184 + int *optcharindex; /* index into value storage */
  185 + int optchar_counter; /* counter for added options */
  186 +
  187 + /* values */
  188 + char **values; /* common value storage */
  189 + int g_value_counter; /* globally updated value index LAME! */
  190 +
  191 + /* help and usage */
  192 + const char **usage; /* usage */
  193 + int max_usage_lines; /* max usage lines reseverd */
  194 + int usage_lines; /* number of usage lines */
  195 +
  196 + bool command_set; /* if argc/argv were provided */
  197 + bool file_set; /* if a filename was provided */
  198 + bool mem_allocated; /* if memory allocated in init() */
  199 + bool posix_style; /* enables to turn off POSIX style options */
  200 + bool verbose; /* silent|verbose */
  201 + bool print_usage; /* usage verbose */
  202 + bool print_help; /* help verbose */
  203 +
  204 + char opt_prefix_char; /* '-' in "-w" */
  205 + char long_opt_prefix[MAX_LONG_PREFIX_LENGTH + 1]; /* '--' in "--width" */
  206 + char file_delimiter_char; /* ':' in width : 100 */
  207 + char file_comment_char; /* '#' in "#this is a comment" */
  208 + char equalsign;
  209 + char comment;
  210 + char delimiter;
  211 + char endofline;
  212 + char whitespace;
  213 + char nullterminate;
  214 +
  215 + bool set; //was static member
  216 + bool once; //was static member
  217 +
  218 + bool hasoptions;
  219 + bool autousage;
  220 +
  221 +private: /* the hidden utils */
  222 + void init();
  223 + void init(int maxopt, int maxcharopt );
  224 + bool alloc();
  225 + void cleanup();
  226 + bool valueStoreOK();
  227 +
  228 + /* grow storage arrays as required */
  229 + bool doubleOptStorage();
  230 + bool doubleCharStorage();
  231 + bool doubleUsageStorage();
  232 +
  233 + bool setValue( const char *option , char *value );
  234 + bool setFlagOn( const char *option );
  235 + bool setValue( char optchar , char *value);
  236 + bool setFlagOn( char optchar );
  237 +
  238 + void addOption( const char* option , int type );
  239 + void addOption( char optchar , int type );
  240 + void addOptionError( const char *opt);
  241 + void addOptionError( char opt);
  242 + bool findFlag( char* value );
  243 + void addUsageError( const char *line );
  244 + bool CommandSet();
  245 + bool FileSet();
  246 + bool POSIX();
  247 +
  248 + char parsePOSIX( char* arg );
  249 + int parseGNU( char *arg );
  250 + bool matchChar( char c );
  251 + int matchOpt( char *opt );
  252 +
  253 + /* dot file methods */
  254 + char *readFile();
  255 + char *readFile( const char* fname );
  256 + bool consumeFile( char *buffer );
  257 + void processLine( char *theline, int length );
  258 + char *chomp( char *str );
  259 + void valuePairs( char *type, char *value );
  260 + void justValue( char *value );
  261 +
  262 + void printVerbose( const char *msg );
  263 + void printVerbose( char *msg );
  264 + void printVerbose( char ch );
  265 + void printVerbose( );
  266 +
  267 +
  268 +};
  269 +
  270 +#endif /* ! _ANYOPTION_H */
... ...
loop_proxy_GT.obj 0 โ†’ 100644
  1 +++ a/loop_proxy_GT.obj
  1 +v 187 414 0
  2 +v 405 293 0
  3 +v 397 413 0
  4 +v 483 496 0
  5 +v 689 591 0
  6 +v 801 705 0
  7 +v 496 677 0
  8 +v 187 293 0
  9 +v 290 226 0
  10 +v 288 462 0
  11 +v 405 293 0
  12 +v 468 232 0
  13 +v 572 228 0
  14 +v 602 303 0
  15 +v 594 432 0
  16 +v 397 413 0
  17 +v 698 466 0
  18 +v 810 415 0
  19 +v 906 484 0
  20 +v 902 608 0
  21 +v 689 591 0
  22 +v 493 561 0
  23 +v 403 510 0
  24 +v 307 597 0
  25 +v 305 708 0
  26 +v 410 758 0
  27 +l 1 8 9 2
  28 +l 1 10 3
  29 +l 2 11 3
  30 +l 2 12 13 14 15 4
  31 +l 3 16 4
  32 +l 4 5
  33 +l 5 17 18 19 20 6
  34 +l 5 21 6
  35 +l 6 7
  36 +l 7 22 23 24 25 26 7
... ...
loop_proxy_T.obj 0 โ†’ 100644
  1 +++ a/loop_proxy_T.obj
  1 +v 186 412 0
  2 +v 185 294 0
  3 +v 123 233 0
  4 +v 343 257 0
  5 +v 361 268 0
  6 +v 404 293 0
  7 +v 401 337 0
  8 +v 396 413 0
  9 +v 308 335 0
  10 +v 443 459 0
  11 +v 591 430 0
  12 +v 514 510 0
  13 +v 801 704 0
  14 +v 497 675 0
  15 +v 438 731 0
  16 +v 291 227 0
  17 +v 287 461 0
  18 +v 467 232 0
  19 +v 571 228 0
  20 +v 600 302 0
  21 +v 690 589 0
  22 +v 699 468 0
  23 +v 905 484 0
  24 +v 900 609 0
  25 +v 497 675 0
  26 +v 424 533 0
  27 +v 306 597 0
  28 +v 304 705 0
  29 +l 1 2
  30 +l 2 3
  31 +l 2 16 4
  32 +l 5 6
  33 +l 6 7
  34 +l 7 8
  35 +l 7 9
  36 +l 8 17 1
  37 +l 8 10
  38 +l 6 18 19 20 11
  39 +l 12 21 22 23 24 13
  40 +l 14 25 13
  41 +l 14 26 27 28 15
... ...
molecule_GT.obj 0 โ†’ 100644
  1 +++ a/molecule_GT.obj
  1 +v 79 265 0
  2 +v 138 305 0
  3 +v 249 374 0
  4 +v 197 417 0
  5 +v 197 490 0
  6 +v 278 545 0
  7 +v 126 445 0
  8 +v 193 598 0
  9 +v 324 377 0
  10 +v 358 317 0
  11 +v 361 436 0
  12 +v 468 512 0
  13 +v 554 569 0
  14 +v 608 718 0
  15 +v 633 511 0
  16 +v 742 512 0
  17 +v 794 551 0
  18 +v 869 493 0
  19 +v 728 600 0
  20 +v 872 608 0
  21 +v 466 238 0
  22 +v 551 173 0
  23 +v 611 32 0
  24 +v 633 237 0
  25 +v 741 237 0
  26 +v 796 198 0
  27 +v 729 150 0
  28 +v 870 140 0
  29 +v 872 260 0
  30 +v 195 264 0
  31 +v 250 302 0
  32 +v 143 381 0
  33 +v 416 396 0
  34 +v 468 433 0
  35 +v 414 551 0
  36 +v 361 516 0
  37 +v 545 673 0
  38 +v 635 433 0
  39 +v 688 395 0
  40 +v 741 431 0
  41 +v 685 548 0
  42 +v 409 355 0
  43 +v 465 320 0
  44 +v 358 238 0
  45 +v 410 199 0
  46 +v 549 74 0
  47 +v 684 203 0
  48 +v 632 319 0
  49 +v 685 356 0
  50 +v 743 316 0
  51 +l 1 2
  52 +l 2 30 31 3
  53 +l 3 4
  54 +l 4 32 2
  55 +l 4 5
  56 +l 5 6
  57 +l 5 7
  58 +l 5 8
  59 +l 3 9
  60 +l 9 10
  61 +l 9 11
  62 +l 11 33 34 12
  63 +l 12 35 36 11
  64 +l 12 13
  65 +l 13 37 14
  66 +l 13 15
  67 +l 15 38 39 40 16
  68 +l 16 41 15
  69 +l 16 17
  70 +l 17 18
  71 +l 17 19
  72 +l 17 20
  73 +l 10 42 43 21
  74 +l 10 44 45 21
  75 +l 21 22
  76 +l 22 46 23
  77 +l 22 24
  78 +l 24 47 25
  79 +l 24 48 49 50 25
  80 +l 25 26
  81 +l 26 27
  82 +l 26 28
  83 +l 26 29
... ...
molecule_T.obj 0 โ†’ 100644
  1 +++ a/molecule_T.obj
  1 +v 137 306 0
  2 +v 75 304 0
  3 +v 249 373 0
  4 +v 197 417 0
  5 +v 279 545 0
  6 +v 126 444 0
  7 +v 193 596 0
  8 +v 324 377 0
  9 +v 335 355 0
  10 +v 359 316 0
  11 +v 347 333 0
  12 +v 466 239 0
  13 +v 550 172 0
  14 +v 611 32 0
  15 +v 632 237 0
  16 +v 633 319 0
  17 +v 741 237 0
  18 +v 688 354 0
  19 +v 870 140 0
  20 +v 729 151 0
  21 +v 872 258 0
  22 +v 362 435 0
  23 +v 469 511 0
  24 +v 634 510 0
  25 +v 609 715 0
  26 +v 547 627 0
  27 +v 633 431 0
  28 +v 688 393 0
  29 +v 742 511 0
  30 +v 794 550 0
  31 +v 871 493 0
  32 +v 871 606 0
  33 +v 728 599 0
  34 +v 249 302 0
  35 +v 142 379 0
  36 +v 197 453 0
  37 +v 207 479 0
  38 +v 224 507 0
  39 +v 159 465 0
  40 +v 180 492 0
  41 +v 195 519 0
  42 +v 382 221 0
  43 +v 466 318 0
  44 +v 412 353 0
  45 +v 570 83 0
  46 +v 686 202 0
  47 +v 739 317 0
  48 +v 443 414 0
  49 +v 415 550 0
  50 +v 362 516 0
  51 +v 509 537 0
  52 +v 547 553 0
  53 +v 580 548 0
  54 +v 567 690 0
  55 +v 545 666 0
  56 +v 741 431 0
  57 +v 687 547 0
  58 +v 688 393 0
  59 +l 1 2
  60 +l 1 34 3
  61 +l 3 4
  62 +l 4 35 1
  63 +l 4 36 37 38 5
  64 +l 6 39 40 41 7
  65 +l 3 8
  66 +l 8 9
  67 +l 10 11
  68 +l 10 42 12
  69 +l 12 43 44 10
  70 +l 12 13
  71 +l 13 45 14
  72 +l 13 15
  73 +l 15 16
  74 +l 15 46 17
  75 +l 17 47 18
  76 +l 17 19
  77 +l 20 21
  78 +l 8 22
  79 +l 22 48 23
  80 +l 23 49 50 22
  81 +l 23 51 52 53 24
  82 +l 25 54 55 26
  83 +l 24 27
  84 +l 28 56 29
  85 +l 29 57 24
  86 +l 29 30
  87 +l 30 31
  88 +l 30 32
  89 +l 30 33
  90 +l 28 58 18
... ...
rts/CHECK_OPENGL_ERROR.h 0 โ†’ 100644
  1 +++ a/rts/CHECK_OPENGL_ERROR.h
  1 +#ifndef RTS_OPENGL_ERROR
  2 +#define RTS_OPENGL_ERROR
  3 +
  4 +#include <stdio.h>
  5 +#include <GL/gl.h>
  6 +#include <GL/glu.h>
  7 +
  8 +#define CHECK_OPENGL_ERROR \
  9 +{ GLenum error; \
  10 + while ( (error = glGetError()) != GL_NO_ERROR) { \
  11 + printf( "OpenGL ERROR: %s\nCHECK POINT: %s (line %d)\n", gluErrorString(error), __FILE__, __LINE__ ); \
  12 + } \
  13 +}
  14 +
  15 +#endif
0 16 \ No newline at end of file
... ...
rts/objJedi.h 0 โ†’ 100644
  1 +++ a/rts/objJedi.h
  1 +#ifndef OBJJEDI_H
  2 +#define OBJJEDI_H
  3 +
  4 +/*OBJ reader and writer.
  5 +
  6 +One aspect of the writer is based on OpenGL output commands. You can send OpenGL commands
  7 +(replacing "gl" and "GL" with "obj" and "OBJ" respectively to render to an Wavefront OBJ file
  8 +*/
  9 +
  10 +//#include "rtsMath.h"
  11 +#include "rtsLinearAlgebra.h"
  12 +#include <vector>
  13 +#include <fstream>
  14 +#include <iostream>
  15 +#include <string.h>
  16 +#include <stdlib.h>
  17 +using namespace std;
  18 +
  19 +//masks for valid vertex components
  20 +#define OBJ_V_X 0x1
  21 +#define OBJ_V_Y 0x2
  22 +#define OBJ_V_Z 0x4
  23 +#define OBJ_V_W 0x8
  24 +
  25 +#define OBJ_VT_U 0x1
  26 +#define OBJ_VT_V 0x2
  27 +#define OBJ_VT_W 0x4
  28 +
  29 +#define OBJ_VN_I 0x1
  30 +#define OBJ_VN_J 0x2
  31 +#define OBJ_VN_K 0x4
  32 +
  33 +#define OBJ_V 0x1
  34 +#define OBJ_VT 0x2
  35 +#define OBJ_VN 0x4
  36 +
  37 +//primitive types
  38 +typedef unsigned char primitive_type;
  39 +
  40 +#define OBJ_END 0x0
  41 +#define OBJ_POINTS 0x1
  42 +#define OBJ_LINES 0x2
  43 +#define OBJ_FACE 0x3
  44 +
  45 +
  46 +#define OBJ_INVALID ULONG_MAX
  47 +//define the point structures
  48 +struct vertex_position{float x,y,z,w; unsigned char mask;};
  49 +struct vertex_texture{float u,v,w; unsigned char mask;};
  50 +struct vertex_normal{float i,j,k; unsigned char mask;};
  51 +//the point structure contains indices to the relative 3-vectors in the lists
  52 +struct vertex
  53 +{
  54 + unsigned int v;
  55 + unsigned int vt;
  56 + unsigned int vn;
  57 +};
  58 +
  59 +struct primitive
  60 +{
  61 + vector<vertex> p; //indices to the point
  62 + unsigned char mask; //mask describing which features (v, vt, vn) are used
  63 + primitive_type type; //the type of primitive (points, lines, face)
  64 +};
  65 +
  66 +//axis-aligned bounding box
  67 +struct AABB
  68 +{
  69 + vertex_position min;
  70 + vertex_position max;
  71 +};
  72 +
  73 +//create variable types
  74 +typedef unsigned int OBJint;
  75 +
  76 +//define the OBJ data class
  77 +class rtsOBJ
  78 +{
  79 +private:
  80 +
  81 + /*Current state variables. These variables are committed to the OBJ object
  82 + when a vertex is added. However, we are careful to only add them once (if they don't
  83 + change with every vertex.
  84 + */
  85 + vertex_texture current_vt;
  86 + vertex_normal current_vn;
  87 + bool vt_changed; //true if a new vt or vn was inserted since the last vertex
  88 + bool vn_changed;
  89 + unsigned char current_primitive_mask; //defines what coordinates are being used by the current primitive
  90 + //global variable storing the current render mode
  91 + OBJint g_CurrentMode;
  92 + //output file stream
  93 + ofstream g_objFile;
  94 + //obj file object
  95 + //objData g_OBJ;
  96 + //number of vertices since the last BEGIN
  97 + unsigned int g_NumVertices;
  98 + /*Attribute mask. This indicates what attributes are stored for each vertex.
  99 + Only a single mask applies to each vertex between objBegin() and objEnd(). The
  100 + attribute mask is flipped the first time an attribute is set but it is fixed after
  101 + the first vertex is passed.*/
  102 + unsigned char g_AttributeMask;
  103 + /*Attribute reset mask. This indicates whether or not an attribute has been
  104 + reset since the last vertex was rendered. This applies to OBJ_VT and OBJ_VN*/
  105 + unsigned char g_AttributeResetMask;
  106 + //latest texture coordinate sent
  107 + unsigned int g_LatestVT;
  108 + //latest vertex normal sent
  109 + unsigned int g_LatestVN;
  110 +
  111 + //extents of the points in the OBJ file
  112 + AABB m_bounds;
  113 +
  114 + OBJint f_InsertPointVertex();
  115 + OBJint f_InsertLineVertex();
  116 + OBJint f_InsertLineLoopVertex();
  117 + OBJint f_InsertLineStripVertex();
  118 + OBJint f_InsertTriangleVertex();
  119 + OBJint f_InsertTriangleStripVertex();
  120 + OBJint f_InsertTriangleFanVertex();
  121 + OBJint f_InsertQuadVertex();
  122 + OBJint f_InsertQuadStripVertex();
  123 + OBJint f_InsertPolygonVertex();
  124 + OBJint f_InsertPreviousFaceVertex(unsigned int v_index);
  125 + OBJint f_InsertFirstFaceVertex(unsigned int v_index);
  126 + OBJint f_InsertNewFaceVertex();
  127 + OBJint f_InsertNewLineVertex();
  128 + OBJint f_CreateNewFace();
  129 + OBJint f_CreateNewLine();
  130 + OBJint f_TerminateLineLoop();
  131 + OBJint f_LoadOBJ(const char* filename);
  132 + OBJint f_LoadSWC(const char* filename);
  133 +
  134 + //insert coordinate commands
  135 + //these are used to handle coordinates of different dimensions (and are called by the associated public function)
  136 + OBJint f_InsertVertexf(float x, float y, float z, float w, unsigned char mask);
  137 + OBJint f_InsertTexCoordf(float u, float v, float w, unsigned char mask);
  138 + OBJint f_InsertNormalf(float i, float j, float k, unsigned char mask);
  139 + //output functions
  140 + void f_OutputVertices();
  141 + void f_OutputPoints();
  142 + void f_OutputLines();
  143 + void f_OutputFaces();
  144 + void f_OutputVertexNormals();
  145 + void f_OutputTextureCoordinates();
  146 + void f_ClearAll();
  147 +
  148 + //methods for reading from a file
  149 + OBJint f_ReadPosition(ifstream &infile);
  150 + OBJint f_ReadNormal(ifstream &infile);
  151 + OBJint f_ReadTexCoord(ifstream &infile);
  152 + OBJint f_ReadVertex(ifstream &infile, vertex &new_point, unsigned char &mask);
  153 + OBJint f_ReadPrimitive(ifstream &infile, primitive_type type);
  154 + OBJint f_AdjustExtents(vertex_position v);
  155 +
  156 +public:
  157 + /*These vectors store the vertex and primitive data from the obj file.
  158 + All vertices, texture coordinates, and normals are stored in m_v, m_vt, m_vn
  159 + respectively. The vectors for each primitive store an index into m_v, m_vt,
  160 + and m_vn identifying the associated coordinate. Basically, the data is stored
  161 + in a structure very similar to the OBJ file itself.
  162 + */
  163 + vector<vertex_position> v_list;
  164 + vector<vertex_texture> vt_list;
  165 + vector<vertex_normal> vn_list;
  166 + vector<primitive> primitives;
  167 +
  168 + vector<unsigned int> points;
  169 + vector<unsigned int> lines;
  170 + vector<unsigned int> faces;
  171 +
  172 +public:
  173 +
  174 + OBJint objOpen(const char* filename);
  175 + OBJint objBegin(OBJint obj_mode);
  176 + OBJint objEnd();
  177 + OBJint objClose();
  178 + OBJint objNormal3f(float i, float j, float k);
  179 + OBJint objNormal2f(float i, float j);
  180 + OBJint objNormal1f(float i);
  181 + OBJint objTexCoord3f(float u, float v, float w);
  182 + OBJint objTexCoord2f(float u, float v);
  183 + OBJint objTexCoord1f(float u);
  184 + OBJint objVertex1f(float x);
  185 + OBJint objVertex2f(float x, float y);
  186 + OBJint objVertex3f(float x, float y, float z);
  187 + OBJint objVertex4f(float x, float y, float z, float w);
  188 + OBJint LoadFile(const char* filename);
  189 + OBJint SaveFile(const char* filename);
  190 +
  191 + //direct insertion methods
  192 + void insertVertexPosition(float x, float y, float z, unsigned char mask = OBJ_V_X | OBJ_V_Y | OBJ_V_Z);
  193 + void insertLine(unsigned int num_points, unsigned int* pointlist, unsigned int* normallist, unsigned int* texturelist);
  194 +
  195 + //get methods
  196 + unsigned int getNumVertices();
  197 + unsigned int getNumLines();
  198 + unsigned int getNumFaces();
  199 + unsigned int getNumPointLists();
  200 + unsigned int getNumTexCoords();
  201 + unsigned int getNumNormals();
  202 +
  203 + //these functions return the coordinate index as well as the value
  204 + unsigned int getNumFaceVertices(unsigned int face);
  205 + unsigned int getFaceVertex(unsigned int face, unsigned int vertex);
  206 + unsigned int getFaceNormal(unsigned int face, unsigned int normal);
  207 + unsigned int getFaceTexCoord(unsigned int face, unsigned int texcoord);
  208 + unsigned int getNumLineVertices(unsigned int line);
  209 + unsigned int getLineVertex(unsigned int line, unsigned int vertex);
  210 + unsigned int getLineTexCoord(unsigned int line, unsigned int texcoord);
  211 + point3D<float> getVertex3d(unsigned int index);
  212 + point3D<float> getTexCoord3d(unsigned int index);
  213 + point3D<float> getNormal3d(unsigned int index);
  214 + vertex_position getVertex(unsigned int index);
  215 + vertex_texture getTexCoord(unsigned int index);
  216 + vertex_normal getNormal(unsigned int index);
  217 + AABB getBoundingBox(){return m_bounds;}
  218 + void Scale(float scale_x, float scale_y, float scale_z);
  219 + void Translate(float trans_x, float trans_y, float trans_z);
  220 +
  221 + float GetDistance(float x, float y, float z);
  222 +
  223 + //return data about primitives
  224 + unsigned int getPrimitiveType(unsigned int primitive);
  225 +
  226 + //constructors
  227 + rtsOBJ();
  228 + void CopyOBJ(const rtsOBJ& obj);
  229 + //assignment
  230 + rtsOBJ& operator=(const rtsOBJ& obj)
  231 + {
  232 + CopyOBJ(obj);
  233 + return *this;
  234 + }
  235 + //copy
  236 + rtsOBJ(const rtsOBJ& obj)
  237 + {
  238 + CopyOBJ(obj);
  239 + //return *this;
  240 + }
  241 +
  242 +
  243 +
  244 + //Iterator stuff
  245 + class iterator
  246 + {
  247 + friend class rtsOBJ;
  248 + private:
  249 + rtsOBJ* obj;
  250 + bool end_primitive;
  251 + bool end_object;
  252 + unsigned int primitive_index;
  253 + public:
  254 + unsigned int operator*();
  255 + void operator++();
  256 + bool operator==(rtsOBJ::iterator operand);
  257 + bool operator!=(rtsOBJ::iterator operand);
  258 + unsigned int size(){return obj->primitives[primitive_index].p.size();};
  259 + void print();
  260 + };
  261 +
  262 + iterator begin();
  263 + iterator end();
  264 +};
  265 +
  266 +//define error codes
  267 +#define OBJ_OK 0x0100
  268 +#define OBJ_ERROR 0x0101
  269 +
  270 +//define the different modes
  271 +#define OBJ_NONE 0x0
  272 +#define OBJ_POINTS 0x1
  273 +#define OBJ_LINES 0x2
  274 +#define OBJ_LINE_STRIP 0x3
  275 +#define OBJ_LINE_LOOP 0x4
  276 +#define OBJ_TRIANGLES 0x5
  277 +#define OBJ_TRIANGLE_STRIP 0x6
  278 +#define OBJ_TRIANGLE_FAN 0x7
  279 +#define OBJ_QUADS 0x8
  280 +#define OBJ_QUAD_STRIP 0x9
  281 +#define OBJ_POLYGON 0x10
  282 +
  283 +
  284 +
  285 +
  286 +
  287 +
  288 +//initialize the OBJ file
  289 +OBJint objOpen(char* filename);
  290 +//close the obj file
  291 +OBJint objClose();
  292 +
  293 +//start rendering in a certain mode
  294 +OBJint objBegin(OBJint mode);
  295 +//stop the current rendering sequence
  296 +OBJint objEnd(void);
  297 +//render a vertex to the file
  298 +OBJint objVertex1f(float x);
  299 +OBJint objVertex2f(float x, float y);
  300 +OBJint objVertex3f(float x, float y, float z);
  301 +OBJint objVertex4f(float x, float y, float z, float w);
  302 +//set a normal vector for a vertex
  303 +OBJint objNormal3f(float i, float j, float k);
  304 +OBJint objNormal2f(float i, float j);
  305 +OBJint objNormal1f(float i);
  306 +//set a texture coordinate for a vertex
  307 +OBJint objTexCoord3f(float u, float v, float w);
  308 +OBJint objTexCoord2f(float u, float v);
  309 +OBJint objTexCoord1f(float u);
  310 +
  311 +//global variable for global functions
  312 +extern rtsOBJ g_OBJ;
  313 +
  314 +/*BUG NOTES
  315 +The standard function calls for inserting vertices don't work anymore. I've fixed points
  316 +but everything beyond that has to be updated.
  317 +*/
  318 +
  319 +#include "objJedi.h"
  320 +#include "rtsVector3d.h"
  321 +#include "rtsPoint3d.h"
  322 +#include <string>
  323 +//variable for use in global functions
  324 +rtsOBJ g_OBJ;
  325 +
  326 +/********UTILITY METHODS*******************************/
  327 +void rtsOBJ::Scale(float scale_x, float scale_y, float scale_z)
  328 +{
  329 + vector<vertex_position>::iterator i;
  330 + for(i = v_list.begin(); i!= v_list.end(); i++)
  331 + {
  332 + (*i).x *= scale_x;
  333 + (*i).y *= scale_y;
  334 + (*i).z *= scale_z;
  335 + }
  336 +}
  337 +
  338 +void rtsOBJ::Translate(float trans_x, float trans_y, float trans_z)
  339 +{
  340 + vector<vertex_position>::iterator i;
  341 + for(i = v_list.begin(); i!= v_list.end(); i++)
  342 + {
  343 + (*i).x += trans_x;
  344 + (*i).y += trans_y;
  345 + (*i).z += trans_z;
  346 + }
  347 +
  348 +}
  349 +
  350 +float rtsOBJ::GetDistance(float x, float y, float z)
  351 +{
  352 + //gets the distance between the specified point and the nearest surface of the OBJ
  353 + //currently only works for lines
  354 +
  355 + //cout<<"Primitives: "<<primitives.size()<<endl;
  356 + unsigned int num_primitives = primitives.size();
  357 + point3D<float> p0, p1, p2;
  358 + float min_dist = 255;
  359 + float dist;
  360 + unsigned int p, l;
  361 + vector3D<float> v, w;
  362 + float c1, c2, b;
  363 + point3D<float> Pb;
  364 +
  365 + //for each line
  366 + for(l=0; l<num_primitives; l++)
  367 + {
  368 + if(primitives[l].type & OBJ_LINES)
  369 + {
  370 + //for each point
  371 + for(p = 1; p<primitives[l].p.size(); p++)
  372 + {
  373 +
  374 + vertex_position v1 = v_list[primitives[l].p[p-1].v];
  375 + vertex_position v2 = v_list[primitives[l].p[p].v];
  376 + p1.x = v1.x;
  377 + p1.y = v1.y;
  378 + p1.z = v1.z;
  379 + p2.x = v2.x;
  380 + p2.y = v2.y;
  381 + p2.z = v2.z;
  382 +
  383 + p0.x = x;
  384 + p0.y = y;
  385 + p0.z = z;
  386 +
  387 + v = p2 - p1;
  388 + w = p0 - p1;
  389 + if((c1 = w*v) <= 0)
  390 + dist = (p1 - p0).Length();
  391 + else if((c2 = v*v) <= c1)
  392 + dist = (p2 - p0).Length();
  393 + else
  394 + {
  395 + b = c1/c2;
  396 + Pb = p1 + b*v;
  397 + dist = (Pb - p0).Length();
  398 + }
  399 + if(dist < min_dist)
  400 + min_dist = dist;
  401 +
  402 +
  403 +
  404 + }
  405 + }
  406 + }
  407 + //cout<<"---------------------------------------------"<<endl;
  408 +
  409 + return min_dist;
  410 +
  411 +
  412 +}
  413 +
  414 +/********CLASS METHOD DEFINITIONS**********************/
  415 +//constructors
  416 +
  417 +//constructor
  418 +rtsOBJ::rtsOBJ()
  419 +{
  420 + g_CurrentMode = OBJ_NONE;
  421 + g_NumVertices = 0;
  422 + g_AttributeMask = 0x0;
  423 + g_AttributeResetMask = 0x0;
  424 + g_LatestVT = 0;
  425 + g_LatestVN = 0;
  426 +
  427 + m_bounds.min.x = m_bounds.min.y = m_bounds.min.z = 99999;
  428 + m_bounds.max.x = m_bounds.max.y = m_bounds.max.z = -99999;
  429 +
  430 + current_primitive_mask = 0x0;
  431 +}
  432 +
  433 +void rtsOBJ::CopyOBJ(const rtsOBJ& obj)
  434 +{
  435 + current_vt = obj.current_vt;
  436 + current_vn = obj.current_vn;
  437 + vt_changed = obj.vt_changed; //true if a new vt or vn was inserted since the last vertex
  438 + vn_changed = obj.vn_changed;
  439 + current_primitive_mask = obj.current_primitive_mask; //defines what coordinates are being used by the current primitive
  440 + //global variable storing the current render mode
  441 + g_CurrentMode = obj.g_CurrentMode;
  442 + //output file stream
  443 + //g_objFile = obj.g_objFile;
  444 + //obj file object
  445 + //objData g_OBJ;
  446 + //number of vertices since the last BEGIN
  447 + g_NumVertices = obj.g_NumVertices;
  448 + /*Attribute mask. This indicates what attributes are stored for each vertex.
  449 + Only a single mask applies to each vertex between objBegin() and objEnd(). The
  450 + attribute mask is flipped the first time an attribute is set but it is fixed after
  451 + the first vertex is passed.*/
  452 + g_AttributeMask = obj.g_AttributeMask;
  453 + /*Attribute reset mask. This indicates whether or not an attribute has been
  454 + reset since the last vertex was rendered. This applies to OBJ_VT and OBJ_VN*/
  455 + g_AttributeResetMask = obj.g_AttributeResetMask;
  456 + //latest texture coordinate sent
  457 + g_LatestVT = obj.g_LatestVT;
  458 + //latest vertex normal sent
  459 + g_LatestVN = obj.g_LatestVN;
  460 + m_bounds = obj.m_bounds;
  461 +
  462 +
  463 + v_list = obj.v_list;
  464 + vt_list = obj.vt_list;
  465 + vn_list = obj.vn_list;
  466 + primitives = obj.primitives;
  467 +
  468 + points = obj.points;
  469 + lines = obj.lines;
  470 + faces = obj.faces;
  471 +}
  472 +
  473 +//opens an obj file for rendering
  474 +OBJint rtsOBJ::objOpen(const char* filename)
  475 +{
  476 + g_objFile.open(filename);
  477 + return OBJ_OK;
  478 +}
  479 +
  480 +//close the obj file
  481 +OBJint rtsOBJ::objClose()
  482 +{
  483 + //TODO: write obj data
  484 + f_OutputVertices();
  485 + f_OutputTextureCoordinates();
  486 + f_OutputVertexNormals();
  487 + f_OutputPoints();
  488 + f_OutputLines();
  489 + f_OutputFaces();
  490 +
  491 + //close the file
  492 + g_objFile.close();
  493 +
  494 + //delete all of the data from the global object
  495 + f_ClearAll();
  496 + return OBJ_OK;
  497 +}
  498 +
  499 +OBJint rtsOBJ::objBegin(OBJint mode)
  500 +{
  501 + //make sure that we aren't currently rendering
  502 + if(g_CurrentMode != OBJ_NONE)
  503 + return OBJ_ERROR;
  504 + //make sure that the given mode is valid
  505 + if(mode < OBJ_POINTS || mode > OBJ_POLYGON)
  506 + return OBJ_ERROR;
  507 +
  508 + //otherwise, go ahead and set the mode
  509 + g_CurrentMode = mode;
  510 + //set the number of vertices to zero
  511 + g_NumVertices = 0;
  512 +
  513 + //reset the current state primitive state
  514 + current_primitive_mask = 0x0;
  515 +
  516 + return OBJ_OK;
  517 +}
  518 +
  519 +OBJint rtsOBJ::objEnd()
  520 +{
  521 + OBJint error = OBJ_OK;
  522 + //check to make sure the number of rendered vertices is valid for the current mode
  523 + switch(g_CurrentMode)
  524 + {
  525 + case OBJ_NONE:
  526 + //can't quit if we haven't started
  527 + error = OBJ_ERROR;
  528 + break;
  529 + case OBJ_LINES:
  530 + //if less than two vertices or an odd number of vertices
  531 + if(g_NumVertices < 2 || g_NumVertices%2 != 0)
  532 + {
  533 + //if there wasn't a vertex at all
  534 + if(g_NumVertices == 0)
  535 + error = OBJ_ERROR;
  536 + //if there was at least one vertex
  537 + else
  538 + {
  539 + //pop the last line off the list
  540 + primitives.pop_back();
  541 + lines.pop_back();
  542 + error = OBJ_ERROR;
  543 + }
  544 + }
  545 + break;
  546 + case OBJ_LINE_STRIP:
  547 + //if less than two vertices
  548 + if(g_NumVertices < 2)
  549 + {
  550 + //if there wasn't a vertex at all
  551 + if(g_NumVertices == 0)
  552 + error = OBJ_ERROR;
  553 + //if there was at least one vertex
  554 + else
  555 + {
  556 + //pop the last line off the list
  557 + primitives.pop_back();
  558 + lines.pop_back();
  559 + error = OBJ_ERROR;
  560 + }
  561 + }
  562 + break;
  563 + case OBJ_LINE_LOOP:
  564 + //if less than three vertices
  565 + if(g_NumVertices < 3)
  566 + {
  567 + //pop the last line off the list
  568 + primitives.pop_back();
  569 + lines.pop_back();
  570 + error = OBJ_ERROR;
  571 + }
  572 + //connect the first and last points
  573 + else
  574 + {
  575 + error = f_TerminateLineLoop();
  576 + }
  577 + break;
  578 + case OBJ_TRIANGLES:
  579 + //if less than three vertices or not a power of three
  580 + if(g_NumVertices < 3 || g_NumVertices%3 !=0)
  581 + {
  582 + primitives.pop_back();
  583 + faces.pop_back();
  584 + error = OBJ_ERROR;
  585 + }
  586 + break;
  587 + case OBJ_TRIANGLE_STRIP:
  588 + //if less than three vertices
  589 + if(g_NumVertices < 3)
  590 + {
  591 + primitives.pop_back();
  592 + faces.pop_back();
  593 + error = OBJ_ERROR;
  594 + }
  595 + break;
  596 + case OBJ_TRIANGLE_FAN:
  597 + //if less than three vertices
  598 + if(g_NumVertices < 3)
  599 + {
  600 + primitives.pop_back();
  601 + faces.pop_back();
  602 + error = OBJ_ERROR;
  603 + }
  604 + break;
  605 + case OBJ_QUADS:
  606 + if(g_NumVertices < 4 || g_NumVertices%4 != 0)
  607 + {
  608 + primitives.pop_back();
  609 + faces.pop_back();
  610 + error = OBJ_ERROR;
  611 + }
  612 + break;
  613 + case OBJ_QUAD_STRIP:
  614 + //has to be at least 4 vertices and an even number
  615 + if(g_NumVertices < 4 || g_NumVertices%2 != 0)
  616 + {
  617 + primitives.pop_back();
  618 + faces.pop_back();
  619 + error = OBJ_ERROR;
  620 + }
  621 + break;
  622 + case OBJ_POLYGON:
  623 + //has to be at least three vertices
  624 + if(g_NumVertices < 3)
  625 + {
  626 + primitives.pop_back();
  627 + faces.pop_back();
  628 + error = OBJ_ERROR;
  629 + }
  630 + break;
  631 + }
  632 +
  633 + //reset the attribute mask
  634 + g_AttributeMask = 0x0;
  635 + //just for closure, reset the attribute reset mask
  636 + g_AttributeResetMask = 0x0;
  637 + //stop rendering
  638 + g_CurrentMode = OBJ_NONE;
  639 + return error;
  640 +}
  641 +
  642 +OBJint rtsOBJ::f_InsertVertexf(float x, float y, float z, float w, unsigned char mask)
  643 +{
  644 + //make sure we're rendering
  645 + if(g_CurrentMode == OBJ_NONE)
  646 + return OBJ_ERROR;
  647 +
  648 + //insert the vertex into the vertex vector
  649 + vertex_position v;
  650 + v.x = x; v.y = y; v.z=z; v.w=w; v.mask = mask;
  651 + v_list.push_back(v);
  652 + f_AdjustExtents(v); //set the bounding box
  653 + //insert texture coordinate and normal if specified for this primitive
  654 + if((current_primitive_mask & OBJ_VT) && (vt_changed))
  655 + vt_list.push_back(current_vt);
  656 + if((current_primitive_mask & OBJ_VN) && (vn_changed))
  657 + vn_list.push_back(current_vn);
  658 +
  659 +
  660 + //increment the number of vertices inserted
  661 + g_NumVertices++;
  662 +
  663 + //handle each case of the vertex creation individually
  664 + OBJint error = OBJ_OK;
  665 + switch(g_CurrentMode)
  666 + {
  667 + case OBJ_POINTS:
  668 + error = f_InsertPointVertex();
  669 + break;
  670 + case OBJ_LINES:
  671 + error = f_InsertLineVertex();
  672 + break;
  673 + case OBJ_LINE_LOOP:
  674 + error = f_InsertLineLoopVertex();
  675 + break;
  676 + case OBJ_LINE_STRIP:
  677 + error = f_InsertLineStripVertex();
  678 + break;
  679 + case OBJ_TRIANGLES:
  680 + error = f_InsertTriangleVertex();
  681 + break;
  682 + case OBJ_TRIANGLE_STRIP:
  683 + error = f_InsertTriangleStripVertex();
  684 + break;
  685 + case OBJ_TRIANGLE_FAN:
  686 + error = f_InsertTriangleFanVertex();
  687 + break;
  688 + case OBJ_QUADS:
  689 + error = f_InsertQuadVertex();
  690 + break;
  691 + case OBJ_QUAD_STRIP:
  692 + error = f_InsertQuadStripVertex();
  693 + break;
  694 + case OBJ_POLYGON:
  695 + error = f_InsertPolygonVertex();
  696 + break;
  697 + }
  698 + //set the reset mask to zero
  699 + g_AttributeResetMask = 0x0;
  700 +
  701 + //set the attribute mask to include vertex position
  702 + g_AttributeMask = g_AttributeMask | OBJ_V;
  703 +
  704 + //return the result of the insertion
  705 + return error;
  706 +}
  707 +
  708 +OBJint rtsOBJ::objVertex1f(float x)
  709 +{
  710 + return f_InsertVertexf(x, 0.0, 0.0, 0.0, OBJ_V_X);
  711 +}
  712 +
  713 +OBJint rtsOBJ::objVertex2f(float x, float y)
  714 +{
  715 + return f_InsertVertexf(x, y, 0.0, 0.0, OBJ_V_X | OBJ_V_Y);
  716 +}
  717 +
  718 +OBJint rtsOBJ::objVertex3f(float x, float y, float z)
  719 +{
  720 + return f_InsertVertexf(x, y, z, 0.0, OBJ_V_X | OBJ_V_Y | OBJ_V_Z);
  721 +
  722 +}
  723 +
  724 +OBJint rtsOBJ::objVertex4f(float x, float y, float z, float w)
  725 +{
  726 + return f_InsertVertexf(x, y, z, w, OBJ_V_X | OBJ_V_Y | OBJ_V_Z | OBJ_V_W);
  727 +}
  728 +
  729 +OBJint rtsOBJ::objNormal3f(float i, float j, float k)
  730 +{
  731 + return f_InsertNormalf(i, j, k, OBJ_VN_I | OBJ_VN_J | OBJ_VN_K);
  732 +}
  733 +OBJint rtsOBJ::objNormal2f(float i, float j)
  734 +{
  735 + return f_InsertNormalf(i, j, 0.0, OBJ_VN_I | OBJ_VN_J);
  736 +}
  737 +
  738 +OBJint rtsOBJ::objNormal1f(float i)
  739 +{
  740 + return f_InsertNormalf(i, 0.0, 0.0, OBJ_VN_I);
  741 +}
  742 +
  743 +OBJint rtsOBJ::f_InsertNormalf(float i, float j, float k, unsigned char mask)
  744 +{
  745 + /*DEPRECATED
  746 + //if the mode is not rendering faces, there is an error
  747 + if(g_CurrentMode < OBJ_TRIANGLES)
  748 + return OBJ_ERROR;
  749 + //if the normal attribute flag is not set, set it (as long as a vertex hasn't been written)
  750 + if(!(g_AttributeMask & OBJ_VN))
  751 + {
  752 + //if a vertex has been rendered, then we can't change the attribute, so exit
  753 + if(g_NumVertices > 0)
  754 + return OBJ_ERROR;
  755 + else
  756 + //otherwise, just set the attribute flag
  757 + g_AttributeMask = g_AttributeMask | OBJ_VN;
  758 + }
  759 +
  760 +
  761 + //insert the new normal into the normal list for the file
  762 + vertex_normal new_vn;
  763 + new_vn.i = i; new_vn.j = j; new_vn.k = k;
  764 + new_vn.mask = mask;
  765 + vn_list.push_back(new_vn);
  766 + */
  767 + current_vn.i = i; //set the current texture state to the given coordinates
  768 + current_vn.j = j;
  769 + current_vn.k = k;
  770 + current_vn.mask = mask; //set the mask as appropriate
  771 + vn_changed = true; //the texture coordinate state has changed
  772 + current_primitive_mask = current_primitive_mask | OBJ_VN; //the current primitive now uses texture coordinates (if it didn't previously)
  773 +
  774 + return OBJ_OK;
  775 +}
  776 +
  777 +OBJint rtsOBJ::objTexCoord3f(float u, float v, float w)
  778 +{
  779 + return f_InsertTexCoordf(u, v, w, OBJ_VT_U | OBJ_VT_V | OBJ_VT_W);
  780 +}
  781 +
  782 +OBJint rtsOBJ::objTexCoord2f(float u, float v)
  783 +{
  784 + return f_InsertTexCoordf(u, v, 0.0, OBJ_VT_U | OBJ_VT_V);
  785 +}
  786 +
  787 +OBJint rtsOBJ::objTexCoord1f(float u)
  788 +{
  789 + return f_InsertTexCoordf(u, 0.0, 0.0, OBJ_VT_U);
  790 +}
  791 +
  792 +OBJint rtsOBJ::f_InsertTexCoordf(float u, float v, float w, unsigned char mask)
  793 +{
  794 + /*
  795 + DEPRECATED
  796 + //if the normal attribute flag is not set, set it (as long as a vertex hasn't been written)
  797 + if(!(g_AttributeMask & OBJ_VT))
  798 + {
  799 + //if a vertex has been rendered, then we can't change the attribute, so exit
  800 + if(g_NumVertices > 0)
  801 + return OBJ_ERROR;
  802 + else
  803 + //otherwise, just set the attribute flag
  804 + g_AttributeMask = g_AttributeMask | OBJ_VT;
  805 + }
  806 +
  807 + //insert the new texture coordinate into the list for the file
  808 + vertex_texture new_vt;
  809 + new_vt.u = u; new_vt.v = v; new_vt.w = w;
  810 + new_vt.mask = mask;
  811 + vt_list.push_back(new_vt);
  812 + */
  813 + current_vt.u = u; //set the current texture state to the given coordinates
  814 + current_vt.v = v;
  815 + current_vt.w = w;
  816 + current_vt.mask = mask; //set the mask as appropriate
  817 + vt_changed = true; //the texture coordinate state has changed
  818 + current_primitive_mask = current_primitive_mask | OBJ_VT; //the current primitive now uses texture coordinates (if it didn't previously)
  819 +
  820 + return OBJ_OK;
  821 +}
  822 +
  823 +
  824 +void rtsOBJ::insertVertexPosition(float x, float y, float z, unsigned char mask)
  825 +{
  826 + vertex_position v;
  827 + v.x = x;
  828 + v.y = y;
  829 + v.z = z;
  830 + v.mask = mask;
  831 +
  832 + v_list.push_back(v);
  833 +}
  834 +
  835 +void rtsOBJ::insertLine(unsigned int num_points, unsigned int* pointlist, unsigned int* normallist, unsigned int* texturelist)
  836 +{
  837 + //create the new primitive
  838 + primitive line;
  839 + line.type = OBJ_LINES;
  840 + line.mask = 0;
  841 +
  842 + //set the mask based on the passed data
  843 + if(pointlist != NULL)
  844 + line.mask = line.mask | OBJ_V;
  845 + if(normallist != NULL)
  846 + line.mask = line.mask | OBJ_VN;
  847 + if(texturelist != NULL)
  848 + line.mask = line.mask | OBJ_VT;
  849 +
  850 + //insert the line
  851 + unsigned int v;
  852 + vertex new_vert;
  853 + for(v=0; v<num_points; v++)
  854 + {
  855 + if(pointlist)
  856 + new_vert.v = pointlist[v];
  857 + if(normallist)
  858 + new_vert.vn = normallist[v];
  859 + if(texturelist)
  860 + new_vert.vt = texturelist[v];
  861 + line.p.push_back(new_vert);
  862 + }
  863 + //insert the new primitive into the list
  864 + primitives.push_back(line);
  865 +}
  866 +OBJint rtsOBJ::f_InsertPointVertex()
  867 +{
  868 + //insert the most recent point into the most recent point list
  869 + //if this is the first vertex, create the point list
  870 + if(g_NumVertices == 1)
  871 + {
  872 + primitive new_p; //create the new point
  873 + new_p.type = OBJ_POINTS;
  874 + new_p.mask = current_primitive_mask;
  875 + points.push_back(primitives.size()); //store the primitive id in the points list
  876 + primitives.push_back(new_p);
  877 + }
  878 +
  879 + //find the id of the most recent primitive
  880 + unsigned int p_index = primitives.size() - 1;
  881 + //find the index of the recent point
  882 + vertex p;
  883 + p.v = v_list.size() - 1;
  884 + //insert the indices for texture coordinates and normal if necessary
  885 + if(primitives[p_index].mask & OBJ_VT)
  886 + p.vt = vt_list.size() - 1;
  887 + if(primitives[p_index].mask & OBJ_VN)
  888 + p.vn = vn_list.size() - 1;
  889 +
  890 + //insert the vertex index into the primitive's point list
  891 + primitives[p_index].p.push_back(p);
  892 +
  893 + //push the point into the points list if it is not the only point in the primitive
  894 + if(g_NumVertices > 1)
  895 + points.push_back(p_index);
  896 +
  897 + return OBJ_OK;
  898 +}
  899 +
  900 +OBJint rtsOBJ::f_InsertLineVertex()
  901 +{
  902 + //if this is an odd vertex, create a new line
  903 + if(g_NumVertices%2 == 1)
  904 + {
  905 + f_CreateNewLine();
  906 + }
  907 +
  908 + f_InsertNewLineVertex();
  909 +
  910 + return OBJ_OK;
  911 +}
  912 +OBJint rtsOBJ::f_InsertLineLoopVertex()
  913 +{
  914 + //technically, this is the same as inserting a line strip vertex
  915 + f_InsertLineStripVertex();
  916 + return OBJ_OK;
  917 +}
  918 +
  919 +OBJint rtsOBJ::f_InsertLineStripVertex()
  920 +{
  921 + if(g_NumVertices == 1)
  922 + {
  923 + f_CreateNewLine();
  924 + }
  925 +
  926 + f_InsertNewLineVertex();
  927 +
  928 + return OBJ_OK;
  929 +}
  930 +
  931 +OBJint rtsOBJ::f_InsertTriangleVertex()
  932 +{
  933 + //if this is the first vertex in a triangle, create a new triangle
  934 + if(g_NumVertices%3 == 1)
  935 + {
  936 + f_CreateNewFace();
  937 + }
  938 +
  939 +
  940 + f_InsertNewFaceVertex();
  941 +
  942 + return OBJ_OK;
  943 +}
  944 +OBJint rtsOBJ::f_InsertTriangleStripVertex()
  945 +{
  946 + //in the special case of the first three vertices, just create a triangle
  947 + if(g_NumVertices < 4)
  948 + f_InsertTriangleVertex();
  949 + else
  950 + {
  951 +
  952 + //create a new face for the new triangle
  953 + f_CreateNewFace();
  954 +
  955 + //make sure to get the ordering right:
  956 + // Even vertices provide the previous two vertices "in order": (v2, v3, v4)
  957 + // Odd vertices provide the previous two vertices in reverse order: (v1, v3, v2)
  958 + if(g_NumVertices % 2 == 1)
  959 + {
  960 + f_InsertPreviousFaceVertex(2);
  961 + f_InsertPreviousFaceVertex(1);
  962 + f_InsertNewFaceVertex();
  963 + }
  964 + else
  965 + {
  966 + f_InsertPreviousFaceVertex(1);
  967 + f_InsertNewFaceVertex();
  968 + f_InsertPreviousFaceVertex(2);
  969 + }
  970 + }
  971 +
  972 + return OBJ_OK;
  973 +}
  974 +OBJint rtsOBJ::f_InsertTriangleFanVertex()
  975 +{
  976 + //in the special case of the first three vertices, just create a triangle
  977 + if(g_NumVertices <4)
  978 + f_InsertTriangleVertex();
  979 + else
  980 + {
  981 + //create a new face for the new triangle
  982 + f_CreateNewFace();
  983 + //add the previous vertices to the face
  984 + f_InsertFirstFaceVertex(0);
  985 + f_InsertPreviousFaceVertex(2);
  986 + //insert the current vertex
  987 + f_InsertNewFaceVertex();
  988 + }
  989 +
  990 + return OBJ_OK;
  991 +}
  992 +OBJint rtsOBJ::f_InsertQuadVertex()
  993 +{
  994 + //if this is the first vertex in a quad, create a new quad
  995 + if(g_NumVertices%4 == 1)
  996 + {
  997 + f_CreateNewFace();
  998 + }
  999 +
  1000 + f_InsertNewFaceVertex();
  1001 +
  1002 + return OBJ_OK;
  1003 +}
  1004 +OBJint rtsOBJ::f_InsertQuadStripVertex()
  1005 +{
  1006 + //in the case of one of the first four vertices, just create a quad
  1007 + if(g_NumVertices < 5)
  1008 + f_InsertQuadVertex();
  1009 + //if the vertex is odd (it will be the third vertex of a quad)
  1010 + else if(g_NumVertices%2 == 1)
  1011 + {
  1012 + //create a new face for the new quad
  1013 + f_CreateNewFace();
  1014 + //add the previous two vertices
  1015 + f_InsertPreviousFaceVertex(2);
  1016 + f_InsertPreviousFaceVertex(3);
  1017 + //add the current vertex
  1018 + f_InsertNewFaceVertex();
  1019 + }
  1020 + else
  1021 + {
  1022 + //if this is the last vertex of the quad, just add it
  1023 + f_InsertNewFaceVertex();
  1024 +
  1025 + }
  1026 + return OBJ_OK;
  1027 +}
  1028 +OBJint rtsOBJ::f_InsertPolygonVertex()
  1029 +{
  1030 + //if this is the first vertex, create the quad
  1031 + if(g_NumVertices == 1)
  1032 + {
  1033 + f_CreateNewFace();
  1034 + }
  1035 + f_InsertNewFaceVertex();
  1036 +
  1037 + return OBJ_OK;
  1038 +}
  1039 +
  1040 +OBJint rtsOBJ::f_InsertPreviousFaceVertex(unsigned int v_index)
  1041 +{
  1042 + /*Finds the vertex used in the previous face with the given index and
  1043 + inserts it into the current face. This limits the redundancy in the file
  1044 + for re-used vertices (in strips and fans). This also transfers texture
  1045 + and normal information.*/
  1046 +
  1047 + //find the index of the previous face
  1048 + unsigned int prev_f_index = primitives.size() - 2;
  1049 + //find the index of the current face
  1050 + unsigned int f_index = prev_f_index +1;
  1051 + //add the vertex information from the previous face to this face
  1052 + primitives[f_index].p.push_back(primitives[prev_f_index].p[v_index]);
  1053 +
  1054 + return OBJ_OK;
  1055 +}
  1056 +
  1057 +OBJint rtsOBJ::f_InsertFirstFaceVertex(unsigned int v_index)
  1058 +{
  1059 + /*Finds the vertex used in the first face (since the last objBegin())
  1060 + with the given index and inserts it at the end of the current face.
  1061 + This includes texture and normal information.*/
  1062 +
  1063 + //The result depends on the type of face being rendered
  1064 + //So far, this function only applies to triangle fans
  1065 + if(g_CurrentMode != OBJ_TRIANGLE_FAN)
  1066 + return OBJ_ERROR;
  1067 +
  1068 + //calculate the number of faces that have been rendered
  1069 + unsigned int num_faces = g_NumVertices - 2;
  1070 + //find the index of the first face
  1071 + unsigned int first_f_index = primitives.size() - num_faces;
  1072 + //find the index of the current face
  1073 + unsigned int f_index = primitives.size() - 1;
  1074 + //transfer the vertex information from the first face to this one
  1075 + primitives[f_index].p.push_back(primitives[first_f_index].p[v_index]);
  1076 +
  1077 +
  1078 + return OBJ_OK;
  1079 +}
  1080 +
  1081 +OBJint rtsOBJ::f_InsertNewFaceVertex()
  1082 +{
  1083 + /*This inserts information about the current vertex into the current face*/
  1084 + //find the new vertex index
  1085 + vertex p;
  1086 + p.v = v_list.size() -1;
  1087 + p.vt = vt_list.size() - 1;
  1088 + p.vn = vn_list.size() -1;
  1089 + //find the face index
  1090 + unsigned int f_index = primitives.size() -1;
  1091 + //INSERT VERTEX AND ATTRIBUTE DATA
  1092 + //just add the vertex to the face
  1093 + primitives[f_index].p.push_back(p);
  1094 +
  1095 + return OBJ_OK;
  1096 +}
  1097 +
  1098 +OBJint rtsOBJ::f_InsertNewLineVertex()
  1099 +{
  1100 + /*This inserts information about the current vertex into the current line*/
  1101 + //find the new vertex index
  1102 + vertex p;
  1103 + p.v = v_list.size() -1;
  1104 + p.vt = vt_list.size() - 1;
  1105 + //find the line index
  1106 + unsigned int l_index = primitives.size() -1;
  1107 +
  1108 + //ADD VERTEX AND ATTRIBUTE INFORMATION
  1109 + //add the vertex to the line
  1110 + primitives[l_index].p.push_back(p);
  1111 +
  1112 + return OBJ_OK;
  1113 +}
  1114 +
  1115 +OBJint rtsOBJ::f_CreateNewFace()
  1116 +{
  1117 + primitive new_f;
  1118 + new_f.type = OBJ_FACE;
  1119 + new_f.mask = g_AttributeMask;
  1120 + faces.push_back(primitives.size());
  1121 + primitives.push_back(new_f);
  1122 +
  1123 +
  1124 + return OBJ_OK;
  1125 +}
  1126 +
  1127 +OBJint rtsOBJ::f_CreateNewLine()
  1128 +{
  1129 + primitive new_l;
  1130 + new_l.type = OBJ_LINES;
  1131 + new_l.mask = g_AttributeMask;
  1132 + lines.push_back(primitives.size());
  1133 + primitives.push_back(new_l);
  1134 +
  1135 + return OBJ_OK;
  1136 +}
  1137 +
  1138 +
  1139 +OBJint rtsOBJ::f_TerminateLineLoop()
  1140 +{
  1141 + /*This function just terminates the line loop by setting the last vertex
  1142 + to the first vertex.*/
  1143 + if(g_CurrentMode != OBJ_LINE_LOOP)
  1144 + return OBJ_ERROR;
  1145 + //find the index for the current line
  1146 + unsigned int l_index = lines.size() -1;
  1147 + //insert the first vertex as the last vertex
  1148 + primitives[l_index].p.push_back(primitives[l_index].p[0]);
  1149 +
  1150 + return OBJ_OK;
  1151 +}
  1152 +
  1153 +void rtsOBJ::f_OutputVertices()
  1154 +{
  1155 + //get the number of vertices in the object
  1156 + unsigned int v_num = v_list.size();
  1157 + for(unsigned int i=0; i<v_num; i++)
  1158 + {
  1159 + g_objFile<<"v";
  1160 + if(v_list[i].mask & OBJ_V_X)
  1161 + g_objFile<<" "<<v_list[i].x;
  1162 + if(v_list[i].mask & OBJ_V_Y)
  1163 + g_objFile<<" "<<v_list[i].y;
  1164 + if(v_list[i].mask & OBJ_V_Z)
  1165 + g_objFile<<" "<<v_list[i].z;
  1166 + if(v_list[i].mask & OBJ_V_W)
  1167 + g_objFile<<" "<<v_list[i].w;
  1168 + g_objFile<<endl;
  1169 + }
  1170 +
  1171 +}
  1172 +
  1173 +void rtsOBJ::f_OutputVertexNormals()
  1174 +{
  1175 + //get the number of normals in the object
  1176 + unsigned int vn_num = vn_list.size();
  1177 + for(unsigned int i=0; i<vn_num; i++)
  1178 + {
  1179 + g_objFile<<"vn ";
  1180 + if(vn_list[i].mask & OBJ_VN_I)
  1181 + {
  1182 + g_objFile<<vn_list[i].i;
  1183 + if(vn_list[i].mask & OBJ_VN_J)
  1184 + {
  1185 + g_objFile<<" "<<vn_list[i].j;
  1186 + if(vn_list[i].mask & OBJ_VN_K)
  1187 + g_objFile<<" "<<vn_list[i].k;
  1188 + }
  1189 + }
  1190 + g_objFile<<endl;
  1191 + }
  1192 +}
  1193 +
  1194 +void rtsOBJ::f_OutputTextureCoordinates()
  1195 +{
  1196 + //get the number of vertices in the object
  1197 + unsigned int vt_num = vt_list.size();
  1198 + for(unsigned int i=0; i<vt_num; i++)
  1199 + {
  1200 + g_objFile<<"vt ";
  1201 + if(vt_list[i].mask & OBJ_VT_U)
  1202 + {
  1203 + g_objFile<<vt_list[i].u;
  1204 + if(vt_list[i].mask & OBJ_VT_V)
  1205 + {
  1206 + g_objFile<<" "<<vt_list[i].v;
  1207 + if(vt_list[i].mask & OBJ_VT_W)
  1208 + g_objFile<<" "<<vt_list[i].w;
  1209 + }
  1210 + }
  1211 + g_objFile<<endl;
  1212 + }
  1213 +}
  1214 +
  1215 +void rtsOBJ::f_OutputPoints()
  1216 +{
  1217 + /*
  1218 + //get the number of point vectors
  1219 + unsigned int p_num = points.size();
  1220 +
  1221 + //for each point vector, output the points
  1222 + for(unsigned int i=0; i<p_num; i++)
  1223 + {
  1224 + g_objFile<<"p";
  1225 + unsigned int v_num = points[i].p.size();
  1226 + for(unsigned int j=0; j<v_num; j++)
  1227 + {
  1228 + g_objFile<<" "<<points[i].p[j].v+1;
  1229 + }
  1230 + g_objFile<<endl;
  1231 + }
  1232 + */
  1233 +}
  1234 +
  1235 +void rtsOBJ::f_OutputLines()
  1236 +{
  1237 + /*
  1238 + //get the number of line vectors
  1239 + unsigned int l_num = lines.size();
  1240 +
  1241 + //for each line vector, output the associated points
  1242 + for(unsigned int i=0; i<l_num; i++)
  1243 + {
  1244 + g_objFile<<"l";
  1245 + unsigned int v_num = lines[i].p.size();
  1246 + for(unsigned int j=0; j<v_num; j++)
  1247 + {
  1248 + g_objFile<<" "<<lines[i].p[j].v+1;
  1249 + //output texture coordinate if there are any
  1250 + if(lines[i].mask & OBJ_VT)
  1251 + g_objFile<<"/"<<lines[i].p[j].vt+1;
  1252 + }
  1253 + g_objFile<<endl;
  1254 + }
  1255 + */
  1256 +}
  1257 +
  1258 +void rtsOBJ::f_OutputFaces()
  1259 +{
  1260 + /*
  1261 + //get the number of faces
  1262 + unsigned int f_num = faces.size();
  1263 +
  1264 + //for each face, output the associated points
  1265 + for(unsigned int i=0; i<f_num; i++)
  1266 + {
  1267 + g_objFile<<"f";
  1268 + //get the number of face vertices
  1269 + unsigned int v_num = faces[i].p.size();
  1270 + for(unsigned int j=0; j<v_num; j++)
  1271 + {
  1272 + g_objFile<<" "<<faces[i].p[j].v+1;
  1273 + //if there are texture coordinates
  1274 + if(faces[i].mask & OBJ_VT)
  1275 + g_objFile<<"/"<<faces[i].p[j].vt+1;
  1276 + //if there is a normal
  1277 + if(faces[i].mask & OBJ_VN)
  1278 + {
  1279 + //but no texture coordinates, put an extra slash
  1280 + if(!(faces[i].mask & OBJ_VT))
  1281 + g_objFile<<"/";
  1282 + g_objFile<<"/"<<faces[i].p[j].vn+1;
  1283 + }
  1284 +
  1285 + }
  1286 + g_objFile<<endl;
  1287 + }
  1288 + */
  1289 +}
  1290 +
  1291 +void rtsOBJ::f_ClearAll()
  1292 +{
  1293 + rtsOBJ();
  1294 + //clear all data from the global obj function
  1295 + faces.clear();
  1296 + lines.clear();
  1297 + points.clear();
  1298 + v_list.clear();
  1299 + vn_list.clear();
  1300 + vt_list.clear();
  1301 + primitives.clear();
  1302 +}
  1303 +
  1304 +/*GLOBAL FUNCTION DEFINITIONS*/
  1305 +//initialize the OBJ file
  1306 +OBJint objOpen(char* filename)
  1307 +{
  1308 + return g_OBJ.objOpen(filename);
  1309 +}
  1310 +//close the obj file
  1311 +OBJint objClose()
  1312 +{
  1313 + return g_OBJ.objClose();
  1314 +}
  1315 +
  1316 +//start rendering in a certain mode
  1317 +OBJint objBegin(OBJint mode)
  1318 +{
  1319 + return g_OBJ.objBegin(mode);
  1320 +}
  1321 +//stop the current rendering sequence
  1322 +OBJint objEnd(void)
  1323 +{
  1324 + return g_OBJ.objEnd();
  1325 +}
  1326 +//render a vertex to the file
  1327 +OBJint objVertex1f(float x)
  1328 +{
  1329 + return g_OBJ.objVertex1f(x);
  1330 +}
  1331 +
  1332 +OBJint objVertex2f(float x, float y)
  1333 +{
  1334 + return g_OBJ.objVertex2f(x, y);
  1335 +}
  1336 +
  1337 +OBJint objVertex3f(float x, float y, float z)
  1338 +{
  1339 + return g_OBJ.objVertex3f(x, y, z);
  1340 +}
  1341 +
  1342 +OBJint objVertex4f(float x, float y, float z, float w)
  1343 +{
  1344 + return g_OBJ.objVertex4f(x, y, z, w);
  1345 +}
  1346 +//set a normal vector for a vertex
  1347 +OBJint objNormal3f(float i, float j, float k)
  1348 +{
  1349 + return g_OBJ.objNormal3f(i, j, k);
  1350 +}
  1351 +OBJint objNormal2f(float i, float j)
  1352 +{
  1353 + return g_OBJ.objNormal2f(i, j);
  1354 +}
  1355 +OBJint objNormal1f(float i)
  1356 +{
  1357 + return g_OBJ.objNormal1f(i);
  1358 +}
  1359 +//set a texture coordinate for a vertex
  1360 +OBJint objTexCoord3f(float u, float v, float w)
  1361 +{
  1362 + return g_OBJ.objTexCoord3f(u, v, w);
  1363 +}
  1364 +
  1365 +OBJint objTexCoord2f(float u, float v)
  1366 +{
  1367 + return g_OBJ.objTexCoord2f(u,v);
  1368 +}
  1369 +
  1370 +OBJint objTexCoord1f(float u)
  1371 +{
  1372 + return g_OBJ.objTexCoord1f(u);
  1373 +}
  1374 +
  1375 +OBJint rtsOBJ::f_ReadPosition(ifstream &infile)
  1376 +{
  1377 + vertex_position new_vertex;
  1378 + //get each coordinate
  1379 + infile>>new_vertex.x;
  1380 + new_vertex.mask = OBJ_V_X;
  1381 +
  1382 + if(infile.peek() == ' ')
  1383 + {
  1384 + infile>>new_vertex.y;
  1385 + new_vertex.mask = new_vertex.mask | OBJ_V_Y;
  1386 + }
  1387 + if(infile.peek() == ' ')
  1388 + {
  1389 + infile>>new_vertex.z;
  1390 + new_vertex.mask = new_vertex.mask | OBJ_V_Z;
  1391 + }
  1392 + if(infile.peek() == ' ')
  1393 + {
  1394 + infile>>new_vertex.w;
  1395 + new_vertex.mask = new_vertex.mask | OBJ_V_W;
  1396 + }
  1397 + int c = infile.peek();
  1398 + //ignore the rest of the line
  1399 + infile.ignore(1000, '\n');
  1400 + c = infile.peek();
  1401 +
  1402 + //cout<<"vertex read: "<<new_vertex.x<<","<<new_vertex.y<<","<<new_vertex.z<<","<<new_vertex.w<<endl;
  1403 + //insert the vertex into the list
  1404 + v_list.push_back(new_vertex);
  1405 +
  1406 + //adjust the extents of the model
  1407 + f_AdjustExtents(new_vertex);
  1408 +
  1409 + return OBJ_OK;
  1410 +}
  1411 +
  1412 +OBJint rtsOBJ::f_ReadNormal(ifstream &infile)
  1413 +{
  1414 + vertex_normal new_normal;
  1415 + infile>>new_normal.i;
  1416 + new_normal.mask = OBJ_VN_I;
  1417 + //get every other component
  1418 + if(infile.peek() == ' ')
  1419 + {
  1420 + infile>>new_normal.j;
  1421 + new_normal.mask = new_normal.mask | OBJ_VN_J;
  1422 + }
  1423 + if(infile.peek() == ' ')
  1424 + {
  1425 + infile>>new_normal.k;
  1426 + new_normal.mask = new_normal.mask | OBJ_VN_K;
  1427 + }
  1428 + //ignore the rest of the line
  1429 + infile.ignore(1000, '\n');
  1430 + //insert the normal
  1431 + vn_list.push_back(new_normal);
  1432 +
  1433 + return OBJ_OK;
  1434 +}
  1435 +
  1436 +OBJint rtsOBJ::f_ReadTexCoord(ifstream &infile)
  1437 +{
  1438 + vertex_texture new_texcoord;
  1439 + infile>>new_texcoord.u;
  1440 + new_texcoord.mask = OBJ_VT_U;
  1441 + //get every other component
  1442 + if(infile.peek() == ' ')
  1443 + {
  1444 + infile>>new_texcoord.v;
  1445 + new_texcoord.mask = new_texcoord.mask | OBJ_VT_V;
  1446 + }
  1447 + if(infile.peek() == ' ')
  1448 + {
  1449 + infile>>new_texcoord.w;
  1450 + new_texcoord.mask = new_texcoord.mask | OBJ_VT_W;
  1451 + }
  1452 +
  1453 + //ignore the rest of the line
  1454 + infile.ignore(1000, '\n');
  1455 + //insert the texture coordinate
  1456 + vt_list.push_back(new_texcoord);
  1457 +
  1458 + return OBJ_OK;
  1459 +
  1460 +}
  1461 +
  1462 +OBJint rtsOBJ::f_ReadVertex(ifstream &infile, vertex &new_point, unsigned char &mask)
  1463 +{
  1464 + //store the line vertex
  1465 + infile>>new_point.v;
  1466 + new_point.v--;
  1467 + mask = OBJ_V;
  1468 + //new_face.v.push_back(new_v - 1);
  1469 + if(infile.peek() == '/')
  1470 + {
  1471 + infile.get();
  1472 + //if there actually is a texcoord
  1473 + if(infile.peek() != '/')
  1474 + {
  1475 + infile>>new_point.vt; //get the index
  1476 + new_point.vt--;
  1477 + mask = mask | OBJ_VT; //update the mask
  1478 + //new_face.vt.push_back(new_vt - 1);
  1479 + }
  1480 + }
  1481 + //check for a normal
  1482 + if(infile.peek() == '/')
  1483 + {
  1484 + infile.get();
  1485 + infile>>new_point.vn; //get the index
  1486 + new_point.vn--;
  1487 + mask = mask | OBJ_VN; //update the mask
  1488 + }
  1489 +
  1490 + return OBJ_OK;
  1491 +}
  1492 +
  1493 +OBJint rtsOBJ::f_ReadPrimitive(ifstream &infile, primitive_type type)
  1494 +{
  1495 + //create a new point list
  1496 + primitive new_primitive;
  1497 + new_primitive.type = type;
  1498 + //until the end of the line
  1499 + while(infile.peek() != '\n')
  1500 + {
  1501 + //read each point
  1502 + if(infile.peek() == ' ')
  1503 + infile.get();
  1504 + else
  1505 + {
  1506 + vertex new_point;
  1507 + f_ReadVertex(infile, new_point, new_primitive.mask);
  1508 + new_primitive.p.push_back(new_point);
  1509 + }
  1510 + }
  1511 + //ignore the rest of the line
  1512 + infile.ignore(1000, '\n');
  1513 +
  1514 + //push the id of the primitive into the new list
  1515 + //:DEBUG:
  1516 + if(type == OBJ_POINTS)
  1517 + points.push_back(primitives.size());
  1518 + else if(type == OBJ_LINES)
  1519 + lines.push_back(primitives.size());
  1520 + else if(type == OBJ_FACE)
  1521 + faces.push_back(primitives.size());
  1522 +
  1523 + primitives.push_back(new_primitive); //push the new primitive
  1524 +
  1525 + return OBJ_OK;
  1526 +}
  1527 +
  1528 +
  1529 +OBJint rtsOBJ::f_AdjustExtents(vertex_position v)
  1530 +{
  1531 + if(v.x < m_bounds.min.x)
  1532 + m_bounds.min.x = v.x;
  1533 + if(v.y < m_bounds.min.y)
  1534 + m_bounds.min.y = v.y;
  1535 + if(v.z < m_bounds.min.z)
  1536 + m_bounds.min.z = v.z;
  1537 +
  1538 + if(v.x > m_bounds.max.x) m_bounds.max.x = v.x;
  1539 + if(v.y > m_bounds.max.y) m_bounds.max.y = v.y;
  1540 + if(v.z > m_bounds.max.z) m_bounds.max.z = v.z;
  1541 +
  1542 + return OBJ_OK;
  1543 +}
  1544 +
  1545 +OBJint rtsOBJ::f_LoadOBJ(const char* filename)
  1546 +{
  1547 + f_ClearAll();
  1548 + //open the file as a stream
  1549 + ifstream infile;
  1550 + infile.open(filename);
  1551 + if(!infile)
  1552 + exit(1);
  1553 +
  1554 + unsigned int vertices = 0;
  1555 +
  1556 + string token;
  1557 + infile>>token;
  1558 + while(!infile.eof())
  1559 + {
  1560 + //if the token is some vertex property
  1561 + if(token == "v")
  1562 + f_ReadPosition(infile);
  1563 + else if(token == "vn")
  1564 + f_ReadNormal(infile);
  1565 + else if(token == "vt")
  1566 + f_ReadTexCoord(infile);
  1567 + else if(token == "p")
  1568 + f_ReadPrimitive(infile, OBJ_POINTS);
  1569 + else if(token == "l")
  1570 + f_ReadPrimitive(infile, OBJ_LINES);
  1571 + else if(token == "f")
  1572 + f_ReadPrimitive(infile, OBJ_FACE);
  1573 + else
  1574 + infile.ignore(9999, '\n');
  1575 + //vertices++;
  1576 +
  1577 + infile>>token;
  1578 + }
  1579 +
  1580 +}
  1581 +
  1582 +OBJint rtsOBJ::f_LoadSWC(const char* filename)
  1583 +{
  1584 + f_ClearAll();
  1585 + //open the file as a stream
  1586 + ifstream infile;
  1587 + infile.open(filename);
  1588 + if(!infile.is_open())
  1589 + return OBJ_ERROR;
  1590 +
  1591 + vector<vertex_position> swcVertices;
  1592 + float token;
  1593 + objBegin(OBJ_LINES);
  1594 + while(!infile.eof())
  1595 + {
  1596 + vertex_position v;
  1597 + infile>>token; //get the id
  1598 + infile>>token; //get the fiber type
  1599 + infile>>v.x; //get the node position
  1600 + infile>>v.y;
  1601 + infile>>v.z;
  1602 + infile>>token; //get the radius
  1603 + infile>>token; //get the parent
  1604 +
  1605 + //insert the node into the swc vector
  1606 + swcVertices.push_back(v);
  1607 + //now draw the line from the parent to the current node
  1608 + if(token != -1)
  1609 + {
  1610 + unsigned int i = (unsigned int)token - 1;
  1611 + objVertex3f(swcVertices[i].x, swcVertices[i].y, swcVertices[i].z);
  1612 + objVertex3f(v.x, v.y, v.z);
  1613 + }
  1614 + }
  1615 + objEnd();
  1616 +
  1617 +
  1618 + return OBJ_OK;
  1619 +
  1620 +}
  1621 +OBJint rtsOBJ::LoadFile(const char* filename)
  1622 +{
  1623 + string strFilename = filename;
  1624 + int length = strFilename.length();
  1625 + string extension = strFilename.substr(strFilename.length() - 3, 3);
  1626 + if(!extension.compare(string("obj")))
  1627 + return f_LoadOBJ(filename);
  1628 + else if(!extension.compare(string("swc")))
  1629 + return f_LoadSWC(filename);
  1630 + else return f_LoadOBJ(filename);
  1631 +
  1632 +}
  1633 +
  1634 +OBJint rtsOBJ::SaveFile(const char* filename)
  1635 +{
  1636 + //open the file as a stream
  1637 + ofstream outfile;
  1638 + outfile.open(filename);
  1639 + if(!outfile.is_open())
  1640 + return OBJ_ERROR;
  1641 +
  1642 + //output vertex positions
  1643 + vector<vertex_position>::iterator v;
  1644 + for(v=v_list.begin(); v!= v_list.end(); v++)
  1645 + {
  1646 + outfile<<"v";
  1647 + if((*v).mask & OBJ_V_X)
  1648 + {
  1649 + outfile<<' '<<(*v).x;
  1650 + if((*v).mask & OBJ_V_Y)
  1651 + {
  1652 + outfile<<' '<<(*v).y;
  1653 + if((*v).mask & OBJ_V_Z)
  1654 + {
  1655 + outfile<<' '<<(*v).z;
  1656 + if((*v).mask & OBJ_V_W)
  1657 + outfile<<' '<<(*v).w;
  1658 + }
  1659 + }
  1660 + }
  1661 + outfile<<'\n';
  1662 + }
  1663 +
  1664 + //output vertex texture coordinates
  1665 + vector<vertex_texture>::iterator vt;
  1666 + for(vt=vt_list.begin(); vt!= vt_list.end(); vt++)
  1667 + {
  1668 + outfile<<"vt";
  1669 + if((*vt).mask & OBJ_VT_U)
  1670 + {
  1671 + outfile<<' '<<(*vt).u;
  1672 + if((*vt).mask & OBJ_VT_V)
  1673 + {
  1674 + outfile<<' '<<(*vt).v;
  1675 + if((*vt).mask & OBJ_VT_W)
  1676 + outfile<<' '<<(*vt).w;
  1677 + }
  1678 + }
  1679 + outfile<<'\n';
  1680 + }
  1681 +
  1682 + //output vertex normal coordinates
  1683 + vector<vertex_normal>::iterator vn;
  1684 + for(vn=vn_list.begin(); vn!= vn_list.end(); vn++)
  1685 + {
  1686 + outfile<<"vn";
  1687 + if((*vn).mask & OBJ_VN_I)
  1688 + {
  1689 + outfile<<' '<<(*vn).i;
  1690 + if((*vn).mask & OBJ_VN_J)
  1691 + {
  1692 + outfile<<' '<<(*vn).j;
  1693 + if((*vn).mask & OBJ_VN_K)
  1694 + outfile<<' '<<(*vn).k;
  1695 + }
  1696 + }
  1697 + outfile<<'\n';
  1698 + }
  1699 +
  1700 + //output each primitive
  1701 + vector<primitive>::iterator p;
  1702 + vector<vertex>::iterator vert;
  1703 + for(p=primitives.begin(); p!= primitives.end(); p++)
  1704 + {
  1705 + switch((*p).type)
  1706 + {
  1707 + case OBJ_POINTS:
  1708 + outfile<<"p"; //output the points token
  1709 + break;
  1710 + case OBJ_LINES:
  1711 + outfile<<"l"; //output the lines token
  1712 + break;
  1713 + case OBJ_FACE:
  1714 + outfile<<"f"; //output the face token
  1715 + break;
  1716 + }
  1717 +
  1718 + //for each vertex in the list for the primitive
  1719 + for(vert = (*p).p.begin(); vert != (*p).p.end(); vert++)
  1720 + {
  1721 + outfile<<' '<<(*vert).v + 1;
  1722 + if((*p).mask & OBJ_VT)
  1723 + outfile<<'/'<<(*vert).vt + 1;
  1724 + if((*p).mask & OBJ_VN)
  1725 + {
  1726 + if(!((*p).mask & OBJ_VT))
  1727 + outfile<<'/';
  1728 + outfile<<'/'<<(*vert).vn + 1;
  1729 + }
  1730 + }
  1731 + outfile<<'\n';
  1732 +
  1733 + }
  1734 +
  1735 +
  1736 +
  1737 +}
  1738 +
  1739 +//get methods
  1740 +unsigned int rtsOBJ::getNumVertices(){return v_list.size();}
  1741 +unsigned int rtsOBJ::getNumLines(){return lines.size();}
  1742 +unsigned int rtsOBJ::getNumFaces(){return faces.size();}
  1743 +unsigned int rtsOBJ::getNumPointLists(){return points.size();}
  1744 +unsigned int rtsOBJ::getNumTexCoords(){return vt_list.size();}
  1745 +unsigned int rtsOBJ::getNumNormals(){return vn_list.size();}
  1746 +
  1747 +//these functions return the coordinate index as well as the value
  1748 +unsigned int rtsOBJ::getNumFaceVertices(unsigned int face){return primitives[face].p.size();}
  1749 +unsigned int rtsOBJ::getFaceVertex(unsigned int face, unsigned int vertex){return primitives[face].p[vertex].v;}
  1750 +unsigned int rtsOBJ::getFaceNormal(unsigned int face, unsigned int normal){return primitives[face].p[normal].vn;}
  1751 +unsigned int rtsOBJ::getFaceTexCoord(unsigned int face, unsigned int texcoord){return primitives[face].p[texcoord].vt;}
  1752 +unsigned int rtsOBJ::getNumLineVertices(unsigned int line){return primitives[line].p.size();}
  1753 +unsigned int rtsOBJ::getLineVertex(unsigned int line, unsigned int vertex){return primitives[line].p[vertex].v;}
  1754 +unsigned int rtsOBJ::getLineTexCoord(unsigned int line, unsigned int texcoord){return primitives[line].p[texcoord].vt;}
  1755 +point3D<float> rtsOBJ::getVertex3d(unsigned int index)
  1756 +{
  1757 + return point3D<float>(v_list[index].x, v_list[index].y, v_list[index].z);
  1758 +}
  1759 +point3D<float> rtsOBJ::getTexCoord3d(unsigned int index)
  1760 +{
  1761 + return point3D<float>(vt_list[index].u, vt_list[index].v, vt_list[index].w);
  1762 +}
  1763 +point3D<float> rtsOBJ::getNormal3d(unsigned int index)
  1764 +{
  1765 + return point3D<float>(vn_list[index].i, vn_list[index].j, vn_list[index].k);
  1766 +}
  1767 +vertex_position rtsOBJ::getVertex(unsigned int index){return v_list[index];}
  1768 +vertex_texture rtsOBJ::getTexCoord(unsigned int index){return vt_list[index];}
  1769 +vertex_normal rtsOBJ::getNormal(unsigned int index){return vn_list[index];}
  1770 +
  1771 +
  1772 +unsigned int rtsOBJ::getPrimitiveType(unsigned int primitive)
  1773 +{
  1774 + /*
  1775 + switch(primitives[i].type)
  1776 + {
  1777 + case OBJ_POINTS:
  1778 + return OBJ_POINTS;
  1779 + break;
  1780 + case OBJ_LINES:
  1781 + return OBJ_LINES;
  1782 + break;
  1783 + case OBJ_FACE:
  1784 + f_RenderFace(i);
  1785 + break;
  1786 + }*/
  1787 + return 0;
  1788 +}
  1789 +/****************************************************/
  1790 +/*******Iterator Methods*****************************/
  1791 +/****************************************************/
  1792 +
  1793 +rtsOBJ::iterator rtsOBJ::begin()
  1794 +{
  1795 + //create an iterator that will be returned and assign it to this OBJ
  1796 + iterator result;
  1797 + result.obj = this;
  1798 + result.end_object = false;
  1799 + result.end_primitive = false;
  1800 +
  1801 + //if there are no primitives, return the end iterator
  1802 + if(primitives.size() == 0)
  1803 + return end();
  1804 +
  1805 + //start at the beginning of the primitive array
  1806 + result.primitive_index = 0;
  1807 +
  1808 + return result;
  1809 +}
  1810 +
  1811 +rtsOBJ::iterator rtsOBJ::end()
  1812 +{
  1813 + //create an end iterator to return
  1814 + iterator result;
  1815 + result.obj = this;
  1816 + result.end_primitive = true;
  1817 + result.primitive_index = result.obj->primitives.size();
  1818 +
  1819 + return result;
  1820 +}
  1821 +
  1822 +void rtsOBJ::iterator::operator++()
  1823 +{
  1824 + primitive_index++;
  1825 + if(primitive_index >= obj->primitives.size())
  1826 + (*this) = obj->end();
  1827 +
  1828 +}
  1829 +
  1830 +bool rtsOBJ::iterator::operator ==(rtsOBJ::iterator operand)
  1831 +{
  1832 + if(operand.primitive_index == primitive_index)
  1833 + return true;
  1834 + else return false;
  1835 +}
  1836 +
  1837 +bool rtsOBJ::iterator::operator !=(rtsOBJ::iterator operand)
  1838 +{
  1839 + if(operand.primitive_index != primitive_index)
  1840 + return true;
  1841 + else return false;
  1842 +}
  1843 +
  1844 +unsigned int rtsOBJ::iterator::operator*()
  1845 +{
  1846 + return primitive_index;
  1847 +}
  1848 +
  1849 +void rtsOBJ::iterator::print()
  1850 +{
  1851 + cout<<"This is a test"<<endl;
  1852 +}
  1853 +
  1854 +
  1855 +
  1856 +
  1857 +#endif
... ...
rts/rtsCamera.h 0 โ†’ 100644
  1 +++ a/rts/rtsCamera.h
  1 +#include "rtsVector3d.h"
  2 +#include "rtsPoint3d.h"
  3 +#include "rtsQuaternion.h"
  4 +
  5 +#ifndef RTS_CAMERA_H
  6 +#define RTS_CAMERA_H
  7 +
  8 +class rtsCamera
  9 +{
  10 + vector3D<float> d; //direction that the camera is pointing
  11 + point3D<float> p; //position of the camera
  12 + vector3D<float> up; //"up" direction
  13 + float focus; //focal length of the camera
  14 + float fov;
  15 +
  16 + //private function makes sure that the up vector is orthogonal to the direction vector and both are normalized
  17 + void stabalize()
  18 + {
  19 + vector3D<float> side = up.X(d);
  20 + up = d.X(side);
  21 + up.Normalize();
  22 + d.Normalize();
  23 + }
  24 +
  25 +public:
  26 + void setPosition(point3D<float> pos)
  27 + {
  28 + p = pos;
  29 + }
  30 + void setPosition(float x, float y, float z){setPosition(point3D<float>(x, y, z));}
  31 +
  32 + void setFocalDistance(float distance){focus = distance;}
  33 + void setFOV(float field_of_view){fov = field_of_view;}
  34 +
  35 + void LookAt(point3D<float> pos)
  36 + {
  37 + //find the new direction
  38 + d = pos - p;
  39 +
  40 + //find the distance from the look-at point to the current position
  41 + focus = d.Length();
  42 +
  43 + //stabalize the camera
  44 + stabalize();
  45 + }
  46 + void LookAt(float px, float py, float pz){LookAt(point3D<float>(px, py, pz));}
  47 + void LookAt(point3D<float> pos, vector3D<float> new_up){up = new_up; LookAt(pos);}
  48 + void LookAt(float px, float py, float pz, float ux, float uy, float uz){LookAt(point3D<float>(px, py, pz), vector3D<float>(ux, uy, uz));}
  49 + void LookAtDolly(float lx, float ly, float lz)
  50 + {
  51 + //find the current focus point
  52 + point3D<float> f = p + focus*d;
  53 + vector3D<float> T = point3D<float>(lx, ly, lz) - f;
  54 + p = p + T;
  55 + }
  56 +
  57 + void Dolly(vector3D<float> direction)
  58 + {
  59 + p = p+direction;
  60 + }
  61 + void Dolly(float x, float y, float z){Dolly(vector3D<float>(x, y, z));}
  62 + void Push(float delta)
  63 + {
  64 + if(delta > focus)
  65 + delta = focus;
  66 +
  67 + focus -= delta;
  68 +
  69 + Dolly(d*delta);
  70 + }
  71 +
  72 + void Pan(float theta_x, float theta_y, float theta_z)
  73 + {
  74 + //x rotation is around the up axis
  75 + rtsQuaternion<float> qx;
  76 + qx.CreateRotation(theta_x, up.x, up.y, up.z);
  77 +
  78 + //y rotation is around the side axis
  79 + vector3D<float> side = up.X(d);
  80 + rtsQuaternion<float> qy;
  81 + qy.CreateRotation(theta_y, side.x, side.y, side.z);
  82 +
  83 + //z rotation is around the direction vector
  84 + rtsQuaternion<float> qz;
  85 + qz.CreateRotation(theta_z, d.x, d.y, d.z);
  86 +
  87 + //combine the rotations in x, y, z order
  88 + rtsQuaternion<float> final = qz*qy*qx;
  89 +
  90 + //get the rotation matrix
  91 + matrix4x4<float> rot_matrix = final.toMatrix();
  92 +
  93 + //apply the rotation
  94 + d = rot_matrix*d;
  95 + up = rot_matrix*up;
  96 +
  97 + //stabalize the camera
  98 + stabalize();
  99 +
  100 + }
  101 + void Pan(float theta_x){Pan(theta_x, 0, 0);}
  102 + void Tilt(float theta_y){Pan(0, theta_y, 0);}
  103 + void Twist(float theta_z){Pan(0, 0, theta_z);}
  104 +
  105 + void Zoom(float delta)
  106 + {
  107 + fov -= delta;
  108 + if(fov < 0.5)
  109 + fov = 0.5;
  110 + if(fov > 180)
  111 + fov = 180;
  112 + }
  113 +
  114 + void OrbitFocus(float theta_x, float theta_y)
  115 + {
  116 + //find the focal point
  117 + point3D<float> focal_point = p + focus*d;
  118 +
  119 + //center the coordinate system on the focal point
  120 + point3D<float> centered = p - (focal_point - point3D<float>(0, 0, 0));
  121 +
  122 + //create the x rotation (around the up vector)
  123 + rtsQuaternion<float> qx;
  124 + qx.CreateRotation(theta_x, up.x, up.y, up.z);
  125 + centered = qx.toMatrix()*centered;
  126 +
  127 + //get a side vector for theta_y rotation
  128 + vector3D<float> side = up.X((point3D<float>(0, 0, 0) - centered).Normalize());
  129 +
  130 + rtsQuaternion<float> qy;
  131 + qy.CreateRotation(theta_y, side.x, side.y, side.z);
  132 + centered = qy.toMatrix()*centered;
  133 +
  134 + //perform the rotation on the centered camera position
  135 + //centered = final.toMatrix()*centered;
  136 +
  137 + //re-position the camera
  138 + p = centered + (focal_point - point3D<float>(0, 0, 0));
  139 +
  140 + //make sure we are looking at the focal point
  141 + LookAt(focal_point);
  142 +
  143 + //stabalize the camera
  144 + stabalize();
  145 +
  146 + }
  147 +
  148 + void Slide(float u, float v)
  149 + {
  150 + vector3D<float> V = up.Normalize();
  151 + vector3D<float> U = up.X(d).Normalize();
  152 +
  153 + p = p + (V * v) + (U * u);
  154 + }
  155 +
  156 + //accessor methods
  157 + point3D<float> getPosition(){return p;}
  158 + vector3D<float> getUp(){return up;}
  159 + vector3D<float> getDirection(){return d;}
  160 + point3D<float> getLookAt(){return p + focus*d;}
  161 + float getFOV(){return fov;}
  162 +
  163 + //output the camera settings
  164 + const void print(ostream& output)
  165 + {
  166 + output<<"Position: "<<p<<endl;
  167 +
  168 + }
  169 + friend ostream& operator<<(ostream& out, const rtsCamera& c)
  170 + {
  171 + out<<"Position: "<<c.p<<endl;
  172 + out<<"Direction: "<<c.d<<endl;
  173 + out<<"Up: "<<c.up<<endl;
  174 + out<<"Focal Distance: "<<c.focus<<endl;
  175 + return out;
  176 + }
  177 +
  178 + //constructor
  179 + rtsCamera()
  180 + {
  181 + p = point3D<float>(0, 0, 0);
  182 + d = vector3D<float>(0, 0, 1);
  183 + up = vector3D<float>(0, 1, 0);
  184 + focus = 1;
  185 +
  186 + }
  187 +};
  188 +
  189 +
  190 +
  191 +#endif
0 192 \ No newline at end of file
... ...
rts/rtsFilename.h 0 โ†’ 100644
  1 +++ a/rts/rtsFilename.h
  1 +#include <string>
  2 +
  3 +using namespace std;
  4 +
  5 +#ifndef RTS_FILENAME_H
  6 +#define RTS_FILENAME_H
  7 +
  8 +class rtsFilename
  9 +{
  10 +private:
  11 + string filename;
  12 +
  13 +public:
  14 + string getFilename()
  15 + {
  16 + int pos = filename.find_last_of("/\\");
  17 + string name = filename.substr(pos+1, filename.size());
  18 + return name;
  19 + }
  20 +
  21 + rtsFilename& operator=(const string str)
  22 + {
  23 + filename = str;
  24 + return *this;
  25 + }
  26 + rtsFilename(const string str){filename = str;}
  27 + rtsFilename(){filename = "";}
  28 +
  29 + string getExtension()
  30 + {
  31 + int pos = filename.find_last_of(".");
  32 + string ext = filename.substr(pos+1, filename.size() - pos);
  33 + return ext;
  34 + }
  35 +
  36 + string getDirectory()
  37 + {
  38 + int pos = filename.find_last_of("/\\");
  39 + string directory;
  40 + if(pos != -1)
  41 + directory = filename.substr(0, pos);
  42 + else
  43 + directory = "";
  44 + return directory;
  45 + }
  46 +
  47 + string getPrefix()
  48 + {
  49 + int slash = filename.find_last_of("/\\");
  50 + int dot = filename.find_last_of(".");
  51 +
  52 + string prefix;
  53 + prefix = filename.substr(slash+1, dot - slash - 1);
  54 + return prefix;
  55 +
  56 + }
  57 +
  58 + string getString()
  59 + {
  60 + return filename;
  61 + }
  62 +
  63 +
  64 +
  65 +};
  66 +
  67 +#endif
0 68 \ No newline at end of file
... ...
rts/rtsGraph.h 0 โ†’ 100644
  1 +++ a/rts/rtsGraph.h
  1 +#ifndef RTS_GRAPH_H
  2 +#define RTS_GRAPH_H
  3 +
  4 +#include <list>
  5 +#include <algorithm>
  6 +
  7 +using namespace std;
  8 +
  9 +template<typename T>
  10 +class rtsGraph
  11 +{
  12 + unsigned int current_id;
  13 +public:
  14 + class rtsGraphNode;
  15 + typedef typename list<rtsGraphNode>::iterator rtsGraphNodePtr;
  16 +
  17 + class rtsGraphNode
  18 + {
  19 + public:
  20 + list<rtsGraphNodePtr> ConnectionList;
  21 + unsigned int ID;
  22 + T Data;
  23 + };
  24 +
  25 + list<rtsGraphNode> NodeList;
  26 +
  27 + rtsGraphNodePtr addNode(T data)
  28 + {
  29 + //Adds a node to the graph. This node is unconnected by default.
  30 +
  31 + //create the new node
  32 + rtsGraphNode new_node;
  33 + //set the data to the data provided
  34 + new_node.Data = data;
  35 + //set the id
  36 + new_node.ID = current_id++;
  37 +
  38 + //add the node to the node list
  39 + NodeList.push_back(new_node);
  40 + rtsGraphNodePtr result = NodeList.end();
  41 + result--;
  42 + return result;
  43 + }
  44 + bool cmpPtr(const rtsGraphNodePtr a, const rtsGraphNodePtr b)
  45 + {
  46 + return (*a).ID < (*b).ID;
  47 + }
  48 +
  49 + void addConnection(rtsGraphNodePtr n0, rtsGraphNodePtr n1)
  50 + {
  51 + //adds a connection between two nodes
  52 + //connect n0 to n1
  53 + (*n0).ConnectionList.push_back(n1);
  54 + (*n1).ConnectionList.push_back(n0);
  55 +
  56 + }
  57 +
  58 + void removeNode(rtsGraphNodePtr n)
  59 + {
  60 +
  61 + typename list<rtsGraphNodePtr>::iterator i;
  62 + typename list<rtsGraphNodePtr>::iterator j;
  63 + typename list<rtsGraphNodePtr>::iterator temp;
  64 + rtsGraphNodePtr m;
  65 + rtsGraphNodePtr k;
  66 + /*Remove all of the connections TO n*/
  67 +
  68 + //for each node m connected to n
  69 + for(i = (*n).ConnectionList.begin(); i != (*n).ConnectionList.end(); i++)
  70 + {
  71 + m = (*i);
  72 + //for each node k connected to m
  73 + j = (*m).ConnectionList.begin();
  74 + while(j != (*m).ConnectionList.end())
  75 + {
  76 + k = (*j);
  77 + //if k is the same as n, remove it
  78 + if(k == n)
  79 + {
  80 + temp = j;
  81 + j++;
  82 + (*m).ConnectionList.erase(temp);
  83 + }
  84 + else
  85 + j++;
  86 +
  87 + }
  88 + }
  89 +
  90 + /*Add all connections to neighboring nodes*/
  91 +
  92 + //for each node m connected to n
  93 + for(i = (*n).ConnectionList.begin(); i != (*n).ConnectionList.end(); i++)
  94 + {
  95 + m = (*i);
  96 + //for each node k connected to n
  97 + for(j = (*n).ConnectionList.begin(); j != (*n).ConnectionList.end(); j++)
  98 + {
  99 + k = (*j);
  100 + if(k != m)
  101 + (*m).ConnectionList.push_back(k);
  102 +
  103 + }
  104 + //(*m).ConnectionList.sort(&rtsGraph<T>::cmpPtr);
  105 + //sort((*m).ConnectionList.begin(), (*m).ConnectionList.end(), rtsGraph<T>::cmpPtr);
  106 + (*m).ConnectionList.unique();
  107 + }
  108 +
  109 +
  110 +
  111 +
  112 +
  113 +
  114 +
  115 + }
  116 +
  117 +
  118 + void PrintGraph()
  119 + {
  120 + rtsGraphNodePtr i;
  121 + typename list<rtsGraphNodePtr>::iterator c;
  122 + for(i = NodeList.begin(); i != NodeList.end(); i++)
  123 + {
  124 + cout<<(*i).Data<<": ";
  125 + for(c = (*i).ConnectionList.begin(); c != (*i).ConnectionList.end(); c++)
  126 + {
  127 + if(c != (*i).ConnectionList.begin())
  128 + cout<<"--";
  129 + cout<<(*(*c)).Data;
  130 + }
  131 + cout<<endl;
  132 +
  133 + }
  134 +
  135 + }
  136 +
  137 +
  138 +
  139 +
  140 +};
  141 +
  142 +#endif
0 143 \ No newline at end of file
... ...
rts/rtsLinearAlgebra.h 0 โ†’ 100644
  1 +++ a/rts/rtsLinearAlgebra.h
  1 +/** \file
  2 + \brief Used to load common 3D linear algebra classes such as matrices, vectors, and points.
  3 +
  4 +The rtsLinearAlgebra.h file is used to load linear algebra objects commonly used in 3D graphics.
  5 +This includes the 3D versions of the vector, point, and matrix classes.
  6 +*/
  7 +
  8 +#define RTS_PI 3.14159 /**<Defines the value of PI used in RTS algorithms*/
  9 +#define TORADIANS(a) (a)*RTS_PI/180.0 /**<Defines a macro that converts a from degrees to radians*/
  10 +#define TODEGREES(a) (a)*180.0/RTS_PI /**<Defines a macro that converts a from radians to degrees*/
  11 +
  12 +#include <math.h>
  13 +#include "rtsVector3d.h"
  14 +#include "rtsPoint3d.h"
  15 +#include "rtsMatrix4x4.h"
0 16 \ No newline at end of file
... ...
rts/rtsMatrix4x4.h 0 โ†’ 100644
  1 +++ a/rts/rtsMatrix4x4.h
  1 +#include <iostream>
  2 +#include <iomanip>
  3 +#include <stdio.h>
  4 +#include <string.h>
  5 +
  6 +#include "rtsVector3d.h"
  7 +#include "rtsPoint3d.h"
  8 +
  9 +using namespace std;
  10 +#ifndef RTSMATRIX4X4_H
  11 +#define RTSMATRIX4X4_H
  12 +
  13 +#define RTS_PI 3.14159
  14 +
  15 +///This class represents a 4x4 matrix, which is often used to represent affine transformations on 3D points and vectors.
  16 +
  17 +///
  18 +///This class is designed to work with point3d<T> and vector3d<T>. Data is stored internally in a column-major form which is compatible with OpenGL.
  19 +///
  20 +
  21 +template <class T>
  22 +class matrix4x4
  23 +{
  24 + /*stored as:
  25 + | 0 4 8 12 |
  26 + | |
  27 + | 1 5 9 13 |
  28 + | |
  29 + | 2 6 10 14 |
  30 + | |
  31 + | 3 7 11 15 |
  32 + */
  33 +public:
  34 + T m_matrix[16];
  35 +
  36 + //constructors
  37 + matrix4x4(); ///<Constructor initializes all values to zero.
  38 + matrix4x4(T c0r0, T c0r1, T c0r2, T c0r3,
  39 + T c1r0, T c1r1, T c1r2, T c1r3,
  40 + T c2r0, T c2r1, T c2r2, T c2r3,
  41 + T c3r0, T c3r1, T c3r2, T c3r3); ///<Constructor initializes all values to those specified as parameters. c=column, r=row
  42 +
  43 + //overloaded operators
  44 + T& operator()(int row, int column){return m_matrix[column*4 + row];} ///<Returns the value at the specified position. This function can be used as both m(0, 0) = x and x = m(0, 0)
  45 + vector3D<T> operator*(vector3D<T> rhs); ///<Overloaded arithmetic operator. This function multiplies a vector by the current matrix, returning the transformed vector3D.
  46 + point3D<T> operator*(point3D<T> rhs); ///<Overloaded arithmetic operator. This function multiplies a point by the current matrix, returning the transformed point3D.
  47 + matrix4x4<T> operator*(matrix4x4<T> rhs); ///<Overloaded arithmetic operator. Computes the result of a matrix x matrix multiplication.
  48 +
  49 + //methods
  50 + void SetIdentity(); ///<Sets the current matrix to the identity matrix.
  51 + void SetRotation(T angle, T x, T y, T z); ///<Creates a matrix that represents a rotation of "angle" degrees around the axis given by (x, y, z).
  52 + void SetTranslation(T x, T y, T z); ///<Creates a matrix that represents a translation specified by the vector (x, y, z).
  53 + void SetScale(T x, T y, T z); ///<Creates a matrix that represents a scale along each axis given by the scalars x, y, and z.
  54 +
  55 + //output
  56 + void Print(int width = 7, int precision = 2);///<Sends the current matrix to the standard output.
  57 +
  58 +};
  59 +
  60 +
  61 +template <class T>
  62 +matrix4x4<T>::matrix4x4()
  63 +{
  64 + memset(m_matrix, 0, sizeof(T)*16);
  65 +}
  66 +
  67 +template <class T>
  68 +matrix4x4<T>::matrix4x4(T c0r0, T c0r1, T c0r2, T c0r3,
  69 + T c1r0, T c1r1, T c1r2, T c1r3,
  70 + T c2r0, T c2r1, T c2r2, T c2r3,
  71 + T c3r0, T c3r1, T c3r2, T c3r3)
  72 +{
  73 +
  74 + T new_matrix[16] = {c0r0,c0r1,c0r2,c0r3,c1r0,c1r1,c1r2,c1r3,c2r0,c2r1,c2r2,c2r3,c3r0,c3r1,c3r2,c3r3};
  75 + memcpy(m_matrix, new_matrix, 16*sizeof(T));
  76 +}
  77 +
  78 +template <class T>
  79 +vector3D<T> matrix4x4<T>::operator*(vector3D<T> rhs)
  80 +{
  81 + vector3D<T> result;
  82 + result.x = m_matrix[0] * rhs.x + m_matrix[4] * rhs.y + m_matrix[8] * rhs.z;
  83 + result.y = m_matrix[1] * rhs.x + m_matrix[5] * rhs.y + m_matrix[9] * rhs.z;
  84 + result.z = m_matrix[2] * rhs.x + m_matrix[6] * rhs.y + m_matrix[10] * rhs.z;
  85 + return result;
  86 +}
  87 +
  88 +template <class T>
  89 +point3D<T> matrix4x4<T>::operator *(point3D<T> rhs)
  90 +{
  91 + point3D<T> result;
  92 + result.x = m_matrix[0] * rhs.x + m_matrix[4] * rhs.y + m_matrix[8] * rhs.z + m_matrix[12];
  93 + result.y = m_matrix[1] * rhs.x + m_matrix[5] * rhs.y + m_matrix[9] * rhs.z + m_matrix[13];
  94 + result.z = m_matrix[2] * rhs.x + m_matrix[6] * rhs.y + m_matrix[10] * rhs.z + m_matrix[14];
  95 + T w = m_matrix[3] + m_matrix[7] + m_matrix[11] + m_matrix[15];
  96 + result.x/=w;
  97 + result.y/=w;
  98 + result.z/=w;
  99 + return result;
  100 +}
  101 +
  102 +template <class T>
  103 +matrix4x4<T> matrix4x4<T>::operator *(matrix4x4<T> rhs)
  104 +{
  105 + matrix4x4<T> result;
  106 + int i,j,r;
  107 + for(i = 0; i<4; i++)
  108 + for(j = 0; j<4; j++)
  109 + for(r=0; r<4; r++)
  110 + result(i, j) += (*this)(i, r) * rhs(r, j);
  111 +
  112 + return result;
  113 +}
  114 +
  115 +
  116 +
  117 +
  118 +template <class T>
  119 +void matrix4x4<T>::SetIdentity()
  120 +{
  121 + T new_matrix[16] = {1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1};
  122 + memcpy(m_matrix, new_matrix, 16*sizeof(T));
  123 +}
  124 +
  125 +template <class T>
  126 +void matrix4x4<T>::SetTranslation(T x, T y, T z)
  127 +{
  128 + T new_matrix[16] = {1,0,0,0,0,1,0,0,0,0,1,0,x,y,z,1};
  129 + memcpy(m_matrix, new_matrix, 16*sizeof(T));
  130 +}
  131 +
  132 +template <class T>
  133 +void matrix4x4<T>::SetScale(T x, T y, T z)
  134 +{
  135 + T new_matrix[16] = {x,0,0,0,0,y,0,0,0,0,z,0,0,0,0,1};
  136 + memcpy(m_matrix, new_matrix, 16*sizeof(T));
  137 +}
  138 +
  139 +template <class T>
  140 +void matrix4x4<T>::SetRotation(T angle, T x, T y, T z)
  141 +{
  142 + //create the axis of rotation
  143 + vector3D<T> axis(x, y, z);
  144 + T length = axis.Length(); //make sure that it is normalized
  145 + if(length != 1)
  146 + axis.Normalize();
  147 +
  148 + T c = cos(angle*RTS_PI/180.0); //compute the sine and cosine of angle
  149 + T s = sin(angle*RTS_PI/180.0);
  150 +
  151 + //create the matrix
  152 + m_matrix[0] = x*x*(1-c) + c;
  153 + m_matrix[1] = y*x*(1-c) + z*s;
  154 + m_matrix[2] = x*z*(1-c) - y*s;
  155 + m_matrix[4] = x*y*(1-c) - z*s;
  156 + m_matrix[5] = y*y*(1-c) + c;
  157 + m_matrix[6] = y*z*(1-c) + x*s;
  158 + m_matrix[8] = x*z*(1-c) + y*s;
  159 + m_matrix[9] = y*z*(1-c) - x*s;
  160 + m_matrix[10]= z*z*(1-c) + c;
  161 + m_matrix[15]= 1;
  162 +}
  163 +
  164 +
  165 +template <class T>
  166 +void matrix4x4<T>::Print(int width, int precision)
  167 +{
  168 + cout<<setiosflags(ios::fixed);
  169 + cout<<setprecision(precision);
  170 + cout<<setw(width)<<m_matrix[0]
  171 + <<setw(width)<<m_matrix[4]
  172 + <<setw(width)<<m_matrix[8]
  173 + <<setw(width)<<m_matrix[12]<<endl
  174 + <<setw(width)<<m_matrix[1]
  175 + <<setw(width)<<m_matrix[5]
  176 + <<setw(width)<<m_matrix[9]
  177 + <<setw(width)<<m_matrix[13]<<endl
  178 + <<setw(width)<<m_matrix[2]
  179 + <<setw(width)<<m_matrix[6]
  180 + <<setw(width)<<m_matrix[10]
  181 + <<setw(width)<<m_matrix[14]<<endl
  182 + <<setw(width)<<m_matrix[3]
  183 + <<setw(width)<<m_matrix[7]
  184 + <<setw(width)<<m_matrix[11]
  185 + <<setw(width)<<m_matrix[15]<<endl;
  186 +}
  187 +
  188 +
  189 +
  190 +
  191 +
  192 +
  193 +
  194 +
  195 +
  196 +#endif
0 197 \ No newline at end of file
... ...
rts/rtsPoint3d.h 0 โ†’ 100644
  1 +++ a/rts/rtsPoint3d.h
  1 +#ifndef RTSPOINT3D_H
  2 +#define RTSPOINT3D_H
  3 +#include "rtsVector3d.h"
  4 +
  5 +///This class is used to store information about a 3D point. It is designed to work with the class vector3D<T> for linear algebra operations.
  6 +
  7 +template <class T> class point3D
  8 +{
  9 + //friend class vector3D<T>;
  10 +public:
  11 + //data values
  12 + T x;
  13 + T y;
  14 + T z;
  15 +
  16 + point3D(); ///<Constructor initializes the point at the origin (0,0,0).
  17 + point3D(T new_x, T new_y, T new_z); ///<Constructor initializes the point to the position specified by (new_x, new_y, new_z).
  18 +
  19 + //operators
  20 + bool operator==(point3D<T> param); ///<Overloaded boolean operator. Returns true if the two oparands are at the same position.
  21 + bool operator!=(point3D<T> param); ///<Overloaded boolean operator for !=
  22 + point3D<T> operator+(vector3D<T> param); ///<Overloaded arithmetic oparator. Returns the sum of the current point and a given vector.
  23 + point3D<T> operator-(vector3D<T> param); ///<Overloaded arithmetic operator. Returns the sum of the current point and the negative of a given vector.
  24 + vector3D<T> operator-(point3D<T> param); ///<Overloaded arithmetic operator. Returns the vector representing the space between two points.
  25 +
  26 + //casting operators
  27 + template <class U> operator point3D<U>(); ///<Overloaded casting operator. Allows casting between points of different types.
  28 +
  29 + //output
  30 + friend ostream& operator<<(ostream& os, const point3D<T> &rhs)
  31 + {
  32 + os<<"("<<rhs.x<<","<<rhs.y<<","<<rhs.z<<")";
  33 + return os;
  34 + }
  35 +
  36 + /*point3D<T> & operator=(const point3D<T> & rhs)
  37 + {
  38 + if(this != &rhs)
  39 + {
  40 + x = rhs.x;
  41 + y = rhs.y;
  42 + z = rhs.z;
  43 + }
  44 + return *this;
  45 + }*/
  46 +
  47 + void print();
  48 +};
  49 +
  50 +template <class T>
  51 +template <class U>
  52 +point3D<T>::operator point3D<U>()
  53 +{
  54 + point3D<U> cast_result(x, y, z);
  55 + return cast_result;
  56 +}
  57 +
  58 +template <class T> point3D<T>::point3D()
  59 +{
  60 + x=0;
  61 + y=0;
  62 + z=0;
  63 +}
  64 +
  65 +template <class T> point3D<T>::point3D(T new_x, T new_y, T new_z)
  66 +{
  67 + x=new_x;
  68 + y=new_y;
  69 + z=new_z;
  70 +}
  71 +
  72 +template <class T>
  73 +point3D<T> point3D<T>::operator -(vector3D<T> param)
  74 +{
  75 + point3D<T> result; //create the result
  76 +
  77 + result.x = x-param.x; //perform the computation
  78 + result.y = y-param.y;
  79 + result.z = z-param.z;
  80 +
  81 + return result;
  82 +}
  83 +
  84 +template <class T>
  85 +vector3D<T> point3D<T>::operator -(point3D<T> param)
  86 +{
  87 + vector3D<T> result;
  88 + result.x = x - param.x;
  89 + result.y = y - param.y;
  90 + result.z = z - param.z;
  91 +
  92 + return result;
  93 +}
  94 +
  95 +template <class T>
  96 +point3D<T> point3D<T>::operator+(vector3D<T> param)
  97 +{
  98 + point3D<T> result; //create the result
  99 +
  100 + result.x = x+param.x; //perform the computation
  101 + result.y = y+param.y;
  102 + result.z = z+param.z;
  103 +
  104 + return result;
  105 +}
  106 +
  107 +template <class T>
  108 +bool point3D<T>::operator ==(point3D<T> param)
  109 +{
  110 + if(x == param.x && y == param.y && z == param.z)
  111 + return true;
  112 + else
  113 + return false;
  114 +}
  115 +
  116 +template <class T>
  117 +bool point3D<T>::operator !=(point3D<T> param)
  118 +{
  119 + if(x != param.x || y != param.y || z != param.z)
  120 + return true;
  121 + else
  122 + return false;
  123 +}
  124 +
  125 +
  126 +
  127 +template <class T>
  128 +void point3D<T>::print()
  129 +{
  130 + cout<<"("<<x<<","<<y<<","<<z<<")"<<endl;
  131 +}
  132 +
  133 +/*template <class T>
  134 +ostream& point3D<T>::operator<<(ostream& os, point3D<T> &rhs)
  135 +{
  136 + os<<"("<<x<<","<<y<<","<<z<<")";
  137 + return os;
  138 +}
  139 +*/
  140 +
  141 +#endif
... ...
rts/rtsQuaternion.h 0 โ†’ 100644
  1 +++ a/rts/rtsQuaternion.h
  1 +#include "rtsMatrix4x4.h"
  2 +
  3 +#ifndef RTS_QUATERNION_H
  4 +#define RTS_QUATERNION_H
  5 +
  6 +template<typename T>
  7 +class rtsQuaternion
  8 +{
  9 +public:
  10 + T w;
  11 + T x;
  12 + T y;
  13 + T z;
  14 +
  15 + void normalize();
  16 + void CreateRotation(T theta, T axis_x, T axis_y, T axis_z);
  17 + rtsQuaternion<T> operator*(rtsQuaternion<T> &rhs);
  18 + matrix4x4<T> toMatrix();
  19 +
  20 +
  21 + rtsQuaternion();
  22 + rtsQuaternion(T w, T x, T y, T z);
  23 +
  24 +};
  25 +
  26 +template<typename T>
  27 +void rtsQuaternion<T>::normalize()
  28 +{
  29 + double length=sqrt(w*w + x*x + y*y + z*z);
  30 + w=w/length;
  31 + x=x/length;
  32 + y=y/length;
  33 + z=z/length;
  34 +}
  35 +
  36 +template<typename T>
  37 +void rtsQuaternion<T>::CreateRotation(T theta, T axis_x, T axis_y, T axis_z)
  38 +{
  39 + //assign the given Euler rotation to this quaternion
  40 + w = cos(theta/2.0);
  41 + x = axis_x*sin(theta/2.0);
  42 + y = axis_y*sin(theta/2.0);
  43 + z = axis_z*sin(theta/2.0);
  44 +
  45 +
  46 +}
  47 +
  48 +template<typename T>
  49 +rtsQuaternion<T> rtsQuaternion<T>::operator *(rtsQuaternion<T> &param)
  50 +{
  51 + float A, B, C, D, E, F, G, H;
  52 +
  53 +
  54 + A = (w + x)*(param.w + param.x);
  55 + B = (z - y)*(param.y - param.z);
  56 + C = (w - x)*(param.y + param.z);
  57 + D = (y + z)*(param.w - param.x);
  58 + E = (x + z)*(param.x + param.y);
  59 + F = (x - z)*(param.x - param.y);
  60 + G = (w + y)*(param.w - param.z);
  61 + H = (w - y)*(param.w + param.z);
  62 +
  63 + rtsQuaternion<T> result;
  64 + result.w = B + (-E - F + G + H) /2;
  65 + result.x = A - (E + F + G + H)/2;
  66 + result.y = C + (E - F + G - H)/2;
  67 + result.z = D + (E - F - G + H)/2;
  68 +
  69 + return result;
  70 +}
  71 +
  72 +template<typename T>
  73 +matrix4x4<T> rtsQuaternion<T>::toMatrix()
  74 +{
  75 + matrix4x4<T> result;
  76 +
  77 +
  78 + double wx, wy, wz, xx, yy, yz, xy, xz, zz, x2, y2, z2;
  79 +
  80 +
  81 + // calculate coefficients
  82 + x2 = x + x; y2 = y + y;
  83 + z2 = z + z;
  84 + xx = x * x2; xy = x * y2; xz = x * z2;
  85 + yy = y * y2; yz = y * z2; zz = z * z2;
  86 + wx = w * x2; wy = w * y2; wz = w * z2;
  87 +
  88 + result(0, 0) = 1.0 - (yy + zz);
  89 + result(0, 1) = xy - wz;
  90 + //m[0][0] = 1.0 - (yy + zz); m[1][0] = xy - wz;
  91 +
  92 + result(0, 2) = xz + wy;
  93 + result(0, 3) = 0.0;
  94 + //m[2][0] = xz + wy; m[3][0] = 0.0;
  95 +
  96 + result(1, 0) = xy + wz;
  97 + result(1, 1) = 1.0 - (xx + zz);
  98 + //m[0][1] = xy + wz; m[1][1] = 1.0 - (xx + zz);
  99 +
  100 + result(1, 2) = yz - wx;
  101 + result(1, 3) = 0.0;
  102 + //m[2][1] = yz - wx; m[3][1] = 0.0;
  103 +
  104 + result(2, 0) = xz - wy;
  105 + result(2, 1) = yz + wx;
  106 + //m[0][2] = xz - wy; m[1][2] = yz + wx;
  107 +
  108 + result(2, 2) = 1.0 - (xx + yy);
  109 + result(3, 2) = 0.0;
  110 + //m[2][2] = 1.0 - (xx + yy); m[3][2] = 0.0;
  111 +
  112 + result(3, 0) = 0.0;
  113 + result(3, 1) = 0.0;
  114 + result(3, 2) = 0.0;
  115 + result(3, 3) = 1.0;
  116 + //m[0][3] = 0; m[1][3] = 0;
  117 + //m[2][3] = 0; m[3][3] = 1;
  118 + /*
  119 + double* orientationmatrix=(double*)m;
  120 + char c;
  121 +
  122 +
  123 + double* result=new double[16];
  124 + double* array=(double*)m;
  125 + for(int i=0; i<16; i++)
  126 + result[i]=array[i];
  127 + */
  128 +
  129 + return result;
  130 +}
  131 +
  132 +template<typename T>
  133 +rtsQuaternion<T>::rtsQuaternion()
  134 +{
  135 + w=0.0; x=0.0; y=0.0; z=0.0;
  136 +}
  137 +
  138 +template<typename T>
  139 +rtsQuaternion<T>::rtsQuaternion(T c, T i, T j, T k)
  140 +{
  141 + w=c; x=i; y=j; z=k;
  142 +}
  143 +
  144 +#endif
... ...
rts/rtsSourceCode.h 0 โ†’ 100644
  1 +++ a/rts/rtsSourceCode.h
  1 +#ifndef RTSSOURCECODE_H
  2 +#define RTSSOURCECODE_H
  3 +
  4 +#include <string>
  5 +#include <fstream>
  6 +#include <vector>
  7 +#include <iostream>
  8 +
  9 +using namespace std;
  10 +
  11 +///This class defines generic source code that can be loaded from text files. It is primarily used by the rts_glShaderProgram class for GLSL programming.
  12 +
  13 +class rtsSourceCode
  14 +{
  15 +public:
  16 + vector<string> source; //the actual source code
  17 + void clear() ///<Clears any current source code from the class.
  18 + {
  19 + source.clear();
  20 + }
  21 + void LoadSource(const char* filename) ///<Loads source code from a specified file.
  22 + {
  23 + ifstream infile; //create an input file
  24 + infile.open(filename); //load the specified file
  25 +
  26 + if(!infile.is_open()) //if the file is not open, exit
  27 + {
  28 + return;
  29 + }
  30 + source.clear(); //remove any previous code
  31 +
  32 + while(!infile.eof())
  33 + {
  34 + string current_line;
  35 + getline(infile, current_line);
  36 + current_line += '\n';
  37 + source.push_back(current_line);
  38 + }
  39 + }
  40 + rtsSourceCode(const char* filename) ///<Constructor creates the class and loads source code from the specified file.
  41 + {
  42 + LoadSource(filename);
  43 + }
  44 + rtsSourceCode(){} ///<Constructor creates a blank class.
  45 + rtsSourceCode& operator+=(const rtsSourceCode& rhs)
  46 + {
  47 + int lines = rhs.source.size();
  48 + for(int l=0; l<lines; l++)
  49 + source.push_back(rhs.source[l]);
  50 + return *this;
  51 + }
  52 + rtsSourceCode& operator+=(const string& rhs)
  53 + {
  54 + source.push_back(rhs);
  55 + return *this;
  56 + }
  57 + void ConsoleOut() ///<Sends the source code to the standard output.
  58 + {
  59 + unsigned int lines = source.size();
  60 + for(unsigned int l = 0; l<lines; l++)
  61 + cout<<l<<": "<<source[l];
  62 + }
  63 +};
  64 +
  65 +#endif
0 66 \ No newline at end of file
... ...
rts/rtsVector3d.h 0 โ†’ 100644
  1 +++ a/rts/rtsVector3d.h
  1 +///This class is used to store information for a 3D vector.
  2 +#include <iostream>
  3 +#include <math.h>
  4 +using namespace std;
  5 +
  6 +#ifndef RTSVECTOR3D_H
  7 +#define RTSVECTOR3D_H
  8 +
  9 +
  10 +template <class T> class vector3D
  11 +{
  12 + //friend class point3D<T>;
  13 +public:
  14 + //data values
  15 + T x;
  16 + T y;
  17 + T z;
  18 +
  19 + vector3D(); ///<Constructor. The resulting vector is initialized to (0,0,0)
  20 + vector3D(T new_x, T new_y, T new_z); ///<Constructor. Initialize the resulting vector to the value specified by (new_x, new_y, new_z)
  21 +
  22 + //operators
  23 + vector3D<T> operator+(vector3D<T> param); ///<Used for vector arithmetic. Allows two vectors with similar types to be added.
  24 + vector3D<T> operator-(vector3D<T> param); ///<Used for vector arithmetic. Allows two vectors with similar types to be subtracted.
  25 + T operator*(vector3D<T> param); ///<Used for vector arithmetic. Computes the inner product of two vectors of the same type.
  26 + vector3D<T> operator*(T param); ///<Used for vector arithmetic. Multiplies a vector by a scalar value of type T.
  27 + vector3D<T> X(vector3D<T> param); ///<Compute the cross product between two vectors
  28 +
  29 + friend vector3D<T> operator*(const T lhs, vector3D<T> rhs){return rhs*lhs;} ///<Allows vectors to be multiplied by scalars in either order
  30 +
  31 + //methods
  32 + vector3D<T> Times(vector3D<T> param); ///<Performs piecewise multiplication between two vectors [ex. (x1*x2, y1*y2, z1*z2)].
  33 + vector3D<T> Normalize(); ///<Returns the normalized version of the vector.
  34 + T Length(); ///<Returns the length of the vector.
  35 +
  36 + //casting operators
  37 + template <class U> operator vector3D<U>(); ///<Casting operator allows explicit casting between vector types.
  38 + //output
  39 + friend ostream& operator<<(ostream& os, const vector3D<T> &rhs)
  40 + {
  41 + os<<"("<<rhs.x<<","<<rhs.y<<","<<rhs.z<<")";
  42 + return os;
  43 + }
  44 + void print();
  45 +};
  46 +
  47 +template <class T>
  48 +template <class U>
  49 +vector3D<T>::operator vector3D<U>()
  50 +{
  51 + vector3D<U> cast_result(x, y, z);
  52 + return cast_result;
  53 +}
  54 +
  55 +template <class T> vector3D<T>::vector3D()
  56 +{
  57 + x=0;
  58 + y=0;
  59 + z=0;
  60 +}
  61 +
  62 +template <class T> vector3D<T>::vector3D(T new_x, T new_y, T new_z)
  63 +{
  64 + x=new_x;
  65 + y=new_y;
  66 + z=new_z;
  67 +}
  68 +
  69 +template <class T>
  70 +vector3D<T> vector3D<T>::operator -(vector3D<T> param)
  71 +{
  72 + vector3D<T> result; //create the result
  73 +
  74 + result.x = x-param.x; //perform the computation
  75 + result.y = y-param.y;
  76 + result.z = z-param.z;
  77 +
  78 + return result;
  79 +}
  80 +
  81 +template <class T>
  82 +vector3D<T> vector3D<T>::operator+(vector3D<T> param)
  83 +{
  84 + vector3D<T> result; //create the result
  85 +
  86 + result.x = x+param.x; //perform the computation
  87 + result.y = y+param.y;
  88 + result.z = z+param.z;
  89 +
  90 + return result;
  91 +}
  92 +
  93 +template <class T>
  94 +vector3D<T> vector3D<T>::Times(vector3D<T> param)
  95 +{
  96 + vector3D<T> result; //create the result
  97 +
  98 + result.x = x*param.x; //perform the computation
  99 + result.y = y*param.y;
  100 + result.z = z*param.z;
  101 +
  102 + return result;
  103 +}
  104 +
  105 +template <class T>
  106 +vector3D<T> vector3D<T>::operator*(T param)
  107 +{
  108 + vector3D<T> result; //create the result
  109 +
  110 + result.x = x*param; //perform the computation
  111 + result.y = y*param;
  112 + result.z = z*param;
  113 +
  114 + return result;
  115 +}
  116 +
  117 +template <class T>
  118 +T vector3D<T>::operator *(vector3D<T> param)
  119 +{
  120 + //This function computes the dot product between two vectors
  121 + return x*param.x + y*param.y + z*param.z;
  122 +}
  123 +
  124 +template <class T>
  125 +vector3D<T> vector3D<T>::X(vector3D<T> param)
  126 +{
  127 + vector3D<T> result;
  128 + result.x=y*param.z - z*param.y;
  129 + result.y=z*param.x - x*param.z;
  130 + result.z=x*param.y - y*param.x;
  131 +
  132 + return result;
  133 +}
  134 +
  135 +template <class T>
  136 +vector3D<T> vector3D<T>::Normalize()
  137 +{
  138 + T length = Length();
  139 + if(length ==0.0)
  140 + {
  141 + x = y = z = 0;
  142 + }
  143 + else
  144 + {
  145 + x/= length;
  146 + y /=length;
  147 + z /=length;
  148 + }
  149 + return *this;
  150 +}
  151 +
  152 +template <class T>
  153 +T vector3D<T>::Length()
  154 +{
  155 + return sqrt(x*x + y*y + z*z);
  156 +}
  157 +
  158 +template <class T>
  159 +void vector3D<T>::print()
  160 +{
  161 + cout<<"["<<x<<","<<y<<","<<z<<"]"<<endl;
  162 +}
  163 +
  164 +#endif
... ...
rts/rts_glShaderObject.h 0 โ†’ 100644
  1 +++ a/rts/rts_glShaderObject.h
  1 +#ifndef RTS_GLSHADERS
  2 +#define RTS_GLSHADERS
  3 +
  4 +#include <GL/glew.h>
  5 +//#include "windows.h"
  6 +#include <GL/gl.h>
  7 +#include "rtsSourceCode.h"
  8 +
  9 +class rts_glShaderObject
  10 +{
  11 +private:
  12 + void init()
  13 + {
  14 + id = 0;
  15 + compiled = false;
  16 + type = GL_FRAGMENT_SHADER;
  17 + }
  18 +public:
  19 + bool compiled;
  20 + GLenum type;
  21 + rtsSourceCode source;
  22 + GLuint id;
  23 + string log;
  24 +
  25 + rts_glShaderObject(GLenum type, const char* filename)
  26 + {
  27 + init(); //initialize the shader
  28 + SetType(type); //set the shader type
  29 + LoadSource(filename); //load the source code
  30 + }
  31 + rts_glShaderObject(GLenum type, rtsSourceCode sourceCode)
  32 + {
  33 + init(); //initialize the shader
  34 + SetType(type); //set the shader type
  35 + source = sourceCode;
  36 + }
  37 + rts_glShaderObject()
  38 + {
  39 + init();
  40 + }
  41 + rts_glShaderObject(GLenum type)
  42 + {
  43 + init();
  44 + SetType(type);
  45 + }
  46 + void LoadSource(const char* filename)
  47 + {
  48 + source = rtsSourceCode(filename); //get the shader source code
  49 +
  50 + }
  51 + void SetType(GLenum type)
  52 + {
  53 + if(id != 0) //if a shader currently exists, delete it
  54 + {
  55 + glDeleteShader(id);
  56 + id = 0;
  57 + }
  58 + type = type;
  59 + id = glCreateShader(type); //create a shader object
  60 + if(id == 0) //if a shader was not created, log an error
  61 + {
  62 + log = "Error getting shader ID from OpenGL";
  63 + return;
  64 + }
  65 + }
  66 + void UploadSource()
  67 + {
  68 + //create the structure for the shader source code
  69 + GLsizei count = source.source.size();
  70 + GLchar** code_string = new GLchar*[count];
  71 + GLint* length = new GLint[count];
  72 + for(int l = 0; l<count; l++) //for each line of code
  73 + {
  74 + length[l] = source.source[l].size();
  75 + code_string[l] = new GLchar[length[l]]; //copy the string into a new structure
  76 + source.source[l].copy(code_string[l], (unsigned int)length[l]);
  77 +
  78 + }
  79 + glShaderSource(id, count, (const GLchar**)code_string, length); //attach the shader source
  80 + }
  81 + void Compile()
  82 + {
  83 + /*
  84 + This function compiles the shader source code, records any errors to a log, and sets the compiled flag.
  85 + */
  86 + //send the source code to the GPU
  87 + UploadSource();
  88 +
  89 + //compile the shader
  90 + glCompileShader(id); //compile the shader
  91 + GLint compile_status;
  92 + glGetShaderiv(id, GL_COMPILE_STATUS, &compile_status); //get the compile status
  93 + if(compile_status != GL_TRUE) //if there was an error
  94 + {
  95 + GLchar buffer[1000]; //create a log buffer
  96 + GLsizei length;
  97 + glGetShaderInfoLog(id, 1000, &length, buffer); //get the log
  98 + log = buffer;
  99 + compiled = false;
  100 + }
  101 + else
  102 + compiled = true;
  103 +
  104 + }
  105 + void PrintLog()
  106 + {
  107 + cout<<log;
  108 + if(log.size() != 0) cout<<endl;
  109 + }
  110 + void Clean(){if(id != 0) glDeleteShader(id);}
  111 +};
  112 +
  113 +
  114 +
  115 +#endif
... ...
rts/rts_glShaderProgram.h 0 โ†’ 100644
  1 +++ a/rts/rts_glShaderProgram.h
  1 +#ifndef RTS_GLSHADERPROGRAM_H
  2 +#define RTS_GLSHADERPROGRAM_H
  3 +
  4 +/*********************************************************
  5 +//create a shader program
  6 + rts_glShaderProgram myProgram;
  7 +//initialize
  8 + myProgram.Init();
  9 +//Attach shaders
  10 + myProgram.AttachShader(GL_FRAGMENT_SHADER, "filename.glsl");
  11 +//Compile and link
  12 + myProgram.Compile();
  13 + myProgram.Link();
  14 + myProgram.PrintLog();
  15 +//attach uniform variables
  16 + myProgram.AttachTextureMap("texture", texture);
  17 + myProgram.AttachGlobalUniform("light_intensity", &intensity);
  18 +
  19 +//use the program
  20 + myProgram.BeginProgram();
  21 + //render
  22 + myProgram.EndProgram();
  23 +**********************************************************/
  24 +
  25 +
  26 +#include "rts_glShaderObject.h"
  27 +#include "rts_glShaderUniform.h"
  28 +#include "rts_glTextureMap.h"
  29 +#include <algorithm>
  30 +
  31 +using namespace std;
  32 +
  33 +class rts_glShaderProgram
  34 +{
  35 +private:
  36 + void get_uniforms()
  37 + {
  38 + GLint num_uniforms;
  39 + glGetProgramiv(id, GL_ACTIVE_UNIFORMS, &num_uniforms); //get the number of uniform variables
  40 + GLint max_name_length;
  41 + glGetProgramiv(id, GL_ACTIVE_UNIFORM_MAX_LENGTH, &max_name_length); //get the maximum uniform name length
  42 + GLchar* name_buffer = new GLchar[max_name_length]; //create a buffer to store the name
  43 + GLsizei length; //I'm not using these yet
  44 + GLint size;
  45 + GLenum type; //variable's data type
  46 + GLint location; //GPU location of the variable
  47 + for(int i=0; i<num_uniforms; i++) //create an rts_glShaderUniform structure for each variable
  48 + {
  49 + glGetActiveUniform(id, i, max_name_length, &length, &size, &type, name_buffer); //get the uniform information
  50 + location = glGetUniformLocation(id, name_buffer); //get the GPU location of the variable
  51 + //create the rts_glShaderUniform structure
  52 + rts_glShaderUniform current;
  53 + current.location = location;
  54 + current.name = name_buffer;
  55 + current.type = type;
  56 + current.p_value = NULL;
  57 +
  58 +
  59 + uniform_list.push_back(current);
  60 + }
  61 +
  62 + }
  63 + int get_index(const char* name)
  64 + {
  65 + unsigned int size = uniform_list.size();
  66 + for(unsigned int i=0; i<size; i++)
  67 + {
  68 + if(uniform_list[i].name == name)
  69 + return i;
  70 + }
  71 + return -1;
  72 + }
  73 + string log;
  74 +public:
  75 + GLuint id;
  76 + bool linked;
  77 + vector<rts_glShaderObject> shader_list; //list of opengl shaders
  78 + vector<rts_glShaderUniform> uniform_list; //list of active uniform variables
  79 + vector<rts_glTextureMap> texture_list; //list of texture maps
  80 +
  81 + rts_glShaderProgram()
  82 + {
  83 + linked = false;
  84 + id = 0;
  85 + }
  86 + void AttachShader(rts_glShaderObject shader)
  87 + {
  88 + if(id == 0)
  89 + {
  90 + Init();
  91 + }
  92 + if(shader.id == 0) //if the shader is invalid
  93 + {
  94 + log = "Shader is invalid";
  95 + return;
  96 + }
  97 +
  98 + //attach the shader to the program
  99 + glAttachShader(id, shader.id); //attach the shader to the program in OpenGL
  100 + CHECK_OPENGL_ERROR
  101 + shader_list.push_back(shader); //push the shader onto our list for later access
  102 + }
  103 + //type = GL_FRAGMENT_SHADER or GL_VERTEX_SHADER
  104 + void AttachShader(GLenum type, const char* filename)
  105 + {
  106 + rts_glShaderObject shader(type, filename);
  107 + AttachShader(shader);
  108 + }
  109 + void AttachShader(GLenum type, rtsSourceCode source)
  110 + {
  111 + rts_glShaderObject shader(type, source);
  112 + AttachShader(shader);
  113 + }
  114 + void PrintLog()
  115 + {
  116 + cout<<log;
  117 +
  118 + if(log.size() != 0) cout<<endl;
  119 + }
  120 + void Compile()
  121 + {
  122 + if(shader_list.size() == 0)
  123 + {
  124 + log = "No shaders to compile";
  125 + return;
  126 + }
  127 +
  128 + vector<rts_glShaderObject>::iterator iter;
  129 + for(iter = shader_list.begin(); iter != shader_list.end(); iter++)
  130 + {
  131 + (*iter).Compile();
  132 + //(*iter).PrintLog();
  133 + }
  134 + }
  135 + void Link()
  136 + {
  137 + glLinkProgram(id); //link the current shader program
  138 + GLint link_status; //test to see if the link went alright
  139 + glGetProgramiv(id, GL_LINK_STATUS, &link_status);
  140 + if(link_status != GL_TRUE)
  141 + {
  142 + linked = false;
  143 + }
  144 + else
  145 + linked = true;
  146 +
  147 + GLsizei length;
  148 + GLchar buffer[1000];
  149 + glGetProgramInfoLog(id, 1000, &length, buffer);
  150 + log = buffer;
  151 +
  152 + get_uniforms(); //create the list of active uniform variables
  153 + }
  154 + void BeginProgram()
  155 + {
  156 + CHECK_OPENGL_ERROR
  157 + if(id == 0) //if the program is invalid, return
  158 + {
  159 + log = "Invalid program, cannot use.";
  160 + return;
  161 + }
  162 + if(!linked)
  163 + {
  164 + cout<<"Shader Program used without being linked."<<endl;
  165 + //exit(1);
  166 + }
  167 +
  168 + //set up all of the texture maps
  169 + int num_textures = texture_list.size();
  170 +
  171 + for(int t=0; t<num_textures; t++)
  172 + {
  173 + glActiveTexture(GL_TEXTURE0 + t);
  174 + CHECK_OPENGL_ERROR
  175 + //glEnable(texture_list[t].texture_type);
  176 + //CHECK_OPENGL_ERROR
  177 + glBindTexture(texture_list[t].texture_type, texture_list[t].name);
  178 + CHECK_OPENGL_ERROR
  179 + }
  180 +
  181 + glUseProgram(id);
  182 + CHECK_OPENGL_ERROR
  183 + }
  184 + void EndProgram()
  185 + {
  186 + CHECK_OPENGL_ERROR
  187 + //return standard functionality
  188 + int num_textures = texture_list.size();
  189 +
  190 + //disable all texture units
  191 + for(int t=0; t<num_textures; t++)
  192 + {
  193 + glActiveTexture(GL_TEXTURE0 + t);
  194 + glDisable(texture_list[t].texture_type);
  195 + CHECK_OPENGL_ERROR
  196 + }
  197 + //make sure that the single default texture unit is active
  198 + if(num_textures > 0)
  199 + glActiveTexture(GL_TEXTURE0);
  200 + CHECK_OPENGL_ERROR
  201 +
  202 + //return to OpenGL default shading
  203 + glUseProgram(0);
  204 + CHECK_OPENGL_ERROR
  205 + }
  206 + void PrintUniforms()
  207 + {
  208 + cout<<"Shader Uniforms: "<<endl;
  209 + unsigned int i;
  210 + for(i=0; i<uniform_list.size(); i++)
  211 + {
  212 + cout<<i<<": "<<uniform_list[i].name<<" "<<uniform_list[i].location<<endl;
  213 + }
  214 + }
  215 + void AttachGlobalUniform(unsigned int index, void* param) //attaches a global variable to the indexed uniform parameter
  216 + {
  217 + uniform_list[index].p_value = param;
  218 + }
  219 + void AttachGlobalUniform(const char* name, void* param)
  220 + {
  221 + //find the index of the shader
  222 + int index = get_index(name);
  223 + if(index != -1)
  224 + AttachGlobalUniform(index, param);
  225 + else
  226 + {
  227 + string strError = "Error finding uniform variable: ";
  228 + strError += name;
  229 + cout<<strError<<endl;
  230 + }
  231 + }
  232 + void AttachTextureMap(unsigned int index, rts_glTextureMap texture) //attaches a texture map to the program
  233 + {
  234 + //if there is not a texture map assigned to the variable
  235 + if(uniform_list[index].p_value == NULL)
  236 + {
  237 + uniform_list[index].p_value = new unsigned int[1];
  238 + ((unsigned int*)uniform_list[index].p_value)[0] = texture_list.size(); //set the parameter value to the index of the texture
  239 + texture_list.push_back(texture); //add the texture to the texture list
  240 + }
  241 + //if there is a texture map assigned, replace it
  242 + else
  243 + {
  244 + texture_list[((unsigned int*)(uniform_list[index].p_value))[0]] = texture;
  245 + }
  246 +
  247 + }
  248 + void AttachTextureMap(const char* name, rts_glTextureMap texture)
  249 + {
  250 + int index = get_index(name);
  251 + if(index != -1) //make sure that the uniform index is valid
  252 + AttachTextureMap(index, texture);
  253 + else
  254 + cout<<"Error finding texture index. Try linking."<<endl;
  255 + }
  256 + void UpdateGlobalUniforms() //sends updated uniform information to the GPU
  257 + {
  258 + CHECK_OPENGL_ERROR
  259 + BeginProgram();
  260 + CHECK_OPENGL_ERROR
  261 + unsigned int num = uniform_list.size();
  262 + for(unsigned int i=0; i<num; i++)
  263 + uniform_list[i].submit_to_gpu();
  264 + EndProgram();
  265 + }
  266 + void Init() //Initialize the shader program
  267 + {
  268 + CHECK_OPENGL_ERROR
  269 + if(id != 0)
  270 + Clean();
  271 + id = glCreateProgram();
  272 + if(id == 0)
  273 + log = "Error getting program ID from OpenGL";
  274 + CHECK_OPENGL_ERROR
  275 + }
  276 + void Clean()
  277 + {
  278 + if(id != 0)
  279 + glDeleteProgram(id);
  280 + id = 0;
  281 +
  282 + //these are allocated outside the object and can just be cleared
  283 + uniform_list.clear();
  284 + texture_list.clear();
  285 +
  286 + //delete each shader from OpenGL
  287 + int num_shad = shader_list.size();
  288 + for(int i=0; i<num_shad; i++)
  289 + shader_list[i].Clean();
  290 + //clear the list
  291 + shader_list.clear();
  292 + }
  293 +};
  294 +
  295 +#endif
... ...
rts/rts_glShaderUniform.h 0 โ†’ 100644
  1 +++ a/rts/rts_glShaderUniform.h
  1 +#ifndef RTS_GLSHADERUNIFORM_H
  2 +#define RTS_GLSHADERUNIFORM_H
  3 +
  4 +#include "CHECK_OPENGL_ERROR.h"
  5 +#include <GL/glew.h>
  6 +#include <string>
  7 +
  8 +using namespace std;
  9 +
  10 +enum rtsUniformEnum {RTS_FLOAT, RTS_INT, RTS_BOOL, RTS_FLOAT_MATRIX};
  11 +
  12 +///This class stores a single uniform variable for GLSL and is designed to be used by the rts_glShaderProgram class.
  13 +struct rts_glShaderUniform
  14 +{
  15 +public:
  16 + string name; //the name of the variable
  17 + GLint location; //the location in the program
  18 + void* p_value; //pointer to the global data representing the value in main memory
  19 + GLenum type; //variable type (float, int, vec2, etc.)
  20 + //rtsUniformEnum rts_type; //type of variable in rts format
  21 + //unsigned int num; //the number of values required by the variable (1 for float, 2 for vec2, etc.)
  22 + string log;
  23 +
  24 + //void convert_type(GLenum gl_type); //converts the OpenGL data type to something useful for rts
  25 + void submit_to_gpu()
  26 + {
  27 + if(location < 0)
  28 + return;
  29 + if(p_value == NULL)
  30 + {
  31 + cout<<"Error in uniform address: "<<name<<endl;
  32 + return;
  33 + }
  34 +
  35 +
  36 + CHECK_OPENGL_ERROR
  37 + switch(type)
  38 + {
  39 + case GL_FLOAT:
  40 + glUniform1fv(location, 1, (float*)p_value);
  41 + break;
  42 + case GL_FLOAT_VEC2:
  43 + glUniform2fv(location, 1, (float*)p_value);
  44 + break;
  45 + case GL_FLOAT_VEC3:
  46 + glUniform3fv(location, 1, (float*)p_value);
  47 + break;
  48 + case GL_FLOAT_VEC4:
  49 + glUniform4fv(location, 1, (float*)p_value);
  50 + break;
  51 + case GL_INT:
  52 + glUniform1iv(location, 1, (int*)p_value);
  53 + break;
  54 + case GL_INT_VEC2:
  55 + glUniform2iv(location, 1, (int*)p_value);
  56 + break;
  57 + case GL_INT_VEC3:
  58 + glUniform3iv(location, 1, (int*)p_value);
  59 + break;
  60 + case GL_INT_VEC4:
  61 + glUniform4iv(location, 1, (int*)p_value);
  62 + break;
  63 + case GL_BOOL:
  64 + glUniform1iv(location, 1, (int*)p_value);
  65 + break;
  66 + case GL_BOOL_VEC2:
  67 + glUniform2iv(location, 1, (int*)p_value);
  68 + break;
  69 + case GL_BOOL_VEC3:
  70 + glUniform3iv(location, 1, (int*)p_value);
  71 + break;
  72 + case GL_BOOL_VEC4:
  73 + glUniform4iv(location, 1, (int*)p_value);
  74 + break;
  75 + case GL_FLOAT_MAT2:
  76 + glUniformMatrix2fv(location, 1, GL_FALSE, (float*)p_value);
  77 + break;
  78 + case GL_FLOAT_MAT3:
  79 + glUniformMatrix3fv(location, 1, GL_FALSE, (float*)p_value);
  80 + break;
  81 + case GL_FLOAT_MAT4:
  82 + glUniformMatrix4fv(location, 1, GL_FALSE, (float*)p_value);
  83 + break;
  84 + case GL_SAMPLER_1D:
  85 + case GL_SAMPLER_2D:
  86 + case GL_SAMPLER_3D:
  87 + case GL_SAMPLER_CUBE:
  88 + case GL_SAMPLER_1D_SHADOW:
  89 + case GL_SAMPLER_2D_SHADOW:
  90 + default:
  91 + glUniform1iv(location, 1, (int*)p_value);
  92 + break;
  93 + }
  94 + CHECK_OPENGL_ERROR
  95 + }
  96 + rts_glShaderUniform()
  97 + {
  98 + location = -1;
  99 + p_value = NULL;
  100 + }
  101 +};
  102 +
  103 +
  104 +
  105 +#endif
0 106 \ No newline at end of file
... ...
rts/rts_glTextureMap.h 0 โ†’ 100644
  1 +++ a/rts/rts_glTextureMap.h
  1 +#ifndef RTS_GLTEXTUREMAP_H
  2 +#define RTS_GLTEXTUREMAP_H
  3 +
  4 +#include <GL/glew.h>
  5 +#include "rtsVector3d.h"
  6 +#include "CHECK_OPENGL_ERROR.h"
  7 +#include <stdlib.h>
  8 +
  9 +///This class stores an OpenGL texture map and is used by rts_glShaderProgram.
  10 +class rts_glTextureMap
  11 +{
  12 +private:
  13 + void get_type() //guesses the texture type based on the size
  14 + {
  15 + if(size.y == 0)
  16 + texture_type = GL_TEXTURE_1D;
  17 + else if(size.z == 0)
  18 + texture_type = GL_TEXTURE_2D;
  19 + else
  20 + texture_type = GL_TEXTURE_3D;
  21 + }
  22 + void set_wrapping() //set the texture wrapping based on the dimensions
  23 + {
  24 + CHECK_OPENGL_ERROR
  25 + switch(texture_type)
  26 + {
  27 + case GL_TEXTURE_3D:
  28 + glTexParameteri(texture_type, GL_TEXTURE_WRAP_R_EXT, GL_REPEAT);
  29 + case GL_TEXTURE_2D:
  30 + glTexParameteri(texture_type, GL_TEXTURE_WRAP_T, GL_MIRRORED_REPEAT);
  31 + case GL_TEXTURE_1D:
  32 + glTexParameteri(texture_type, GL_TEXTURE_WRAP_S, GL_REPEAT);
  33 + break;
  34 + case GL_TEXTURE_RECTANGLE_ARB:
  35 + glTexParameteri(texture_type, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
  36 + glTexParameteri(texture_type, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
  37 + break;
  38 +
  39 + default:
  40 + break;
  41 + }
  42 + CHECK_OPENGL_ERROR
  43 + }
  44 + //void set_bits(GLvoid* bits);
  45 +public:
  46 + vector3D<GLsizei> size; //vector representing the size of the texture
  47 + GLuint name; //texture name assigned by OpenGL
  48 + GLenum texture_type; //1D, 2D, 3D
  49 + GLint internal_format; //number of components (ex. 4 for RGBA)
  50 + GLenum pixel_format; //type of data (RGBA, LUMINANCE)
  51 + GLenum data_type; //data type of the bits (float, int, etc.)
  52 +
  53 + //constructor
  54 + rts_glTextureMap()
  55 + {
  56 + name = 0;
  57 + }
  58 +
  59 + void BeginTexture()
  60 + {
  61 + glEnable(texture_type);
  62 + glBindTexture(texture_type, name);
  63 + CHECK_OPENGL_ERROR
  64 + }
  65 + void EndTexture()
  66 + {
  67 + glDisable(texture_type);
  68 + CHECK_OPENGL_ERROR
  69 + }
  70 +
  71 + ///Creates an OpenGL texture map. This function requires basic information about the texture map as well as a pointer to the bit data describing the texture.
  72 + void Init(GLvoid *bits,
  73 + GLenum type = GL_TEXTURE_2D,
  74 + GLsizei width = 256,
  75 + GLsizei height = 256,
  76 + GLsizei depth = 0,
  77 + GLint internalformat = 1,
  78 + GLenum format = GL_LUMINANCE,
  79 + GLenum datatype = GL_UNSIGNED_BYTE,
  80 + GLint interpolation = GL_LINEAR)
  81 + {
  82 + CHECK_OPENGL_ERROR
  83 + if(name != 0)
  84 + glDeleteTextures(1, &name);
  85 +
  86 +
  87 + CHECK_OPENGL_ERROR
  88 + if(datatype == GL_FLOAT)
  89 + {
  90 + glPixelStorei(GL_PACK_ALIGNMENT, 4);
  91 + glPixelStorei(GL_UNPACK_ALIGNMENT, 4); //I honestly don't know what this does but it fixes problems
  92 + }
  93 + else if(datatype == GL_UNSIGNED_BYTE)
  94 + {
  95 + //glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
  96 + //glPixelStorei(GL_PACK_ALIGNMENT, 1);
  97 + }
  98 + else if(datatype == GL_UNSIGNED_SHORT)
  99 + {
  100 + //glPixelStorei(GL_UNPACK_ALIGNMENT, 2);
  101 + //glPixelStorei(GL_PACK_ALIGNMENT, 2);
  102 + }
  103 + CHECK_OPENGL_ERROR
  104 + glGenTextures(1, &name); //get the texture name from OpenGL
  105 + //cout<<"OpenGL Name: "<<name<<endl;
  106 + CHECK_OPENGL_ERROR
  107 + size = vector3D<GLuint>(width, height, depth); //assign the texture size
  108 + //get_type(); //guess the type based on the size
  109 + texture_type = type; //set the type of texture
  110 + glEnable(texture_type); //enable the texture map
  111 + CHECK_OPENGL_ERROR
  112 + glBindTexture(texture_type, name); //bind the texture for editing
  113 + CHECK_OPENGL_ERROR
  114 + set_wrapping(); //set the texture wrapping parameters
  115 + CHECK_OPENGL_ERROR
  116 + glTexParameteri(texture_type, GL_TEXTURE_MAG_FILTER, interpolation); //set filtering
  117 + CHECK_OPENGL_ERROR
  118 + glTexParameteri(texture_type, GL_TEXTURE_MIN_FILTER, interpolation);
  119 + CHECK_OPENGL_ERROR
  120 + internal_format = internalformat; //set the number of components per pixel
  121 + pixel_format = format; //set the pixel format
  122 + data_type = datatype; //set the data type
  123 + SetBits(bits); //send the bits to the OpenGL driver
  124 + glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); //replace the specified vertex color
  125 + CHECK_OPENGL_ERROR
  126 + glDisable(texture_type);
  127 +
  128 + glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
  129 + glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
  130 + glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
  131 + }
  132 + void Clean()
  133 + {
  134 + if(name != 0)
  135 + {
  136 + glDeleteTextures(1, &name);
  137 + CHECK_OPENGL_ERROR
  138 + name = 0;
  139 + }
  140 + }
  141 + void SetBits(GLvoid *bits)
  142 + {
  143 + glEnable(texture_type); //enable the texture map
  144 + CHECK_OPENGL_ERROR
  145 + glBindTexture(texture_type, name);
  146 + CHECK_OPENGL_ERROR
  147 +
  148 + switch(texture_type)
  149 + {
  150 + case GL_TEXTURE_3D:
  151 + glTexImage3D(texture_type, 0, internal_format, size.x, size.y, size.z, 0, pixel_format, data_type, bits);
  152 + CHECK_OPENGL_ERROR
  153 + break;
  154 + case GL_TEXTURE_2D:
  155 + case GL_TEXTURE_RECTANGLE_ARB:
  156 + glTexImage2D(texture_type, 0, internal_format, size.x, size.y, 0, pixel_format, data_type, bits);
  157 + CHECK_OPENGL_ERROR
  158 + break;
  159 + case GL_TEXTURE_1D:
  160 + glTexImage1D(texture_type, 0, internal_format, size.x, 0, pixel_format, data_type, bits);
  161 + CHECK_OPENGL_ERROR
  162 + break;
  163 + default:
  164 + //glTexImage2D(texture_type, 0, internal_format, size.x, size.y, 0, pixel_format, data_type, bits);
  165 + break;
  166 + }
  167 + CHECK_OPENGL_ERROR
  168 + }
  169 + void ResetBits(GLvoid *bits)
  170 + {
  171 + glEnable(texture_type); //enable the texture map
  172 + CHECK_OPENGL_ERROR
  173 + glBindTexture(texture_type, name);
  174 + CHECK_OPENGL_ERROR
  175 +
  176 + switch(texture_type)
  177 + {
  178 + case GL_TEXTURE_3D:
  179 + //glTexImage3D(texture_type, 0, internal_format, size.x, size.y, size.z, 0, pixel_format, data_type, bits);
  180 + break;
  181 + case GL_TEXTURE_2D:
  182 + case GL_TEXTURE_RECTANGLE_ARB:
  183 + glTexSubImage2D(texture_type, 0, 0, 0, size.x, size.y, pixel_format, data_type, bits);
  184 + CHECK_OPENGL_ERROR
  185 + break;
  186 + case GL_TEXTURE_1D:
  187 + //glTexImage1D(texture_type, 0, internal_format, size.x, 0, pixel_format, data_type, bits);
  188 + break;
  189 + default:
  190 + //glTexImage2D(texture_type, 0, internal_format, size.x, size.y, 0, pixel_format, data_type, bits);
  191 + break;
  192 + }
  193 + glDisable(texture_type);
  194 + CHECK_OPENGL_ERROR
  195 + }
  196 + void* GetBits(GLenum format, GLenum type)
  197 + {
  198 + //returns the texture data
  199 +
  200 + int components;
  201 + switch(format)
  202 + {
  203 + case GL_RED:
  204 + case GL_GREEN:
  205 + case GL_BLUE:
  206 + case GL_ALPHA:
  207 + case GL_LUMINANCE:
  208 + components = 1;
  209 + break;
  210 + case GL_LUMINANCE_ALPHA:
  211 + components = 2;
  212 + break;
  213 + case GL_RGB:
  214 + case GL_BGR:
  215 + components = 3;
  216 + break;
  217 + case GL_RGBA:
  218 + case GL_BGRA:
  219 + components = 4;
  220 + break;
  221 + }
  222 +
  223 + int type_size;
  224 + switch(type)
  225 + {
  226 + case GL_UNSIGNED_BYTE:
  227 + case GL_BYTE:
  228 + type_size = sizeof(char);
  229 + break;
  230 + case GL_UNSIGNED_SHORT:
  231 + case GL_SHORT:
  232 + type_size = sizeof(short);
  233 + break;
  234 + case GL_UNSIGNED_INT:
  235 + case GL_INT:
  236 + type_size = sizeof(int);
  237 + break;
  238 + case GL_FLOAT:
  239 + type_size = sizeof(float);
  240 + break;
  241 + }
  242 +
  243 + //allocate memory for the texture
  244 + void* result = malloc(components*type_size * size.x * size.y);
  245 +
  246 + BeginTexture();
  247 + glGetTexImage(texture_type, 0, format, type, result);
  248 +
  249 + CHECK_OPENGL_ERROR
  250 + EndTexture();
  251 +
  252 +
  253 + return result;
  254 +
  255 + }
  256 +};
  257 +
  258 +#define RTS_UNKNOWN 0
  259 +
  260 +#endif
0 261 \ No newline at end of file
... ...
rts/rts_glutRenderWindow.h 0 โ†’ 100644
  1 +++ a/rts/rts_glutRenderWindow.h
  1 +#include <GL/glew.h>
  2 +#include <GL/glut.h>
  3 +#include "rtsQuaternion.h"
  4 +#include "rtsCamera.h"
  5 +
  6 +float d_angle = 0.05;
  7 +
  8 +rtsCamera rts_glut_camera;
  9 +unsigned int mouse_x;
  10 +unsigned int mouse_y;
  11 +int mouse_button;
  12 +
  13 +
  14 +//user display function pointer
  15 +void (*UserDisplay)(void);
  16 +
  17 +
  18 +
  19 +/*void KeyboardFunction(unsigned char key, int x, int y)
  20 +{
  21 + if(key == 27)
  22 + exit(0);
  23 +
  24 +}*/
  25 +
  26 +/*void SpecialKeys(int key, int x, int y)
  27 +{
  28 + rtsQuaternion<float> new_rotation;
  29 +
  30 + if(key == GLUT_KEY_UP)
  31 + rts_glut_camera.OrbitFocus(0, d_angle);
  32 + if(key == GLUT_KEY_DOWN)
  33 + rts_glut_camera.OrbitFocus(0, -d_angle);
  34 + if(key == GLUT_KEY_LEFT)
  35 + rts_glut_camera.OrbitFocus(d_angle, 0.0);
  36 + if(key == GLUT_KEY_RIGHT)
  37 + rts_glut_camera.OrbitFocus(-d_angle, 0.0);
  38 +}*/
  39 +
  40 +void MouseDrag(int x, int y)
  41 +{
  42 + int dx = x - mouse_x;
  43 + int dy = y - mouse_y;
  44 +
  45 + if(mouse_button == GLUT_LEFT_BUTTON)
  46 + rts_glut_camera.OrbitFocus(-dx*0.01, dy*0.01);
  47 + else if(mouse_button == GLUT_MIDDLE_BUTTON)
  48 + rts_glut_camera.Zoom(dy*rts_glut_camera.getFOV()/60.0);
  49 +
  50 + mouse_x = x;
  51 + mouse_y = y;
  52 +
  53 +}
  54 +
  55 +void MouseMove(int x, int y)
  56 +{
  57 + mouse_x = x;
  58 + mouse_y = y;
  59 +}
  60 +
  61 +void MouseClick(int button, int state, int x, int y)
  62 +{
  63 + if(state == GLUT_DOWN)
  64 + mouse_button = button;
  65 +
  66 +
  67 +}
  68 +
  69 +void IdleFunction()
  70 +{
  71 + glutPostRedisplay();
  72 +}
  73 +
  74 +void RenderCamera()
  75 +{
  76 + //set viewport
  77 + glMatrixMode(GL_PROJECTION);
  78 + glLoadIdentity();
  79 + glViewport(0, 0, glutGet(GLUT_WINDOW_WIDTH), glutGet(GLUT_WINDOW_HEIGHT));
  80 +
  81 + //compute the aspect ratio
  82 + float aspect_ratio = (float)glutGet(GLUT_WINDOW_WIDTH)/(float)glutGet(GLUT_WINDOW_HEIGHT);
  83 + gluPerspective(rts_glut_camera.getFOV(), aspect_ratio, 0.01, 10.0);
  84 +
  85 + //render the camera
  86 + glMatrixMode(GL_MODELVIEW);
  87 + glLoadIdentity();
  88 +
  89 + point3D<float> camera_position = rts_glut_camera.getPosition();
  90 + vector3D<float> camera_up = rts_glut_camera.getUp();
  91 + gluLookAt(camera_position.x,
  92 + camera_position.y,
  93 + camera_position.z,
  94 + 0.0, 0.0, 0.0,
  95 + camera_up.x,
  96 + camera_up.y,
  97 + camera_up.z);
  98 +}
  99 +
  100 +void rts_glutInitialize(const char* WindowName, int width = 1024, int height = 768)
  101 +{
  102 + char *myargv [1];
  103 + int myargc=1;
  104 + myargv [0]=strdup ("AppName");
  105 + glutInit(&myargc, myargv);
  106 +
  107 + glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH);
  108 + glutInitWindowSize(width, height);
  109 + glutInitWindowPosition(200,0);
  110 + glutCreateWindow(WindowName);
  111 +
  112 + //initialize GLEW
  113 + GLenum err = glewInit();
  114 + if(err != GLEW_OK)
  115 + fprintf(stderr, "Error: %s\n", glewGetErrorString(err));
  116 + if (!glewIsSupported("GL_VERSION_2_0"))
  117 + {
  118 + printf("OpenGL 2.0 not supported\n");
  119 + //exit(1);
  120 + }
  121 + glEnable(GL_DEPTH_TEST);
  122 +
  123 + glClearColor(1.0, 1.0, 1.0, 0.0);
  124 +
  125 + rts_glut_camera.setPosition(0.0, 0.0, -1.0);
  126 + rts_glut_camera.setFOV(60);
  127 + rts_glut_camera.LookAt(0.0, 0.0, 0.0, 0.0, 1.0, 0.0);
  128 +}
  129 +
  130 +void DisplayFunction()
  131 +{
  132 + RenderCamera();
  133 + UserDisplay();
  134 + glutSwapBuffers();
  135 +}
  136 +
  137 +void rts_glutStart(void (*display_func)(void))
  138 +{
  139 + //glutSpecialFunc(SpecialKeys);
  140 + //glutKeyboardFunc(KeyboardFunction);
  141 + glutDisplayFunc(DisplayFunction);
  142 + glutMotionFunc(MouseDrag);
  143 + glutMouseFunc(MouseClick);
  144 + glutPassiveMotionFunc(MouseMove);
  145 + UserDisplay = display_func;
  146 + glutIdleFunc(IdleFunction);
  147 +
  148 +
  149 +
  150 + //glutReshapeFunc(ReshapeFunction);
  151 + //glutMouseFunc(MouseFunction);
  152 + //glutMotionFunc(MotionFunction);
  153 + glutMainLoop();
  154 +
  155 +}
... ...
rtsFiberNetwork.h 0 โ†’ 100644
  1 +++ a/rtsFiberNetwork.h
  1 +#include <string>
  2 +#include <fstream>
  3 +#include <algorithm>
  4 +//#include "PerformanceData.h"
  5 +#include "rts/objJedi.h"
  6 +#include "rts/rtsPoint3d.h"
  7 +#include "rts/rtsFilename.h"
  8 +#include <ANN/ANN.h>
  9 +//#include <exception>
  10 +
  11 +#include <boost/graph/graph_traits.hpp>
  12 +#include <boost/graph/adjacency_list.hpp>
  13 +#include <boost/graph/breadth_first_search.hpp>
  14 +using namespace boost;
  15 +
  16 +
  17 +//Performance
  18 +//PerformanceData PD;
  19 +
  20 +#ifndef RTS_FIBER_NETWORK_H
  21 +#define RTS_FIBER_NETWORK_H
  22 +
  23 +//definitions for topologyNode labels
  24 +#define RTS_TOPOLOGY_NODE_NOEXIST 0
  25 +#define RTS_TOPOLOGY_NODE_INVALID 1
  26 +#define RTS_TOPOLOGY_NODE_VALID 2
  27 +
  28 +#define RTS_TOPOLOGY_EDGE_NOEXIST 0
  29 +#define RTS_TOPOLOGY_EDGE_EXIST 1
  30 +
  31 +//Properties for the topology graph
  32 +struct vertex_position_t
  33 +{
  34 + typedef vertex_property_tag kind;
  35 +};
  36 +typedef property<vertex_position_t, point3D<float>, property<vertex_color_t, int> > VertexProperties;
  37 +typedef list<int> EdgeSequence;
  38 +typedef pair<EdgeSequence, EdgeSequence> EdgeMapping;
  39 +typedef vector<EdgeMapping> CoreGraphList;
  40 +typedef property<edge_weight_t, float, property<edge_color_t, EdgeSequence> > EdgeProperties;
  41 +typedef adjacency_list<listS, vecS, undirectedS, VertexProperties, EdgeProperties> TopologyGraph;
  42 +typedef graph_traits<TopologyGraph>::edge_descriptor TopologyEdge;
  43 +typedef graph_traits<TopologyGraph>::vertex_descriptor TopologyVertex;
  44 +
  45 +
  46 +EdgeSequence global_EdgeSequence;
  47 +float global_Weight;
  48 +list<float> global_NeighborWeights;
  49 +list<TopologyEdge> global_EdgeDescriptorSequence;
  50 +vector<TopologyVertex> global_Predecessors;
  51 +TopologyVertex global_Source;
  52 +pair<TopologyEdge, bool> BOOST_SmallestEdge(int v0, int v1, const TopologyGraph& G)
  53 +{
  54 + pair<TopologyEdge, bool> edge_pair = edge(v0, v1, G);
  55 + //if the edge doesn't exist, return the false pair
  56 + if(!edge_pair.second)
  57 + return edge_pair;
  58 +
  59 + //cout<<"Smallest edge: "<<endl;
  60 + //BOOST_PrintGraph(G);
  61 +
  62 + //otherwise, make sure it is the edge with the least weight
  63 + graph_traits<TopologyGraph>::out_edge_iterator oi, oi_end;
  64 + TopologyEdge min_e = edge_pair.first;
  65 + float min_weight = get(edge_weight_t(), G, min_e);
  66 +
  67 + for(boost::tuples::tie(oi, oi_end) = out_edges(v0, G); oi!=oi_end; oi++)
  68 + {
  69 + if(target(*oi, G) == v1)
  70 + {
  71 + //cout<<"Edge weight for "<<v0<<": "<<get(edge_weight_t(), G, *oi)<<endl;
  72 + if(get(edge_weight_t(), G, *oi) < min_weight)
  73 + {
  74 + min_weight = get(edge_weight_t(), G, *oi);
  75 + min_e = *oi;
  76 + }
  77 + }
  78 + }
  79 + edge_pair.first = min_e;
  80 + edge_pair.second = true;
  81 + return edge_pair;
  82 +}
  83 +class boundary_bfs_visitor : public default_bfs_visitor
  84 +{
  85 +public:
  86 + void discover_vertex(TopologyVertex v, const TopologyGraph& G) const throw(TopologyVertex)
  87 + {
  88 + //cout<<"discovered: "<<v<<endl;
  89 + //global_EdgeSequence.push_back(get(vertex_color_t(), G, v));
  90 + if(get(vertex_color_t(), G, v) >= 0 && v != global_Source)
  91 + {
  92 + TopologyVertex v0, v1;
  93 + v0 = v1 = v;
  94 + pair<TopologyEdge, bool> e;
  95 + global_Weight = 0.0;
  96 + while(v1 != global_Source)
  97 + {
  98 + v1 = global_Predecessors[v0];
  99 + e = BOOST_SmallestEdge(v0, v1, G);
  100 + global_EdgeSequence.push_back(get(edge_color_t(), G, e.first).front());
  101 + global_EdgeDescriptorSequence.push_back(e.first);
  102 + global_Weight += get(edge_weight_t(), G, e.first);
  103 + v0 = v1;
  104 + }
  105 + //cout<<"Weight test: "<<global_Weight<<endl;
  106 + throw v;
  107 + }
  108 +
  109 + }
  110 + void tree_edge(TopologyEdge e, const TopologyGraph& G) const
  111 + {
  112 + global_Predecessors[target(e, G)] = source(e, G);
  113 + }
  114 +};
  115 +
  116 +
  117 +
  118 +bool compare_edges(pair<TopologyEdge, float> e0, pair<TopologyEdge, float> e1)
  119 +{
  120 + if(e0.second < e1.second)
  121 + return true;
  122 + else return false;
  123 +}
  124 +
  125 +
  126 +struct Fiber
  127 +{
  128 + vector<point3D<float> > pointList;
  129 + vector<float> errorList;
  130 + int n0;
  131 + int n1;
  132 + float length;
  133 + float error;
  134 + int mapped_to; //edge in another graph that maps to this one (-1 if a mapping doesn't exist)
  135 + void* FiberData;
  136 +
  137 + Fiber()
  138 + {
  139 + error = 1.0;
  140 + FiberData = NULL;
  141 + }
  142 +};
  143 +
  144 +struct Node
  145 +{
  146 + point3D<float> p;
  147 + void* NodeData;
  148 + float error;
  149 + int color;
  150 + int incident;
  151 +
  152 + Node()
  153 + {
  154 + error = 1.0;
  155 + NodeData = NULL;
  156 + incident = 0;
  157 + }
  158 +};
  159 +
  160 +struct geometryPoint
  161 +{
  162 + point3D<float> p;
  163 + unsigned int fiberIdx;
  164 + unsigned int pointIdx;
  165 + float dist;
  166 + int fiberID;
  167 +};
  168 +
  169 +struct topologyEdge
  170 +{
  171 + int label;
  172 + unsigned int n0;
  173 + unsigned int n1;
  174 + float error;
  175 +};
  176 +struct topologyNode
  177 +{
  178 + point3D<float> p;
  179 + int label;
  180 + list<unsigned int> connections;
  181 + unsigned int compatible;
  182 +};
  183 +
  184 +
  185 +
  186 +
  187 +#define MAX_DIST 9999.0;
  188 +
  189 +class rtsFiberNetwork
  190 +{
  191 +private:
  192 + bool fiber_started;
  193 + unsigned int num_points;
  194 + float cull_value; //used to cull fibers based on geometric error
  195 +
  196 + vector<geometryPoint> getNetPointSamples(float subdiv)
  197 + {
  198 + vector<geometryPoint> result;
  199 +
  200 + unsigned int f;
  201 + list<point3D<float> > fiberPoints;
  202 + list<point3D<float> >::iterator p;
  203 + for(f = 0; f<FiberList.size(); f++)
  204 + {
  205 + fiberPoints.clear();
  206 + fiberPoints = SubdivideFiber(f, subdiv);
  207 +
  208 + for(p=fiberPoints.begin(); p!=fiberPoints.end(); p++)
  209 + {
  210 + geometryPoint fp;
  211 + fp.p = (*p);
  212 + fp.fiberID = f;
  213 + fp.dist = MAX_DIST;
  214 + result.push_back(fp);
  215 + }
  216 + }
  217 + return result;
  218 +
  219 +
  220 + }
  221 +
  222 + void BF_ComputeL1Distance(vector<geometryPoint>* N0, vector<geometryPoint>* N1);
  223 + void KD_ComputeEnvelopeDistance(rtsFiberNetwork* network, vector<geometryPoint>* Samples, float sigma)
  224 + {
  225 + //build the point arrays
  226 + ANNpointArray dataPts0 = annAllocPts(Samples->size(), 3);
  227 + for(unsigned int i=0; i<Samples->size(); i++)
  228 + {
  229 + dataPts0[i][0] = (*Samples)[i].p.x;
  230 + dataPts0[i][1] = (*Samples)[i].p.y;
  231 + dataPts0[i][2] = (*Samples)[i].p.z;
  232 + }
  233 +
  234 + //create ANN variables
  235 + ANNkd_tree* kdTree;
  236 + ANNpoint queryPt = annAllocPt(3);
  237 + ANNidxArray nearestIdx = new ANNidx[1];
  238 + ANNdistArray nearestDist = new ANNdist[1];
  239 +
  240 + //compare network 0 to network 1
  241 + //PD.StartTimer(LOG_N_DIST_BUILD0);
  242 + kdTree = new ANNkd_tree(dataPts0, Samples->size(), 3);
  243 + //PD.EndTimer(LOG_N_DIST_BUILD0);
  244 + //PD.StartTimer(LOG_N_DIST_SEARCH0);
  245 +
  246 + //test each point in the network to the Samples list
  247 + unsigned int f, p;
  248 + int nodenum;
  249 + float gauss_dist;
  250 + for(f=0; f<network->FiberList.size(); f++)
  251 + {
  252 + //clear the error list
  253 + network->FiberList[f].errorList.clear();
  254 +
  255 + //compute the distance at the nodes
  256 + nodenum = network->FiberList[f].n0;
  257 + queryPt[0] = network->NodeList[nodenum].p.x;
  258 + queryPt[1] = network->NodeList[nodenum].p.y;
  259 + queryPt[2] = network->NodeList[nodenum].p.z;
  260 + kdTree->annkSearch(queryPt, 1, nearestIdx, nearestDist);
  261 + gauss_dist = 1.0f - GaussianEnvelope(sqrtf((float)nearestDist[0]), sigma);
  262 + network->NodeList[nodenum].error = gauss_dist;
  263 +
  264 + nodenum = network->FiberList[f].n1;
  265 + queryPt[0] = network->NodeList[nodenum].p.x;
  266 + queryPt[1] = network->NodeList[nodenum].p.y;
  267 + queryPt[2] = network->NodeList[nodenum].p.z;
  268 + kdTree->annkSearch(queryPt, 1, nearestIdx, nearestDist);
  269 + gauss_dist = 1.0f - GaussianEnvelope(sqrtf((float)nearestDist[0]), sigma);
  270 + network->NodeList[nodenum].error = gauss_dist;
  271 +
  272 + //compute the distance at each point along the fiber
  273 + for(p=0; p<network->FiberList[f].pointList.size(); p++)
  274 + {
  275 + queryPt[0] = network->FiberList[f].pointList[p].x;
  276 + queryPt[1] = network->FiberList[f].pointList[p].y;
  277 + queryPt[2] = network->FiberList[f].pointList[p].z;
  278 + kdTree->annkSearch(queryPt, 1, nearestIdx, nearestDist);
  279 + gauss_dist = 1.0f - GaussianEnvelope(sqrtf((float)nearestDist[0]), sigma);
  280 + network->FiberList[f].errorList.push_back(gauss_dist);
  281 + }
  282 + }
  283 + /*for(int i=0; i<N1->size(); i++)
  284 + {
  285 + queryPt[0] = (*N1)[i].p.x;
  286 + queryPt[1] = (*N1)[i].p.y;
  287 + queryPt[2] = (*N1)[i].p.z;
  288 + kdTree->annkSearch(queryPt, 1, nearestIdx, nearestDist);
  289 + (*N1)[i].dist = sqrt(nearestDist[0]);
  290 + } */
  291 + //delete kdTree;
  292 + //PD.EndTimer(LOG_N_DIST_SEARCH0);
  293 +
  294 + /*
  295 + //compare network 1 to network 0
  296 + PD.StartTimer(LOG_N_DIST_BUILD1);
  297 + kdTree = new ANNkd_tree(dataPts1, N1->size(), 3);
  298 + PD.EndTimer(LOG_N_DIST_BUILD1);
  299 + PD.StartTimer(LOG_N_DIST_SEARCH1);
  300 + for(int i=0; i<N0->size(); i++)
  301 + {
  302 + queryPt[0] = (*N0)[i].p.x;
  303 + queryPt[1] = (*N0)[i].p.y;
  304 + queryPt[2] = (*N0)[i].p.z;
  305 + kdTree->annkSearch(queryPt, 1, nearestIdx, nearestDist);
  306 + (*N0)[i].dist = sqrt(nearestDist[0]);
  307 + }
  308 + PD.EndTimer(LOG_N_DIST_SEARCH1);
  309 + //delete kdTree;
  310 + */
  311 + annClose();
  312 + //delete kdTree;
  313 + }
  314 +
  315 + void BD_ComputeL1Distance(vector<geometryPoint>* N0, vector<geometryPoint>* N1);
  316 + list<point3D<float> > SubdivideSegment(point3D<float> p0, point3D<float> p1, float spacing)
  317 + {
  318 +
  319 + //find the direction of travel
  320 + vector3D<float> v = p1 - p0;
  321 +
  322 + //set the step size to the voxel size
  323 + float length = v.Length();
  324 + v.Normalize();
  325 +
  326 + float l;
  327 + list<point3D<float> > result;
  328 + point3D<float> p;
  329 + for(l=0.0; l<length; l+=spacing)
  330 + {
  331 + p = p0 + v*l;
  332 + result.push_back(p);
  333 + }
  334 + return result;
  335 +
  336 +
  337 + }
  338 +
  339 + list<point3D<float> > SubdivideFiber(unsigned int f, float spacing)
  340 + {
  341 + list<point3D<float> > result;
  342 + list<point3D<float> > segment;
  343 +
  344 + point3D<float> p0;
  345 + point3D<float> p1;
  346 +
  347 + int node = FiberList[f].n0;
  348 + p0 = NodeList[node].p;
  349 +
  350 + for(unsigned int p=0; p<FiberList[f].pointList.size(); p++)
  351 + {
  352 + segment.clear();
  353 + //p0 = getFiberPoint(f, p-1);
  354 + //p1 = getFiberPoint(f, p);
  355 + p1 = FiberList[f].pointList[p];
  356 + segment = SubdivideSegment(p0, p1, spacing);
  357 +
  358 + //result.push_back(p0);
  359 + result.insert(result.end(), segment.begin(), segment.end());
  360 + //result.push_back(p1);
  361 + p0 = p1;
  362 + }
  363 +
  364 + //subdivide the last segment
  365 + node = FiberList[f].n1;
  366 + p1 = NodeList[node].p;
  367 + segment.clear();
  368 + segment = SubdivideSegment(p0, p1, spacing);
  369 + result.insert(result.end(), segment.begin(), segment.end());
  370 +
  371 +
  372 + return result;
  373 + }
  374 +
  375 + float GaussianEnvelope(float x, float std){return exp(-(x*x)/(2*std*std));}
  376 + //vector<topologyNode> initNodeList(rtsFiberNetwork* network);
  377 + void initTopologyGraph(vector<topologyNode>* Nodes, vector<topologyEdge>* Edges, rtsFiberNetwork* Network);
  378 + void MapDeviationToNetwork(vector<geometryPoint>* source);
  379 + void topLabelNodes(vector<topologyNode>* N0, vector<topologyNode>* N1, float epsilon);
  380 + bool topMergeNode(vector<topologyNode>* NodeList, vector<topologyEdge>* EdgeList, unsigned int node);
  381 + int topCollapse(vector<topologyNode>* Nodelist, vector<topologyEdge>* EdgeList);
  382 + void topComputeMergePoints(vector<topologyNode>* NodeList);
  383 + bool topDetectEdge(vector<topologyNode>* NodeList, vector<topologyEdge>* EdgeList, unsigned int node0, unsigned int node1);
  384 + bool topDeleteEdge(vector<topologyNode>* NodeList, vector<topologyEdge>* EdgeList, unsigned int node0, unsigned int node1);
  385 + unsigned int topGetNearestConnected(vector<topologyNode>* NodeList, unsigned int node, bool must_be_compatible);
  386 + void ComputeBoundingVolume();
  387 + float GeometryMetric(rtsFiberNetwork* network, float std)
  388 + {
  389 + //At this point each vertex in the network has an error in the range of [0 1]
  390 + //This function computes the average error of each fiber and the entire network based
  391 + //on the error at each vertex.
  392 + unsigned int f, p;
  393 + float fiber_length;
  394 + float fiber_metric;
  395 + float total_metric = 0.0;
  396 + float total_length = 0.0;
  397 + point3D<float> p0, p1;
  398 + float e0, e1;
  399 + int node;
  400 +
  401 + //compute the metric for every fiber in the network
  402 + for(f=0; f<network->FiberList.size(); f++)
  403 + {
  404 + fiber_metric = 0.0;
  405 + fiber_length = 0.0;
  406 +
  407 + //start at the first node
  408 + node = network->FiberList[f].n0;
  409 + p0 = network->NodeList[node].p;
  410 + e0 = network->NodeList[node].error;
  411 +
  412 + //iterate through every intermediary node
  413 + for(p=0; p<network->FiberList[f].errorList.size(); p++)
  414 + {
  415 + p1 = network->FiberList[f].pointList[p];
  416 + e1 = network->FiberList[f].errorList[p];
  417 + //keep a running sum of both the fiber length and the average error
  418 + fiber_length += (p0 - p1).Length();
  419 + fiber_metric += (e0+e1)/2 * (p0 - p1).Length();
  420 +
  421 + //shift
  422 + p0 = p1;
  423 + e0 = e1;
  424 +
  425 + }
  426 +
  427 + //end at the last fiber node
  428 + node = network->FiberList[f].n1;
  429 + p1 = network->NodeList[node].p;
  430 + e1 = network->NodeList[node].error;
  431 + fiber_length += (p0 - p1).Length();
  432 + fiber_metric += (e0+e1)/2 * (p0 - p1).Length();
  433 +
  434 + //compute and store the average fiber error
  435 + network->FiberList[f].error = fiber_metric/fiber_length;
  436 +
  437 + //keep a running total of the network error
  438 + //do not include if the fiber is culled
  439 + if(network->FiberList[f].error <= network->cull_value)
  440 + {
  441 + total_length += fiber_length;
  442 + total_metric += fiber_metric;
  443 + }
  444 + }
  445 +
  446 + //compute the final error for the entire network
  447 + return total_metric / total_length;
  448 + }
  449 +
  450 + void MY_ComputeTopology(rtsFiberNetwork* testNetwork, float std);
  451 + void BOOST_MapEdgesToFibers(rtsFiberNetwork* network, TopologyGraph& G)
  452 + {
  453 + /*
  454 + //initialize the fiber mapping to -1
  455 + for(int f=0; f<network->FiberList.size(); f++)
  456 + network->FiberList[f].mapped_to = -1;
  457 +
  458 + //for each edge in the graph, set the mapping
  459 + graph_traits<TopologyGraph>::edge_iterator ei, ei_end;
  460 + int map;
  461 + for(tie(ei, ei_end) = edges(G); ei != ei_end; ei++)
  462 + {
  463 + map = get(edge_color_t(), G, *ei);
  464 + network->FiberList[map].mapped_to = 1;
  465 + }
  466 + */
  467 +
  468 + }
  469 + void BOOST_InvalidateValence2Vertices(TopologyGraph& G)
  470 + {
  471 + graph_traits<TopologyGraph>::vertex_iterator vi, vi_end;
  472 + for(boost::tuples::tie(vi, vi_end) = vertices(G); vi!= vi_end; vi++)
  473 + {
  474 + if(degree(*vi, G) == 2)
  475 + {
  476 + put(vertex_color_t(), G, *vi, -1);
  477 + cout<<"invalidated"<<endl;
  478 + }
  479 +
  480 + }
  481 + }
  482 + CoreGraphList BOOST_ComputeTopology(rtsFiberNetwork* testNetwork, float sigma)
  483 + {
  484 + //construct a graph representation of each network
  485 + TopologyGraph GT = BOOST_BuildGraph(this);
  486 + TopologyGraph T = BOOST_BuildGraph(testNetwork);
  487 +
  488 + cout<<"BEFORE CLEANING"<<endl;
  489 + cout<<"GT****************************"<<endl;
  490 + //BOOST_PrintGraph(GT);
  491 + cout<<"T*****************************"<<endl;
  492 + //BOOST_PrintGraph(T);
  493 +
  494 + //clean up degeneracies in the graphs
  495 + BOOST_CleanGraph(GT, sigma);
  496 + BOOST_CleanGraph(T, sigma);
  497 +
  498 + //color the vertices
  499 + BOOST_KD_ColorGraph(GT, T, sigma);
  500 + BOOST_KD_ColorGraph(T, GT, sigma);
  501 +
  502 + //color the vertices in GT based on the GT indices
  503 + //the colors now match those in T
  504 + BOOST_SaveGTIndices(GT);
  505 +
  506 + //apply the colors to the network
  507 + BOOST_ApplyColorsToNetwork(GT, this);
  508 + BOOST_ApplyColorsToNetwork(T, testNetwork);
  509 +
  510 + int false_positives = 0;
  511 + int false_negatives = 0;
  512 +
  513 + //merge spurs
  514 + //BOOST_PrintGraph(T);
  515 + int false_positive_spines = BOOST_RemoveSpines(T);
  516 + int false_negative_spines = BOOST_RemoveSpines(GT);
  517 + cout<<"False Positive Spines: "<<false_positive_spines<<endl;
  518 + cout<<"False Negative Spines: "<<false_negative_spines<<endl;
  519 + //BOOST_PrintGraph(T);
  520 +
  521 +
  522 + false_positives += false_positive_spines;
  523 + false_negatives += false_negative_spines;
  524 +
  525 + //merge invalid vertices together
  526 + //this function also merges invalid vertices with valid vertices if their degree = 2
  527 +
  528 + //BOOST_PrintGraph(T);
  529 + BOOST_MergeInvalidVertices(GT);
  530 + BOOST_MergeInvalidVertices(T);
  531 + //BOOST_PrintGraph(T);
  532 +
  533 + //merge the compatible vertices
  534 + int compatible_spines = BOOST_MergeCompatibleVertices(T);
  535 + cout<<"Compatibility errors in T: "<<compatible_spines<<endl;
  536 + false_positives += compatible_spines;
  537 +
  538 +
  539 + CoreGraphList core = BOOST_FindCore(GT, T);
  540 +
  541 + //BOOST_PrintGraph(GT);
  542 + //BOOST_InvalidateValence2Vertices(GT);
  543 + //BOOST_InvalidateValence2Vertices(T);
  544 + //BOOST_PrintGraph(GT);
  545 + //BOOST_MergeInvalidVertices(GT);
  546 + //BOOST_MergeInvalidVertices(T);
  547 +
  548 + //core = BOOST_FindCore(GT, T);
  549 +
  550 +
  551 +
  552 +
  553 + int T_topology_errors = num_edges(T) - core.size();
  554 + int GT_topology_errors = num_edges(T) - core.size();
  555 +
  556 + false_positives += T_topology_errors;
  557 + false_negatives += GT_topology_errors;
  558 +
  559 + cout<<"False Positive Edges: "<<false_positives<<endl;
  560 + cout<<"False Negative Edges: "<<false_negatives<<endl;
  561 +
  562 + return core;
  563 + }
  564 + list<pair<TopologyVertex, EdgeSequence> > BOOST_FindNeighbors(TopologyGraph G, TopologyVertex node)
  565 + {
  566 + //Finds all colored vertices that can be reached from "node"
  567 + pair<TopologyVertex, EdgeSequence> edge_map;
  568 + list<pair<TopologyVertex, EdgeSequence> > result;
  569 +
  570 + do{
  571 + global_Predecessors.clear();
  572 + global_Predecessors.resize(num_vertices(G));
  573 + global_Source = node;
  574 + global_EdgeSequence.clear();
  575 + global_EdgeDescriptorSequence.clear();
  576 + global_Weight = 0.0;
  577 + boundary_bfs_visitor vis;
  578 + try{
  579 + breadth_first_search(G, global_Source, visitor(vis));
  580 + }
  581 + catch(TopologyVertex& vert_id)
  582 + {
  583 + edge_map.first = vert_id;
  584 + edge_map.second = global_EdgeSequence;
  585 + result.push_back(edge_map);
  586 + global_NeighborWeights.push_back(global_Weight);
  587 + //clear_vertex(vert_id, G);
  588 + remove_edge(global_EdgeDescriptorSequence.front(), G);
  589 + }
  590 + }while(!global_EdgeSequence.empty());
  591 + return result;
  592 + }
  593 +
  594 + TopologyGraph BOOST_FindCoreGraph(TopologyGraph G)
  595 + {
  596 + TopologyGraph result;
  597 + //first insert all vertices
  598 + graph_traits<TopologyGraph>::vertex_iterator vi, vi_end;
  599 + graph_traits<TopologyGraph>::vertex_descriptor v;
  600 + for(boost::tuples::tie(vi, vi_end) = vertices(G); vi!=vi_end; vi++)
  601 + {
  602 + v = add_vertex(result);
  603 + put(vertex_color_t(), result, v, get(vertex_color_t(), G, *vi));
  604 + put(vertex_position_t(), result, v, get(vertex_position_t(), G, *vi));
  605 + }
  606 +
  607 + //for each vertex in the graph, find all of the neighbors
  608 + list<pair<TopologyVertex, EdgeSequence> > neighborhood;
  609 + list<pair<TopologyVertex, EdgeSequence> >::iterator ni;
  610 + list<float>::iterator wi;
  611 + pair<TopologyEdge, bool> e;
  612 + for(boost::tuples::tie(vi, vi_end) = vertices(G); vi!=vi_end; vi++)
  613 + {
  614 + //only look for neighbors if the vertex has a color
  615 + if(get(vertex_color_t(), G, *vi) >= 0)
  616 + {
  617 + global_NeighborWeights.clear();
  618 + neighborhood = BOOST_FindNeighbors(G, *vi);
  619 + for(ni = neighborhood.begin(), wi = global_NeighborWeights.begin(); ni != neighborhood.end(); ni++, wi++)
  620 + {
  621 + e = add_edge(*vi, (*ni).first, result);
  622 + put(edge_color_t(), result, e.first, (*ni).second);
  623 + //cout<<"Inserting weight: "<<*wi<<endl;
  624 + put(edge_weight_t(), result, e.first, (*wi));
  625 +
  626 + }
  627 + clear_vertex(*vi, G);
  628 + }
  629 + }
  630 + //BOOST_PrintGraph(G);
  631 + //BOOST_PrintGraph(result);
  632 + return result;
  633 + }
  634 +
  635 + CoreGraphList BOOST_CompareCoreGraphs(TopologyGraph GTc, TopologyGraph Tc)
  636 + {
  637 + //cout<<"Core Before:"<<endl;
  638 + //BOOST_PrintGraph(GTc);
  639 +
  640 + CoreGraphList result;
  641 + EdgeMapping TtoGT;
  642 + pair<TopologyEdge, bool> e_Tc, e_GTc;
  643 + graph_traits<TopologyGraph>::edge_iterator ei, ei_end, ei_temp;
  644 + graph_traits<TopologyGraph>::vertex_descriptor v0, v1;
  645 +
  646 + //cout<<"Tc"<<endl;
  647 + //BOOST_PrintGraph(Tc);
  648 + //test each edge in T
  649 + boost::tuples::tie(ei, ei_end) = edges(Tc);
  650 + while(ei!=ei_end)
  651 + {
  652 + //see if there is a corresponding edge in GT
  653 + v0 = get(vertex_color_t(), Tc, source(*ei, Tc));
  654 + v1 = get(vertex_color_t(), Tc, target(*ei, Tc));
  655 + //e = edge(v0, v1, GTc);
  656 + e_GTc = BOOST_SmallestEdge(v0, v1, GTc);
  657 + //if(v0 == 1 || v1 == 1)
  658 + // cout<<"test"<<endl;
  659 +
  660 + if(e_GTc.second)
  661 + {
  662 + e_Tc = BOOST_SmallestEdge(source(*ei, Tc), target(*ei, Tc), Tc);
  663 +
  664 + //create the mapping
  665 + TtoGT.first = get(edge_color_t(), Tc, e_Tc.first);
  666 + TtoGT.second = get(edge_color_t(), GTc, e_GTc.first);
  667 + result.push_back(TtoGT);
  668 +
  669 + //remove the edge
  670 + remove_edge(e_GTc.first, GTc);
  671 + remove_edge(e_Tc.first, Tc);
  672 + boost::tuples::tie(ei, ei_end) = edges(Tc);
  673 + }
  674 + else
  675 + ei++;
  676 + }
  677 +
  678 +
  679 +
  680 + //cout<<"Core after comparison: "<<endl;
  681 + //cout<<"GTc"<<endl;
  682 + //BOOST_PrintGraph(GTc);
  683 + //cout<<"Tc"<<endl;
  684 + //BOOST_PrintGraph(Tc);
  685 + return result;
  686 + }
  687 +
  688 + CoreGraphList NEW_ComputeTopology(rtsFiberNetwork* testNetwork, float sigma)
  689 + {
  690 + //cout<<"Number of Ground-Truth Nodes: "<<NodeList.size()<<endl;
  691 + //cout<<"Number of Test-Case Nodes: "<<testNetwork->NodeList.size()<<endl;
  692 +
  693 + //construct a graph representation of each network
  694 + TopologyGraph GT = BOOST_BuildGraph(this);
  695 + TopologyGraph T = BOOST_BuildGraph(testNetwork);
  696 +
  697 + //color the vertices
  698 + BOOST_KD_ColorGraphs(T, GT, sigma);
  699 +
  700 + //apply the colors to the network
  701 + BOOST_ApplyColorsToNetwork(GT, this);
  702 + BOOST_ApplyColorsToNetwork(T, testNetwork);
  703 +
  704 + //remove spurs
  705 + //cout<<"Removing Spines...";
  706 + //int false_positive_spines = BOOST_RemoveSpines(T);
  707 + //int false_negative_spines = BOOST_RemoveSpines(GT);
  708 + //cout<<"done"<<endl;
  709 + //cout<<"False Positive Spines: "<<false_positive_spines<<endl;
  710 + //cout<<"False Negative Spines: "<<false_negative_spines<<endl;
  711 +
  712 + //initialize the global predecessor list
  713 + //cout<<"Computing Core Connectivity for T...";
  714 + TopologyGraph Tc = BOOST_FindCoreGraph(T);
  715 + //cout<<"done"<<endl;
  716 + //cout<<"Computing Core Connectivity for GT...";
  717 + TopologyGraph GTc = BOOST_FindCoreGraph(GT);
  718 + //cout<<"done"<<endl;
  719 + //cout<<"Comparing Graphs...";
  720 + return BOOST_CompareCoreGraphs(GTc, Tc);
  721 + //cout<<"done"<<endl;
  722 + }
  723 + TopologyGraph BOOST_BuildGraph(rtsFiberNetwork* network)
  724 + {
  725 + //create the graph
  726 + TopologyGraph g(network->NodeList.size());
  727 +
  728 + //for each fiber in the graph, create an edge
  729 + int n0, n1;
  730 + typedef std::pair<int, int> Edge;
  731 + typedef std::pair<boost::graph_traits<TopologyGraph>::edge_descriptor, bool> EdgeIDType;
  732 + EdgeIDType edge_id;
  733 + Edge new_edge;
  734 + EdgeProperties ep;
  735 + EdgeSequence edge_sequence;
  736 + for(unsigned int f=0; f<network->FiberList.size(); f++)
  737 + {
  738 + if(!network->isCulled(f))
  739 + {
  740 + n0 = network->FiberList[f].n0;
  741 + n1 = network->FiberList[f].n1;
  742 + new_edge = Edge(n0, n1);
  743 + edge_id = add_edge(new_edge.first, new_edge.second, network->FiberList[f].error*network->FiberList[f].length, g);
  744 +
  745 + //add the starting edge color
  746 + edge_sequence.clear();
  747 + edge_sequence.push_back(f);
  748 + put(edge_color_t(), g, edge_id.first, edge_sequence);
  749 + }
  750 + else
  751 + cout<<"culled"<<endl;
  752 + }
  753 +
  754 + //for each vertex in the graph, assign the position
  755 + typedef property_map<TopologyGraph, vertex_position_t>::type PositionMap;
  756 + PositionMap positions = get(vertex_position_t(), g);
  757 +
  758 + for(unsigned int v=0; v<network->NodeList.size(); v++)
  759 + positions[v] = network->NodeList[v].p;
  760 +
  761 + return g;
  762 + }
  763 + void BOOST_KD_ColorGraph(TopologyGraph& G, TopologyGraph& compareTo, float sigma)
  764 + {
  765 + //get the number of vertices in compareTo
  766 + int verts = num_vertices(compareTo);
  767 + //allocate enough space in an ANN array
  768 + ANNpointArray dataPts = annAllocPts(verts, 3);
  769 +
  770 + //get the vertex positions
  771 + typedef property_map<TopologyGraph, vertex_position_t>::type PositionMap;
  772 + PositionMap positions = get(vertex_position_t(), compareTo);
  773 + //insert the positions into the ANN list
  774 + for(int v=0; v<verts; v++)
  775 + {
  776 + dataPts[v][0] = positions[v].x;
  777 + dataPts[v][1] = positions[v].y;
  778 + dataPts[v][2] = positions[v].z;
  779 + }
  780 + //build the KD tree
  781 + ANNkd_tree* kdTree;
  782 + kdTree = new ANNkd_tree(dataPts, verts, 3);
  783 +
  784 + //PERFORM THE NEAREST NEIGHBOR SEARCH
  785 + //allocate variables
  786 + ANNpoint queryPt = annAllocPt(3);
  787 + ANNidxArray nearestIdx = new ANNidx[1];
  788 + ANNdistArray nearestDist = new ANNdist[1];
  789 +
  790 + //get the position map for G
  791 + positions = get(vertex_position_t(), G);
  792 + //get the vertex color map (valid/invalid)
  793 + typedef property_map<TopologyGraph, vertex_color_t>::type ColorMap;
  794 + ColorMap colors = get(vertex_color_t(), G);
  795 + //get the vertex compatibility map
  796 + //typedef property_map<TopologyGraph, vertex_compatibility_t>::type CompatibilityMap;
  797 + //CompatibilityMap compatibility = get(vertex_compatibility_t(), G);
  798 + //get the index property map
  799 + //typedef property_map<TopologyGraph, vertex_index_t>::type IndexMap;
  800 + //IndexMap index = get(vertex_index, G);
  801 +
  802 + //query each vertex in G
  803 + typedef graph_traits<TopologyGraph>::vertex_iterator vertex_iter;
  804 + std::pair<vertex_iter, vertex_iter> vp;
  805 + point3D<float> pos;
  806 + for (vp = vertices(G); vp.first != vp.second; ++vp.first)
  807 + {
  808 + pos = positions[*vp.first];
  809 + queryPt[0] = pos.x;
  810 + queryPt[1] = pos.y;
  811 + queryPt[2] = pos.z;
  812 + //perform the 1-NN search
  813 + kdTree->annkSearch(queryPt, 1, nearestIdx, nearestDist);
  814 + //if the distance is less than sigma, label as valid
  815 + if(sqrt(nearestDist[0]) < sigma)
  816 + {
  817 + colors[*vp.first] = nearestIdx[0];
  818 + //compatibility[*vp.first] = nearestIdx[0];
  819 + }
  820 + else
  821 + {
  822 + colors[*vp.first] = -1;
  823 + //compatibility[*vp.first] = -1;
  824 + }
  825 + }
  826 + }
  827 + void BOOST_KD_ColorGraphs(TopologyGraph& T, TopologyGraph& GT, float sigma)
  828 + {
  829 + /*Colors both graphs for the connectivity metric:
  830 + 1) Create a kd-tree using the vertices in GT
  831 + 2) Find a vertex in GT near each vertex in T
  832 + a) If a vertex in GT isn't found, the vertex in T is assigned a color of -1
  833 + b) If a vertex in GT is found, the vertex in T is assigned the corresponding index
  834 + 3) Vertices in GT are assigned their own index if they are found (-1 if they aren't)
  835 + */
  836 +
  837 + //initialize each vertex in T with a color of -1
  838 + graph_traits<TopologyGraph>::vertex_iterator vi, vi_end;
  839 + for (boost::tuples::tie(vi, vi_end) = vertices(T); vi != vi_end; vi++)
  840 + {
  841 + put(vertex_color_t(), T, *vi, -1);
  842 + }
  843 +
  844 + //initialize each vertex in GT with -1
  845 + for (boost::tuples::tie(vi, vi_end) = vertices(GT); vi != vi_end; vi++)
  846 + {
  847 + put(vertex_color_t(), GT, *vi, -1);
  848 + }
  849 + //BOOST_PrintGraph(T);
  850 +
  851 + //CREATE THE KD TREE REPRESENTING GT
  852 + //get the number of vertices in GT
  853 + int verts = num_vertices(T);
  854 + //allocate enough space in an ANN array
  855 + ANNpointArray dataPts = annAllocPts(verts, 3);
  856 +
  857 + //get the vertex positions
  858 + typedef property_map<TopologyGraph, vertex_position_t>::type PositionMap;
  859 + PositionMap positions = get(vertex_position_t(), T);
  860 + //insert the positions into the ANN list
  861 + for(int v=0; v<verts; v++)
  862 + {
  863 + dataPts[v][0] = positions[v].x;
  864 + dataPts[v][1] = positions[v].y;
  865 + dataPts[v][2] = positions[v].z;
  866 + //set the color for each vertex in GT to -1
  867 + //put(vertex_color_t(), T, v, -1);
  868 + }
  869 + //build the KD tree
  870 + ANNkd_tree* kdTree;
  871 + kdTree = new ANNkd_tree(dataPts, verts, 3);
  872 +
  873 + //PERFORM THE NEAREST NEIGHBOR SEARCH
  874 + //allocate variables
  875 + ANNpoint queryPt = annAllocPt(3);
  876 + ANNidxArray nearestIdx = new ANNidx[1];
  877 + ANNdistArray nearestDist = new ANNdist[1];
  878 +
  879 + //get the position map for T
  880 + //positions = get(vertex_position_t(), G);
  881 + //get the vertex color map
  882 + //typedef property_map<TopologyGraph, vertex_color_t>::type ColorMap;
  883 + //ColorMap colors = get(vertex_color_t(), G);
  884 +
  885 + //query each vertex in T
  886 + //std::pair<vertex_iter, vertex_iter> vp;
  887 + point3D<float> pos;
  888 + int num_undetected = 0;
  889 + for (boost::tuples::tie(vi, vi_end) = vertices(GT); vi != vi_end; vi++)
  890 + {
  891 + //pos = positions[*vp.first];
  892 + pos = get(vertex_position_t(), GT, *vi);
  893 + queryPt[0] = pos.x;
  894 + queryPt[1] = pos.y;
  895 + queryPt[2] = pos.z;
  896 + //perform the 1-NN search
  897 + kdTree->annkSearch(queryPt, 1, nearestIdx, nearestDist);
  898 + //if the distance is less than sigma, label as valid
  899 + if(sqrt(nearestDist[0]) < sigma)
  900 + {
  901 + //colors[*vp.first] = nearestIdx[0];
  902 + //color T
  903 + put(vertex_color_t(), T, nearestIdx[0], (int)*vi);
  904 + //color GT
  905 + put(vertex_color_t(), GT, *vi, (int)*vi);
  906 + //compatibility[*vp.first] = nearestIdx[0];
  907 + }
  908 + else
  909 + {
  910 + //put(vertex_color_t(), T, *vi, -1);
  911 + num_undetected++;
  912 + //compatibility[*vp.first] = -1;
  913 + }
  914 + }
  915 +
  916 + //find undetected and falsely detected nodes
  917 + //cout<<"Number of Undetected Nodes: "<<num_undetected<<endl;
  918 + int false_positive = 0;
  919 + int true_positive = 0;
  920 + for (boost::tuples::tie(vi, vi_end) = vertices(T); vi != vi_end; vi++)
  921 + {
  922 + if(get(vertex_color_t(), T, *vi) == -1)
  923 + false_positive++;
  924 + else
  925 + true_positive++;
  926 + }
  927 + //cout<<"Number of False Positive Nodes: "<<false_positive<<endl;
  928 + //cout<<"Number of True Positive Nodes: "<<true_positive<<endl;
  929 +
  930 +
  931 +
  932 + }
  933 + void BOOST_CleanGraph(TopologyGraph& G, float sigma)
  934 + {
  935 + //This function cleans up degenerate cases in the ground truth and warns the user about them
  936 + //These include:
  937 + // Ground truth nodes that are within sigma of other ground truth nodes
  938 +
  939 + //we do a 1-NN search across all vertices, looking for distance values < sigma
  940 +
  941 + bool error_detected = false;
  942 + bool vertex_error;
  943 +
  944 + int merged_edges = 0;
  945 +
  946 + //go through each vertex
  947 + graph_traits<TopologyGraph>::vertex_iterator vi, vtmp, vi_end;
  948 + boost::tuples::tie(vi, vi_end) = vertices(G);
  949 + pair<graph_traits<TopologyGraph>::edge_descriptor, bool> e_remove;
  950 + graph_traits<TopologyGraph>::adjacency_iterator ai, ai_end;
  951 + graph_traits<TopologyGraph>::vertex_descriptor v_remove;
  952 + point3D<float> vp, ap;
  953 + vector3D<float> v_dist;
  954 + float dist;
  955 + while(vi != vi_end)
  956 + {
  957 + //get the color of the vertex
  958 + vp = get(vertex_position_t(), G, *vi);
  959 +
  960 + //check every adjacent vertex
  961 + vertex_error = false;
  962 + for(boost::tuples::tie(ai, ai_end) = adjacent_vertices(*vi, G); ai != ai_end; ai++)
  963 + {
  964 + //get the position of the adjacent vertex
  965 + ap = get(vertex_position_t(), G, *ai);
  966 + //find the distance between the two points
  967 + v_dist = vp - ap;
  968 + dist = v_dist.Length();
  969 +
  970 + if(dist <= sigma)
  971 + {
  972 + error_detected = true;
  973 + vertex_error = true;
  974 + v_remove = *vi;
  975 + e_remove = edge(*vi, *ai, G);
  976 + }
  977 + }
  978 + if(vertex_error)
  979 + {
  980 + //merge the vertices along edge "e_remove"
  981 + BOOST_MergeVertices(G, e_remove.first, v_remove);
  982 +
  983 + //refresh the vertex iterator
  984 + boost::tuples::tie(vtmp, vi_end) = vertices(G);
  985 + }
  986 + else
  987 + vi++;
  988 + }
  989 +
  990 +
  991 + }
  992 + void BOOST_SaveGTIndices(TopologyGraph& G)
  993 + {
  994 + //changes the ground truth colors to vertex indices
  995 + graph_traits<TopologyGraph>::vertex_iterator vi, vi_end;
  996 + int index;
  997 + for(boost::tuples::tie(vi, vi_end) = vertices(G); vi != vi_end; vi++)
  998 + {
  999 + //only change the color if the vertex is valid
  1000 + if(get(vertex_color_t(), G, *vi) >= 0)
  1001 + {
  1002 + index = get(vertex_index_t(), G, *vi);
  1003 + put(vertex_color_t(), G, *vi, index);
  1004 + }
  1005 + }
  1006 + }
  1007 + void BOOST_ApplyColorsToNetwork(TopologyGraph& from, rtsFiberNetwork* to)
  1008 + {
  1009 + //get the index property
  1010 + typedef property_map<TopologyGraph, vertex_index_t>::type IndexMap;
  1011 + IndexMap index = get(vertex_index, from);
  1012 + //get the vertex color (valid/invalid)
  1013 + typedef property_map<TopologyGraph, vertex_color_t>::type ColorMap;
  1014 + ColorMap colors = get(vertex_color_t(), from);
  1015 +
  1016 + //go through each vertex and apply the appropriate color to the associated fiber node
  1017 + typedef graph_traits<TopologyGraph>::vertex_iterator vertex_iter;
  1018 + std::pair<vertex_iter, vertex_iter> vp;
  1019 + int idx;
  1020 + for (vp = vertices(from); vp.first != vp.second; ++vp.first)
  1021 + {
  1022 + idx = index[*vp.first];
  1023 + to->NodeList[idx].color = colors[*vp.first];
  1024 + }
  1025 + //cout << index[*vp.first] <<":"<<colors[*vp.first]<<"("<<compatibility[*vp.first]<<")= "<<positions[*vp.first]<<endl;
  1026 +
  1027 + }
  1028 + void BOOST_MergeVertices(TopologyGraph& G, graph_traits<TopologyGraph>::edge_descriptor e, graph_traits<TopologyGraph>::vertex_descriptor v)
  1029 + {
  1030 + //cout<<"MERGE VERTEX TEST-------------------------------"<<endl;
  1031 + //get the vertex descriptor for v0 and v1
  1032 + graph_traits<TopologyGraph>::vertex_descriptor v0, v1;
  1033 + v0 = v;
  1034 + v1 = target(e, G);
  1035 + if(v1 == v) v1 = source(e, G);
  1036 +
  1037 + //we will merge v0 to v1 (although the order doesn't matter)
  1038 + //well, okay, it does matter as far as the vertex position is concerned...maybe I'll fix that
  1039 +
  1040 + //get the current edge's colors
  1041 + EdgeSequence removed_colors = get(edge_color_t(), G, e);
  1042 + float removed_weight = get(edge_weight_t(), G, e);
  1043 +
  1044 + //first delete the current edge
  1045 + remove_edge(e, G);
  1046 +
  1047 + //for each edge coming into v0, create a corresponding edge into v1
  1048 + pair<graph_traits<TopologyGraph>::edge_descriptor, bool> new_edge;
  1049 + graph_traits<TopologyGraph>::in_edge_iterator ei, ei_end;
  1050 + EdgeSequence new_colors;
  1051 + float weight;
  1052 + for(boost::tuples::tie(ei, ei_end) = in_edges(v0, G); ei != ei_end; ei++)
  1053 + {
  1054 + //create a new edge for each edge coming in to v0
  1055 + new_edge = add_edge(source(*ei, G), v1, G);
  1056 + new_colors = get(edge_color_t(), G, *ei);
  1057 +
  1058 + //add the removed colors to the new edge
  1059 + new_colors.insert(new_colors.end(), removed_colors.begin(), removed_colors.end());
  1060 +
  1061 + weight = get(edge_weight_t(), G, *ei) + removed_weight;
  1062 + put(edge_weight_t(), G, new_edge.first, weight);
  1063 + put(edge_color_t(), G, new_edge.first, new_colors);
  1064 + }
  1065 +
  1066 + //now remove v0 from the graph
  1067 + clear_vertex(v0, G);
  1068 + //remove_vertex(v0, G);
  1069 +
  1070 + //cout<<"END MERGE VERTEX TEST-------------------------------"<<endl;
  1071 +
  1072 + }
  1073 + void BOOST_MergeInvalidVertices(TopologyGraph& G)
  1074 + {
  1075 + //merges vertices that have color < 0
  1076 +
  1077 + //go through each vertex
  1078 + graph_traits<TopologyGraph>::vertex_iterator vi, vtmp, vi_end;
  1079 + boost::tuples::tie(vi, vi_end) = vertices(G);
  1080 + int color;
  1081 + float min_weight;
  1082 + float weight;
  1083 + graph_traits<TopologyGraph>::edge_descriptor e_remove;
  1084 + graph_traits<TopologyGraph>::in_edge_iterator ei, ei_end;
  1085 + //graph_traits<TopologyGraph>::vertex_descriptor v_remove;
  1086 + bool vertex_removal;
  1087 +
  1088 + //merge neighbors that are both invalid
  1089 + //for each vertex
  1090 + for(boost::tuples::tie(vi, vi_end) = vertices(G); vi!=vi_end; vi++)
  1091 + {
  1092 + vertex_removal = false;
  1093 + color = get(vertex_color_t(), G, *vi);
  1094 +
  1095 + //if the vertex is invalid
  1096 + if(color < 0)
  1097 + {
  1098 +
  1099 + //get the incident edge with the lowest weight
  1100 + min_weight = 99999.0;
  1101 + for(boost::tuples::tie(ei, ei_end) = in_edges(*vi, G); ei != ei_end; ei++)
  1102 + {
  1103 + if(get(vertex_color_t(), G, source(*ei, G)) == get(vertex_color_t(), G, target(*ei, G)))
  1104 + {
  1105 + vertex_removal = true;
  1106 + weight = get(edge_weight_t(), G, *ei);
  1107 + cout<<"weight: "<<weight<<" source color: "<<color<<endl;
  1108 + if(weight <= min_weight)
  1109 + {
  1110 + min_weight = get(edge_weight_t(), G, *ei);
  1111 + e_remove = *ei;
  1112 + }
  1113 + }
  1114 + }
  1115 + //if a vertex is to be removed, remove it
  1116 + if(vertex_removal)
  1117 + {
  1118 + cout<<"Min Weight: "<<min_weight<<endl;
  1119 + //merge the vertices along edge "max_edge"
  1120 + BOOST_MergeVertices(G, e_remove, *vi);
  1121 + }
  1122 +
  1123 + }
  1124 +
  1125 + }
  1126 +
  1127 + //merge a vertex with its neighbor if it is invalid and degree=2
  1128 + for(boost::tuples::tie(vi, vi_end) = vertices(G); vi!=vi_end; vi++)
  1129 + {
  1130 + //if the vertex is invalid
  1131 + if(color < 0 && degree(*vi, G) == 2)
  1132 + {
  1133 + boost::tuples::tie(ei, ei_end) = in_edges(*vi, G);
  1134 + e_remove = *ei;
  1135 + BOOST_MergeVertices(G, e_remove, *vi);
  1136 + }
  1137 + }
  1138 +
  1139 + }
  1140 + int BOOST_RemoveSpines(TopologyGraph& G)
  1141 + {
  1142 + //merges vertices that have color < 0
  1143 + int merged_spines = 0;
  1144 +
  1145 + //go through each vertex
  1146 + graph_traits<TopologyGraph>::vertex_iterator vi, vtmp, vi_end;
  1147 + boost::tuples::tie(vi, vi_end) = vertices(G);
  1148 + graph_traits<TopologyGraph>::edge_descriptor max_edge;
  1149 + graph_traits<TopologyGraph>::in_edge_iterator ei, ei_end;
  1150 + graph_traits<TopologyGraph>::vertex_descriptor v_next, v_this;
  1151 + graph_traits<TopologyGraph>::adjacency_iterator ai, ai_end;
  1152 + int v_degree;
  1153 +
  1154 + //for each vertex
  1155 + for(boost::tuples::tie(vi, vi_end) = vertices(G); vi!=vi_end; vi++)
  1156 + {
  1157 + //if the vertex is invalid AND degree=1
  1158 + v_degree = degree(*vi, G);
  1159 + if(get(vertex_color_t(), G, *vi) < 0 && v_degree == 1)
  1160 + {
  1161 + //delete the entire spur
  1162 + v_this = *vi;
  1163 + do{
  1164 + //get the adjacent vertex
  1165 + boost::tuples::tie(ai, ai_end) = adjacent_vertices(v_this, G);
  1166 + //cout<<*ai<<endl;
  1167 + v_next = *ai;
  1168 + //clear the current vertex (there should only be one edge)
  1169 + clear_vertex(v_this, G);
  1170 + v_this = v_next;
  1171 + }while(degree(v_this, G) == 1 && get(vertex_color_t(), G, v_this) < 0);
  1172 + merged_spines++;
  1173 + }
  1174 + }
  1175 +
  1176 +
  1177 + return merged_spines;
  1178 + }
  1179 + int BOOST_MergeCompatibleVertices(TopologyGraph& G)
  1180 + {
  1181 + int merged_edges = 0;
  1182 +
  1183 + //go through each vertex
  1184 + graph_traits<TopologyGraph>::vertex_iterator vi, vtmp, vi_end;
  1185 + boost::tuples::tie(vi, vi_end) = vertices(G);
  1186 + int color;
  1187 + pair<graph_traits<TopologyGraph>::edge_descriptor, bool> e_remove;
  1188 + graph_traits<TopologyGraph>::adjacency_iterator ai, ai_end;
  1189 + graph_traits<TopologyGraph>::vertex_descriptor v_remove;
  1190 + int num_incident;
  1191 + bool merge_found;
  1192 + while(vi != vi_end)
  1193 + {
  1194 + //get the color of the vertex
  1195 + color = get(vertex_color_t(), G, *vi);
  1196 + //if the vertex is valid
  1197 + if(color >= 0)
  1198 + {
  1199 + //run through each adjacent vertex
  1200 + merge_found = false;
  1201 + for(boost::tuples::tie(ai, ai_end) = adjacent_vertices(*vi, G); ai != ai_end; ai++)
  1202 + {
  1203 + //if the two vertices are compatible
  1204 + if(color == get(vertex_color_t(), G, *ai) && (*vi != *ai))
  1205 + {
  1206 + v_remove = *vi;
  1207 + e_remove = edge(*vi, *ai, G);
  1208 + merge_found = true;
  1209 + }
  1210 + }
  1211 + if(merge_found)
  1212 + {
  1213 + num_incident = degree(v_remove, G);
  1214 + BOOST_MergeVertices(G, e_remove.first, v_remove);
  1215 + if(num_incident == 1) merged_edges++;
  1216 + boost::tuples::tie(vtmp, vi_end) = vertices(G);
  1217 + }
  1218 + else vi++;
  1219 + }
  1220 + else
  1221 + vi++;
  1222 + }
  1223 +
  1224 + return merged_edges;
  1225 + }
  1226 +
  1227 + EdgeSequence BOOST_RemoveEdge(int v0, int v1, TopologyGraph& G)
  1228 + {
  1229 + //look for a direct edge
  1230 + pair<graph_traits<TopologyGraph>::edge_descriptor, bool> e0, e1;
  1231 + e0 = BOOST_SmallestEdge(v0, v1, G);
  1232 +
  1233 + //if it exists, remove it and return the edge sequence
  1234 + EdgeSequence sequence0, sequence1;
  1235 + sequence0.clear();
  1236 + if(e0.second)
  1237 + {
  1238 + sequence0 = get(edge_color_t(), G, e0.first);
  1239 + remove_edge(e0.first, G);
  1240 + }
  1241 + //otherwise look for an indirect edge
  1242 +
  1243 + else
  1244 + {
  1245 + graph_traits<TopologyGraph>::adjacency_iterator ai, ai_end;
  1246 + //for each vertex adjacent to v0
  1247 + for(boost::tuples::tie(ai, ai_end) = adjacent_vertices(v0, G); ai!=ai_end; ai++)
  1248 + {
  1249 + //if the adjacent vertex is invalid
  1250 + if(get(vertex_color_t(), G, *ai) < 0)
  1251 + {
  1252 + //see if v1 is also connected
  1253 + e1 = BOOST_SmallestEdge(v1, *ai, G);
  1254 + //if it is
  1255 + if(e1.second)
  1256 + {
  1257 + sequence0 = get(edge_color_t(), G, e1.first);
  1258 + e0 = BOOST_SmallestEdge(v0, *ai, G);
  1259 + sequence1 = get(edge_color_t(), G, e0.first);
  1260 + sequence0.insert(sequence0.end(), sequence1.begin(), sequence1.end());
  1261 + remove_edge(e0.first, G);
  1262 + remove_edge(e1.first, G);
  1263 + return sequence0;
  1264 + }
  1265 + }
  1266 + }
  1267 + }
  1268 + return sequence0;
  1269 +
  1270 + }
  1271 + CoreGraphList BOOST_FindCore(TopologyGraph& GT, TopologyGraph& T)
  1272 + {
  1273 + CoreGraphList Gc;
  1274 +
  1275 + int FP = 0;
  1276 + int FN = 0;
  1277 +
  1278 + //Find edges that exist in both GT and T
  1279 + EdgeSequence T_Path, GT_Path;
  1280 + EdgeMapping path_pair;
  1281 +
  1282 + //create iterators for the edges in T
  1283 + graph_traits<TopologyGraph>::edge_iterator ei, ei_end;
  1284 +
  1285 + //for each edge in T, remove the corresponding edge in GT (if it exists) and put the details in the core garph list
  1286 + int v0, v1;
  1287 + pair<graph_traits<TopologyGraph>::edge_descriptor, bool> e;
  1288 + pair<graph_traits<TopologyGraph>::edge_descriptor, bool> e_T, e_GT;
  1289 +
  1290 + graph_traits<TopologyGraph>::vertex_descriptor s, t;
  1291 + list<graph_traits<TopologyGraph>::edge_descriptor> to_remove;
  1292 + list<graph_traits<TopologyGraph>::edge_descriptor>::iterator remove_iter;
  1293 +
  1294 + /*//add all edges to a list
  1295 + list<pair<TopologyEdge, float>> EdgeList;
  1296 + for(tie(ei, ei_end) = edges(T); ei!=ei_end; ei++)
  1297 + {
  1298 + pair<TopologyEdge, float> edge_data;
  1299 + edge_data.first = *ei;
  1300 + edge_data.second = get(edge_weight_t(), T, *ei);
  1301 + EdgeList.push_back(edge_data);
  1302 + }
  1303 + EdgeList.sort(compare_edges);*/
  1304 +
  1305 + //find direct connections
  1306 + for(boost::tuples::tie(ei, ei_end) = edges(T); ei!=ei_end; ei++)
  1307 + {
  1308 + //get the ID for the corresponding vertices in GT
  1309 + s = source(*ei, T);
  1310 + t = target(*ei, T);
  1311 + v0 = get(vertex_color_t(), T, s);
  1312 + v1 = get(vertex_color_t(), T, t);
  1313 +
  1314 + //if both vertices are valid
  1315 + if(v0 >= 0 && v1 >= 0)
  1316 + {
  1317 + GT_Path = BOOST_RemoveEdge(v0, v1, GT);
  1318 + //if there was a corresponding edge in GT
  1319 + if(GT_Path.size() > 0)
  1320 + {
  1321 + //get the edge path from T
  1322 + T_Path = get(edge_color_t(), T, *ei);
  1323 + //create the path pair and add it to the core graph list
  1324 + path_pair.first = T_Path;
  1325 + path_pair.second = GT_Path;
  1326 + Gc.push_back(path_pair);
  1327 + }
  1328 + else
  1329 + FP++;
  1330 + //mark the edge for removal from T
  1331 + to_remove.push_back(*ei);
  1332 +
  1333 + }
  1334 + }
  1335 + for(remove_iter = to_remove.begin(); remove_iter != to_remove.end(); remove_iter++)
  1336 + remove_edge(*remove_iter, T);
  1337 +
  1338 +
  1339 + //find indirect connections (these are connections that use one invalid point)
  1340 + graph_traits<TopologyGraph>::adjacency_iterator ai, ai_end;
  1341 + bool match_found;
  1342 + while(num_edges(T) > 0)
  1343 + {
  1344 + boost::tuples::tie(ei, ei_end) = edges(T);
  1345 +
  1346 + //s = valid point, t = invalid
  1347 + s = source(*ei, T);
  1348 + if(get(vertex_color_t(), T, s) < 0)
  1349 + {
  1350 + t = s;
  1351 + s = target(*ei, T);
  1352 + }
  1353 + else
  1354 + t = target(*ei, T);
  1355 + //for each point adjacent to the invalid point
  1356 + match_found = false;
  1357 + v0 = get(vertex_color_t(), T, s);
  1358 + for(boost::tuples::tie(ai, ai_end) = adjacent_vertices(t, T); ai!=ai_end; ai++)
  1359 + {
  1360 + //get the edge path from T
  1361 + e = edge(t, *ai, T);
  1362 + //make sure that the first and second edges are not the same
  1363 + if(e.first != *ei)
  1364 + {
  1365 + v1 = get(vertex_color_t(), T, *ai);
  1366 + GT_Path = BOOST_RemoveEdge(v0, v1, GT);
  1367 + //if there was a corresponding edge in GT
  1368 + if(GT_Path.size() > 0)
  1369 + {
  1370 + match_found = true;
  1371 + T_Path = get(edge_color_t(), T, e.first);
  1372 + EdgeSequence temp = get(edge_color_t(), T, *ei);
  1373 + T_Path.insert(T_Path.end(), temp.begin(), temp.end());
  1374 +
  1375 + //create the path pair and add it to the core graph list
  1376 + path_pair.first = T_Path;
  1377 + path_pair.second = GT_Path;
  1378 + Gc.push_back(path_pair);
  1379 +
  1380 + //remove both edges and break
  1381 + remove_edge(e.first, T);
  1382 + remove_edge(*ei, T);
  1383 + break;
  1384 + }
  1385 + }
  1386 + }
  1387 + if(!match_found)
  1388 + {
  1389 + FP++;
  1390 + remove_edge(*ei, T);
  1391 + }
  1392 + }
  1393 +
  1394 + cout<<"False Positive Edges in Core: "<<FP<<endl;
  1395 +
  1396 +
  1397 +
  1398 + return Gc;
  1399 + }
  1400 +
  1401 + TopologyGraph BOOST_RemapGraph(TopologyGraph& G, rtsFiberNetwork* network);
  1402 + void BOOST_PrintGraph(TopologyGraph G)
  1403 + {
  1404 + //get the index property
  1405 + typedef property_map<TopologyGraph, vertex_index_t>::type IndexMap;
  1406 + IndexMap index = get(vertex_index, G);
  1407 +
  1408 + //get the position property
  1409 + typedef property_map<TopologyGraph, vertex_position_t>::type PositionMap;
  1410 + PositionMap positions = get(vertex_position_t(), G);
  1411 + //get the vertex color (valid/invalid)
  1412 + typedef property_map<TopologyGraph, vertex_color_t>::type ColorMap;
  1413 + ColorMap colors = get(vertex_color_t(), G);
  1414 + //get vertex compatibility
  1415 + //typedef property_map<TopologyGraph, vertex_compatibility_t>::type CompatibilityMap;
  1416 + //CompatibilityMap compatibility = get(vertex_compatibility_t(), G);
  1417 +
  1418 + std::cout << "vertices(g) = "<<endl;
  1419 + typedef graph_traits<TopologyGraph>::vertex_iterator vertex_iter;
  1420 + std::pair<vertex_iter, vertex_iter> vp;
  1421 + for (vp = vertices(G); vp.first != vp.second; ++vp.first)
  1422 + cout << index[*vp.first] <<"("<<colors[*vp.first]<<") = "<<positions[*vp.first]<<endl;
  1423 + cout << endl;
  1424 +
  1425 + //get the edge weight property
  1426 + typedef property_map<TopologyGraph, edge_weight_t>::type WeightMap;
  1427 + WeightMap weights = get(edge_weight_t(), G);
  1428 +
  1429 + std::cout << "edges(source, dest): weight to_fiber"<<endl;
  1430 + graph_traits<TopologyGraph>::edge_iterator ei, ei_end;
  1431 + EdgeSequence edge_sequence;
  1432 + for (boost::tuples::tie(ei, ei_end) = edges(G); ei != ei_end; ++ei)
  1433 + {
  1434 + std::cout << "(" << index[source(*ei, G)] << "," << index[target(*ei, G)] << "): "<<weights[*ei]<<" {";
  1435 + edge_sequence = get(edge_color_t(), G, *ei);
  1436 + for(EdgeSequence::iterator i = edge_sequence.begin(); i != edge_sequence.end(); i++)
  1437 + cout<<*i<<" ";
  1438 + cout<<"}"<<endl;
  1439 + }
  1440 +
  1441 + std::cout << std::endl;
  1442 +
  1443 +
  1444 + }
  1445 +
  1446 + //network geometry functions
  1447 + double computeFiberLength(int f)
  1448 + {
  1449 + //return the length of the fiber f
  1450 + point3D<float> p0 = NodeList[FiberList[f].n0].p;
  1451 + point3D<float> p1;
  1452 +
  1453 + double length = 0.0;
  1454 + int num_points = FiberList[f].pointList.size();
  1455 + int p;
  1456 + for(p=0; p<num_points; p++)
  1457 + {
  1458 + p1 = FiberList[f].pointList[p];
  1459 + length += (p1 - p0).Length();
  1460 + p0 = p1;
  1461 + }
  1462 + p1 = NodeList[FiberList[f].n1].p;
  1463 + length += (p1 - p0).Length();
  1464 + return length;
  1465 +
  1466 + }
  1467 + void refreshFiberLengths()
  1468 + {
  1469 + for(unsigned int f=0; f<FiberList.size(); f++)
  1470 + FiberList[f].length = (float)computeFiberLength(f);
  1471 + }
  1472 +
  1473 + void refreshIncidence()
  1474 + {
  1475 + for(unsigned int n=0; n<NodeList.size(); n++)
  1476 + NodeList[n].incident = 0;
  1477 +
  1478 + for(unsigned int f=0; f<FiberList.size(); f++)
  1479 + {
  1480 + NodeList[FiberList[f].n0].incident++;
  1481 + NodeList[FiberList[f].n1].incident++;
  1482 + }
  1483 + }
  1484 +
  1485 +public:
  1486 + vector<Fiber> FiberList;
  1487 + vector<Node> NodeList;
  1488 + point3D<float> min_pos;
  1489 + point3D<float> max_pos;
  1490 +
  1491 + //constructors
  1492 + rtsFiberNetwork()
  1493 + {
  1494 + fiber_started = false;
  1495 + num_points = false;
  1496 + cull_value = 1.0;
  1497 + min_pos = point3D<float>(9999, 9999, 9999);
  1498 + max_pos = point3D<float>(-9999, -9999, -9999);
  1499 + }
  1500 +
  1501 + //get functions
  1502 + point3D<float> getNodeCoord(int node){return NodeList[node].p;}
  1503 + point3D<float> getNodeCoord(int fiber, bool node);
  1504 + point3D<float> getFiberPoint(unsigned int fiber, unsigned int point);
  1505 +
  1506 + //network culling
  1507 + float getCullValue(){return cull_value;}
  1508 + void setCullValue(float cull){cull_value = cull;}
  1509 + bool isCulled(int f)
  1510 + {
  1511 + if(FiberList[f].error <= cull_value)
  1512 + return false;
  1513 + else return true;
  1514 + }
  1515 +
  1516 + //statistics functions
  1517 + double getTotalLength();
  1518 + double getFiberLength(int f)
  1519 + {
  1520 + return FiberList[f].length;
  1521 + }
  1522 +
  1523 +
  1524 +
  1525 + //drawing functions
  1526 + void StartFiber(float x, float y, float z)
  1527 + {
  1528 + fiber_started = true;
  1529 + num_points = 1;
  1530 +
  1531 + //create a start node and an end node
  1532 + Node n;
  1533 + n.p = point3D<float>(x, y, z);
  1534 + NodeList.push_back(n);
  1535 + NodeList.push_back(n);
  1536 +
  1537 + //create a fiber
  1538 + Fiber f;
  1539 + f.n0 = NodeList.size()-2;
  1540 + f.n1 = NodeList.size()-1;
  1541 + FiberList.push_back(f);
  1542 +
  1543 + }
  1544 + void StartFiber(int node)
  1545 + {
  1546 + fiber_started = true;
  1547 + num_points = 1;
  1548 +
  1549 + //the start node is specified
  1550 + //specify the end node
  1551 + Node n = NodeList[node];
  1552 + NodeList.push_back(n);
  1553 +
  1554 + //create a fiber
  1555 + Fiber f;
  1556 + f.n0 = node;
  1557 + f.n1 = NodeList.size()-1;
  1558 + FiberList.push_back(f);
  1559 + }
  1560 +
  1561 + void ContinueFiber(float x, float y, float z)
  1562 + {
  1563 + if(!fiber_started)
  1564 + {
  1565 + StartFiber(x, y, z);
  1566 + return;
  1567 + }
  1568 + num_points++;
  1569 +
  1570 + //store the last node coordinate in the fiber list
  1571 + int f = FiberList.size() - 1;
  1572 + int n = NodeList.size() - 1;
  1573 +
  1574 + if(num_points > 2)
  1575 + FiberList[f].pointList.push_back(NodeList[n].p);
  1576 + NodeList[n].p = point3D<float>(x, y, z);
  1577 + //NodeList[n].p.print();
  1578 + //cout<<endl;
  1579 + }
  1580 +
  1581 + void EndFiber()
  1582 + {
  1583 + fiber_started = false;
  1584 + }
  1585 + void StartBranch(int node)
  1586 + {
  1587 +
  1588 + num_points = 1;
  1589 + fiber_started = true;
  1590 +
  1591 + //create an end node only
  1592 + Fiber f;
  1593 + f.n0 = node;
  1594 +
  1595 + Node n = NodeList[node];
  1596 + NodeList.push_back(n);
  1597 +
  1598 +
  1599 + f.n1 = NodeList.size()-1;
  1600 + FiberList.push_back(f);
  1601 +
  1602 + }
  1603 +
  1604 + void EndBranch(int node)
  1605 + {
  1606 + int n = NodeList.size() - 1;
  1607 + int f = FiberList.size() - 1;
  1608 +
  1609 + //store the current node position in the fiber list
  1610 + FiberList[f].pointList.push_back(NodeList[n].p);
  1611 +
  1612 + //set the picked node as the fiber destination
  1613 + FiberList[f].n1 = node;
  1614 +
  1615 + //remove the final node (now not used)
  1616 + NodeList.pop_back();
  1617 +
  1618 + fiber_started = false;
  1619 + }
  1620 +
  1621 + void ConnectFiber(unsigned int node)
  1622 + {
  1623 + if(!fiber_started)
  1624 + {
  1625 + StartFiber(node);
  1626 + return;
  1627 + }
  1628 + if(node >= NodeList.size() - 1)
  1629 + return;
  1630 +
  1631 + int f = FiberList.size() - 1;
  1632 +
  1633 + //add the last point
  1634 + FiberList[f].pointList.push_back(NodeList[FiberList[f].n1].p);
  1635 +
  1636 + //attach to the specified node
  1637 + FiberList[f].n1 = node;
  1638 + NodeList.pop_back();
  1639 + fiber_started = false;
  1640 + }
  1641 + void StartFiber(point3D<float> p){StartFiber(p.x, p.y, p.z);}
  1642 + void ContinueFiber(point3D<float> p){ContinueFiber(p.x, p.y, p.z);}
  1643 +
  1644 + void Clear()
  1645 + {
  1646 + FiberList.clear();
  1647 + NodeList.clear();
  1648 + fiber_started = false;
  1649 + }
  1650 +
  1651 + //loading functions
  1652 + void MergeNodes(float sigma)
  1653 + {
  1654 + //create a KD tree for all nodes in the network
  1655 + //get the number of vertices in GT
  1656 + int verts = NodeList.size();
  1657 + //allocate enough space in an ANN array
  1658 + ANNpointArray dataPts = annAllocPts(verts, 3);
  1659 +
  1660 + //insert the positions into the ANN list
  1661 + for(int v=0; v<verts; v++)
  1662 + {
  1663 + dataPts[v][0] = NodeList[v].p.x;
  1664 + dataPts[v][1] = NodeList[v].p.y;
  1665 + dataPts[v][2] = NodeList[v].p.z;
  1666 + }
  1667 + //build the KD tree
  1668 + ANNkd_tree* kdTree;
  1669 + kdTree = new ANNkd_tree(dataPts, verts, 3);
  1670 +
  1671 + //create a map
  1672 + vector<int> NodeMap;
  1673 + NodeMap.resize(NodeList.size(), -1);
  1674 +
  1675 + ANNpoint queryPt = annAllocPt(3);
  1676 + ANNidxArray nearestIdx = new ANNidx[1];
  1677 + ANNdistArray nearestDist = new ANNdist[1];
  1678 +
  1679 + for(unsigned int n=0; n<NodeList.size(); n++)
  1680 + {
  1681 + queryPt[0] = NodeList[n].p.x;
  1682 + queryPt[1] = NodeList[n].p.y;
  1683 + queryPt[2] = NodeList[n].p.z;
  1684 + //perform the 1-NN search
  1685 + kdTree->annkSearch(queryPt, 1, nearestIdx, nearestDist);
  1686 +
  1687 + NodeMap[n] = nearestIdx[0];
  1688 + }
  1689 +
  1690 + //set the nodes for each fiber to those mapped
  1691 + for(unsigned int f=0; f<FiberList.size(); f++)
  1692 + {
  1693 + FiberList[f].n0 = NodeMap[FiberList[f].n0];
  1694 + FiberList[f].n1 = NodeMap[FiberList[f].n1];
  1695 + }
  1696 +
  1697 + RemoveExcessNodes();
  1698 + refreshIncidence();
  1699 + }
  1700 + void RemoveExcessNodes()
  1701 + {
  1702 + vector<int> NodeMap;
  1703 + NodeMap.resize(NodeList.size(), -1);
  1704 + vector<int> FiberNum;
  1705 + FiberNum.resize(NodeList.size(), 0);
  1706 +
  1707 + vector<Node> newNodeList;
  1708 +
  1709 + //run through each fiber
  1710 + int node;
  1711 + for(unsigned int f=0; f<FiberList.size(); f++)
  1712 + {
  1713 + node = FiberList[f].n0;
  1714 + //if this node has not been encountered
  1715 + if(NodeMap[node] == -1)
  1716 + {
  1717 + NodeMap[node] = newNodeList.size();
  1718 + FiberList[f].n0 = NodeMap[node];
  1719 + newNodeList.push_back(NodeList[node]);
  1720 +
  1721 + FiberNum[node]++;
  1722 + }
  1723 + else
  1724 + {
  1725 + FiberList[f].n0 = NodeMap[node];
  1726 +
  1727 + FiberNum[node]++;
  1728 + }
  1729 +
  1730 + node = FiberList[f].n1;
  1731 + if(NodeMap[node] == -1)
  1732 + {
  1733 + NodeMap[node] = newNodeList.size();
  1734 + FiberList[f].n1 = NodeMap[node];
  1735 + newNodeList.push_back(NodeList[node]);
  1736 +
  1737 + FiberNum[node]++;
  1738 + }
  1739 + else
  1740 + {
  1741 + FiberList[f].n1 = NodeMap[node];
  1742 +
  1743 + FiberNum[node]++;
  1744 + }
  1745 + }
  1746 +
  1747 + NodeList = newNodeList;
  1748 + }
  1749 + void LoadSWC(string filename)
  1750 + {
  1751 + //open the file
  1752 + ifstream infile;
  1753 + infile.open(filename.c_str());
  1754 + if(!infile)
  1755 + exit(1);
  1756 +
  1757 + //variables to read
  1758 + int id, type, parent;
  1759 + int prev_id = 0;
  1760 + float x, y, z, r;
  1761 +
  1762 + vector<int> branchIDList;
  1763 + vector<int> correspondingNodeList;
  1764 +
  1765 + vector<int>::iterator iter;
  1766 + int index;
  1767 +
  1768 + char c;
  1769 + //first pass, get branch points and find bounds
  1770 + while(!infile.eof())
  1771 + {
  1772 + c = infile.peek();
  1773 + if((c <'0' || c > '9') && c != 32)
  1774 + infile.ignore(9999, '\n');
  1775 + else
  1776 + {
  1777 + infile>>id;
  1778 + infile>>type;
  1779 + infile>>x;
  1780 + infile>>y;
  1781 + infile>>z;
  1782 + infile>>r;
  1783 + infile>>parent;
  1784 +
  1785 +
  1786 + //root nodes and branch nodes
  1787 + if(parent != id-1 && parent != -1)
  1788 + branchIDList.push_back(parent);
  1789 + if(x < min_pos.x) min_pos.x = x;
  1790 + if(y < min_pos.y) min_pos.y = y;
  1791 + if(z < min_pos.z) min_pos.z = z;
  1792 + if(x > max_pos.x) max_pos.x = x;
  1793 + if(y > max_pos.y) max_pos.y = y;
  1794 + if(z > max_pos.z) max_pos.z = z;
  1795 + }
  1796 + }//end while
  1797 + //sort the branch points
  1798 + sort(branchIDList.begin(), branchIDList.end());
  1799 + //set the number of corresponding nodes
  1800 + correspondingNodeList.resize(branchIDList.size());
  1801 +
  1802 + //second pass, build the tree
  1803 + infile.close();
  1804 + infile.clear();
  1805 + infile.open(filename.c_str());
  1806 + while(!infile.eof())
  1807 + {
  1808 + c = infile.peek();
  1809 + if((c <'0' || c > '9') && c != 32)
  1810 + infile.ignore(9999, '\n');
  1811 + else
  1812 + {
  1813 + infile>>id;
  1814 + infile>>type;
  1815 + infile>>x;
  1816 + infile>>y;
  1817 + infile>>z;
  1818 + infile>>r;
  1819 + infile>>parent;
  1820 +
  1821 +
  1822 + //if we are starting a new fiber
  1823 + if(parent == -1)
  1824 + StartFiber(x, y, z);
  1825 + else
  1826 + {
  1827 + //see if the parent is in the branch list
  1828 + iter = find(branchIDList.begin(), branchIDList.end(), parent);
  1829 + //if the parent point is a branch point
  1830 + if(iter != branchIDList.end())
  1831 + {
  1832 + index = iter - branchIDList.begin();
  1833 + StartBranch(correspondingNodeList[index]);
  1834 + ContinueFiber(x, y, z);
  1835 + }
  1836 + else
  1837 + ContinueFiber(x, y, z);
  1838 + }
  1839 + //if the current node is in the branch list
  1840 + iter = find(branchIDList.begin(), branchIDList.end(), id);
  1841 + if(iter != branchIDList.end())
  1842 + {
  1843 + //get the id and store the corresponding node value
  1844 + index = iter - branchIDList.begin();
  1845 + correspondingNodeList[index] = NodeList.size()-1;
  1846 + }
  1847 + }
  1848 + }//end while
  1849 + refreshFiberLengths();
  1850 + refreshIncidence();
  1851 +
  1852 + }
  1853 +
  1854 + void LoadOBJ(string filename)
  1855 + {
  1856 + //first load the OBJ file
  1857 + rtsOBJ objFile;
  1858 + objFile.LoadFile(filename.c_str());
  1859 +
  1860 + /*Create two lists. Each element represents a point in the OBJ file. We will
  1861 + first go through each fiber (line) and find the vertex associated with the two ends of the fiber.
  1862 + The validList value is "true" if the associated point in the OBJ file is a junction. It is "false"
  1863 + if the point is just an intermediate point on a fiber. The pointList value stores the new value of the junction
  1864 + in the NodeList of this FiberNetwork structure.*/
  1865 +
  1866 + vector<bool> validList;
  1867 + validList.assign(objFile.v_list.size(), false);
  1868 + vector<unsigned int> pointList;
  1869 + pointList.assign(objFile.v_list.size(), 0);
  1870 +
  1871 + /*Run through each fiber:
  1872 + 1) See if each fiber node has already been created by looking at validList (true = created)
  1873 + 2) If the node has not been created, create it and set validList to true and pointList to the node index in this structure.
  1874 + 3) Create an empty fiber with the appropriate node values assigned.*/
  1875 + unsigned int f;
  1876 + unsigned int line_verts;
  1877 + unsigned int v0, vn;
  1878 + Node node_new;
  1879 + for(f=0; f<objFile.getNumLines(); f++)
  1880 + {
  1881 + //find out how many vertices there are in the line
  1882 + line_verts = objFile.getNumLineVertices(f);
  1883 + v0 = objFile.getLineVertex(f, 0);
  1884 + vn = objFile.getLineVertex(f, line_verts - 1);
  1885 +
  1886 + //if the nodes don't exist, create them
  1887 + if(!validList[v0])
  1888 + {
  1889 + node_new.p = objFile.getVertex3d(v0);
  1890 + pointList[v0] = NodeList.size();
  1891 + NodeList.push_back(node_new);
  1892 + validList[v0] = true;
  1893 + }
  1894 + if(!validList[vn])
  1895 + {
  1896 + node_new.p = objFile.getVertex3d(vn);
  1897 + pointList[vn] = NodeList.size();
  1898 + NodeList.push_back(node_new);
  1899 + validList[vn] = true;
  1900 + }
  1901 + //create the new fiber
  1902 + Fiber fiber_new;
  1903 + fiber_new.n0 = pointList[v0];
  1904 + fiber_new.n1 = pointList[vn];
  1905 +
  1906 + //get all of the intermediate line vertices and insert them in the fiber
  1907 + for(unsigned int i=1; i<line_verts-1; i++)
  1908 + {
  1909 + fiber_new.pointList.push_back(objFile.getVertex3d(objFile.getLineVertex(f, i)));
  1910 + //fiber_new.pointList.push_back(objFile.get
  1911 + }
  1912 + FiberList.push_back(fiber_new);
  1913 + }
  1914 +
  1915 + RemoveExcessNodes();
  1916 +
  1917 + ComputeBoundingVolume();
  1918 + refreshFiberLengths();
  1919 + refreshIncidence();
  1920 +
  1921 + }
  1922 + void LoadFile(string filename)
  1923 + {
  1924 + rtsFilename file = filename;
  1925 + string extension = file.getExtension();
  1926 + if(extension.compare("obj") == 0)
  1927 + LoadOBJ(filename);
  1928 + else if(extension.compare("swc") == 0)
  1929 + LoadSWC(filename);
  1930 +
  1931 + }
  1932 +
  1933 +
  1934 + //saving functions
  1935 + void SaveOBJ(string filename)
  1936 + {
  1937 + ofstream outfile;
  1938 + outfile.open(filename.c_str());
  1939 +
  1940 + //output all vertices
  1941 +
  1942 + //first output all nodes
  1943 + for(unsigned int n=0; n<NodeList.size(); n++)
  1944 + outfile<<"v "<<NodeList[n].p.x<<" "<<NodeList[n].p.y<<" "<<NodeList[n].p.z<<endl;
  1945 + //then output all fiber points
  1946 + for(unsigned int f=0; f<FiberList.size(); f++)
  1947 + for(unsigned int p=0; p<FiberList[f].pointList.size(); p++)
  1948 + outfile<<"v "<<FiberList[f].pointList[p].x<<" "<<FiberList[f].pointList[p].y<<" "<<FiberList[f].pointList[p].z<<endl;
  1949 +
  1950 + //now output each of the fibers
  1951 + int i = NodeList.size() + 1;
  1952 + for(unsigned int f=0; f<FiberList.size(); f++)
  1953 + {
  1954 + outfile<<"l ";
  1955 + outfile<<FiberList[f].n0+1<<" ";
  1956 + for(unsigned int p=0; p<FiberList[f].pointList.size(); p++)
  1957 + {
  1958 + outfile<<i<<" ";
  1959 + i++;
  1960 + }
  1961 + outfile<<FiberList[f].n1+1;
  1962 + outfile<<endl;
  1963 + }
  1964 +
  1965 + outfile.close();
  1966 +
  1967 + }
  1968 +
  1969 + //transform functions
  1970 + void Translate(float x, float y, float z);
  1971 + void Translate(point3D<float> p){Translate(p.x, p.y, p.z);}
  1972 +
  1973 + void Oscillate(float frequency, float magnitude)
  1974 + {
  1975 + //impliment a sinusoidal oscillation along each fiber
  1976 + vector3D<float> side(0.0, 0.0, 1.0);
  1977 + vector3D<float> dir, normal;
  1978 + point3D<float> p0, p1;
  1979 + float t;
  1980 +
  1981 + //for each fiber
  1982 + for(unsigned int f=0; f<FiberList.size(); f++)
  1983 + {
  1984 + p0 = NodeList[FiberList[f].n0].p;
  1985 + t=0.0;
  1986 +
  1987 + num_points = FiberList[f].pointList.size();
  1988 + for(unsigned int p = 0; p<num_points; p++)
  1989 + {
  1990 + p1 = FiberList[f].pointList[p];
  1991 + dir = p0 - p1;
  1992 + t+= dir.Length();
  1993 + normal = dir.X(side);
  1994 + normal.Normalize();
  1995 + FiberList[f].pointList[p] = FiberList[f].pointList[p] + magnitude*sin(t*frequency)*normal;
  1996 +
  1997 + p0 = p1;
  1998 + }
  1999 +
  2000 +
  2001 + }
  2002 +
  2003 + }
  2004 +
  2005 + void Crop(float px, float py, float pz, float sx, float sy, float sz)
  2006 + {
  2007 + vector<Fiber> newFiberList;
  2008 + for(unsigned int f=0; f<FiberList.size(); f++)
  2009 + {
  2010 + int n0 = FiberList[f].n0;
  2011 + int n1 = FiberList[f].n1;
  2012 + point3D<float> p0 = NodeList[n0].p;
  2013 + point3D<float> p1 = NodeList[n1].p;
  2014 +
  2015 + if(p0.x > px && p0.y > py && p0.z > pz &&
  2016 + p1.x > px && p1.y > py && p1.z > pz &&
  2017 + p0.x < px+sx && p0.y < py+sy && p0.z < pz+sz &&
  2018 + p1.x < px+sx && p1.y < py+sy && p1.z < pz+sz)
  2019 + {
  2020 + newFiberList.push_back(FiberList[f]);
  2021 + }
  2022 + }
  2023 + FiberList.clear();
  2024 + FiberList = newFiberList;
  2025 + RemoveExcessNodes();
  2026 + ComputeBoundingVolume();
  2027 + }
  2028 + void ThresholdLength(float min_length, float max_length = 99999)
  2029 + {
  2030 + vector<Fiber> newFiberList;
  2031 + refreshFiberLengths();
  2032 + for(unsigned int f=0; f<FiberList.size(); f++)
  2033 + {
  2034 + if(FiberList[f].length > min_length && FiberList[f].length < max_length)
  2035 + {
  2036 + newFiberList.push_back(FiberList[f]);
  2037 + }
  2038 + }
  2039 + FiberList.clear();
  2040 + FiberList = newFiberList;
  2041 + RemoveExcessNodes();
  2042 + ComputeBoundingVolume();
  2043 + }
  2044 + void ThresholdSpines(float min_length)
  2045 + {
  2046 + vector<Fiber> newFiberList;
  2047 + refreshIncidence();
  2048 + refreshFiberLengths();
  2049 + for(unsigned int f=0; f<FiberList.size(); f++)
  2050 + {
  2051 + if(FiberList[f].length > min_length || (NodeList[FiberList[f].n0].incident > 1 && NodeList[FiberList[f].n1].incident > 1))
  2052 + {
  2053 + newFiberList.push_back(FiberList[f]);
  2054 + }
  2055 + }
  2056 + FiberList.clear();
  2057 + FiberList = newFiberList;
  2058 + RemoveExcessNodes();
  2059 + ComputeBoundingVolume();
  2060 +
  2061 + }
  2062 + //subdivision
  2063 + void SubdivideNetwork(float spacing)
  2064 + {
  2065 + list<point3D<float> > subdivided;
  2066 + list<point3D<float> >::iterator p;
  2067 + for(unsigned int f=0; f<FiberList.size(); f++)
  2068 + {
  2069 + //get the subdivided fiber
  2070 + subdivided.clear();
  2071 + subdivided = SubdivideFiber(f, spacing);
  2072 +
  2073 + //clean up the current fiber
  2074 + FiberList[f].pointList.clear();
  2075 + //copy the subdivided fiber into the current fiber point list
  2076 + for(p = subdivided.begin(); p!=subdivided.end(); p++)
  2077 + FiberList[f].pointList.push_back(*p);
  2078 +
  2079 + }
  2080 +
  2081 +
  2082 + }
  2083 +
  2084 + void Resample(float spacing)
  2085 + {
  2086 + point3D<float> p0, p1;
  2087 + vector<point3D<float> > newPointList;
  2088 + for(unsigned int f=0; f<FiberList.size(); f++)
  2089 + {
  2090 + newPointList.clear();
  2091 + p0 = NodeList[FiberList[f].n0].p;
  2092 + for(unsigned int p=0; p<FiberList[f].pointList.size(); p++)
  2093 + {
  2094 + p1 = FiberList[f].pointList[p];
  2095 + if( (p1 - p0).Length() >= spacing )
  2096 + {
  2097 + newPointList.push_back(p1);
  2098 + }
  2099 + }
  2100 + FiberList[f].pointList = newPointList;
  2101 + }
  2102 + }
  2103 + //network comparison
  2104 + CoreGraphList CompareNetworks(rtsFiberNetwork* testNetwork, float sigmaG, float sigmaC, float &gFPR, float &gFNR, float &cFPR, float &cFNR)
  2105 + {
  2106 + //create point clouds that densely sample each network
  2107 + vector<geometryPoint> netPointList0, netPointList1;
  2108 + netPointList0 = getNetPointSamples(sigmaG);
  2109 + netPointList1 = testNetwork->getNetPointSamples(sigmaG);
  2110 +
  2111 + //compute the L1 distance between vertices in one network to the point cloud representing the other network
  2112 + KD_ComputeEnvelopeDistance(testNetwork, &netPointList0, sigmaG);
  2113 + KD_ComputeEnvelopeDistance(this, &netPointList1, sigmaG);
  2114 +
  2115 + //compute the geometry metric using the distance values for each vertex
  2116 + //float FPR, FNR;
  2117 + gFNR = GeometryMetric(this, sigmaG);
  2118 + gFPR = GeometryMetric(testNetwork, sigmaG);
  2119 +
  2120 + CoreGraphList core;
  2121 + core = NEW_ComputeTopology(testNetwork, sigmaC);
  2122 +
  2123 + //Changes made by James Burck (Thanks James!)--------
  2124 + float TP = (float)core.size();
  2125 +
  2126 + float TPandFP = (float)FiberList.size(); // formerly P, actaully TPandFN
  2127 + float TPandFN = (float)testNetwork->FiberList.size(); // actually TPandFP
  2128 +
  2129 + cFNR = (TPandFN - TP) / TPandFN;
  2130 + cFPR = (TPandFP - TP) / TPandFP;
  2131 + //---------------------------------------------------
  2132 +
  2133 + return core;
  2134 + }
  2135 +
  2136 +
  2137 +};
  2138 +
  2139 +void rtsFiberNetwork::initTopologyGraph(vector<topologyNode>* Nodes, vector<topologyEdge>* Edges, rtsFiberNetwork* network)
  2140 +{
  2141 + /*This function constructs a graph based on the given network.*/
  2142 + Nodes->clear();
  2143 + Edges->clear();
  2144 +
  2145 + topologyNode node;
  2146 + topologyEdge edge;
  2147 + //for each node in the fiber network, construct a topologyNode
  2148 + for(unsigned int n=0; n<network->NodeList.size(); n++)
  2149 + {
  2150 + node.compatible = 0;
  2151 + node.label = RTS_TOPOLOGY_NODE_INVALID;
  2152 + node.p = network->NodeList[n].p;
  2153 + Nodes->push_back(node);
  2154 + }
  2155 +
  2156 + //now fill in all the edges
  2157 + for(unsigned int f=0; f<network->FiberList.size(); f++)
  2158 + {
  2159 + edge.n0 = network->FiberList[f].n0;
  2160 + edge.error = network->FiberList[f].error;
  2161 + edge.n1 = network->FiberList[f].n1;
  2162 + edge.label = RTS_TOPOLOGY_EDGE_EXIST;
  2163 +
  2164 + //attach the edge to each connected node in the node list
  2165 + (*Nodes)[edge.n0].connections.push_back(Edges->size());
  2166 + (*Nodes)[edge.n1].connections.push_back(Edges->size());
  2167 +
  2168 + //insert the edge into the list
  2169 + Edges->push_back(edge);
  2170 + }
  2171 +
  2172 +}
  2173 +
  2174 +void rtsFiberNetwork::BF_ComputeL1Distance(vector<geometryPoint>* N0, vector<geometryPoint>*N1)
  2175 +{
  2176 + unsigned int i, j;
  2177 + vector3D<float> v;
  2178 + float dist;
  2179 + for(i=0; i<N0->size(); i++)
  2180 + {
  2181 + for(j=0; j<N1->size(); j++)
  2182 + {
  2183 + v = (*N0)[i].p - (*N1)[j].p;
  2184 + dist = v.Length();
  2185 + if(dist < (*N0)[i].dist)
  2186 + (*N0)[i].dist = dist;
  2187 + if(dist < (*N1)[j].dist)
  2188 + (*N1)[j].dist = dist;
  2189 + }
  2190 + }
  2191 +}
  2192 +
  2193 +void rtsFiberNetwork::BD_ComputeL1Distance(vector<geometryPoint>* N0, vector<geometryPoint>*N1)
  2194 +{
  2195 + //build the point arrays
  2196 + ANNpointArray dataPts0 = annAllocPts(N0->size(), 3);
  2197 + for(unsigned int i=0; i<N0->size(); i++)
  2198 + {
  2199 + dataPts0[i][0] = (*N0)[i].p.x;
  2200 + dataPts0[i][1] = (*N0)[i].p.y;
  2201 + dataPts0[i][2] = (*N0)[i].p.z;
  2202 + }
  2203 + ANNpointArray dataPts1 = annAllocPts(N1->size(), 3);
  2204 + for(unsigned int i=0; i<N1->size(); i++)
  2205 + {
  2206 + dataPts1[i][0] = (*N1)[i].p.x;
  2207 + dataPts1[i][1] = (*N1)[i].p.y;
  2208 + dataPts1[i][2] = (*N1)[i].p.z;
  2209 + }
  2210 +
  2211 + //create ANN variables
  2212 + ANNbd_tree* bdTree;
  2213 + ANNpoint queryPt = annAllocPt(3);
  2214 + ANNidxArray nearestIdx = new ANNidx[1];
  2215 + ANNdistArray nearestDist = new ANNdist[1];
  2216 +
  2217 + //compare network 0 to network 1
  2218 + //bdTree = new ANNkd_tree(dataPts0, N0->size(), 3);
  2219 + bdTree = new ANNbd_tree(dataPts0, N0->size(), 3);
  2220 + for(unsigned int i=0; i<N1->size(); i++)
  2221 + {
  2222 + queryPt[0] = (*N1)[i].p.x;
  2223 + queryPt[1] = (*N1)[i].p.y;
  2224 + queryPt[2] = (*N1)[i].p.z;
  2225 + bdTree->annkSearch(queryPt, 1, nearestIdx, nearestDist);
  2226 + (*N1)[i].dist = sqrtf((float)nearestDist[0]);
  2227 + }
  2228 + delete bdTree;
  2229 +
  2230 + //compare network 1 to network 0
  2231 + bdTree = new ANNbd_tree(dataPts1, N1->size(), 3);
  2232 + for(unsigned int i=0; i<N1->size(); i++)
  2233 + {
  2234 + queryPt[0] = (*N0)[i].p.x;
  2235 + queryPt[1] = (*N0)[i].p.y;
  2236 + queryPt[2] = (*N0)[i].p.z;
  2237 + bdTree->annkSearch(queryPt, 1, nearestIdx, nearestDist);
  2238 + (*N0)[i].dist = sqrtf((float)nearestDist[0]);
  2239 + }
  2240 + delete bdTree;
  2241 +
  2242 + annClose();
  2243 +}
  2244 +
  2245 +void rtsFiberNetwork::MapDeviationToNetwork(vector<geometryPoint>* source)
  2246 +{
  2247 +
  2248 +
  2249 +}
  2250 +
  2251 +void rtsFiberNetwork::topLabelNodes(vector<topologyNode>* N0, vector<topologyNode>* N1, float sigma)
  2252 +{
  2253 + unsigned int i0, i1;
  2254 + vector3D<float> v;
  2255 + float min_d;
  2256 + unsigned int min_i;
  2257 + for(i0=0; i0 < N0->size(); i0++)
  2258 + {
  2259 + v = (*N0)[i0].p - (*N1)[0].p;
  2260 + min_d = v.Length();
  2261 + min_i = 0;
  2262 + for(i1=0; i1 < N1->size(); i1++)
  2263 + {
  2264 + v = (*N0)[i0].p - (*N1)[i1].p;
  2265 + if(v.Length() < min_d)
  2266 + {
  2267 + min_d = v.Length();
  2268 + min_i = i1;
  2269 + }
  2270 + }
  2271 + //if the minimum distance from point i0 is less than sigma
  2272 + if(min_d < sigma)
  2273 + {
  2274 + (*N0)[i0].label = RTS_TOPOLOGY_NODE_VALID;
  2275 + (*N0)[i0].compatible = min_i;
  2276 + }
  2277 + }
  2278 +}
  2279 +
  2280 +bool rtsFiberNetwork::topDetectEdge(vector<topologyNode>* NodeList, vector<topologyEdge>* EdgeList, unsigned int node0, unsigned int node1)
  2281 +{
  2282 + //This function determines if there is an edge linking node0 and node1
  2283 + list<unsigned int>::iterator i;
  2284 + for(i = (*NodeList)[node0].connections.begin(); i!=(*NodeList)[node0].connections.end(); i++)
  2285 + {
  2286 + if( ((*EdgeList)[*i].n0 == node0 && (*EdgeList)[*i].n1 == node1) ||
  2287 + ((*EdgeList)[*i].n0 == node1 && (*EdgeList)[*i].n1 == node0) )
  2288 + return true;
  2289 + }
  2290 + return false;
  2291 +}
  2292 +bool rtsFiberNetwork::topDeleteEdge(vector<topologyNode>* NodeList, vector<topologyEdge>* EdgeList, unsigned int node0, unsigned int node1)
  2293 +{
  2294 + //this function deletes the first edge found linking node0 and node1
  2295 + list<unsigned int>::iterator i;
  2296 + unsigned int edge_id;
  2297 + for(i = (*NodeList)[node0].connections.begin(); i!=(*NodeList)[node0].connections.end(); i++)
  2298 + {
  2299 + if( (*EdgeList)[*i].n0 == node1 || (*EdgeList)[*i].n1 == node1 )
  2300 + {
  2301 + //delete the edge
  2302 +
  2303 + edge_id = *i;
  2304 + //remove the edge from node0 and node1
  2305 + (*NodeList)[node0].connections.remove(edge_id);
  2306 + (*NodeList)[node1].connections.remove(edge_id);
  2307 + //remove the edge
  2308 + (*EdgeList)[edge_id].label = RTS_TOPOLOGY_EDGE_NOEXIST;
  2309 + return true;
  2310 + }
  2311 + }
  2312 + return false;
  2313 +
  2314 +}
  2315 +bool rtsFiberNetwork::topMergeNode(vector<topologyNode>* NodeList, vector<topologyEdge>* EdgeList, unsigned int node)
  2316 +{
  2317 + /*this function merges a specific node with it's neighbor based on the following rules:
  2318 + 1) If the node is invalid, remove adjacent edge with the highest error
  2319 + 2) If the node is valid, merge with adjacent compatible node, removing the edge with the largest error
  2320 + */
  2321 +
  2322 + //if the node doesn't exist, just return.
  2323 + if( (*NodeList)[node].label == RTS_TOPOLOGY_NODE_NOEXIST) return false;
  2324 + //if this node isn't connected to anything, just remove the node
  2325 + if( (*NodeList)[node].connections.size() == 0)
  2326 + {
  2327 + (*NodeList)[node].label = RTS_TOPOLOGY_NODE_NOEXIST;
  2328 + return false;
  2329 + }
  2330 +
  2331 + //FIND THE DESTINATION NODE
  2332 + //create the destination node
  2333 + unsigned int edge_to_remove;
  2334 +
  2335 + //if the node is invalid, find the edge with the highest error
  2336 + if( (*NodeList)[node].label == RTS_TOPOLOGY_NODE_INVALID)
  2337 + {
  2338 + list<unsigned int>::iterator i;
  2339 + float highest_error = 0.0;
  2340 + for(i=(*NodeList)[node].connections.begin(); i!=(*NodeList)[node].connections.end(); i++)
  2341 + {
  2342 + //if the current edge has a higher error, record it
  2343 + if((*EdgeList)[(*i)].error >= highest_error)
  2344 + {
  2345 + highest_error = (*EdgeList)[(*i)].error;
  2346 + edge_to_remove = (*i);
  2347 + }
  2348 + }
  2349 + }
  2350 +
  2351 + //if the node is valid, find the compatible edge with the highest error
  2352 + if( (*NodeList)[node].label == RTS_TOPOLOGY_NODE_VALID)
  2353 + {
  2354 + list<unsigned int>::iterator i;
  2355 + float highest_error = 0.0;
  2356 + bool compatible_detected = false;
  2357 + unsigned int node0, node1;
  2358 + for(i=(*NodeList)[node].connections.begin(); i!=(*NodeList)[node].connections.end(); i++)
  2359 + {
  2360 + node0 = (*EdgeList)[(*i)].n0;
  2361 + node1 = (*EdgeList)[(*i)].n1;
  2362 + //find a compatible edge with the highest weight
  2363 + if((*NodeList)[node0].label == RTS_TOPOLOGY_NODE_VALID && (*NodeList)[node1].label == RTS_TOPOLOGY_NODE_VALID &&
  2364 + (*NodeList)[node0].compatible == (*NodeList)[node1].compatible && (*EdgeList)[(*i)].error >= highest_error)
  2365 + {
  2366 + highest_error = (*EdgeList)[(*i)].error;
  2367 + edge_to_remove = (*i);
  2368 + compatible_detected = true;
  2369 + }
  2370 + }
  2371 + //if a compatible node was not attached, just leave the node and return
  2372 + if(!compatible_detected) return false;
  2373 + }
  2374 +
  2375 + //PERFORM THE MERGE
  2376 +
  2377 + //find the node that we are merging to
  2378 + unsigned int merge_to;
  2379 + if((*EdgeList)[edge_to_remove].n0 == node)
  2380 + merge_to = (*EdgeList)[edge_to_remove].n1;
  2381 + else
  2382 + merge_to = (*EdgeList)[edge_to_remove].n0;
  2383 +
  2384 + list<unsigned int>::iterator i;
  2385 + //remove the edge from 'node'
  2386 + for(i = (*NodeList)[node].connections.begin(); i!=(*NodeList)[node].connections.end(); i++)
  2387 + if((*i) == edge_to_remove)
  2388 + {
  2389 + (*NodeList)[node].connections.erase(i);
  2390 + break;
  2391 + }
  2392 + //remove the edge from 'merge_to'
  2393 + for(i = (*NodeList)[merge_to].connections.begin(); i!=(*NodeList)[merge_to].connections.end(); i++)
  2394 + if((*i) == edge_to_remove)
  2395 + {
  2396 + (*NodeList)[merge_to].connections.erase(i);
  2397 + break;
  2398 + }
  2399 +
  2400 + //update all of the edges connected to 'node'
  2401 + for(i = (*NodeList)[node].connections.begin(); i!=(*NodeList)[node].connections.end(); i++)
  2402 + {
  2403 + if((*EdgeList)[(*i)].n0 == node)
  2404 + (*EdgeList)[(*i)].n0 = merge_to;
  2405 + else
  2406 + (*EdgeList)[(*i)].n1 = merge_to;
  2407 + }
  2408 + //add all edges in 'node' to the edges in 'merge_to'
  2409 + for(i = (*NodeList)[node].connections.begin(); i!=(*NodeList)[node].connections.end(); i++)
  2410 + {
  2411 + (*NodeList)[merge_to].connections.push_back( (*i) );
  2412 + }
  2413 + //sort the list and remove duplicates
  2414 + //duplicates occur if two merged points were connected by multiple edges
  2415 + (*NodeList)[merge_to].connections.sort();
  2416 + (*NodeList)[merge_to].connections.unique();
  2417 +
  2418 + //get rid of 'node'
  2419 + (*NodeList)[node].connections.clear();
  2420 + (*NodeList)[node].label = RTS_TOPOLOGY_NODE_NOEXIST;
  2421 +
  2422 + //remove the edge
  2423 + (*EdgeList)[edge_to_remove].label = RTS_TOPOLOGY_EDGE_NOEXIST;
  2424 + return true;
  2425 +}
  2426 +int rtsFiberNetwork::topCollapse(vector<topologyNode>* NodeList, vector<topologyEdge>*EdgeList)
  2427 +{
  2428 + unsigned int n;
  2429 + unsigned int topology_changes = 0;
  2430 + unsigned int num_connections;
  2431 + bool node_merged = false;
  2432 + for(n=0; n<NodeList->size(); n++)
  2433 + {
  2434 + //if this node is the end of a barb, mark it as a topology change
  2435 + num_connections = (*NodeList)[n].connections.size();
  2436 + node_merged = topMergeNode(NodeList, EdgeList, n);
  2437 + if(num_connections == 1 && node_merged == true)
  2438 + topology_changes++;
  2439 +
  2440 + }
  2441 +
  2442 + return topology_changes;
  2443 +}
  2444 +void rtsFiberNetwork::MY_ComputeTopology(rtsFiberNetwork* testNetwork, float sigma)
  2445 +{
  2446 + //initialize the topology graphs
  2447 + vector<topologyNode> GT_nodes;
  2448 + vector<topologyEdge> GT_edges;
  2449 + initTopologyGraph(&GT_nodes, &GT_edges, this);
  2450 + vector<topologyNode> T_nodes;
  2451 + vector<topologyEdge> T_edges;
  2452 + initTopologyGraph(&T_nodes, &T_edges, testNetwork);
  2453 +
  2454 + //label the nodes in each list as VALID or INVALID
  2455 + //this function also determines node compatibility in the Test array
  2456 + topLabelNodes(&GT_nodes, &T_nodes, sigma);
  2457 + topLabelNodes(&T_nodes, &GT_nodes, sigma);
  2458 +
  2459 + //copy the error to the fiber networks
  2460 + for(unsigned int i=0; i<T_nodes.size(); i++)
  2461 + {
  2462 + if(T_nodes[i].label == RTS_TOPOLOGY_NODE_VALID)
  2463 + testNetwork->NodeList[i].error = 0.0;
  2464 + else
  2465 + testNetwork->NodeList[i].error = 1.0;
  2466 + }
  2467 + for(unsigned int i=0; i<GT_nodes.size(); i++)
  2468 + {
  2469 + if(GT_nodes[i].label == RTS_TOPOLOGY_NODE_VALID)
  2470 + this->NodeList[i].error = 0.0;
  2471 + else
  2472 + this->NodeList[i].error = 1.0;
  2473 + }
  2474 +
  2475 + unsigned int FP_edges = topCollapse(&T_nodes, &T_edges);
  2476 + unsigned int FN_edges = topCollapse(&GT_nodes, &GT_edges);
  2477 +
  2478 + //mark all the nodes in T as invalid again
  2479 + //this will be used to compute topological errors
  2480 + unsigned int n;
  2481 + for(n=0; n<T_nodes.size(); n++)
  2482 + {
  2483 + T_nodes[n].label = RTS_TOPOLOGY_NODE_INVALID;
  2484 + }
  2485 +
  2486 + //for each edge in T
  2487 + unsigned int e;
  2488 + for(e=0; e<T_edges.size(); e++)
  2489 + {
  2490 + //if the edge exists in T
  2491 + if(T_edges[e].label == RTS_TOPOLOGY_EDGE_EXIST)
  2492 + {
  2493 + //if the the edge exists in GT
  2494 + if(topDetectEdge(&GT_nodes, &GT_edges, T_nodes[T_edges[e].n0].compatible, T_nodes[T_edges[e].n1].compatible))
  2495 + {
  2496 + //set both nodes to valid, in order to detect topological errors
  2497 + T_nodes[T_edges[e].n0].label = RTS_TOPOLOGY_NODE_VALID;
  2498 + T_nodes[T_edges[e].n1].label = RTS_TOPOLOGY_NODE_VALID;
  2499 + //delete the edge in GT
  2500 + topDeleteEdge(&GT_nodes, &GT_edges, T_nodes[T_edges[e].n0].compatible, T_nodes[T_edges[e].n1].compatible);
  2501 + }
  2502 + else
  2503 + FP_edges++;
  2504 + }
  2505 + }
  2506 +
  2507 + //run through all edges in GT
  2508 + //for each edge that still exists, increment the FN_edges counter
  2509 + for(e=0; e<GT_edges.size(); e++)
  2510 + {
  2511 + if(GT_edges[e].label == RTS_TOPOLOGY_EDGE_EXIST)
  2512 + FN_edges++;
  2513 + }
  2514 +
  2515 + //find topological errors
  2516 + //these are nodes that are valid AND are duplicates
  2517 + list<unsigned int> validPoints;
  2518 + for(n=0; n<T_nodes.size(); n++)
  2519 + if(T_nodes[n].label == RTS_TOPOLOGY_NODE_VALID)
  2520 + validPoints.push_back(T_nodes[n].compatible);
  2521 + validPoints.sort();
  2522 + list<unsigned int>::iterator i;
  2523 + unsigned int last;
  2524 + unsigned int topErrors = 0;
  2525 + for(i = validPoints.begin(); i != validPoints.end(); i++)
  2526 + {
  2527 + if(i != validPoints.begin())
  2528 + if(*i == last)
  2529 + topErrors++;
  2530 + last = *i;
  2531 + }
  2532 +
  2533 +
  2534 +
  2535 + cout<<"False Positive Edges: "<<FP_edges<<endl;
  2536 + cout<<"False Negative Edges: "<<FN_edges<<endl;
  2537 + cout<<"Topological Errors: "<<topErrors<<endl;
  2538 +
  2539 +
  2540 +}
  2541 +TopologyGraph rtsFiberNetwork::BOOST_RemapGraph(TopologyGraph& G, rtsFiberNetwork* network)
  2542 +{
  2543 + //create the graph
  2544 + TopologyGraph result(network->NodeList.size());
  2545 +
  2546 + //add all edges in G to result (based on compatibility (original index), NOT current index)
  2547 + graph_traits<TopologyGraph>::edge_iterator ei, ei_end;
  2548 + graph_traits<TopologyGraph>::vertex_descriptor v0, v1;
  2549 + int idx0, idx1;
  2550 + for(boost::tuples::tie(ei, ei_end) = edges(G); ei != ei_end; ei++)
  2551 + {
  2552 + v0 = source(*ei, G);
  2553 + v1 = target(*ei, G);
  2554 + idx0 = get(vertex_color_t(), G, v0);
  2555 + idx1 = get(vertex_color_t(), G, v1);
  2556 + add_edge(idx0, idx1, result);
  2557 + }
  2558 + return result;
  2559 +
  2560 +}
  2561 +point3D<float> rtsFiberNetwork::getNodeCoord(int fiber, bool node)
  2562 +{
  2563 + //Return the node coordinate based on a fiber (edge)
  2564 + //node value is false = source, true = dest
  2565 +
  2566 + if(node)
  2567 + return getNodeCoord(FiberList[fiber].n1);
  2568 + else
  2569 + return getNodeCoord(FiberList[fiber].n0);
  2570 +
  2571 +}
  2572 +
  2573 +double rtsFiberNetwork::getTotalLength()
  2574 +{
  2575 + //go through each fiber and measure the length
  2576 + int num_fibers = FiberList.size();
  2577 + double length = 0.0;
  2578 + int f;
  2579 + for(f=0; f<num_fibers; f++)
  2580 + length += getFiberLength(f);
  2581 + return length;
  2582 +}
  2583 +point3D<float> rtsFiberNetwork::getFiberPoint(unsigned int fiber, unsigned int point)
  2584 +{
  2585 + if(point == 0)
  2586 + return NodeList[FiberList[fiber].n0].p;
  2587 + if(point == FiberList[fiber].pointList.size() + 1)
  2588 + return NodeList[FiberList[fiber].n1].p;
  2589 +
  2590 + return FiberList[fiber].pointList[point-1];
  2591 +
  2592 +}
  2593 +
  2594 +void rtsFiberNetwork::ComputeBoundingVolume()
  2595 +{
  2596 + //find the bounding volume for the nodes
  2597 + min_pos = NodeList[0].p;
  2598 + max_pos = NodeList[0].p;
  2599 + for(unsigned int n=0; n<NodeList.size(); n++)
  2600 + {
  2601 + if(NodeList[n].p.x < min_pos.x)
  2602 + min_pos.x = NodeList[n].p.x;
  2603 + if(NodeList[n].p.y < min_pos.y)
  2604 + min_pos.y = NodeList[n].p.y;
  2605 + if(NodeList[n].p.z < min_pos.z)
  2606 + min_pos.z = NodeList[n].p.z;
  2607 +
  2608 + if(NodeList[n].p.x > max_pos.x)
  2609 + max_pos.x = NodeList[n].p.x;
  2610 + if(NodeList[n].p.y > max_pos.y)
  2611 + max_pos.y = NodeList[n].p.y;
  2612 + if(NodeList[n].p.z > max_pos.z)
  2613 + max_pos.z = NodeList[n].p.z;
  2614 + }
  2615 +
  2616 + //combine with the bounding volume for the fibers
  2617 + for(unsigned int f=0; f<FiberList.size(); f++)
  2618 + {
  2619 + for(unsigned int p=0; p<FiberList[f].pointList.size(); p++)
  2620 + {
  2621 + if(FiberList[f].pointList[p].x < min_pos.x)
  2622 + min_pos.x = FiberList[f].pointList[p].x;
  2623 + if(FiberList[f].pointList[p].y < min_pos.y)
  2624 + min_pos.y = FiberList[f].pointList[p].y;
  2625 + if(FiberList[f].pointList[p].z < min_pos.z)
  2626 + min_pos.z = FiberList[f].pointList[p].z;
  2627 +
  2628 + if(FiberList[f].pointList[p].x > max_pos.x)
  2629 + max_pos.x = FiberList[f].pointList[p].x;
  2630 + if(FiberList[f].pointList[p].y > max_pos.y)
  2631 + max_pos.y = FiberList[f].pointList[p].y;
  2632 + if(FiberList[f].pointList[p].z > max_pos.z)
  2633 + max_pos.z = FiberList[f].pointList[p].z;
  2634 + }
  2635 + }
  2636 +
  2637 +}
  2638 +void rtsFiberNetwork::Translate(float x, float y, float z)
  2639 +{
  2640 + //translates the network while maintaining all connectivity
  2641 +
  2642 + //create a translation vector
  2643 + vector3D<float> translate(x, y, z);
  2644 +
  2645 + //translate all nodes
  2646 + int num_nodes = NodeList.size();
  2647 + int n;
  2648 + for(n=0; n<num_nodes; n++)
  2649 + NodeList[n].p = NodeList[n].p + translate;
  2650 +
  2651 + int num_fibers = FiberList.size();
  2652 + int num_points;
  2653 + int f, p;
  2654 + for(f=0; f<num_fibers; f++)
  2655 + {
  2656 + num_points = FiberList[f].pointList.size();
  2657 + for(p=0; p<num_points; p++)
  2658 + FiberList[f].pointList[p] = FiberList[f].pointList[p] + translate;
  2659 + }
  2660 +
  2661 + //translate the bounding box
  2662 + min_pos = min_pos + translate;
  2663 + max_pos = max_pos + translate;
  2664 +
  2665 +}
  2666 +
  2667 +#endif
... ...