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_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 | \ No newline at end of file | 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 | \ No newline at end of file | 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 | \ No newline at end of file | 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 | \ No newline at end of file | 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 | \ No newline at end of file | 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 | \ No newline at end of file | 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 | \ No newline at end of file | 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 | \ No newline at end of file | 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 | \ No newline at end of file | 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 | \ No newline at end of file | 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 | \ No newline at end of file | 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 | \ No newline at end of file | 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 |