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