1 | /* -*- mode: c++; c-basic-offset: 4; indent-tabs-mode: nil -*- */ |
---|
2 | /* ====================================================================== |
---|
3 | * AUTHOR: Wei Qiao <qiaow@purdue.edu> |
---|
4 | * Purdue Rendering and Perceptualization Lab (PURPL) |
---|
5 | * |
---|
6 | * Copyright (c) 2004-2012 HUBzero Foundation, LLC |
---|
7 | * |
---|
8 | * See the file "license.terms" for information on usage and |
---|
9 | * redistribution of this file, and for a DISCLAIMER OF ALL WARRANTIES. |
---|
10 | * ====================================================================== |
---|
11 | */ |
---|
12 | #include <assert.h> |
---|
13 | #include <stdio.h> |
---|
14 | #include <stdlib.h> |
---|
15 | #include <math.h> |
---|
16 | |
---|
17 | #include "TransferFunctionGLUTWindow.h" |
---|
18 | #include "ColorGradientGLUTWindow.h" |
---|
19 | #include "ColorPaletteWindow.h" |
---|
20 | #include "ControlPoint.h" |
---|
21 | #include "TransferFunctionMain.h" |
---|
22 | |
---|
23 | /****************Result Array******************/ |
---|
24 | int numOfOutput=NUM_OF_OUTPUT; |
---|
25 | float* output=(float*)malloc(sizeof(float)*numOfOutput); //result array |
---|
26 | /**********************************************/ |
---|
27 | |
---|
28 | //Histograms |
---|
29 | Histogram Hist[4]; |
---|
30 | |
---|
31 | int tf_winx, tf_winy; |
---|
32 | int tf_unitWidth; |
---|
33 | extern double distanceThreshold; |
---|
34 | ControlPoint *tf_gvSelectedPoint; |
---|
35 | bool tf_gvIsDragging=false; |
---|
36 | ControlPoint* tf_pointList=0; |
---|
37 | int tf_numOfPoints; |
---|
38 | |
---|
39 | float tfMaximum; |
---|
40 | int tf_pointEditState; |
---|
41 | |
---|
42 | namespace TransferFunctionWindow |
---|
43 | { |
---|
44 | int winx = 600; |
---|
45 | int winy = 150; |
---|
46 | |
---|
47 | int unitHeight; |
---|
48 | |
---|
49 | double gv_X, gv_Y; |
---|
50 | double gv_lastY; |
---|
51 | |
---|
52 | bool gvScaleDragging=false; |
---|
53 | |
---|
54 | double gv_DX, gv_DY; |
---|
55 | |
---|
56 | float lv_tf_height_scale = 2.0; |
---|
57 | float last_lv_tf_height_scale= 2.0; |
---|
58 | |
---|
59 | float lv_tf_width_scale = 1.0; |
---|
60 | float last_lv_tf_width_scale= 1.0; |
---|
61 | }; |
---|
62 | |
---|
63 | using namespace TransferFunctionWindow; |
---|
64 | |
---|
65 | TransferFunctionGLUTWindow::TransferFunctionGLUTWindow() |
---|
66 | { |
---|
67 | } |
---|
68 | |
---|
69 | TransferFunctionGLUTWindow::~TransferFunctionGLUTWindow() |
---|
70 | { |
---|
71 | } |
---|
72 | |
---|
73 | void TransferFunctionGLUTWindow::tfInit(int main_window_x, int main_window_y) |
---|
74 | { |
---|
75 | //initialize the global list of contorlPoint "tf_pointList" |
---|
76 | tf_winx=main_window_x; |
---|
77 | tf_winy=main_window_y*2/3; |
---|
78 | |
---|
79 | unitHeight = (int)(0.8*tf_winy); |
---|
80 | tf_unitWidth = (int)(0.95*tf_winx); |
---|
81 | |
---|
82 | //printf("tf_unitWidth=%d\n", tf_unitWidth); |
---|
83 | |
---|
84 | tf_pointList = new ControlPoint(15,15); |
---|
85 | tf_pointList->next = new ControlPoint(15+tf_unitWidth,15); |
---|
86 | |
---|
87 | int i=0; |
---|
88 | for (i=0;i<numOfOutput;i++) { |
---|
89 | //output[i]=0; |
---|
90 | color_table[i][3]=0; |
---|
91 | } |
---|
92 | tf_numOfPoints=2; |
---|
93 | tf_pointEditState=0; |
---|
94 | |
---|
95 | tf_gvSelectedPoint = new ControlPoint(0,0); |
---|
96 | |
---|
97 | fprintf(stderr, "Transferfunction Init...\n"); |
---|
98 | } |
---|
99 | |
---|
100 | void TransferFunctionGLUTWindow::tfDisplay() |
---|
101 | { |
---|
102 | glClearColor( 1.0f, 1.0f, 1.0f, 1.0f ); |
---|
103 | glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); |
---|
104 | |
---|
105 | glColor3d(0, 0, 0); |
---|
106 | |
---|
107 | //draw x and y axis |
---|
108 | glBegin(GL_LINES); |
---|
109 | glVertex2d(15, 15); |
---|
110 | glVertex2d(15, winy); |
---|
111 | |
---|
112 | glVertex2d(15, 15); |
---|
113 | glVertex2d(winx, 15); |
---|
114 | glEnd(); |
---|
115 | |
---|
116 | //printf("tf_unitWidth=%d\n", tf_unitWidth); |
---|
117 | |
---|
118 | //draw label for X |
---|
119 | glRasterPos2f(2, 2); |
---|
120 | glutBitmapCharacter(GLUT_BITMAP_HELVETICA_12, '0'); |
---|
121 | |
---|
122 | glRasterPos2f(18+tf_unitWidth, 2); |
---|
123 | glutBitmapCharacter(GLUT_BITMAP_HELVETICA_12, '1'); |
---|
124 | |
---|
125 | //draw marker on axis |
---|
126 | glLineWidth(2.0); |
---|
127 | glBegin(GL_LINES); |
---|
128 | glVertex2d(15+tf_unitWidth, 20); |
---|
129 | glVertex2d(15+tf_unitWidth, 15); |
---|
130 | |
---|
131 | int k; |
---|
132 | k = 1; |
---|
133 | while (15+k*unitHeight/lv_tf_height_scale < winy) { |
---|
134 | glVertex2d(20, 15+k*unitHeight/lv_tf_height_scale); |
---|
135 | glVertex2d(15, 15+k*unitHeight/lv_tf_height_scale); |
---|
136 | k++; |
---|
137 | } |
---|
138 | glEnd(); |
---|
139 | glLineWidth(1.0); |
---|
140 | |
---|
141 | //draw label for Y |
---|
142 | k = 1; |
---|
143 | |
---|
144 | #ifdef notdef |
---|
145 | char label[3]; |
---|
146 | while (15+k*unitHeight/lv_tf_height_scale < winy) { |
---|
147 | glRasterPos2f(2,15+k*unitHeight/lv_tf_height_scale); |
---|
148 | label[0]=0; |
---|
149 | label[1]=0; |
---|
150 | label[2]=0; |
---|
151 | itoa(k, label, 10); |
---|
152 | int i=0; |
---|
153 | while (label[i]!=0) { |
---|
154 | glutBitmapCharacter(GLUT_BITMAP_HELVETICA_10, label[i]); |
---|
155 | i++; |
---|
156 | } |
---|
157 | k++; |
---|
158 | } |
---|
159 | printf("tf_unitWidth=%d\n", tf_unitWidth); |
---|
160 | #endif |
---|
161 | |
---|
162 | //draw all points |
---|
163 | ControlPoint* cur=tf_pointList; |
---|
164 | while (cur!=0) { |
---|
165 | cur->glDraw(); |
---|
166 | cur=cur->next; |
---|
167 | } |
---|
168 | |
---|
169 | glEnable(GL_LINE_SMOOTH); |
---|
170 | glLineWidth(2.0); |
---|
171 | |
---|
172 | //connect all points |
---|
173 | cur=tf_pointList; |
---|
174 | glBegin(GL_LINES); |
---|
175 | glVertex2d(cur->x, cur->y); |
---|
176 | |
---|
177 | while (cur!=0) { |
---|
178 | if (cur->next!=0) { |
---|
179 | glVertex2d(cur->x, cur->y); |
---|
180 | glVertex2d(cur->x, cur->y); |
---|
181 | } else { |
---|
182 | glVertex2d(cur->x, cur->y); |
---|
183 | } |
---|
184 | cur=cur->next; |
---|
185 | } |
---|
186 | glVertex2d(winx, 15); |
---|
187 | glEnd(); |
---|
188 | |
---|
189 | glLineWidth(1.0); |
---|
190 | glDisable(GL_LINE_SMOOTH); |
---|
191 | plotHist(); |
---|
192 | |
---|
193 | glutSwapBuffers(); |
---|
194 | } |
---|
195 | |
---|
196 | bool TransferFunctionGLUTWindow::SelectPoint(double x, double y) |
---|
197 | { |
---|
198 | //printf("select point\n"); |
---|
199 | |
---|
200 | if (tf_numOfPoints==0) |
---|
201 | return false; |
---|
202 | |
---|
203 | //Reset selected/dragged flags |
---|
204 | ControlPoint* cur=tf_pointList; |
---|
205 | while (cur!=0) { |
---|
206 | cur->dragged=false; |
---|
207 | cur->selected=false; |
---|
208 | cur=cur->next; |
---|
209 | } |
---|
210 | |
---|
211 | tf_gvSelectedPoint = NULL; |
---|
212 | |
---|
213 | //Traverse the points and find the one that seems close |
---|
214 | cur=tf_pointList; |
---|
215 | while (cur!=0) { |
---|
216 | double distanceSq; |
---|
217 | distanceSq = (cur->x - x)*(cur->x - x) + (cur->y - y)*(cur->y - y); |
---|
218 | |
---|
219 | if (distanceSq < distanceThreshold) { |
---|
220 | cur->selected = true; |
---|
221 | tf_gvSelectedPoint = cur; |
---|
222 | return true; |
---|
223 | } |
---|
224 | cur=cur->next; |
---|
225 | } |
---|
226 | |
---|
227 | return false; |
---|
228 | } |
---|
229 | |
---|
230 | void TransferFunctionGLUTWindow::tfMouse(int button, int state, int x, int y) |
---|
231 | { |
---|
232 | //printf("tf mouse\n"); |
---|
233 | //printf("(%d,%d)\n", x, y); |
---|
234 | GLint viewportVector[4]; |
---|
235 | double scX, scY; |
---|
236 | |
---|
237 | glGetIntegerv(GL_VIEWPORT, viewportVector); |
---|
238 | |
---|
239 | gv_X = scX = x; |
---|
240 | gv_Y = scY = viewportVector[3] - (GLint) y - 1; |
---|
241 | |
---|
242 | gv_lastY = scY; |
---|
243 | |
---|
244 | //Selecting point, begin dragging |
---|
245 | bool gvIsSelected = SelectPoint(scX, scY); |
---|
246 | |
---|
247 | if (button == GLUT_LEFT_BUTTON && state == GLUT_DOWN) { |
---|
248 | if (gvIsSelected && tf_pointEditState==0) { |
---|
249 | assert(tf_gvSelectedPoint!=NULL); |
---|
250 | gv_DX = scX - tf_gvSelectedPoint->x; //Offset from current point to selected point, for dragging corrections |
---|
251 | gv_DY = scY - tf_gvSelectedPoint->y; |
---|
252 | |
---|
253 | tf_gvSelectedPoint->dragged = true; |
---|
254 | tf_gvIsDragging = true; |
---|
255 | } |
---|
256 | /*else if ((!gvIsSelected) && tf_pointEditState==1) { |
---|
257 | GLint viewportVector[4]; |
---|
258 | double scX, scY; |
---|
259 | |
---|
260 | glGetIntegerv(GL_VIEWPORT, viewportVector); |
---|
261 | |
---|
262 | gv_X = scX = x; |
---|
263 | gv_Y = scY = viewportVector[3] - (GLint) y - 1; |
---|
264 | tf_gvSelectedPoint=addPoint(scX - gv_DX,scY - gv_DY); |
---|
265 | tf_pointEditState=0; |
---|
266 | WriteControlPoints(); |
---|
267 | }*/ |
---|
268 | } else if (button == GLUT_LEFT_BUTTON && state == GLUT_UP) { |
---|
269 | // End dragging code. |
---|
270 | tf_gvIsDragging = false; |
---|
271 | if (tf_gvSelectedPoint) |
---|
272 | tf_gvSelectedPoint->dragged = false; |
---|
273 | } |
---|
274 | |
---|
275 | if (button == GLUT_RIGHT_BUTTON && state == GLUT_UP) { |
---|
276 | GLint viewportVector[4]; |
---|
277 | double scX, scY; |
---|
278 | |
---|
279 | glGetIntegerv(GL_VIEWPORT, viewportVector); |
---|
280 | |
---|
281 | gv_X = scX = x; |
---|
282 | gv_Y = scY = viewportVector[3] - (GLint) y - 1; |
---|
283 | tf_gvSelectedPoint=addPoint(scX - gv_DX,scY - gv_DY); |
---|
284 | tf_pointEditState=0; |
---|
285 | WriteControlPoints(); |
---|
286 | } |
---|
287 | |
---|
288 | if (button == GLUT_MIDDLE_BUTTON && state == GLUT_DOWN) |
---|
289 | gvScaleDragging = true; |
---|
290 | |
---|
291 | if (button == GLUT_MIDDLE_BUTTON && state == GLUT_UP) |
---|
292 | gvScaleDragging = false; |
---|
293 | |
---|
294 | glutPostRedisplay(); |
---|
295 | } |
---|
296 | |
---|
297 | void TransferFunctionGLUTWindow::tfMotion(int x, int y) |
---|
298 | { |
---|
299 | GLint viewportVector[4]; |
---|
300 | double scX, scY; |
---|
301 | |
---|
302 | glGetIntegerv(GL_VIEWPORT, viewportVector); |
---|
303 | |
---|
304 | gv_X = scX = x; |
---|
305 | gv_Y = scY = viewportVector[3] - (GLint) y - 1; |
---|
306 | |
---|
307 | if (tf_gvIsDragging == true && tf_gvSelectedPoint!=NULL) { |
---|
308 | //Dragging handling code. |
---|
309 | tf_gvSelectedPoint->dragged = true; |
---|
310 | |
---|
311 | ControlPoint* cur=tf_pointList; |
---|
312 | while (cur->next!=0) { |
---|
313 | cur=cur->next; |
---|
314 | } |
---|
315 | |
---|
316 | //update x, y values for selected point |
---|
317 | if (tf_gvSelectedPoint!=tf_pointList && tf_gvSelectedPoint!=cur) { |
---|
318 | //not the first one, not the last one |
---|
319 | tf_gvSelectedPoint->x = scX - gv_DX; |
---|
320 | if (tf_gvSelectedPoint->x<=15) { |
---|
321 | tf_gvSelectedPoint->x=16; |
---|
322 | } else if (tf_gvSelectedPoint->x>=15+tf_unitWidth) { |
---|
323 | tf_gvSelectedPoint->x=15+tf_unitWidth-1; |
---|
324 | } |
---|
325 | } |
---|
326 | tf_gvSelectedPoint->y = scY - gv_DY; |
---|
327 | |
---|
328 | //Boundary conditions, so we can't drag point away from the screen. |
---|
329 | if (scY - gv_DY > viewportVector[3]) |
---|
330 | tf_gvSelectedPoint->y = viewportVector[3] - 1; |
---|
331 | //points can't be dragged below x axis |
---|
332 | if (scY - gv_DY < 15) |
---|
333 | tf_gvSelectedPoint->y = 15; |
---|
334 | |
---|
335 | boundaryChecking(); |
---|
336 | } |
---|
337 | |
---|
338 | if (gvScaleDragging == true) { |
---|
339 | last_lv_tf_height_scale=lv_tf_height_scale; |
---|
340 | lv_tf_height_scale += (scY - gv_lastY)*0.007; |
---|
341 | gv_lastY = scY; |
---|
342 | scalePointsY((int)(scY - gv_lastY)); |
---|
343 | } |
---|
344 | |
---|
345 | WriteControlPoints(); |
---|
346 | |
---|
347 | glutPostRedisplay(); |
---|
348 | } |
---|
349 | |
---|
350 | void TransferFunctionGLUTWindow::tfIdle() |
---|
351 | { |
---|
352 | /* |
---|
353 | glutSetWindow(tfWinId); |
---|
354 | glutPostRedisplay(); |
---|
355 | |
---|
356 | glutSetWindow(cmWinId); |
---|
357 | glutPostRedisplay(); |
---|
358 | |
---|
359 | glutSetWindow(cpWinId); |
---|
360 | glutPostRedisplay(); |
---|
361 | */ |
---|
362 | } |
---|
363 | |
---|
364 | void TransferFunctionGLUTWindow::tfKeyboard(unsigned char key, int x, int y) |
---|
365 | { |
---|
366 | switch (key) { |
---|
367 | case 'q': |
---|
368 | exit(0); |
---|
369 | break; |
---|
370 | case 'a': |
---|
371 | tf_pointEditState=1; |
---|
372 | break; |
---|
373 | case 'd': |
---|
374 | tf_pointEditState=2; |
---|
375 | if (tf_gvSelectedPoint!=NULL) { |
---|
376 | removePoint(tf_gvSelectedPoint); |
---|
377 | tf_gvSelectedPoint=0; |
---|
378 | WriteControlPoints(); |
---|
379 | glutPostRedisplay(); |
---|
380 | } |
---|
381 | tf_pointEditState=0; |
---|
382 | break; |
---|
383 | case 'p': |
---|
384 | printPoints(); |
---|
385 | break; |
---|
386 | case 'w': |
---|
387 | printInterpolation(); |
---|
388 | break; |
---|
389 | case 'r': |
---|
390 | readHist(); |
---|
391 | break; |
---|
392 | case 'u': |
---|
393 | dumpHist(); |
---|
394 | break; |
---|
395 | case 'i': |
---|
396 | printHist(); |
---|
397 | break; |
---|
398 | |
---|
399 | default: |
---|
400 | break; |
---|
401 | } |
---|
402 | } |
---|
403 | |
---|
404 | void TransferFunctionGLUTWindow::tfReshape(int x, int y) |
---|
405 | { |
---|
406 | //do not accept 0 value!!! |
---|
407 | if (x==0 || y==0) |
---|
408 | return; |
---|
409 | |
---|
410 | last_lv_tf_height_scale=lv_tf_height_scale; |
---|
411 | lv_tf_height_scale=lv_tf_height_scale*y/winy; |
---|
412 | |
---|
413 | last_lv_tf_width_scale= lv_tf_width_scale; |
---|
414 | lv_tf_width_scale=lv_tf_width_scale*x/winx; |
---|
415 | scalePointsX(); |
---|
416 | |
---|
417 | float xy_aspect; |
---|
418 | |
---|
419 | //lastWinx= winx; |
---|
420 | //lastWiny= winy; |
---|
421 | |
---|
422 | winx = x; |
---|
423 | winy = y; |
---|
424 | |
---|
425 | unitHeight = (int)(0.8*y); |
---|
426 | tf_unitWidth = (int)(0.95*x); |
---|
427 | |
---|
428 | xy_aspect = (float)x / (float)y; |
---|
429 | glViewport( 0, 0, x, y ); |
---|
430 | |
---|
431 | glMatrixMode( GL_PROJECTION ); |
---|
432 | glLoadIdentity(); |
---|
433 | |
---|
434 | //Set up most convenient projection |
---|
435 | gluOrtho2D(0, x, 0, y); |
---|
436 | glutPostRedisplay(); |
---|
437 | } |
---|
438 | |
---|
439 | void TransferFunctionGLUTWindow::ReadControlPoints() |
---|
440 | { |
---|
441 | //read the live variables and update the points. |
---|
442 | } |
---|
443 | |
---|
444 | void update_tf_texture(); |
---|
445 | |
---|
446 | void TransferFunctionGLUTWindow::WriteControlPoints() |
---|
447 | { |
---|
448 | //special case: all points have the same y coordinates |
---|
449 | double rangeY=0; |
---|
450 | float unitY=0; |
---|
451 | float unitX=0; |
---|
452 | double maxY=tf_pointList->y; |
---|
453 | double maxX=tf_pointList->x; |
---|
454 | |
---|
455 | //special case: all points have the same y coordinates,generate an error |
---|
456 | ControlPoint* cur=tf_pointList; |
---|
457 | int allSameY=1; |
---|
458 | int y=(int)tf_pointList->y; |
---|
459 | while (cur!=0) { |
---|
460 | if (cur->y!=y) { |
---|
461 | allSameY=0; |
---|
462 | break; |
---|
463 | } |
---|
464 | cur=cur->next; |
---|
465 | } |
---|
466 | |
---|
467 | if (allSameY==1) { |
---|
468 | int i=0; |
---|
469 | for (i=0; i<numOfOutput; i++){ |
---|
470 | //output[i]=0; |
---|
471 | color_table[i][3]=0; |
---|
472 | } |
---|
473 | return; |
---|
474 | } |
---|
475 | |
---|
476 | //get max Y |
---|
477 | cur=tf_pointList; |
---|
478 | while (cur!=0) { |
---|
479 | if (cur->y>maxY) { |
---|
480 | maxY=cur->y; |
---|
481 | } |
---|
482 | if (cur->x>maxX) { |
---|
483 | maxX=cur->x; |
---|
484 | } |
---|
485 | cur=cur->next; |
---|
486 | } |
---|
487 | |
---|
488 | //get min Y |
---|
489 | cur=tf_pointList; |
---|
490 | double minY=maxY; |
---|
491 | while (cur!=0) { |
---|
492 | if (cur->y<minY) { |
---|
493 | minY=cur->y; |
---|
494 | } |
---|
495 | cur=cur->next; |
---|
496 | } |
---|
497 | |
---|
498 | //range of Y |
---|
499 | rangeY=maxY-minY; |
---|
500 | |
---|
501 | tfMaximum = ((float) rangeY) / (unitHeight/lv_tf_height_scale); |
---|
502 | |
---|
503 | //unit to map [0,1] to [0, rangeY] |
---|
504 | unitY=1/(float)rangeY; |
---|
505 | unitX=(float)(maxX-15)/(float)numOfOutput; |
---|
506 | |
---|
507 | cur=tf_pointList; |
---|
508 | ControlPoint* next=cur->next; |
---|
509 | double x1=cur->x; |
---|
510 | double y1=(cur->y)-minY; |
---|
511 | double x2=next->x; |
---|
512 | double y2=(next->y)-minY; |
---|
513 | float slope=((float)(y2-y1))/((float)(x2-x1)); |
---|
514 | float t; //t=(x-a)/(b-a) |
---|
515 | |
---|
516 | int i=0; |
---|
517 | for (i=0; i<numOfOutput; i++) { |
---|
518 | if (unitX*i+15>x2) { |
---|
519 | //go to next line segment |
---|
520 | cur=next; |
---|
521 | next=next->next; |
---|
522 | if (next==0) { |
---|
523 | return; |
---|
524 | } |
---|
525 | x1=cur->x; |
---|
526 | y1=cur->y-minY; |
---|
527 | x2=next->x; |
---|
528 | y2=next->y-minY; |
---|
529 | |
---|
530 | slope=((float)(y2-y1))/((float)(x2-x1)); |
---|
531 | } |
---|
532 | t=((float)(unitX*i+15-x1))/((float)(x2-x1)); |
---|
533 | //output[i] = (y1+t*(y2-y1))/rangeY; |
---|
534 | color_table[i][3]=control_point_scale*(y1+t*(y2-y1))/rangeY; |
---|
535 | } |
---|
536 | |
---|
537 | update_tf_texture(); |
---|
538 | glutSetWindow(transferFunctionWindow); |
---|
539 | } |
---|
540 | |
---|
541 | void TransferFunctionGLUTWindow::printInterpolation() |
---|
542 | { |
---|
543 | WriteControlPoints(); |
---|
544 | int i=0; |
---|
545 | for (i=0; i<numOfOutput; i++) { |
---|
546 | //printf("%f, ",output[i]); |
---|
547 | fprintf(stderr, "%f, ",color_table[i][3]); |
---|
548 | } |
---|
549 | fprintf(stderr, "\n"); |
---|
550 | } |
---|
551 | |
---|
552 | //sort all controlpoints by bubble sort |
---|
553 | void |
---|
554 | TransferFunctionGLUTWindow::sortPoints() |
---|
555 | { |
---|
556 | if (tf_numOfPoints==0) |
---|
557 | return; |
---|
558 | |
---|
559 | //bubble-sort list in ascending order by X |
---|
560 | ControlPoint* cur; |
---|
561 | ControlPoint* pre; |
---|
562 | ControlPoint* a; |
---|
563 | ControlPoint* b; |
---|
564 | cur=tf_pointList; |
---|
565 | |
---|
566 | int i; |
---|
567 | pre = NULL; /* Suppress compiler warning */ |
---|
568 | for (i=0; i<tf_numOfPoints-1; i++) { |
---|
569 | while (cur->next!=NULL) { |
---|
570 | if (cur->x > cur->next->x) { |
---|
571 | if (cur==tf_pointList) { |
---|
572 | //first node |
---|
573 | a=tf_pointList; |
---|
574 | b=tf_pointList->next; |
---|
575 | a->next=b->next; |
---|
576 | b->next=a; |
---|
577 | tf_pointList=b; |
---|
578 | cur=tf_pointList; |
---|
579 | } else { |
---|
580 | a=cur; |
---|
581 | b=cur->next; |
---|
582 | a->next=b->next; |
---|
583 | b->next=a; |
---|
584 | pre->next=b; |
---|
585 | cur=b; |
---|
586 | } |
---|
587 | } |
---|
588 | pre=cur; |
---|
589 | cur=cur->next; |
---|
590 | } |
---|
591 | cur=tf_pointList; |
---|
592 | } |
---|
593 | WriteControlPoints(); |
---|
594 | } |
---|
595 | |
---|
596 | ControlPoint* |
---|
597 | TransferFunctionGLUTWindow::addPoint(double x, double y) |
---|
598 | { |
---|
599 | //check if x is between first and last point |
---|
600 | //if not return without adding point |
---|
601 | ControlPoint* last=tf_pointList; |
---|
602 | while (last->next!=0){ |
---|
603 | last=last->next; |
---|
604 | } |
---|
605 | if (x<15 || x>last->x || y<15) { |
---|
606 | return tf_pointList; |
---|
607 | } |
---|
608 | |
---|
609 | ControlPoint* cur=tf_pointList; |
---|
610 | ControlPoint* pre=cur; |
---|
611 | |
---|
612 | //if x is the first or last. Don't add, but update. |
---|
613 | if (x==cur->x) { |
---|
614 | cur->y=y; |
---|
615 | return tf_pointList; |
---|
616 | } else if(x==last->x) { |
---|
617 | last->y=y; |
---|
618 | return last; |
---|
619 | } |
---|
620 | |
---|
621 | while (cur->next!=0) { |
---|
622 | if (x<=cur->x){ |
---|
623 | ControlPoint* newPoint=new ControlPoint(x,y); |
---|
624 | if (cur==tf_pointList) { |
---|
625 | newPoint->next=tf_pointList; |
---|
626 | tf_pointList=newPoint; |
---|
627 | } else { |
---|
628 | newPoint->next=pre->next; |
---|
629 | pre->next=newPoint; |
---|
630 | } |
---|
631 | tf_numOfPoints++; |
---|
632 | //map->addKey(x, new Color(0,0,0)); |
---|
633 | return newPoint; |
---|
634 | } |
---|
635 | pre=cur; |
---|
636 | cur=cur->next; |
---|
637 | } |
---|
638 | |
---|
639 | if (x<=cur->x) { |
---|
640 | ControlPoint* newPoint=new ControlPoint(x,y); |
---|
641 | newPoint->next=pre->next; |
---|
642 | pre->next=newPoint; |
---|
643 | tf_numOfPoints++; |
---|
644 | //map->addKey(x, new Color(0,0,0)); |
---|
645 | return newPoint; |
---|
646 | } else { |
---|
647 | cur->next=new ControlPoint(x,y); |
---|
648 | tf_numOfPoints++; |
---|
649 | //map->addKey(x, new Color(0,0,0)); |
---|
650 | return cur->next; |
---|
651 | } |
---|
652 | } |
---|
653 | |
---|
654 | void |
---|
655 | TransferFunctionGLUTWindow::removePoint(void* ptr) |
---|
656 | { |
---|
657 | if (tf_numOfPoints==0) |
---|
658 | return; |
---|
659 | |
---|
660 | ControlPoint* last=tf_pointList; |
---|
661 | while (last->next!=0) { |
---|
662 | last=last->next; |
---|
663 | } |
---|
664 | |
---|
665 | if (ptr==tf_pointList || ptr==last) { |
---|
666 | /* |
---|
667 | if (tf_numOfPoints=1) { |
---|
668 | delete(ptr); |
---|
669 | tf_pointList=0; |
---|
670 | } else { |
---|
671 | tf_pointList=tf_pointList->next; |
---|
672 | delete(ptr); |
---|
673 | } |
---|
674 | */ |
---|
675 | return; |
---|
676 | } else { |
---|
677 | //find the previous point |
---|
678 | ControlPoint* cur=tf_pointList; |
---|
679 | ControlPoint* pre=cur; |
---|
680 | while (cur->next!=0) { |
---|
681 | if (cur==ptr) { |
---|
682 | break; |
---|
683 | } |
---|
684 | pre=cur; |
---|
685 | cur=cur->next; |
---|
686 | } |
---|
687 | pre->next=cur->next; |
---|
688 | map->removeKey(cur->x); |
---|
689 | delete(cur); |
---|
690 | } |
---|
691 | tf_numOfPoints--; |
---|
692 | } |
---|
693 | |
---|
694 | //remove all points but the two initial points |
---|
695 | void TransferFunctionGLUTWindow::cleanUpPoints() |
---|
696 | { |
---|
697 | if (tf_numOfPoints<2) |
---|
698 | return; |
---|
699 | |
---|
700 | ControlPoint* cur=tf_pointList; |
---|
701 | |
---|
702 | if (tf_numOfPoints==2) { |
---|
703 | cur->x=15; |
---|
704 | cur->y=15; |
---|
705 | |
---|
706 | cur->next->x=15+tf_unitWidth; |
---|
707 | cur->next->y=15; |
---|
708 | return; |
---|
709 | } |
---|
710 | |
---|
711 | cur=tf_pointList->next; |
---|
712 | ControlPoint* pre=tf_pointList; |
---|
713 | |
---|
714 | while (cur->next!=0){ |
---|
715 | if(pre!=tf_pointList) |
---|
716 | delete(pre); |
---|
717 | pre=cur; |
---|
718 | cur=cur->next; |
---|
719 | } |
---|
720 | |
---|
721 | delete(pre); |
---|
722 | tf_pointList->next=cur; |
---|
723 | |
---|
724 | tf_pointList->x=15; |
---|
725 | tf_pointList->y=15; |
---|
726 | |
---|
727 | tf_pointList->next->x=15+tf_unitWidth; |
---|
728 | tf_pointList->next->y=15; |
---|
729 | |
---|
730 | tf_numOfPoints=2; |
---|
731 | TransferFunctionGLUTWindow::WriteControlPoints(); |
---|
732 | } |
---|
733 | |
---|
734 | //debugging: print out all points |
---|
735 | void |
---|
736 | TransferFunctionGLUTWindow::printPoints() |
---|
737 | { |
---|
738 | ControlPoint* cur=tf_pointList; |
---|
739 | fprintf(stderr, "********************\n"); |
---|
740 | fprintf(stderr, "Total points %d \n", tf_numOfPoints); |
---|
741 | |
---|
742 | if (tf_numOfPoints==0) |
---|
743 | return; |
---|
744 | |
---|
745 | while (cur->next!=0) { |
---|
746 | fprintf(stderr, "(%g,%g)\n", cur->x, cur->y); |
---|
747 | cur=cur->next; |
---|
748 | } |
---|
749 | fprintf(stderr, "(%g,%g)\n", cur->x, cur->y); |
---|
750 | fprintf(stderr, "********************\n"); |
---|
751 | } |
---|
752 | |
---|
753 | ControlPoint* |
---|
754 | TransferFunctionGLUTWindow::boundaryChecking() |
---|
755 | { |
---|
756 | assert(tf_gvSelectedPoint!=0); |
---|
757 | assert(tf_pointList!=0); |
---|
758 | //find left and right neighbor in the list |
---|
759 | //If point is dragged passing the neighbor, the points are reordered. |
---|
760 | |
---|
761 | ControlPoint* left=tf_pointList; |
---|
762 | ControlPoint* right=tf_pointList; |
---|
763 | |
---|
764 | while (right!=tf_gvSelectedPoint) { |
---|
765 | left=right; |
---|
766 | right=right->next; |
---|
767 | } |
---|
768 | |
---|
769 | //selected point is not the right-end point |
---|
770 | if (right->next!=0) { |
---|
771 | right=right->next; |
---|
772 | if (tf_gvSelectedPoint->x>right->x) { |
---|
773 | sortPoints(); |
---|
774 | } |
---|
775 | } |
---|
776 | |
---|
777 | //selected point is not the left-end point |
---|
778 | if (left!=tf_gvSelectedPoint) { |
---|
779 | if (tf_gvSelectedPoint->x<left->x){ |
---|
780 | sortPoints(); |
---|
781 | } |
---|
782 | } |
---|
783 | |
---|
784 | return tf_gvSelectedPoint; |
---|
785 | } |
---|
786 | |
---|
787 | void |
---|
788 | TransferFunctionGLUTWindow::scalePointsY(int offset) |
---|
789 | { |
---|
790 | if (tf_numOfPoints<2) |
---|
791 | return; |
---|
792 | |
---|
793 | ControlPoint* cur=tf_pointList; |
---|
794 | while (cur!=0) { |
---|
795 | cur->y=((cur->y)-offset-15)*((float)last_lv_tf_height_scale/(float)lv_tf_height_scale)+15; |
---|
796 | cur=cur->next; |
---|
797 | } |
---|
798 | WriteControlPoints(); |
---|
799 | } |
---|
800 | |
---|
801 | void |
---|
802 | TransferFunctionGLUTWindow::scalePointsX() |
---|
803 | { |
---|
804 | ControlPoint* cur=tf_pointList; |
---|
805 | while (cur!=0) { |
---|
806 | cur->x=(cur->x-15)*((float)lv_tf_width_scale/(float)last_lv_tf_width_scale)+15; |
---|
807 | cur=cur->next; |
---|
808 | } |
---|
809 | WriteControlPoints(); |
---|
810 | } |
---|
811 | |
---|
812 | void |
---|
813 | TransferFunctionGLUTWindow::dumpHist() |
---|
814 | { |
---|
815 | /* |
---|
816 | FILE* fp = fopen("HistFile", "wt"); |
---|
817 | |
---|
818 | if(!fp) |
---|
819 | return; //error |
---|
820 | |
---|
821 | int i=0; |
---|
822 | for (i=0; i<Hist.range; i++){ |
---|
823 | fprintf(fp, "%d\n", Hist.count[i]); |
---|
824 | } |
---|
825 | printf("Histogram dumped.\n"); |
---|
826 | fclose(fp); |
---|
827 | */ |
---|
828 | } |
---|
829 | |
---|
830 | void |
---|
831 | TransferFunctionGLUTWindow::readHist() |
---|
832 | { |
---|
833 | /* |
---|
834 | FILE* fp = fopen("HistFile", "rt"); |
---|
835 | |
---|
836 | if(!fp) |
---|
837 | return; //error |
---|
838 | |
---|
839 | char buf[100]; //buffer to store one line from file |
---|
840 | char* token; //pointer to token in the buffer |
---|
841 | char seps[]="\n"; |
---|
842 | |
---|
843 | unsigned long value; |
---|
844 | |
---|
845 | int counter=0; |
---|
846 | |
---|
847 | while(true){ |
---|
848 | //read file |
---|
849 | if (fgets(buf, 100, fp)==NULL) |
---|
850 | break; |
---|
851 | token=strtok(buf, seps); |
---|
852 | value=atof(token); |
---|
853 | Hist.count[counter]=value; |
---|
854 | counter++; |
---|
855 | } |
---|
856 | printf("Histgram loaded. Total number of values:%d\n", counter); |
---|
857 | tfDisplay(); |
---|
858 | fclose(fp); |
---|
859 | */ |
---|
860 | } |
---|
861 | |
---|
862 | //output histogram to console |
---|
863 | void TransferFunctionGLUTWindow::printHist() |
---|
864 | { |
---|
865 | int i=0; |
---|
866 | |
---|
867 | for(int j=0; j<4; j++){ |
---|
868 | for (i=0; i<Hist[j].range; i++){ |
---|
869 | fprintf(stderr, "%ld\t", Hist[j].count[i]); |
---|
870 | } |
---|
871 | fprintf(stderr, "\n\n"); |
---|
872 | } |
---|
873 | |
---|
874 | /* |
---|
875 | for (i=0; i<Hist_p.range; i++){ |
---|
876 | printf("%ld\t", Hist_p.count[i]); |
---|
877 | } |
---|
878 | printf("\n\n"); |
---|
879 | |
---|
880 | for (i=0; i<Hist_d.range; i++){ |
---|
881 | printf("%ld\t", Hist_d.count[i]); |
---|
882 | } |
---|
883 | printf("\n\n"); |
---|
884 | |
---|
885 | for (i=0; i<Hist_ss.range; i++){ |
---|
886 | printf("%ld\t", Hist_ss.count[i]); |
---|
887 | } |
---|
888 | printf("\n\n"); |
---|
889 | */ |
---|
890 | } |
---|
891 | |
---|
892 | void |
---|
893 | TransferFunctionGLUTWindow::plotHist() |
---|
894 | { |
---|
895 | for (int j=0; j<4; j++) { |
---|
896 | Histogram cur = Hist[j]; |
---|
897 | |
---|
898 | float unitX=(float)tf_unitWidth/(float)(cur.range-1); |
---|
899 | float unitY; |
---|
900 | unsigned long maxY; |
---|
901 | unsigned long minY; |
---|
902 | double rangeY; |
---|
903 | |
---|
904 | float result[256]; |
---|
905 | |
---|
906 | //get max Y |
---|
907 | maxY=0; |
---|
908 | int i=0; |
---|
909 | for (i=0; i<cur.range; i++) { |
---|
910 | if (cur.count[i]>maxY) |
---|
911 | maxY=cur.count[i]; |
---|
912 | } |
---|
913 | //printf("maxY=%d\n", maxY); |
---|
914 | |
---|
915 | //get min Y |
---|
916 | minY=maxY; |
---|
917 | for (i=0; i<cur.range; i++) { |
---|
918 | if (cur.count[i]<minY) |
---|
919 | minY=cur.count[i]; |
---|
920 | } |
---|
921 | //printf("minY=%d\n", minY); |
---|
922 | |
---|
923 | //rangeY=(double)log(maxY-minY); |
---|
924 | //rangeY=(double)(maxY-minY); |
---|
925 | rangeY=(float)log(float(maxY - minY)); |
---|
926 | unitY=(float)(winy-20)/(float)rangeY; |
---|
927 | |
---|
928 | //reduce all values with log then by minY |
---|
929 | for (i=0; i<cur.range; i++) { |
---|
930 | if (cur.count[i]==0) { |
---|
931 | result[i]=0; |
---|
932 | } else { |
---|
933 | //result[i]=log((double)(cur.count[i])); |
---|
934 | //result[i]=double(cur.count[i]); |
---|
935 | //result[i]=log((float)(cur.count[i]))-log((float)minY); |
---|
936 | result[i]=log((float)(cur.count[i])-(float)minY); |
---|
937 | } |
---|
938 | } |
---|
939 | |
---|
940 | //draw points |
---|
941 | glColor3d(0, 0, 1); |
---|
942 | glBegin(GL_LINES); |
---|
943 | for (i=0; i<cur.range-1; i++) { |
---|
944 | glVertex2f(15+i*unitX, 15+result[i]*unitY); |
---|
945 | glVertex2f(15+(i+1)*unitX, 15+result[i+1]*unitY); |
---|
946 | } |
---|
947 | glEnd(); |
---|
948 | glColor3d(0, 0, 0); |
---|
949 | } |
---|
950 | } |
---|