Commit ebb721c7e4788ddc420c63fc3292664ef83ac89e
0 parents
new repository for STIM lab
Showing
47 changed files
with
11234 additions
and
0 deletions
Show diff stats
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 | ... | ... |
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 | ... | ... |
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 | ... | ... |
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 | ... | ... |
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 | ... | ... |
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 | + | ... | ... |
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 | ... | ... |
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 | +} | ... | ... |
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 | ... | ... |
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 | + | ... | ... |
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 | +) | ... | ... |
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 | + | ... | ... |
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 | ... | ... |
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 | ... | ... |
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 | +} | ... | ... |
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 | +} | ... | ... |
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 | +} | ... | ... |
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 | +//------------------------------------------------------------------------------- | ... | ... |
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 | ... | ... |
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 | +} | ... | ... |
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 | +} | ... | ... |
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 | +} | ... | ... |
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 */ | ... | ... |
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 | ... | ... |
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 | ... | ... |
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 | ... | ... |
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 | ... | ... |
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 | ... | ... |
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 | ... | ... |
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 | ... | ... |
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 | ... | ... |
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 | ... | ... |
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 | ... | ... |
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 | ... | ... |
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 | ... | ... |
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> ¶m) | |
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 | ... | ... |
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 | ... | ... |
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 | ... | ... |
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 | ... | ... |
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 | ... | ... |
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 | ... | ... |
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 | ... | ... |
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 | +} | ... | ... |
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(>_nodes, >_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(>_nodes, &T_nodes, sigma); | |
2457 | + topLabelNodes(&T_nodes, >_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(>_nodes, >_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(>_nodes, >_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(>_nodes, >_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 | ... | ... |