[2798] | 1 | /* -*- mode: c++; c-basic-offset: 4; indent-tabs-mode: nil -*- */ |
---|
[2897] | 2 | /* ====================================================================== |
---|
[953] | 3 | * AUTHOR: Wei Qiao <qiaow@purdue.edu> |
---|
| 4 | * Purdue Rendering and Perceptualization Lab (PURPL) |
---|
| 5 | * |
---|
[3177] | 6 | * Copyright (c) 2004-2012 HUBzero Foundation, LLC |
---|
[953] | 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 | |
---|
[1117] | 79 | unitHeight = (int)(0.8*tf_winy); |
---|
| 80 | tf_unitWidth = (int)(0.95*tf_winx); |
---|
[953] | 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; |
---|
[2897] | 88 | for (i=0;i<numOfOutput;i++) { |
---|
[953] | 89 | //output[i]=0; |
---|
| 90 | color_table[i][3]=0; |
---|
[2897] | 91 | } |
---|
[953] | 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; |
---|
[2897] | 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 | } |
---|
[953] | 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; |
---|
[2897] | 153 | while (label[i]!=0) { |
---|
[953] | 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; |
---|
[2897] | 164 | while (cur!=0) { |
---|
[953] | 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 | |
---|
[2897] | 177 | while (cur!=0) { |
---|
| 178 | if (cur->next!=0) { |
---|
[953] | 179 | glVertex2d(cur->x, cur->y); |
---|
| 180 | glVertex2d(cur->x, cur->y); |
---|
[2897] | 181 | } else { |
---|
| 182 | glVertex2d(cur->x, cur->y); |
---|
[953] | 183 | } |
---|
| 184 | cur=cur->next; |
---|
| 185 | } |
---|
[2897] | 186 | glVertex2d(winx, 15); |
---|
[953] | 187 | glEnd(); |
---|
| 188 | |
---|
| 189 | glLineWidth(1.0); |
---|
| 190 | glDisable(GL_LINE_SMOOTH); |
---|
| 191 | plotHist(); |
---|
| 192 | |
---|
[2897] | 193 | glutSwapBuffers(); |
---|
[953] | 194 | } |
---|
| 195 | |
---|
| 196 | bool TransferFunctionGLUTWindow::SelectPoint(double x, double y) |
---|
| 197 | { |
---|
| 198 | //printf("select point\n"); |
---|
[2897] | 199 | |
---|
[953] | 200 | if (tf_numOfPoints==0) |
---|
| 201 | return false; |
---|
| 202 | |
---|
| 203 | //Reset selected/dragged flags |
---|
| 204 | ControlPoint* cur=tf_pointList; |
---|
[2897] | 205 | while (cur!=0) { |
---|
[953] | 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; |
---|
[2897] | 215 | while (cur!=0) { |
---|
[953] | 216 | double distanceSq; |
---|
| 217 | distanceSq = (cur->x - x)*(cur->x - x) + (cur->y - y)*(cur->y - y); |
---|
[2897] | 218 | |
---|
| 219 | if (distanceSq < distanceThreshold) { |
---|
[953] | 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); |
---|
[2897] | 238 | |
---|
[953] | 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 | |
---|
[2897] | 247 | if (button == GLUT_LEFT_BUTTON && state == GLUT_DOWN) { |
---|
| 248 | if (gvIsSelected && tf_pointEditState==0) { |
---|
[953] | 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; |
---|
[2897] | 252 | |
---|
[953] | 253 | tf_gvSelectedPoint->dragged = true; |
---|
| 254 | tf_gvIsDragging = true; |
---|
| 255 | } |
---|
[2897] | 256 | /*else if ((!gvIsSelected) && tf_pointEditState==1) { |
---|
[953] | 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(); |
---|
[2897] | 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 | } |
---|
[953] | 274 | |
---|
[2897] | 275 | if (button == GLUT_RIGHT_BUTTON && state == GLUT_UP) { |
---|
| 276 | GLint viewportVector[4]; |
---|
| 277 | double scX, scY; |
---|
[953] | 278 | |
---|
[2897] | 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 | } |
---|
[953] | 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 | |
---|
[2897] | 307 | if (tf_gvIsDragging == true && tf_gvSelectedPoint!=NULL) { |
---|
[953] | 308 | //Dragging handling code. |
---|
| 309 | tf_gvSelectedPoint->dragged = true; |
---|
| 310 | |
---|
| 311 | ControlPoint* cur=tf_pointList; |
---|
[2897] | 312 | while (cur->next!=0) { |
---|
[953] | 313 | cur=cur->next; |
---|
| 314 | } |
---|
| 315 | |
---|
| 316 | //update x, y values for selected point |
---|
[2897] | 317 | if (tf_gvSelectedPoint!=tf_pointList && tf_gvSelectedPoint!=cur) { |
---|
[953] | 318 | //not the first one, not the last one |
---|
| 319 | tf_gvSelectedPoint->x = scX - gv_DX; |
---|
[2897] | 320 | if (tf_gvSelectedPoint->x<=15) { |
---|
[953] | 321 | tf_gvSelectedPoint->x=16; |
---|
[2897] | 322 | } else if (tf_gvSelectedPoint->x>=15+tf_unitWidth) { |
---|
[953] | 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 | |
---|
[2897] | 335 | boundaryChecking(); |
---|
[953] | 336 | } |
---|
| 337 | |
---|
[2897] | 338 | if (gvScaleDragging == true) { |
---|
[953] | 339 | last_lv_tf_height_scale=lv_tf_height_scale; |
---|
| 340 | lv_tf_height_scale += (scY - gv_lastY)*0.007; |
---|
| 341 | gv_lastY = scY; |
---|
[1117] | 342 | scalePointsY((int)(scY - gv_lastY)); |
---|
[2897] | 343 | } |
---|
[953] | 344 | |
---|
| 345 | WriteControlPoints(); |
---|
| 346 | |
---|
[2897] | 347 | glutPostRedisplay(); |
---|
[953] | 348 | } |
---|
| 349 | |
---|
[2897] | 350 | void TransferFunctionGLUTWindow::tfIdle() |
---|
| 351 | { |
---|
[953] | 352 | /* |
---|
| 353 | glutSetWindow(tfWinId); |
---|
| 354 | glutPostRedisplay(); |
---|
| 355 | |
---|
| 356 | glutSetWindow(cmWinId); |
---|
| 357 | glutPostRedisplay(); |
---|
| 358 | |
---|
| 359 | glutSetWindow(cpWinId); |
---|
| 360 | glutPostRedisplay(); |
---|
| 361 | */ |
---|
| 362 | } |
---|
| 363 | |
---|
[2897] | 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; |
---|
[953] | 398 | |
---|
[2897] | 399 | default: |
---|
| 400 | break; |
---|
| 401 | } |
---|
[953] | 402 | } |
---|
| 403 | |
---|
[2897] | 404 | void TransferFunctionGLUTWindow::tfReshape(int x, int y) |
---|
| 405 | { |
---|
[953] | 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 | |
---|
[1117] | 425 | unitHeight = (int)(0.8*y); |
---|
| 426 | tf_unitWidth = (int)(0.95*x); |
---|
[953] | 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; |
---|
[1117] | 458 | int y=(int)tf_pointList->y; |
---|
[2897] | 459 | while (cur!=0) { |
---|
| 460 | if (cur->y!=y) { |
---|
[953] | 461 | allSameY=0; |
---|
| 462 | break; |
---|
| 463 | } |
---|
| 464 | cur=cur->next; |
---|
| 465 | } |
---|
| 466 | |
---|
[2897] | 467 | if (allSameY==1) { |
---|
[953] | 468 | int i=0; |
---|
[2897] | 469 | for (i=0; i<numOfOutput; i++){ |
---|
[953] | 470 | //output[i]=0; |
---|
| 471 | color_table[i][3]=0; |
---|
| 472 | } |
---|
| 473 | return; |
---|
| 474 | } |
---|
| 475 | |
---|
| 476 | //get max Y |
---|
| 477 | cur=tf_pointList; |
---|
[2897] | 478 | while (cur!=0) { |
---|
| 479 | if (cur->y>maxY) { |
---|
[953] | 480 | maxY=cur->y; |
---|
| 481 | } |
---|
[2897] | 482 | if (cur->x>maxX) { |
---|
[953] | 483 | maxX=cur->x; |
---|
| 484 | } |
---|
| 485 | cur=cur->next; |
---|
| 486 | } |
---|
| 487 | |
---|
| 488 | //get min Y |
---|
| 489 | cur=tf_pointList; |
---|
| 490 | double minY=maxY; |
---|
[2897] | 491 | while (cur!=0) { |
---|
| 492 | if (cur->y<minY) { |
---|
[953] | 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; |
---|
[2897] | 517 | for (i=0; i<numOfOutput; i++) { |
---|
| 518 | if (unitX*i+15>x2) { |
---|
[953] | 519 | //go to next line segment |
---|
| 520 | cur=next; |
---|
| 521 | next=next->next; |
---|
[2897] | 522 | if (next==0) { |
---|
[953] | 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); |
---|
[2897] | 539 | } |
---|
[953] | 540 | |
---|
[2897] | 541 | void TransferFunctionGLUTWindow::printInterpolation() |
---|
| 542 | { |
---|
[953] | 543 | WriteControlPoints(); |
---|
| 544 | int i=0; |
---|
[2897] | 545 | for (i=0; i<numOfOutput; i++) { |
---|
[953] | 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 */ |
---|
[2897] | 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) { |
---|
[953] | 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 | } |
---|
[2897] | 605 | if (x<15 || x>last->x || y<15) { |
---|
[953] | 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. |
---|
[2897] | 613 | if (x==cur->x) { |
---|
[953] | 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; |
---|
[2897] | 661 | while (last->next!=0) { |
---|
[953] | 662 | last=last->next; |
---|
| 663 | } |
---|
| 664 | |
---|
[2897] | 665 | if (ptr==tf_pointList || ptr==last) { |
---|
[953] | 666 | /* |
---|
[2897] | 667 | if (tf_numOfPoints=1) { |
---|
| 668 | delete(ptr); |
---|
| 669 | tf_pointList=0; |
---|
| 670 | } else { |
---|
| 671 | tf_pointList=tf_pointList->next; |
---|
| 672 | delete(ptr); |
---|
[953] | 673 | } |
---|
| 674 | */ |
---|
| 675 | return; |
---|
| 676 | } else { |
---|
| 677 | //find the previous point |
---|
| 678 | ControlPoint* cur=tf_pointList; |
---|
| 679 | ControlPoint* pre=cur; |
---|
[2897] | 680 | while (cur->next!=0) { |
---|
[953] | 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 |
---|
[2897] | 695 | void TransferFunctionGLUTWindow::cleanUpPoints() |
---|
| 696 | { |
---|
[953] | 697 | if (tf_numOfPoints<2) |
---|
| 698 | return; |
---|
| 699 | |
---|
| 700 | ControlPoint* cur=tf_pointList; |
---|
| 701 | |
---|
[2897] | 702 | if (tf_numOfPoints==2) { |
---|
[953] | 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; |
---|
[2897] | 726 | |
---|
[953] | 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 | |
---|
[2897] | 745 | while (cur->next!=0) { |
---|
[953] | 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 | |
---|
[2897] | 764 | while (right!=tf_gvSelectedPoint) { |
---|
[953] | 765 | left=right; |
---|
| 766 | right=right->next; |
---|
| 767 | } |
---|
| 768 | |
---|
| 769 | //selected point is not the right-end point |
---|
[2897] | 770 | if (right->next!=0) { |
---|
[953] | 771 | right=right->next; |
---|
[2897] | 772 | if (tf_gvSelectedPoint->x>right->x) { |
---|
[953] | 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; |
---|
[2897] | 794 | while (cur!=0) { |
---|
[953] | 795 | cur->y=((cur->y)-offset-15)*((float)last_lv_tf_height_scale/(float)lv_tf_height_scale)+15; |
---|
| 796 | cur=cur->next; |
---|
[2897] | 797 | } |
---|
[953] | 798 | WriteControlPoints(); |
---|
| 799 | } |
---|
| 800 | |
---|
| 801 | void |
---|
| 802 | TransferFunctionGLUTWindow::scalePointsX() |
---|
| 803 | { |
---|
| 804 | ControlPoint* cur=tf_pointList; |
---|
[2897] | 805 | while (cur!=0) { |
---|
[953] | 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 | { |
---|
[2897] | 895 | for (int j=0; j<4; j++) { |
---|
[953] | 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; |
---|
[2897] | 903 | |
---|
[953] | 904 | float result[256]; |
---|
[2897] | 905 | |
---|
[953] | 906 | //get max Y |
---|
| 907 | maxY=0; |
---|
| 908 | int i=0; |
---|
[2897] | 909 | for (i=0; i<cur.range; i++) { |
---|
[953] | 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; |
---|
[2897] | 917 | for (i=0; i<cur.range; i++) { |
---|
[953] | 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 |
---|
[2897] | 929 | for (i=0; i<cur.range; i++) { |
---|
| 930 | if (cur.count[i]==0) { |
---|
[953] | 931 | result[i]=0; |
---|
[2897] | 932 | } else { |
---|
[953] | 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); |
---|
[2897] | 936 | result[i]=log((float)(cur.count[i])-(float)minY); |
---|
| 937 | } |
---|
[953] | 938 | } |
---|
| 939 | |
---|
| 940 | //draw points |
---|
| 941 | glColor3d(0, 0, 1); |
---|
| 942 | glBegin(GL_LINES); |
---|
[2897] | 943 | for (i=0; i<cur.range-1; i++) { |
---|
[953] | 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 | } |
---|