1 #include <../src/sys/classes/draw/utils/axisimpl.h> /*I "petscdraw.h" I*/ 2 3 PetscClassId PETSC_DRAWAXIS_CLASSID = 0; 4 5 #undef __FUNCT__ 6 #define __FUNCT__ "PetscDrawAxisCreate" 7 /*@ 8 PetscDrawAxisCreate - Generate the axis data structure. 9 10 Collective on PetscDraw 11 12 Input Parameters: 13 . win - PetscDraw object where axis to to be made 14 15 Ouput Parameters: 16 . axis - the axis datastructure 17 18 Level: advanced 19 20 @*/ 21 PetscErrorCode PetscDrawAxisCreate(PetscDraw draw,PetscDrawAxis *axis) 22 { 23 PetscDrawAxis ad; 24 PetscErrorCode ierr; 25 26 PetscFunctionBegin; 27 PetscValidHeaderSpecific(draw,PETSC_DRAW_CLASSID,1); 28 PetscValidPointer(axis,2); 29 30 ierr = PetscHeaderCreate(ad,PETSC_DRAWAXIS_CLASSID,"DrawAxis","Draw Axis","Draw",PetscObjectComm((PetscObject)draw),PetscDrawAxisDestroy,NULL);CHKERRQ(ierr); 31 ierr = PetscLogObjectParent((PetscObject)draw,(PetscObject)ad);CHKERRQ(ierr); 32 33 ierr = PetscObjectReference((PetscObject)draw);CHKERRQ(ierr); 34 ad->win = draw; 35 36 ad->xticks = PetscADefTicks; 37 ad->yticks = PetscADefTicks; 38 ad->xlabelstr = PetscADefLabel; 39 ad->ylabelstr = PetscADefLabel; 40 ad->ac = PETSC_DRAW_BLACK; 41 ad->tc = PETSC_DRAW_BLACK; 42 ad->cc = PETSC_DRAW_BLACK; 43 ad->xlabel = NULL; 44 ad->ylabel = NULL; 45 ad->toplabel = NULL; 46 47 *axis = ad; 48 PetscFunctionReturn(0); 49 } 50 51 #undef __FUNCT__ 52 #define __FUNCT__ "PetscDrawAxisDestroy" 53 /*@ 54 PetscDrawAxisDestroy - Frees the space used by an axis structure. 55 56 Collective on PetscDrawAxis 57 58 Input Parameters: 59 . axis - the axis context 60 61 Level: advanced 62 63 @*/ 64 PetscErrorCode PetscDrawAxisDestroy(PetscDrawAxis *axis) 65 { 66 PetscErrorCode ierr; 67 68 PetscFunctionBegin; 69 if (!*axis) PetscFunctionReturn(0); 70 PetscValidHeaderSpecific(*axis,PETSC_DRAWAXIS_CLASSID,1); 71 if (--((PetscObject)(*axis))->refct > 0) {*axis = NULL; PetscFunctionReturn(0);} 72 73 ierr = PetscFree((*axis)->toplabel);CHKERRQ(ierr); 74 ierr = PetscFree((*axis)->xlabel);CHKERRQ(ierr); 75 ierr = PetscFree((*axis)->ylabel);CHKERRQ(ierr); 76 ierr = PetscDrawDestroy(&(*axis)->win);CHKERRQ(ierr); 77 ierr = PetscHeaderDestroy(axis);CHKERRQ(ierr); 78 PetscFunctionReturn(0); 79 } 80 81 #undef __FUNCT__ 82 #define __FUNCT__ "PetscDrawAxisSetColors" 83 /*@ 84 PetscDrawAxisSetColors - Sets the colors to be used for the axis, 85 tickmarks, and text. 86 87 Logically Collective on PetscDrawAxis 88 89 Input Parameters: 90 + axis - the axis 91 . ac - the color of the axis lines 92 . tc - the color of the tick marks 93 - cc - the color of the text strings 94 95 Level: advanced 96 97 @*/ 98 PetscErrorCode PetscDrawAxisSetColors(PetscDrawAxis axis,int ac,int tc,int cc) 99 { 100 PetscFunctionBegin; 101 PetscValidHeaderSpecific(axis,PETSC_DRAWAXIS_CLASSID,1); 102 PetscValidLogicalCollectiveInt(axis,ac,2); 103 PetscValidLogicalCollectiveInt(axis,tc,3); 104 PetscValidLogicalCollectiveInt(axis,cc,4); 105 axis->ac = ac; axis->tc = tc; axis->cc = cc; 106 PetscFunctionReturn(0); 107 } 108 109 #undef __FUNCT__ 110 #define __FUNCT__ "PetscDrawAxisSetLabels" 111 /*@C 112 PetscDrawAxisSetLabels - Sets the x and y axis labels. 113 114 Logically Collective on PetscDrawAxis 115 116 Input Parameters: 117 + axis - the axis 118 . top - the label at the top of the image 119 - xlabel,ylabel - the labes for the x and y axis 120 121 Notes: Must be called before PetscDrawAxisDraw() or PetscDrawLGDraw() 122 There should be no newlines in the arguments 123 124 Level: advanced 125 126 @*/ 127 PetscErrorCode PetscDrawAxisSetLabels(PetscDrawAxis axis,const char top[],const char xlabel[],const char ylabel[]) 128 { 129 PetscErrorCode ierr; 130 131 PetscFunctionBegin; 132 PetscValidHeaderSpecific(axis,PETSC_DRAWAXIS_CLASSID,1); 133 ierr = PetscFree(axis->xlabel);CHKERRQ(ierr); 134 ierr = PetscFree(axis->ylabel);CHKERRQ(ierr); 135 ierr = PetscFree(axis->toplabel);CHKERRQ(ierr); 136 ierr = PetscStrallocpy(xlabel,&axis->xlabel);CHKERRQ(ierr); 137 ierr = PetscStrallocpy(ylabel,&axis->ylabel);CHKERRQ(ierr); 138 ierr = PetscStrallocpy(top,&axis->toplabel);CHKERRQ(ierr); 139 PetscFunctionReturn(0); 140 } 141 142 #undef __FUNCT__ 143 #define __FUNCT__ "PetscDrawAxisSetLimits" 144 /*@ 145 PetscDrawAxisSetLimits - Sets the limits (in user coords) of the axis 146 147 Logically Collective on PetscDrawAxis 148 149 Input Parameters: 150 + axis - the axis 151 . xmin,xmax - limits in x 152 - ymin,ymax - limits in y 153 154 Options Database: 155 . -drawaxis_hold - hold the initial set of axis limits for future plotting 156 157 Level: advanced 158 159 .seealso: PetscDrawAxisSetHoldLimits() 160 161 @*/ 162 PetscErrorCode PetscDrawAxisSetLimits(PetscDrawAxis axis,PetscReal xmin,PetscReal xmax,PetscReal ymin,PetscReal ymax) 163 { 164 PetscErrorCode ierr; 165 166 PetscFunctionBegin; 167 PetscValidHeaderSpecific(axis,PETSC_DRAWAXIS_CLASSID,1); 168 if (axis->hold) PetscFunctionReturn(0); 169 axis->xlow = xmin; 170 axis->xhigh= xmax; 171 axis->ylow = ymin; 172 axis->yhigh= ymax; 173 ierr = PetscOptionsHasName(((PetscObject)axis)->options,((PetscObject)axis)->prefix,"-drawaxis_hold",&axis->hold);CHKERRQ(ierr); 174 PetscFunctionReturn(0); 175 } 176 177 #undef __FUNCT__ 178 #define __FUNCT__ "PetscDrawAxisGetLimits" 179 /*@ 180 PetscDrawAxisGetLimits - Gets the limits (in user coords) of the axis 181 182 Not Collective 183 184 Input Parameters: 185 + axis - the axis 186 . xmin,xmax - limits in x 187 - ymin,ymax - limits in y 188 189 Level: advanced 190 191 .seealso: PetscDrawAxisSetLimits() 192 193 @*/ 194 PetscErrorCode PetscDrawAxisGetLimits(PetscDrawAxis axis,PetscReal *xmin,PetscReal *xmax,PetscReal *ymin,PetscReal *ymax) 195 { 196 PetscFunctionBegin; 197 PetscValidHeaderSpecific(axis,PETSC_DRAWAXIS_CLASSID,1); 198 *xmin = axis->xlow; 199 *xmax = axis->xhigh; 200 *ymin = axis->ylow; 201 *ymax = axis->yhigh; 202 PetscFunctionReturn(0); 203 } 204 205 #undef __FUNCT__ 206 #define __FUNCT__ "PetscDrawAxisSetHoldLimits" 207 /*@ 208 PetscDrawAxisSetHoldLimits - Causes an axis to keep the same limits until this is called 209 again 210 211 Logically Collective on PetscDrawAxis 212 213 Input Parameters: 214 + axis - the axis 215 - hold - PETSC_TRUE - hold current limits, PETSC_FALSE allow limits to be changed 216 217 Level: advanced 218 219 Notes: 220 Once this has been called with PETSC_TRUE the limits will not change if you call 221 PetscDrawAxisSetLimits() until you call this with PETSC_FALSE 222 223 .seealso: PetscDrawAxisSetLimits() 224 225 @*/ 226 PetscErrorCode PetscDrawAxisSetHoldLimits(PetscDrawAxis axis,PetscBool hold) 227 { 228 PetscFunctionBegin; 229 PetscValidHeaderSpecific(axis,PETSC_DRAWAXIS_CLASSID,1); 230 PetscValidLogicalCollectiveBool(axis,hold,2); 231 axis->hold = hold; 232 PetscFunctionReturn(0); 233 } 234 235 #undef __FUNCT__ 236 #define __FUNCT__ "PetscDrawAxisDraw" 237 /*@ 238 PetscDrawAxisDraw - PetscDraws an axis. 239 240 Collective on PetscDrawAxis 241 242 Input Parameter: 243 . axis - Axis structure 244 245 Level: advanced 246 247 Note: 248 This draws the actual axis. The limits etc have already been set. 249 By picking special routines for the ticks and labels, special 250 effects may be generated. These routines are part of the Axis 251 structure (axis). 252 @*/ 253 PetscErrorCode PetscDrawAxisDraw(PetscDrawAxis axis) 254 { 255 int i,ntick,numx,numy,ac,tc,cc; 256 PetscMPIInt rank; 257 size_t len,ytlen=0; 258 PetscReal coors[4],tickloc[MAXSEGS],sep,tw,th; 259 PetscReal xl,xr,yl,yr,dxl=0,dyl=0,dxr=0,dyr=0; 260 char *p; 261 PetscDraw draw; 262 PetscBool isnull; 263 PetscErrorCode ierr; 264 265 PetscFunctionBegin; 266 PetscValidHeaderSpecific(axis,PETSC_DRAWAXIS_CLASSID,1); 267 ierr = PetscDrawIsNull(axis->win,&isnull);CHKERRQ(ierr); 268 if (isnull) PetscFunctionReturn(0); 269 ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)axis),&rank);CHKERRQ(ierr); 270 271 draw = axis->win; 272 273 ac = axis->ac; tc = axis->tc; cc = axis->cc; 274 if (axis->xlow == axis->xhigh) {axis->xlow -= .5; axis->xhigh += .5;} 275 if (axis->ylow == axis->yhigh) {axis->ylow -= .5; axis->yhigh += .5;} 276 277 ierr = PetscDrawCollectiveBegin(draw);CHKERRQ(ierr); 278 if (rank) goto finally; 279 280 /* get cannonical string size */ 281 ierr = PetscDrawSetCoordinates(draw,0,0,1,1);CHKERRQ(ierr); 282 ierr = PetscDrawStringGetSize(draw,&tw,&th);CHKERRQ(ierr); 283 /* lower spacing */ 284 if (axis->xlabelstr) dyl += 1.5*th; 285 if (axis->xlabel) dyl += 1.5*th; 286 /* left spacing */ 287 if (axis->ylabelstr) dxl += 7.5*tw; 288 if (axis->ylabel) dxl += 2.0*tw; 289 /* right and top spacing */ 290 if (axis->xlabelstr) dxr = 2.5*tw; 291 if (axis->ylabelstr) dyr = 0.5*th; 292 if (axis->toplabel) dyr = 1.5*th; 293 /* extra spacing */ 294 dxl += 0.7*tw; dxr += 0.5*tw; 295 dyl += 0.2*th; dyr += 0.2*th; 296 /* determine coordinates */ 297 xl = (dxl*axis->xhigh + dxr*axis->xlow - axis->xlow) / (dxl + dxr - 1); 298 xr = (dxl*axis->xhigh + dxr*axis->xlow - axis->xhigh) / (dxl + dxr - 1); 299 yl = (dyl*axis->yhigh + dyr*axis->ylow - axis->ylow) / (dyl + dyr - 1); 300 yr = (dyl*axis->yhigh + dyr*axis->ylow - axis->yhigh) / (dyl + dyr - 1); 301 ierr = PetscDrawSetCoordinates(draw,xl,yl,xr,yr);CHKERRQ(ierr); 302 ierr = PetscDrawStringGetSize(draw,&tw,&th);CHKERRQ(ierr); 303 304 /* PetscDraw the axis lines */ 305 ierr = PetscDrawLine(draw,axis->xlow,axis->ylow,axis->xhigh,axis->ylow,ac);CHKERRQ(ierr); 306 ierr = PetscDrawLine(draw,axis->xlow,axis->ylow,axis->xlow,axis->yhigh,ac);CHKERRQ(ierr); 307 ierr = PetscDrawLine(draw,axis->xlow,axis->yhigh,axis->xhigh,axis->yhigh,ac);CHKERRQ(ierr); 308 ierr = PetscDrawLine(draw,axis->xhigh,axis->ylow,axis->xhigh,axis->yhigh,ac);CHKERRQ(ierr); 309 310 /* PetscDraw the top label */ 311 if (axis->toplabel) { 312 PetscReal x = (axis->xlow + axis->xhigh)/2, y = axis->yhigh + 0.5*th; 313 ierr = PetscDrawStringCentered(draw,x,y,cc,axis->toplabel);CHKERRQ(ierr); 314 } 315 316 /* PetscDraw the X ticks and labels */ 317 if (axis->xticks) { 318 numx = (int)(.15*(axis->xhigh-axis->xlow)/tw); numx = PetscClipInterval(numx,2,6); 319 ierr = (*axis->xticks)(axis->xlow,axis->xhigh,numx,&ntick,tickloc,MAXSEGS);CHKERRQ(ierr); 320 /* PetscDraw in tick marks */ 321 for (i=0; i<ntick; i++) { 322 ierr = PetscDrawLine(draw,tickloc[i],axis->ylow,tickloc[i],axis->ylow+.5*th,tc);CHKERRQ(ierr); 323 ierr = PetscDrawLine(draw,tickloc[i],axis->yhigh,tickloc[i],axis->yhigh-.5*th,tc);CHKERRQ(ierr); 324 } 325 /* label ticks */ 326 if (axis->xlabelstr) { 327 for (i=0; i<ntick; i++) { 328 if (i < ntick - 1) sep = tickloc[i+1] - tickloc[i]; 329 else if (i > 0) sep = tickloc[i] - tickloc[i-1]; 330 else sep = 0.0; 331 ierr = (*axis->xlabelstr)(tickloc[i],sep,&p);CHKERRQ(ierr); 332 ierr = PetscDrawStringCentered(draw,tickloc[i],axis->ylow-1.5*th,cc,p);CHKERRQ(ierr); 333 } 334 } 335 } 336 if (axis->xlabel) { 337 PetscReal x = (axis->xlow + axis->xhigh)/2, y = axis->ylow - 1.5*th; 338 if (axis->xlabelstr) y -= 1.5*th; 339 ierr = PetscDrawStringCentered(draw,x,y,cc,axis->xlabel);CHKERRQ(ierr); 340 } 341 342 /* PetscDraw the Y ticks and labels */ 343 if (axis->yticks) { 344 numy = (int)(.50*(axis->yhigh-axis->ylow)/th); numy = PetscClipInterval(numy,2,6); 345 ierr = (*axis->yticks)(axis->ylow,axis->yhigh,numy,&ntick,tickloc,MAXSEGS);CHKERRQ(ierr); 346 /* PetscDraw in tick marks */ 347 for (i=0; i<ntick; i++) { 348 ierr = PetscDrawLine(draw,axis->xlow,tickloc[i],axis->xlow+.5*tw,tickloc[i],tc);CHKERRQ(ierr); 349 ierr = PetscDrawLine(draw,axis->xhigh,tickloc[i],axis->xhigh-.5*tw,tickloc[i],tc);CHKERRQ(ierr); 350 } 351 /* label ticks */ 352 if (axis->ylabelstr) { 353 for (i=0; i<ntick; i++) { 354 if (i < ntick - 1) sep = tickloc[i+1] - tickloc[i]; 355 else if (i > 0) sep = tickloc[i] - tickloc[i-1]; 356 else sep = 0.0; 357 ierr = (*axis->ylabelstr)(tickloc[i],sep,&p);CHKERRQ(ierr); 358 ierr = PetscStrlen(p,&len);CHKERRQ(ierr); ytlen = PetscMax(ytlen,len); 359 ierr = PetscDrawString(draw,axis->xlow-(len+.5)*tw,tickloc[i]-.5*th,cc,p);CHKERRQ(ierr); 360 } 361 } 362 } 363 if (axis->ylabel) { 364 PetscReal x = axis->xlow - 2.0*tw, y = (axis->ylow + axis->yhigh)/2; 365 if (axis->ylabelstr) x -= (ytlen+.5)*tw; 366 ierr = PetscStrlen(axis->ylabel,&len);CHKERRQ(ierr); 367 ierr = PetscDrawStringVertical(draw,x,y+len*th/2,cc,axis->ylabel);CHKERRQ(ierr); 368 } 369 370 ierr = PetscDrawGetCoordinates(draw,&coors[0],&coors[1],&coors[2],&coors[3]);CHKERRQ(ierr); 371 finally: 372 ierr = PetscDrawCollectiveEnd(draw);CHKERRQ(ierr); 373 ierr = MPI_Bcast(coors,4,MPIU_REAL,0,PetscObjectComm((PetscObject)draw));CHKERRQ(ierr); 374 ierr = PetscDrawSetCoordinates(draw,coors[0],coors[1],coors[2],coors[3]);CHKERRQ(ierr); 375 PetscFunctionReturn(0); 376 } 377 378 #undef __FUNCT__ 379 #define __FUNCT__ "PetscStripe0" 380 /* 381 Removes all zeros but one from .0000 382 */ 383 PetscErrorCode PetscStripe0(char *buf) 384 { 385 PetscErrorCode ierr; 386 size_t n; 387 PetscBool flg; 388 char *str; 389 390 PetscFunctionBegin; 391 ierr = PetscStrlen(buf,&n);CHKERRQ(ierr); 392 ierr = PetscStrendswith(buf,"e00",&flg);CHKERRQ(ierr); 393 if (flg) buf[n-3] = 0; 394 ierr = PetscStrstr(buf,"e0",&str);CHKERRQ(ierr); 395 if (str) { 396 buf[n-2] = buf[n-1]; 397 buf[n-1] = 0; 398 } 399 ierr = PetscStrstr(buf,"e-0",&str);CHKERRQ(ierr); 400 if (str) { 401 buf[n-2] = buf[n-1]; 402 buf[n-1] = 0; 403 } 404 PetscFunctionReturn(0); 405 } 406 407 #undef __FUNCT__ 408 #define __FUNCT__ "PetscStripAllZeros" 409 /* 410 Removes all zeros but one from .0000 411 */ 412 PetscErrorCode PetscStripAllZeros(char *buf) 413 { 414 PetscErrorCode ierr; 415 size_t i,n; 416 417 PetscFunctionBegin; 418 ierr = PetscStrlen(buf,&n);CHKERRQ(ierr); 419 if (buf[0] != '.') PetscFunctionReturn(0); 420 for (i=1; i<n; i++) { 421 if (buf[i] != '0') PetscFunctionReturn(0); 422 } 423 buf[0] = '0'; 424 buf[1] = 0; 425 PetscFunctionReturn(0); 426 } 427 428 #undef __FUNCT__ 429 #define __FUNCT__ "PetscStripTrailingZeros" 430 /* 431 Removes trailing zeros 432 */ 433 PetscErrorCode PetscStripTrailingZeros(char *buf) 434 { 435 PetscErrorCode ierr; 436 char *found; 437 size_t i,n,m = PETSC_MAX_INT; 438 439 PetscFunctionBegin; 440 /* if there is an e in string DO NOT strip trailing zeros */ 441 ierr = PetscStrchr(buf,'e',&found);CHKERRQ(ierr); 442 if (found) PetscFunctionReturn(0); 443 444 ierr = PetscStrlen(buf,&n);CHKERRQ(ierr); 445 /* locate decimal point */ 446 for (i=0; i<n; i++) { 447 if (buf[i] == '.') {m = i; break;} 448 } 449 /* if not decimal point then no zeros to remove */ 450 if (m == PETSC_MAX_INT) PetscFunctionReturn(0); 451 /* start at right end of string removing 0s */ 452 for (i=n-1; i>m; i++) { 453 if (buf[i] != '0') PetscFunctionReturn(0); 454 buf[i] = 0; 455 } 456 PetscFunctionReturn(0); 457 } 458 459 #undef __FUNCT__ 460 #define __FUNCT__ "PetscStripInitialZero" 461 /* 462 Removes leading 0 from 0.22 or -0.22 463 */ 464 PetscErrorCode PetscStripInitialZero(char *buf) 465 { 466 PetscErrorCode ierr; 467 size_t i,n; 468 469 PetscFunctionBegin; 470 ierr = PetscStrlen(buf,&n);CHKERRQ(ierr); 471 if (buf[0] == '0') { 472 for (i=0; i<n; i++) buf[i] = buf[i+1]; 473 } else if (buf[0] == '-' && buf[1] == '0') { 474 for (i=1; i<n; i++) buf[i] = buf[i+1]; 475 } 476 PetscFunctionReturn(0); 477 } 478 479 #undef __FUNCT__ 480 #define __FUNCT__ "PetscStripZeros" 481 /* 482 Removes the extraneous zeros in numbers like 1.10000e6 483 */ 484 PetscErrorCode PetscStripZeros(char *buf) 485 { 486 PetscErrorCode ierr; 487 size_t i,j,n; 488 489 PetscFunctionBegin; 490 ierr = PetscStrlen(buf,&n);CHKERRQ(ierr); 491 if (n<5) PetscFunctionReturn(0); 492 for (i=1; i<n-1; i++) { 493 if (buf[i] == 'e' && buf[i-1] == '0') { 494 for (j=i; j<n+1; j++) buf[j-1] = buf[j]; 495 ierr = PetscStripZeros(buf);CHKERRQ(ierr); 496 PetscFunctionReturn(0); 497 } 498 } 499 PetscFunctionReturn(0); 500 } 501 502 #undef __FUNCT__ 503 #define __FUNCT__ "PetscStripZerosPlus" 504 /* 505 Removes the plus in something like 1.1e+2 or 1.1e+02 506 */ 507 PetscErrorCode PetscStripZerosPlus(char *buf) 508 { 509 PetscErrorCode ierr; 510 size_t i,j,n; 511 512 PetscFunctionBegin; 513 ierr = PetscStrlen(buf,&n);CHKERRQ(ierr); 514 if (n<5) PetscFunctionReturn(0); 515 for (i=1; i<n-2; i++) { 516 if (buf[i] == '+') { 517 if (buf[i+1] == '0') { 518 for (j=i+1; j<n; j++) buf[j-1] = buf[j+1]; 519 PetscFunctionReturn(0); 520 } else { 521 for (j=i+1; j<n+1; j++) buf[j-1] = buf[j]; 522 PetscFunctionReturn(0); 523 } 524 } else if (buf[i] == '-') { 525 if (buf[i+1] == '0') { 526 for (j=i+1; j<n; j++) buf[j] = buf[j+1]; 527 PetscFunctionReturn(0); 528 } 529 } 530 } 531 PetscFunctionReturn(0); 532 } 533