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