1: 
   2: /******************************************************************************
   3:  *  bitdraw - 	implements the bitmap drawing primitives necessary to turn
   4:  *		ditroff draw commands into a pixel vector for interpress
   5:  *
   6:  *
   7:  *	John Mellor-Crummey (Xerox Corp)
   8:  *
   9:  * 	Copyright (c) 1985 Xerox Corp.
  10:  *
  11:  ******************************************************************************/
  12: 
  13: 
  14: #include <math.h>
  15: #include <stdio.h>
  16: #include <ctype.h>
  17: 
  18: #include "defs.h"
  19: #include "externs.h"
  20: 
  21: 
  22: /*------------------------------------------------------------------------------
  23:  *	bitmapDrawCircle	incrementally compute the points for one octant
  24:  *				of a circle and complete the figure by
  25:  *				reflecting the points into each of the octants.
  26:  *
  27:  *		based on an algorithm by J. Michener from
  28:  *		Fundamentals of Interactive Computer Graphics,
  29:  *		Foley & Van Dam, 1982, p. 445
  30:  *----------------------------------------------------------------------------*/
  31: bitmapDrawCircle(d)
  32: int d;
  33: {
  34:     int x,y,xc,yc,delta;
  35: 
  36:     xc = hor_pos + d/2;
  37:     yc = ver_pos;
  38:     delta = 3 - d;
  39:     x = 0;
  40:     y = d/2;
  41:     while ( x < y)
  42:     {
  43:         octPlot(x,y,xc,yc);
  44:         if (delta < 0)
  45:             delta = delta + 4 * x + 6;
  46:         else
  47:         {
  48:             delta = delta + 4 * (x - y) + 10;
  49:             y--;
  50:         }
  51:         x++;
  52:     }
  53:     if (x == y) octPlot(x,y,xc,yc);
  54:     hMov(xc + d/2);
  55:     vMov(yc);
  56: }
  57: 
  58: 
  59: /*------------------------------------------------------------------------------
  60:  *	octPlot		reflect the point  x,y into each of the eight
  61:  *			octants centered about xc,yc and set the pixels
  62:  *			in a bitmap
  63:  *----------------------------------------------------------------------------*/
  64: octPlot(x,y,xc,yc)
  65: int x,y,xc,yc;
  66: {
  67:     vMov(yc + y);
  68:     hMov(xc + x); setpixel();
  69:     hMov(xc - x); setpixel();
  70:     vMov(yc - y); setpixel();
  71:     hMov(xc + x); setpixel();
  72:     vMov(yc + x);
  73:     hMov(xc + y); setpixel();
  74:     hMov(xc - y); setpixel();
  75:     vMov(yc - x); setpixel();
  76:     hMov(xc + y); setpixel();
  77: }
  78: 
  79: /*------------------------------------------------------------------------------
  80:  *	bitmapDrawEllipse	incrementally compute the points for one
  81:  *				quadrant of an ellipse and complete the figure
  82:  *				by reflecting the points into each of the
  83:  *				quadrants.
  84:  *----------------------------------------------------------------------------*/
  85: bitmapDrawEllipse(xdiam,ydiam)
  86: int xdiam,ydiam;
  87: {
  88:     int x,y,xc,yc,a,b;
  89:     int fourAsq,fourAsqY;
  90:     int sixBsq,twoBsq,fourBsq,fourBsqX;
  91:     int d;
  92:     int midpoint;
  93: 
  94:     a = xdiam / 2;
  95:     b = ydiam / 2;
  96:     xc = hor_pos + a;
  97:     yc = ver_pos;
  98: 
  99:     x = 0;
 100:     y = b;
 101:     fourAsq = a * a * 4;
 102:     twoBsq = b * b * 2;
 103:     fourBsq = twoBsq + twoBsq;
 104:     sixBsq = fourBsq + twoBsq;
 105:     fourAsqY = fourAsq * y;
 106:     fourBsqX = 0;
 107:     midpoint = a * a * sqrt((double) 1.0 / (a * a + b * b));
 108:     d = twoBsq +  a * a * (2 * b  + 1);
 109: 
 110:     while(x < midpoint)
 111:     {
 112:         quadPlot(x,y,xc,yc);
 113:         if (d > 0) /* case 2 -> y-- */
 114:         {
 115:             d += fourAsq - fourAsqY;
 116:             fourAsqY -= fourAsq;
 117:             y--;
 118:         }
 119:         d += fourBsqX + sixBsq;
 120:         fourBsqX += fourBsq;
 121:         x++;
 122:     }
 123:     d -= twoBsq * x - b * b;
 124:     while(y >= 0)
 125:     {
 126:         quadPlot(x,y,xc,yc);
 127:         if (d > 0) /* case 3 -> x++ */
 128:         {
 129:             d += fourBsqX + sixBsq;
 130:             fourBsqX += fourBsq;
 131:             x++;
 132:         }
 133:         d += fourAsq - fourAsqY;
 134:         fourAsqY -= fourAsq;
 135:         y--;
 136:     }
 137:     hMov(xc + a);
 138:     vMov(yc);
 139: }
 140: 
 141: 
 142: /*------------------------------------------------------------------------------
 143:  *	quadPlot	reflect the point  x,y into each of the four
 144:  *			quadrants centered about xc,yc and set the pixels
 145:  *			in a bitmap
 146:  *----------------------------------------------------------------------------*/
 147: quadPlot(x,y,xc,yc)
 148: int x,y,xc,yc;
 149: {
 150:     vMov(yc + y);
 151:     hMov(xc + x); setpixel();
 152:     hMov(xc - x); setpixel();
 153:     vMov(yc - y); setpixel();
 154:     hMov(xc + x); setpixel();
 155: }
 156: 
 157: 
 158: /*------------------------------------------------------------------------------
 159:  *	bitmapDrawCircle	incrementally draw a circular arc in a c
 160:  *				counterclockwise direction. the arguments are
 161:  *				relative coordinates for the center point
 162:  *				from the current point, and the termination
 163:  *				point from the center point.
 164:  *
 165:  *		based on an algorithm by J. Bresenham
 166:  *		A Linear Algorithm for Incremental Digital
 167:  *		Display of Circular Arcs, Communications of the ACM,
 168:  *		Feb. 1977, pp. 103-104.
 169:  *----------------------------------------------------------------------------*/
 170: bitmapDrawArc(relxc,relyc,relxt,relyt)
 171: int relxc,relyc,relxt,relyt;
 172: {
 173:     int xc,yc;
 174:     int Xsprime,Ysprime,Xtprime,Ytprime;
 175:     int Xshat,Yshat,Xthat,Ythat,Xs,Ys,Xt,Yt,Xi,Yi;
 176:     int delta,deltai,deltaprime;
 177:     int M1x,M1y,M2x,M2y,M3x,M3y;
 178:     int q,qs,qt,qstar;
 179:     int move;
 180:     int xsave;
 181:     int radius;
 182:     double angle;
 183:     int xplot,yplot;
 184: 
 185:     xc = hor_pos + relxc;
 186:     yc = ver_pos + relyc;
 187:     Xtprime =  hor_pos;
 188:     Ytprime = ver_pos;
 189:     Xsprime = relxt + xc;
 190:     Ysprime = relyt + yc;
 191: 
 192:     /* get the radius from the start point */
 193:     radius = hypot((double) relxc,(double) relyc);
 194: 
 195:     /* readjust start point to be sure it is on proper grid point */
 196:     angle = atan2((double) (Ysprime - yc),(double) (Xsprime - xc));
 197:     xplot = Xsprime = radius * cos(angle) + xc + .5;
 198:     yplot = Ysprime = radius * sin(angle) + yc + .5;
 199: 
 200:     /* readjust termination point to be sure it is on proper grid point */
 201:     angle = atan2((double) (Ytprime - yc),(double) (Xtprime - xc));
 202:     Xtprime = radius * cos(angle) + xc + .5;
 203:     Ytprime = radius * sin(angle) + yc + .5;
 204: 
 205:     /* compute start and end points of the arc as relative coordinates */
 206:     Xshat = Xsprime - xc;
 207:     Yshat = Ysprime - yc;
 208:     Xthat = Xtprime - xc;
 209:     Ythat = Ytprime - yc;
 210: 
 211:     /* implement the quadrant transforms to normalize to first quadrant
 212: 	 * for both start and end points
 213: 	 */
 214: 
 215:     if (Xshat < 0)
 216:     {
 217:         if (Yshat < 0)
 218:         {
 219:             Xs =  abs(Yshat);
 220:             Ys =  abs(Xshat);
 221:             qs = 3;
 222:             M1x = 0; M1y = -1;
 223:             M2x = 1; M2y = -1;
 224:             M3x = 1; M3y = 0;
 225:         }
 226:         else
 227:         {
 228:             Xs =  abs(Xshat);
 229:             Ys =  abs(Yshat);
 230:             qs = 2;
 231:             M1x = -1; M1y =  0;
 232:             M2x = -1; M2y = -1;
 233:             M3x =  0; M3y = -1;
 234:         }
 235:     }
 236:     else
 237:     {
 238:         if (Yshat < 0)
 239:         {
 240:             Xs =  abs(Xshat);
 241:             Ys =  abs(Yshat);
 242:             qs = 0;
 243:             M1x = 1; M1y = 0;
 244:             M2x = 1; M2y = 1;
 245:             M3x = 0; M3y = 1;
 246:         }
 247:         else
 248:         {
 249:             Xs =  abs(Yshat);
 250:             Ys =  abs(Xshat);
 251:             qs = 1;
 252:             M1x =  0; M1y =  1;
 253:             M2x = -1; M2y = 1;
 254:             M3x = -1; M3y = 0;
 255:         }
 256:     }
 257: 
 258:     if (Xthat < 0)
 259:     {
 260:         if (Ythat < 0)
 261:         {
 262:             Xt =  abs(Ythat);
 263:             Yt =  abs(Xthat);
 264:             qt = 3;
 265:         }
 266:         else
 267:         {
 268:             Xt =  abs(Xthat);
 269:             Yt =  abs(Ythat);
 270:             qt = 2;
 271:         }
 272:     }
 273:     else
 274:     {
 275:         if (Ythat < 0)
 276:         {
 277:             Xt =  abs(Xthat);
 278:             Yt =  abs(Ythat);
 279:             qt = 0;
 280:         }
 281:         else
 282:         {
 283:             Xt =  abs(Ythat);
 284:             Yt =  abs(Xthat);
 285:             qt = 1;
 286:         }
 287:     }
 288: 
 289:     /* calculate number of quadrants */
 290:     qstar = (4 + qt - qs) % 4;
 291:     if ((qstar == 0) && (Xt <= Xs) && (Yt >= Ys))
 292:         q = 3;
 293:     else    q = qstar - 1;
 294: 
 295:     /* initialize for iteration */
 296:     deltai = 2 * (Xs - Ys + 1);
 297:     Xi = Xs;
 298:     Yi = Ys;
 299: 
 300:     while(TRUE)
 301:     {
 302:         if ((q < 0) && (Xt <= Xi) && (Yt >= Yi))
 303:             break;
 304: 
 305:         hMov(xplot);
 306:         vMov(yplot);
 307:         setpixel();
 308: 
 309:         if (Yi < 1)
 310:         {
 311:             xsave = Xi;
 312:             Xi = - Yi;
 313:             Yi = xsave;
 314:             deltai = deltai - 4 * xsave;
 315: 
 316:             q = q - 1;
 317:             M1x = M3x;
 318:             M1y = M3y;
 319: 
 320:             xsave = M2x;
 321:             M2x = - M2y;
 322:             M2y = xsave;
 323: 
 324:             xsave = M3x;
 325:             M3x = - M3y;
 326:             M3y = xsave;
 327: 
 328:             continue;
 329:         }
 330:         if (deltai <= 0)
 331:         {
 332:             delta = 2 * (deltai + Yi) - 1;
 333:             if (delta > 0)
 334:                 move = M2;
 335:             else    move = M1;
 336:         }
 337:         else
 338:         {
 339:             deltaprime = 2 * (deltai - Xi) - 1;
 340:             if (deltaprime > 0)
 341:                 move = M3;
 342:             else    move = M2;
 343:         }
 344: 
 345:         switch(move)
 346:         {
 347:         case M1:
 348:             Xi++;
 349:             deltai = deltai + 2* Xi + 1;
 350:             xplot += M1x;
 351:             yplot += M1y;
 352:             break;
 353:         case M2:
 354:             Xi++;
 355:             Yi--;
 356:             deltai = deltai + 2* (Xi - Yi) + 2;
 357:             xplot += M2x;
 358:             yplot += M2y;
 359:             break;
 360:         case M3:
 361:             Yi--;
 362:             deltai = deltai - 2 * Yi + 1;
 363:             xplot += M3x;
 364:             yplot += M3y;
 365:             break;
 366:         }
 367:     }
 368: }
 369: 
 370: 
 371: /*------------------------------------------------------------------------------
 372:  *	bitmapDrawWigglyLine	interpolate a curve between the sets of
 373:  *				relative points. the interpolation is done
 374:  *				using a spline like method to produce a curve
 375:  *				compatible with other output of ipic
 376:  *				(if the wiggly line should have arrowheads,
 377:  *				ipic assumes that the wiggly line will pass
 378:  *				close to the 2nd to last point in the curve
 379:  *				when it computes the tilt of the arrowheads.
 380:  *				For a smoother curve such as a
 381:  *				B-spline, the arrowheads will not be tilted
 382:  *				correctly as the spline is not guaranteed to
 383:  *				pass through the 2nd to last point)
 384:  *----------------------------------------------------------------------------*/
 385: bitmapDrawWigglyLine(s)
 386: char *s;
 387: {
 388:     int x[maxPointsInSpline],y[maxPointsInSpline];
 389:     int xi,yi,i,j,numPoints;
 390:     float temp1,temp2,temp3,t,dis;
 391:     float euclidDist();
 392: 
 393:     /* skip all leading white space */
 394:     while(white(*s)) s++;
 395:     if(!isdigit(*s)) return;
 396: 
 397:     /* read in the x y pairs of points for the spline */
 398:     for(numPoints = 2; ((numPoints< maxPointsInSpline) &&
 399:         (readNumber(&s,&x[numPoints]) != NULL) &&
 400:         (readNumber(&s,&y[numPoints]) != NULL)); numPoints++);
 401:     numPoints++;
 402: 
 403:     /* first point of curve is current point */
 404:     x[1] = hor_pos;
 405:     y[1] = ver_pos;
 406: 
 407:     /* turn relative points into absolute points */
 408:     for (i = 2; i < numPoints; i++)
 409:     {
 410:         x[i] += x[i-1];
 411:         y[i] += y[i-1];
 412:     }
 413: 
 414:     /* if the wiggle's ends meet, insure the curve meets */
 415:     if ((x[1] == x[numPoints-1]) && (y[1] == y[numPoints-1]))
 416:     {
 417:         x[0] = x[numPoints-2];
 418:         y[0] = y[numPoints-2];
 419:         x[numPoints] = x[2];
 420:         y[numPoints] = y[2];
 421:     }
 422:     else
 423:     {
 424:         x[0] = x[1];
 425:         y[0] = y[1];
 426:         x[numPoints] = x[numPoints-1];
 427:         y[numPoints] = y[numPoints-1];
 428:     }
 429:     numPoints++;
 430: 
 431:     /* position next pointers to the start of spline */
 432:     hMov((x[0] + x[1]) / 2);
 433:     vMov((y[0] + y[1]) / 2);
 434: 
 435:     for (i = 0; i < numPoints - 2; i++)
 436:     {
 437:         dis = (euclidDist(x[i],y[i], x[i+1],y[i+1]) +
 438:                euclidDist(x[i+1],y[i+1], x[i+2],y[i+2])) / 2;
 439:         for(j=1;j<dis;j++)
 440:         {
 441:             t = (float) j/dis;
 442:             temp1 = 0.5 * t * t;
 443:             temp2 = -temp1 - temp1 + t + 0.5;
 444:             temp3 = temp1 - t + 0.5;
 445: 
 446:             xi = temp1 * x[i+2] + temp2 * x[i+1] + temp3 * x[i] + 0.5;
 447:             yi = temp1 * y[i+2] + temp2 * y[i+1] + temp3 * y[i] + 0.5;
 448:             if (xi != hor_pos || yi != ver_pos)
 449:             {
 450:                 hMov(xi);
 451:                 vMov(yi);
 452:                 setpixel();
 453:             }
 454:         }
 455:     }
 456: }
 457: 
 458: 
 459: /*-----------------------------------------------------------------------------
 460:  *	readNumber	read an integer from the string pointed to by *ptr,
 461:  *			returning the integer in val, and updating *ptr for
 462:  *			the caller
 463:  *---------------------------------------------------------------------------*/
 464: readNumber(ptr,val)
 465: char **ptr;
 466: int *val;
 467: {
 468:     int sign = 1;
 469: 
 470:     *val = 0;
 471: 
 472:     if (**ptr == '-')
 473:     {
 474:         sign = -1;
 475:         ++*ptr;
 476:     }
 477:     while(isdigit(**ptr))
 478:     {
 479:         *val = *val * 10 + **ptr - '0';
 480:         ++*ptr;
 481:     }
 482:     *val = *val * sign;
 483: 
 484:     /* skip all trailing white space */
 485:     while(white(**ptr) || **ptr == '\n') ++*ptr;
 486: 
 487:     /* return next char -- if at end of string this is NULL */
 488:     return(**ptr);
 489: }
 490: 
 491: 
 492: /*-----------------------------------------------------------------------------
 493:  *	euclidDist	compute euclidean distance between the two cartesian
 494:  *			coordinates
 495:  *---------------------------------------------------------------------------*/
 496: float euclidDist(x, y, x1, y1)
 497: int x1,y1,x,y;
 498: {
 499:     double deltax, deltay;
 500: 
 501:     deltax = x - x1;
 502:     deltay = y - y1;
 503:     return(sqrt(deltax*deltax + deltay*deltay) + 0.5);
 504: }

Defined functions

euclidDist defined in line 496; used 3 times
octPlot defined in line 64; used 2 times
quadPlot defined in line 147; used 2 times
readNumber defined in line 464; used 4 times
Last modified: 1985-09-04
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 1774
Valid CSS Valid XHTML 1.0 Strict