1 #include
2 #include "global.h" 3 #include "graphicsData.h" 4 #include "trees.h" 5 6 #define SQR(x) (x)*(x) 7 #define PI (4.0 * atan(1.0)) 8 9 /*** referenced from file processAttrib.c ***/ 10 extern void pickAttribColor (float, float, float, eco_color, eco_color*); 11 12 /*** referenced from file formCallbacks.c ***/ 13 extern string brchFile1, lvsFile1, rtsFile1, brchFile2, lvsFile2, rtsFile2; 14 15 void defineRootSegments (int,eco_color); 16 void pickRootCylinder (string,float,float,float,int); 17 void GenerateMesh (int,int,float,float,eco_color); 18 void GenerateTrans (float,float,float,float,float,float,float); 19 void multMatrices (matrix,matrix,matrix); 20 21 InitializeTrees () 22 { 23 eco_color temp; 24 temp.red = BRANCHCOLOR_RED; 25 temp.green = BRANCHCOLOR_GREEN; 26 temp.blue = BRANCHCOLOR_BLUE; 27 printf ("(backcolor c0 0.53 0.84 0.98)\n"); 28 printf ("(ap-override off)\n"); 29 printf ("(hdefine geometry branch { "); 30 GenerateMesh (BRANCH_X_DIM, BRANCH_Y_DIM, 1.0, 1.0, temp); 31 printf ("})\n"); 32 printf ("(if (real-id tree1) (delete tree1))\n"); 33 printf ("(if (real-id tree2) (delete tree2))\n"); 34 fflush (stdout); 35 } 36 37 /******************************************************************** 38 * GenerateTree: 39 * Defines the tree by writing the appropriate Geomview GCL 40 * commands to the standard output 41 ********************************************************************/ 42 43 GenerateTree (int treeID, treeData t) 44 { 45 int i; 46 /* 47 * if the tree has previously been defined, delete it 48 */ 49 printf ("(if (real-id tree%d) (delete tree%d))\n", treeID,treeID); 50 51 /* 52 * define the three tree parts 53 */ 54 if (t.leavesChanged) 55 GenerateLeaves (treeID,t.leafType,t.minLfValue,t.maxLfValue, 56 t.minLfValueOrig,t.maxLfValueOrig,t.leafColor,t.L); 57 if (t.rootsChanged) 58 GenerateRoots (treeID,t.displayRoots,t.rootType, 59 t.minRtValue,t.maxRtValue,t.minRtValueOrig, 60 t.maxRtValueOrig,t.rootColor,t.R); 61 if (t.branchChanged) 62 GenerateBranches (treeID,t.displayBranches,t.B); 63 64 /* 65 * define the tree 66 */ 67 printf ("(geometry tree%d ", treeID); 68 printf (" appearance lighting { ambient .3 .3 .3 replacelights "); 69 if (t.displaySun) { 70 for (i = 0; i < 2; i++) 71 printf ("light { color 1 1 1 position %f %f %f 0 location local } ", 72 t.sunVec_x,t.sunVec_y,t.sunVec_z); 73 } else { 74 printf ("light { color 0.6 0.6 0.6 position 1 1 0 0 location local } "); 75 printf ("light { color 0.8 0.8 0.8 position -1 -1 0 0 location local } "); 76 } 77 printf ("} "); 78 printf ("{ LIST { : branches%d } { : leaves%d } { : rootsystem%d }})\n", 79 treeID,treeID,treeID); 80 printf ("(bbox-draw tree%d no)\n", treeID); 81 fflush (stdout); 82 } 83 84 /******************************************************************** 85 * GenerateLeaves: 86 * Defines all of the leaves that make up the tree being defined 87 ********************************************************************/ 88 89 GenerateLeaves (treeID,leafType,min,max,minOrig,maxOrig,color,L) 90 int treeID; eco_leafType leafType; 91 float min,max,minOrig,maxOrig; 92 eco_color color; 93 lfStructPtr L; 94 { 95 float x0,y0,z0,x1,y1,z1,x2,y2,z2,x3,y3,z3; 96 float psyn, shade, lpi, value; 97 eco_color newColor; 98 strpointer shadeStr; 99 lfStructPtr cur = L; 100 101 /* 102 * if leaves have previously been defined, delete them 103 */ 104 printf ("(if (real-id leaves%d) (delete leaves%d))\n", treeID,treeID); 105 106 /* 107 * define flat shading if user wants normal colored leaves 108 * define constant shading if user wants leaves colored according 109 * to an attribute value 110 */ 111 if (leafType == NORMAL) 112 shadeStr = "flat"; 113 else 114 shadeStr = "constant"; 115 116 /* 117 * define leaves by sending the appropriate Geomview GCL 118 * commands to standard output 119 */ 120 printf ("(hdefine geometry leaves%d appearance { shading %s } { CQUAD ",treeID,shadeStr); 121 while (cur != NULL) { 122 if (leafType != NORMAL) { 123 switch (leafType) { 124 case PSYN: 125 value = cur->psyn; break; 126 case SHADE: 127 value = cur->shade; break; 128 case LPI: 129 value = cur->lpi; break; 130 case PPFDSUN: 131 value = cur->ppfdSUN; break; 132 case PPFDSHADE: 133 value = cur->ppfdSHADE; break; 134 } 135 if ((value >= min) && (value <= max)) { 136 pickAttribColor (value, minOrig, maxOrig, color, &newColor); 137 printLeaf (cur, newColor); 138 } 139 } else { 140 printLeaf (cur, color); 141 } 142 cur = cur->next; 143 } 144 printf ("})\n"); 145 fflush (stdout); 146 } 147 148 /******************************************************************** 149 * GenerateBranches: 150 * Defines the branches of the tree being defined 151 ********************************************************************/ 152 153 GenerateBranches (int treeID, bool display, brchSegPtr B) 154 { 155 brchSegPtr cur = B; 156 157 /* 158 * if the branches have previously been defined, delete them 159 */ 160 printf ("(if (real-id branches%d) (delete branches%d))\n", treeID,treeID); 161 162 /* 163 * define the branches by sending the appropriate GCL commands 164 * to the standard output 165 */ 166 if (display) { 167 168 /* if user wants the branches displayed, define all branch segments */ 169 170 printf ("(hdefine geometry branches%d { LIST ",treeID); 171 while (cur != NULL) { 172 printf ("{ INST geom { : branch }"); 173 printf (" transform { "); 174 GenerateTrans (cur->x1, cur->y1, cur->z1, cur->x2, cur->y2, 175 cur->z2, cur->radius); 176 printf (" }} "); 177 cur = cur->next; 178 } 179 printf ("})\n"); 180 } else { 181 182 /* otherwise, define branches as an empty list (nothing is drawn) */ 183 184 printf ("(hdefine geometry branches%d { LIST {} })\n",treeID); 185 } 186 fflush(stdout); 187 } 188 189 /******************************************************************** 190 * GenerateRoots: 191 * Defines the roots for the tree being defined 192 ********************************************************************/ 193 194 GenerateRoots (treeID,showRoots,rootType,min,max,minOrig,maxOrig, 195 rootColor,R) 196 int treeID; bool showRoots; eco_rootType rootType; 197 float min, max, minOrig, maxOrig; 198 eco_color rootColor; rtSegPtr R; 199 { 200 int i, numGrps, count; 201 float radius, value; 202 eco_color newColor; 203 rtSegPtr cur = R; 204 string cylStr; 205 206 /* 207 * if roots have previously been defined, delete them 208 */ 209 printf ("(if (real-id rootsystem%d) (delete rootsystem%d))\n", treeID,treeID); 210 printf ("(if (real-id root%d) (delete root%d))\n", treeID,treeID); 211 212 /* 213 * define the roots by sending the appropriate Geomview GCL commands 214 * to standard output 215 */ 216 if (showRoots) { 217 /* if user wants the roots displayed, define all root segments */ 218 219 if ((rootType == NORMAL) || (rootType == DOUBLE)) { 220 221 /* roots are colored using one color */ 222 223 printf ("(hdefine geometry root%d { ",treeID); 224 GenerateMesh (ROOT_X_DIM, ROOT_Y_DIM, 1.0, 1.0, rootColor); 225 printf ("})\n"); 226 fflush(stdout); 227 228 printf ("(hdefine geometry rootsystem%d appearance { shading constant } { LIST ",treeID); 229 while (cur != NULL) { 230 printf ("{ INST geom { : root%d }",treeID); 231 printf (" transform { "); 232 radius = cur->radius; 233 if (rootType == DOUBLE) radius *= 2.0; 234 GenerateTrans (cur->x1, cur->y1, cur->z1, cur->x2, cur->y2, 235 cur->z2, radius); 236 printf (" }} "); 237 cur = cur->next; 238 } 239 printf (" })\n"); 240 } else { 241 242 /* roots are to be colored according to attribute values */ 243 if (rootType == ORDER) { 244 defineRootSegments (maxOrig+1,rootColor); 245 } else if (rootType == DIAM) { 246 defineRootSegments (3,rootColor); 247 } else { 248 defineRootSegments (10,rootColor); 249 } 250 printf ("(hdefine geometry rootsystem%d appearance { shading constant } { LIST ",treeID); 251 while (cur != NULL) { 252 if (rootType == DIAM) { 253 value = cur->diameter; 254 pickRootCylinder (cylStr,value,minOrig,maxOrig,3); 255 } else if (rootType == ORDER) { 256 value = cur->order; 257 pickRootCylinder (cylStr,value,minOrig,maxOrig,maxOrig+1); 258 } else if (rootType == RHO) { 259 value = cur->rho; 260 pickRootCylinder (cylStr,value,minOrig,maxOrig,10); 261 } 262 if ((value >= min) && (value <= max)) { 263 printf ("{ INST geom { "); 264 printf (": %s } ", cylStr); 265 printf ("transform { "); 266 GenerateTrans (cur->x1, cur->y1, cur->z1, cur->x2, 267 cur->y2, cur->z2, 2*(cur->radius)); 268 printf (" }} "); 269 } 270 cur = cur->next; 271 } 272 printf ("})\n"); 273 } 274 } else { 275 276 /* if the user does not want roots displayed, define them as an 277 * empty list */ 278 279 printf ("(hdefine geometry rootsystem%d { LIST {}})\n",treeID); 280 } 281 fflush(stdout); 282 } 283 284 /********************************************************************** 285 * defineRootSegments: 286 * Defines a given number of cylinders (numGrps) colored with 287 * different shades of the baseColor (from white to black). 288 * These cylinders will be used to define the root segments of a 289 * tree whose roots are colored according to root attribute values. 290 ***********************************************************************/ 291 292 void defineRootSegments (int numGrps,eco_color baseColor) 293 { 294 int x; 295 eco_color newColor; 296 for (x=1; x<=numGrps; x++) { 297 pickAttribColor (x, 1, numGrps, baseColor, &newColor); 298 printf ("(hdefine geometry roots%d { ",x); 299 GenerateMesh (ROOT_X_DIM,ROOT_Y_DIM,1.0,1.0,newColor); 300 printf (" })\n"); 301 } 302 } 303 304 /********************************************************************** 305 * pickRootCylinder: 306 * Chooses one of the cylinders defined in defineRootSegments 307 * to use in the definition of the current root segment being 308 * drawn based on the position of the segments attribute value 309 * in the attribute range. 310 ***********************************************************************/ 311 312 void pickRootCylinder (string rtStr,float value,float min,float max,int numGrps) 313 { 314 float range,high,low; 315 int x; 316 int rndMin = min; 317 int rndMax = max; 318 range = (max-min+1) / numGrps; 319 high = min; 320 for (x=1; x<=numGrps; x++) { 321 low = high; 322 high = low + range; 323 if ((value >= low) && (value < high)) 324 break; 325 } 326 sprintf (rtStr, "roots%d", x); 327 } 328 329 330 /********************************************************************* 331 * GenerateMesh: 332 * Defines a cylinder using the Geomview MESH object based on 333 * the given height, radius, and color. 334 *********************************************************************/ 335 336 void GenerateMesh (int xdim,int ydim,float height,float radius,eco_color color) 337 { 338 int i, j; 339 float dy, theta, dtheta, x, y, z; 340 printf ("CuMESH "); 341 printf ("%1d %1d ", xdim, ydim); 342 theta = 0.0; 343 dtheta = 2*PI/xdim; 344 dy = height/(ydim-1); 345 for (j=0, y=0; j (x0, y0, z0),(x1, y1, z1) 361 *********************************************************************/ 362 363 void GenerateTrans (float x0,float y0,float z0,float x1,float y1, 364 float z1,float radius) 365 { 366 float tx1, ty1, tz1, height; 367 float Phi, cosPhi, sinPhi, Theta, cosTheta, sinTheta; 368 matrix rotY, rotZ, trans, scale, prod1, prod2; 369 int i, j; 370 371 tx1 = x1-x0; 372 ty1 = y1-y0; 373 tz1 = z1-z0; 374 height = sqrt (SQR(tx1) + SQR(ty1) + SQR(tz1)); 375 376 /* 377 * Compute the matrix that scales the unit cylinder 378 * to the size of the cylinder being created 379 */ 380 scale[0][1] = scale[0][2] = scale[0][3] = 0.0; 381 scale[1][0] = scale[1][2] = scale[1][3] = 0.0; 382 scale[2][0] = scale[2][1] = scale[2][3] = 0.0; 383 scale[3][0] = scale[3][1] = scale[3][2] = 0.0; 384 scale[0][0] = radius; /* scale x */ 385 scale[1][1] = height; /* scale y */ 386 scale[2][2] = radius; /* scale z */ 387 scale[3][3] = 1.0; 388 389 /* 390 * Compute the matrix that rotates the unit cylinder about 391 * the z-axis to the y value of the cylinder being created 392 */ 393 Phi = acos (ty1/height); 394 395 /** Phi is negative since rotation is in clockwise direction **/ 396 cosPhi = cos (-Phi); 397 sinPhi = sin (-Phi); 398 399 rotZ[0][2] = rotZ[0][3] = rotZ[1][2] = rotZ[1][3] = rotZ[2][3] = 0.0; 400 rotZ[2][0] = rotZ[2][1] = rotZ[3][0] = rotZ[3][1] = rotZ[3][2] = 0.0; 401 rotZ[0][0] = cosPhi; 402 rotZ[0][1] = sinPhi; 403 rotZ[1][0] = -sinPhi; 404 rotZ[1][1] = cosPhi; 405 rotZ[2][2] = rotZ[3][3] = 1.0; 406 407 /* 408 * Compute the matrix that rotates the unit cylinder about 409 * the y-axis to the correct x & z value for the cylinder 410 * being created 411 */ 412 if (tx1 == 0) { 413 if (tz1 < 0) 414 Theta = PI/2; 415 else if (tz1 > 0) 416 Theta = -PI/2; 417 else 418 Theta = 0.0; 419 } else { 420 Theta = atan (fabs(tz1)/fabs(tx1)); 421 /** Adjust Theta to account for the quadrant Theta should 422 * rotate the cylinder to (quadrants of the x and z-axis) 423 */ 424 if (tx1 > 0) { 425 if (tz1 > 0) 426 Theta = -Theta; 427 } else { 428 if (tz1 > 0) 429 Theta = -PI + Theta; 430 else 431 Theta = PI - Theta; 432 } 433 } 434 435 cosTheta = cos (Theta); 436 sinTheta = sin (Theta); 437 rotY[0][1] = rotY[0][3] = rotY[1][0] = rotY[1][2] = rotY[1][3] = 0.0; 438 rotY[2][1] = rotY[2][3] = rotY[3][0] = rotY[3][1] = rotY[3][2] = 0.0; 439 rotY[0][0] = cosTheta; 440 rotY[0][2] = -sinTheta; 441 rotY[2][0] = sinTheta; 442 rotY[2][2] = cosTheta; 443 rotY[1][1] = rotY[3][3] = 1.0; 444 445 /* 446 * Compute the matrix that translates the cylinder to the 447 * correct position 448 */ 449 trans[0][0] = trans[1][1] = trans[2][2] = trans[3][3] = 1.0; 450 trans[0][1] = trans[0][2] = trans[0][3] = 0.0; 451 trans[1][0] = trans[1][2] = trans[1][3] = 0.0; 452 trans[2][0] = trans[2][1] = trans[2][3] = 0.0; 453 trans[3][0] = x0; 454 trans[3][1] = y0; 455 trans[3][2] = z0; 456 457 /* 458 * Compute the composite matrix 459 */ 460 multMatrices (prod1, rotY, trans); 461 multMatrices (prod2, rotZ, prod1); 462 multMatrices (prod1, scale, prod2); 463 464 /* 465 * print the tranform to standard output 466 */ 467 for (i=0; i<4; i++) { 468 for (j=0; j<4; j++) { 469 printf ("%f ", prod1[i][j]); 470 } 471 } 472 } 473 474 /********************************************************************** 475 * multMatrices: 476 * Multiplies the matrices m1 and m2 and places the result in 477 * product 478 **********************************************************************/ 479 480 void multMatrices (product, m1, m2) 481 matrix product, m1, m2; 482 { 483 int i, j, k; 484 for (i=0; i<4; i++) { 485 for (j=0; j<4; j++) { 486 product[i][j] = 0.0; 487 for (k=0; k<4; k++ ) { 488 product[i][j] += m1[i][k]*m2[k][j]; 489 490 } 491 } 492 } 493 } 494 495 /******************** end of createTree.c **************************/ 496