void arc_extreme(double x0, double y0, double x1, double y1, double xc, double yc) /* start, end, center */ { /* assumes center isn't too far out */ double r, xmin, ymin, xmax, ymax; int j, k; x0 -= xc; y0 -= yc; /* move to center */ x1 -= xc; y1 -= yc; xmin = (x0<x1)?x0:x1; ymin = (y0<y1)?y0:y1; xmax = (x0>x1)?x0:x1; ymax = (y0>y1)?y0:y1; r = sqrt(x0*x0 + y0*y0); if (r > 0.0) { j = quadrant(x0,y0); k = quadrant(x1,y1); if (j == k && y1*x0 < x1*y0) { /* viewed as complex numbers, if Im(z1/z0)<0, arc is big */ if( xmin > -r) xmin = -r; if( ymin > -r) ymin = -r; if( xmax < r) xmax = r; if( ymax < r) ymax = r; } else { while (j != k) { switch (j) { case 1: if( ymax < r) ymax = r; break; /* north */ case 2: if( xmin > -r) xmin = -r; break; /* west */ case 3: if( ymin > -r) ymin = -r; break; /* south */ case 4: if( xmax < r) xmax = r; break; /* east */ } j = j%4 + 1; } } } xmin += xc; ymin += yc; xmax += xc; ymax += yc; extreme(xmin, ymin); extreme(xmax, ymax); }
//************************************************************************************* // //************************************************************************************* void IMainMenuScreen::Render() { mpContext->ClearBackground(); c32 valid_colour( mpContext->GetDefaultTextColour() ); c32 invalid_colour( 200, 200, 200 ); f32 min_scale( 0.60f ); f32 max_scale( 1.0f ); s32 SCREEN_LEFT = 20; s32 SCREEN_RIGHT = SCREEN_WIDTH - 20; mpContext->SetFontStyle( CUIContext::FS_HEADING ); s32 y( TEXT_AREA_TOP + mpContext->GetFontHeight() ); for( s32 i = -2; i <= 2; ++i ) { EMenuOption option( AsMenuOption( mCurrentOption + i ) ); c32 text_col( IsOptionValid( option ) ? valid_colour : invalid_colour ); const char * option_text( gMenuOptionNames[ option ] ); u32 text_width( mpContext->GetTextWidth( option_text ) ); f32 diff( f32( mCurrentOption + i ) - mCurrentDisplayOption ); f32 dist( Abs( diff ) ); s32 centre( ( SCREEN_WIDTH - text_width ) / 2 ); s32 extreme( diff < 0 ? SCREEN_LEFT : s32( SCREEN_RIGHT - (text_width * min_scale) ) ); // Interpolate between central and extreme position and centre f32 scale( max_scale + (min_scale - max_scale) * dist ); s32 x( s32( centre + (extreme - centre) * dist ) ); mpContext->DrawTextScale( x, y, scale, option_text, text_col ); } mpContext->SetFontStyle( CUIContext::FS_REGULAR ); mOptionComponents[ GetCurrentOption() ]->Render(); }
/** * Return whether the given point `p` is in the given polygon `poly`. * Uses above pointInPolygon-prefixed functions as well. * Source: http://www.geeksforgeeks.org/how-to-check-if-a-given-point-lies-inside-a-polygon/ * This appears to work a lot better than what we were using before: http://alienryderflex.com/polygon/ */ bool Rectangle::PointInPolygon(const Vector2 &p, const Vector2* poly, int vertices) { if(vertices < 3) { return false; } Vector2 extreme(10000.0f, p.Y); int count = 0; int i = 0; do { int next = (i + 1) % vertices; if(pointInPolygonDoIntersect(poly[i], poly[next], p, extreme)) { if(pointInPolygonOrientation(poly[i], p, poly[next]) == 0) { return pointInPolygonOnSegment(poly[i], p, poly[next]); } count++; } i = next; } while(i != 0); return count & 1; }
// Returns true if the Ponto p lies inside the Poligono bool isInside(vector<Ponto> Poligono, Ponto p){ if (Poligono.size() < 3) return false; Ponto extreme(INF, p.y); int count = 0, i = 0; do{ int next = (i+1)%Poligono.size(); if (interSegSeg(Poligono[i], Poligono[next], p, extreme)) { if (orientation(Poligono[i], p, Poligono[next]) == 0) return interPtSeg(p, Poligono[i], Poligono[next]); count++; } i = next; } while (i != 0); return count&1; // Same as (count%2 == 1) }
obj *linegen(int type) { static double prevdx = HT; static double prevdy = 0; static double prevw = HT10; static double prevh = HT5; int i, j, some, head, ddtype, invis, chop; double ddval, chop1, chop2, x0, y0, x1, y1; double sin(), cos(), atan2(), theta; double defx, defy; obj *p, *ppos; static int xtab[] = { 1, 0, -1, 0 }; /* R=0, U=1, L=2, D=3 */ static int ytab[] = { 0, 1, 0, -1 }; double dx[500], dy[500]; int ndxy; double nx, ny; Attr *ap; nx = curx; ny = cury; defx = getfval("linewid"); defy = getfval("lineht"); prevh = getfval("arrowht"); prevw = getfval("arrowwid"); dx[0] = dy[0] = ndxy = some = head = invis = 0; chop = chop1 = chop2 = 0; ddtype = ddval = 0; for (i = 0; i < nattr; i++) { ap = &attr[i]; switch (ap->a_type) { case TEXTATTR: savetext(ap->a_sub, ap->a_val.p); break; case HEAD: head += ap->a_val.i; break; case INVIS: invis = INVIS; break; case CHOP: if (chop++ == 0) chop1 = chop2 = ap->a_val.f; else chop2 = ap->a_val.f; break; case DOT: case DASH: ddtype = ap->a_type==DOT ? DOTBIT : DASHBIT; if (ap->a_sub == DEFAULT) ddval = getfval("dashwid"); else ddval = ap->a_val.f; break; case SAME: dx[ndxy] = prevdx; dy[ndxy] = prevdy; some++; break; case LEFT: dx[ndxy] -= (ap->a_sub==DEFAULT) ? defx : ap->a_val.f; some++; hvmode = L_DIR; break; case RIGHT: dx[ndxy] += (ap->a_sub==DEFAULT) ? defx : ap->a_val.f; some++; hvmode = R_DIR; break; case UP: dy[ndxy] += (ap->a_sub==DEFAULT) ? defy : ap->a_val.f; some++; hvmode = U_DIR; break; case DOWN: dy[ndxy] -= (ap->a_sub==DEFAULT) ? defy : ap->a_val.f; some++; hvmode = D_DIR; break; case HEIGHT: /* length of arrowhead */ prevh = ap->a_val.f; break; case WIDTH: /* width of arrowhead */ prevw = ap->a_val.f; break; case TO: if (some) { nx += dx[ndxy]; ny += dy[ndxy]; ndxy++; dx[ndxy] = dy[ndxy] = some = 0; } ppos = attr[i].a_val.o; dx[ndxy] = ppos->o_x - nx; dy[ndxy] = ppos->o_y - ny; some++; break; case BY: if (some) { nx += dx[ndxy]; ny += dy[ndxy]; ndxy++; dx[ndxy] = dy[ndxy] = some = 0; } ppos = ap->a_val.o; dx[ndxy] = ppos->o_x; dy[ndxy] = ppos->o_y; some++; break; case THEN: /* turn off any previous accumulation */ if (some) { nx += dx[ndxy]; ny += dy[ndxy]; ndxy++; dx[ndxy] = dy[ndxy] = some = 0; } break; case FROM: case AT: ppos = ap->a_val.o; nx = curx = ppos->o_x; ny = cury = ppos->o_y; break; } } if (some) { nx += dx[ndxy]; ny += dy[ndxy]; ndxy++; defx = dx[ndxy-1]; defy = dy[ndxy-1]; } else { defx *= xtab[hvmode]; defy *= ytab[hvmode]; dx[ndxy] = defx; dy[ndxy] = defy; ndxy++; nx += defx; ny += defy; } prevdx = defx; prevdy = defy; if (chop) { if (chop == 1 && chop1 == 0) /* just said "chop", so use default */ chop1 = chop2 = getfval("circlerad"); theta = atan2(dy[0], dx[0]); x0 = chop1 * cos(theta); y0 = chop1 * sin(theta); curx += x0; cury += y0; dx[0] -= x0; dy[0] -= y0; theta = atan2(dy[ndxy-1], dx[ndxy-1]); x1 = chop2 * cos(theta); y1 = chop2 * sin(theta); nx -= x1; ny -= y1; dx[ndxy-1] -= x1; dy[ndxy-1] -= y1; dprintf("chopping %g %g %g %g; cur=%g,%g end=%g,%g\n", x0, y0, x1, y1, curx, cury, nx, ny); } p = makenode(type, 5 + 2 * ndxy); curx = p->o_val[0] = nx; cury = p->o_val[1] = ny; if (head || type == ARROW) { p->o_nhead = getfval("arrowhead"); p->o_val[2] = prevw; p->o_val[3] = prevh; if (head == 0) head = HEAD2; /* default arrow head */ } p->o_attr = head | invis | ddtype; p->o_val[4] = ndxy; nx = p->o_x; ny = p->o_y; for (i = 0, j = 5; i < ndxy; i++, j += 2) { p->o_val[j] = dx[i]; p->o_val[j+1] = dy[i]; if (type == LINE || type == ARROW) extreme(nx += dx[i], ny += dy[i]); else if (type == SPLINE && i < ndxy-1) { /* to compute approx extreme of spline at p, * compute midway between p-1 and p+1, * then go 3/4 from there to p */ double ex, ey, xi, yi, xi1, yi1; xi = nx + dx[i]; yi = ny + dy[i]; /* p */ xi1 = xi + dx[i+1]; yi1 = yi + dy[i+1]; /* p+1 */ ex = (nx+xi1)/2; ey = (ny+yi1)/2; /* midway */ ex += 0.75*(xi-ex); ey += 0.75*(yi-ey); extreme(ex, ey); nx = xi; ny = yi; } } p->o_ddval = ddval; if (dbg) { printf("S or L from %g %g to %g %g with %d elements:\n", p->o_x, p->o_y, curx, cury, ndxy); for (i = 0, j = 5; i < ndxy; i++, j += 2) printf("%g %g\n", p->o_val[j], p->o_val[j+1]); } extreme(p->o_x, p->o_y); extreme(curx, cury); return(p); }
obj* blockgen(obj *p, obj *q) /* handles [...] */ { int i, invis, at, with; double ddval, h, w, xwith, ywith; double x0, y0, x1, y1, cx, cy; obj *ppos; Attr *ap; invis = at = 0; with = xwith = ywith = 0; ddval = 0; w = p->o_val[2] - p->o_val[0]; h = p->o_val[3] - p->o_val[1]; cx = (p->o_val[2] + p->o_val[0]) / 2; /* geom ctr of [] wrt local orogin */ cy = (p->o_val[3] + p->o_val[1]) / 2; dprintf("cx,cy=%g,%g\n", cx, cy); for (i = 0; i < nattr; i++) { ap = &attr[i]; switch (ap->a_type) { case HEIGHT: h = ap->a_val.f; break; case WIDTH: w = ap->a_val.f; break; case WITH: with = ap->a_val.i; /* corner */ break; case PLACE: /* actually with position ... */ ppos = ap->a_val.o; xwith = cx - ppos->o_x; ywith = cy - ppos->o_y; with = PLACE; break; case AT: case FROM: ppos = ap->a_val.o; curx = ppos->o_x; cury = ppos->o_y; at++; break; case INVIS: invis = INVIS; break; case TEXTATTR: savetext(ap->a_sub, ap->a_val.p); break; } } if (with) { switch (with) { case NORTH: ywith = -h / 2; break; case SOUTH: ywith = h / 2; break; case EAST: xwith = -w / 2; break; case WEST: xwith = w / 2; break; case NE: xwith = -w / 2; ywith = -h / 2; break; case SE: xwith = -w / 2; ywith = h / 2; break; case NW: xwith = w / 2; ywith = -h / 2; break; case SW: xwith = w / 2; ywith = h / 2; break; } curx += xwith; cury += ywith; } if (!at) { if (isright(hvmode)) curx += w / 2; else if (isleft(hvmode)) curx -= w / 2; else if (isup(hvmode)) cury += h / 2; else cury -= h / 2; } x0 = curx - w / 2; y0 = cury - h / 2; x1 = curx + w / 2; y1 = cury + h / 2; extreme(x0, y0); extreme(x1, y1); p->o_x = curx; p->o_y = cury; p->o_nt1 = ntext1; p->o_nt2 = ntext; ntext1 = ntext; p->o_val[0] = w; p->o_val[1] = h; p->o_val[2] = cx; p->o_val[3] = cy; p->o_val[5] = q->o_nobj - 1; /* last item in [...] */ p->o_ddval = ddval; p->o_attr = invis; dprintf("[] %g %g %g %g at %g %g, h=%g, w=%g\n", x0, y0, x1, y1, curx, cury, h, w); if (isright(hvmode)) curx = x1; else if (isleft(hvmode)) curx = x0; else if (isup(hvmode)) cury = y1; else cury = y0; for (i = 0; i <= 5; i++) q->o_val[i] = p->o_val[i]; stack[nstack+1].p_symtab = NULL; /* so won't be found again */ blockadj(p); /* fix up coords for enclosed blocks */ return(p); }
void mexFunction(int nlhs, mxArray * plhs[], int nrhs, const mxArray * prhs[]) { int buflen, status; char *input_buf; if (nrhs<1){ mexErrMsgTxt("Input 1 must be a row vector string"); } /* 1. input must be a string and row vector */ if (mxIsChar(prhs[0]) && (mxGetM(prhs[0]) == 1)) { /* get the length of the input string */ buflen = mxGetN(prhs[0]) + 1; /* allocate memory for input and output strings */ input_buf=mxCalloc(buflen, sizeof(char)); /* copy the string data from prhs[0] into a C string input_ buf. */ status = mxGetString(prhs[0], input_buf, buflen); if (strcmp(input_buf,"hull\0") == 0) { hull(nlhs, plhs, nrhs -1, prhs + 1); return; } if (strcmp(input_buf,"extreme\0") == 0) { extreme(nlhs, plhs, nrhs -1, prhs + 1); return; } if (strcmp(input_buf,"reduce_h\0") == 0) { reduce_h(nlhs, plhs, nrhs -1, prhs + 1); return; } if (strcmp(input_buf,"reduce_v\0") == 0) { reduce_v(nlhs, plhs, nrhs -1, prhs + 1); return; } if (strcmp(input_buf,"copy_v\0") == 0) { copy_v(nlhs, plhs, nrhs -1, prhs + 1); return; } if (strcmp(input_buf,"copy_h\0") == 0) { copy_h(nlhs, plhs, nrhs -1, prhs + 1); return; } if (strcmp(input_buf,"v_hull_extreme\0") == 0) { v_hull_extreme(nlhs, plhs, nrhs -1, prhs + 1); return; } if (strcmp(input_buf,"adj_extreme\0") == 0) { adj_extreme(nlhs, plhs, nrhs -1, prhs + 1); return; } if (strcmp(input_buf,"solve_lp\0") == 0) { solve_lp(nlhs, plhs, nrhs -1, prhs + 1); return; } if (strcmp(input_buf,"solve_lp_DS\0") == 0) { solve_lp_DS(nlhs, plhs, nrhs -1, prhs + 1); return; } if (strcmp(input_buf,"find_interior\0") == 0) { find_interior(nlhs, plhs, nrhs -1, prhs + 1); return; } if (strcmp(input_buf,"find_interior_DS\0") == 0) { find_interior_DS(nlhs, plhs, nrhs -1, prhs + 1); return; } if (strcmp(input_buf,"version\0") == 0) { printf("Version %s\n", CDDMEX_VERSION); return; } mexErrMsgTxt("Unknown function"); } else { mexErrMsgTxt("Input 1 must be a row vector string"); } }
obj *circgen(type) { static float rad[2] = { HT2, WID2 }; static float rad2[2] = { HT2, HT2 }; static float x0, y0, x1, y1, x2, y2; int i, at, t, invis, ddtype, with; float xwith, ywith; float r, r2, ddval; obj *p, *ppos; Attr *ap; at = invis = ddtype = 0; with = xwith = ywith = 0; t = (type == CIRCLE) ? 0 : 1; if (type == CIRCLE) r = r2 = getfval("circlerad"); else if (type == ELLIPSE) { r = getfval("ellipsewid") / 2; r2 = getfval("ellipseht") / 2; } for (i = 0; i < nattr; i++) { ap = &attr[i]; switch (ap->a_type) { case TEXTATTR: savetext(ap->a_sub, ap->a_val.p); break; case RADIUS: r = ap->a_val.f; break; case DIAMETER: case WIDTH: r = ap->a_val.f / 2; break; case HEIGHT: r2 = ap->a_val.f / 2; break; case SAME: r = rad[t]; r2 = rad2[t]; break; case WITH: with = ap->a_val.i; break; case AT: ppos = ap->a_val.o; curx = ppos->o_x; cury = ppos->o_y; at++; break; case INVIS: invis = INVIS; break; case DOT: case DASH: ddtype = ap->a_type==DOT ? DOTBIT : DASHBIT; if (ap->a_sub == DEFAULT) ddval = getfval("dashwid"); else ddval = ap->a_val.f; break; } } if (type == CIRCLE) r2 = r; /* probably superfluous */ if (with) { switch (with) { case NORTH: ywith = -r2; break; case SOUTH: ywith = r2; break; case EAST: xwith = -r; break; case WEST: xwith = r; break; case NE: xwith = -r * 0.707; ywith = -r2 * 0.707; break; case SE: xwith = -r * 0.707; ywith = r2 * 0.707; break; case NW: xwith = r * 0.707; ywith = -r2 * 0.707; break; case SW: xwith = r * 0.707; ywith = r2 * 0.707; break; } curx += xwith; cury += ywith; } if (!at) { if (isright(hvmode)) curx += r; else if (isleft(hvmode)) curx -= r; else if (isup(hvmode)) cury += r2; else cury -= r2; } p = makenode(type, 2); p->o_val[0] = rad[t] = r; p->o_val[1] = rad2[t] = r2; if (r <= 0 || r2 <= 0) { yyerror("%s has invalid radius %g\n", (type==CIRCLE) ? "circle" : "ellipse", r<r2 ? r : r2); } p->o_attr = invis | ddtype; extreme(curx+r, cury+r2); extreme(curx-r, cury-r2); if (type == CIRCLE) dprintf("C %g %g %g\n", curx, cury, r); if (type == ELLIPSE) dprintf("E %g %g %g %g\n", curx, cury, r, r2); if (isright(hvmode)) curx += r; else if (isleft(hvmode)) curx -= r; else if (isup(hvmode)) cury += r2; else cury -= r2; return(p); }
obj *textgen(void) { int i, sub, nstr, at, with, hset, invis; double xwith, ywith, h, w, x0, y0, x1, y1; obj *p, *ppos; Attr *ap; at = with = nstr = hset = invis = 0; h = getfval("textht"); w = getfval("textwid"); for (i = 0; i < nattr; i++) { ap = &attr[i]; switch (ap->a_type) { case HEIGHT: h = ap->a_val.f; hset++; break; case WIDTH: w = ap->a_val.f; break; case WITH: with = ap->a_val.i; break; case INVIS: invis = INVIS; break; case AT: ppos = ap->a_val.o; curx = ppos->o_x; cury = ppos->o_y; at++; break; case TEXTATTR: sub = ap->a_sub; if (ap->a_val.p == NULL) /* an isolated modifier */ text[ntext-1].t_type = sub; else { savetext(sub, ap->a_val.p); nstr++; } break; } } if (hset == 0) /* no explicit ht cmd */ h *= nstr; if (with) { xwith = ywith = 0.0; switch (with) { case NORTH: ywith = -h / 2; break; case SOUTH: ywith = h / 2; break; case EAST: xwith = -w / 2; break; case WEST: xwith = w / 2; break; case NE: xwith = -w / 2; ywith = -h / 2; break; case SE: xwith = -w / 2; ywith = h / 2; break; case NW: xwith = w / 2; ywith = -h / 2; break; case SW: xwith = w / 2; ywith = h / 2; break; } curx += xwith; cury += ywith; } if (!at) { if (isright(hvmode)) curx += w / 2; else if (isleft(hvmode)) curx -= w / 2; else if (isup(hvmode)) cury += h / 2; else cury -= h / 2; } x0 = curx - w / 2; y0 = cury - h / 2; x1 = curx + w / 2; y1 = cury + h / 2; extreme(x0, y0); extreme(x1, y1); dprintf("Text h %g w %g at %g,%g\n", h, w, curx, cury); p = makenode(TEXT, 2); p->o_attr = invis; p->o_val[0] = w; p->o_val[1] = h; if (isright(hvmode)) curx = x1; else if (isleft(hvmode)) curx = x0; else if (isup(hvmode)) cury = y1; else cury = y0; return(p); }
obj* movegen(void) { static double prevdx, prevdy; int i, some; double defx, defy, dx, dy; obj *p; obj *ppos; static int xtab[] = { 1, 0, -1, 0 }; /* R=0, U=1, L=2, D=3 */ static int ytab[] = { 0, 1, 0, -1 }; Attr *ap; defx = getfval("movewid"); defy = getfval("moveht"); dx = dy = some = 0; for (i = 0; i < nattr; i++) { ap = &attr[i]; switch (ap->a_type) { case TEXTATTR: savetext(ap->a_sub, ap->a_val.p); break; case SAME: dx = prevdx; dy = prevdy; some++; break; case LEFT: dx -= (ap->a_sub==DEFAULT) ? defx : ap->a_val.f; some++; hvmode = L_DIR; break; case RIGHT: dx += (ap->a_sub==DEFAULT) ? defx : ap->a_val.f; some++; hvmode = R_DIR; break; case UP: dy += (ap->a_sub==DEFAULT) ? defy : ap->a_val.f; some++; hvmode = U_DIR; break; case DOWN: dy -= (ap->a_sub==DEFAULT) ? defy : ap->a_val.f; some++; hvmode = D_DIR; break; case TO: ppos = ap->a_val.o; dx = ppos->o_x - curx; dy = ppos->o_y - cury; some++; break; case BY: ppos = ap->a_val.o; dx = ppos->o_x; dy = ppos->o_y; some++; break; case FROM: case AT: ppos = ap->a_val.o; curx = ppos->o_x; cury = ppos->o_y; break; } } if (some) { defx = dx; defy = dy; } else { defx *= xtab[hvmode]; defy *= ytab[hvmode]; } prevdx = defx; prevdy = defy; extreme(curx, cury); curx += defx; cury += defy; extreme(curx, cury); p = makenode(MOVE, 0); dprintf("M %g %g\n", curx, cury); return(p); }
obj *boxgen(void) { static double prevh = HT; static double prevw = WID; /* golden mean, sort of */ int i, at, battr, with; double ddval, fillval, xwith, ywith; double h, w, x0, y0, x1, y1; obj *p, *ppos; Attr *ap; h = getfval("boxht"); w = getfval("boxwid"); at = battr = with = 0; ddval = fillval = xwith = ywith = 0; for (i = 0; i < nattr; i++) { ap = &attr[i]; switch (ap->a_type) { case HEIGHT: h = ap->a_val.f; break; case WIDTH: w = ap->a_val.f; break; case SAME: h = prevh; w = prevw; break; case WITH: with = ap->a_val.i; /* corner */ break; case AT: ppos = ap->a_val.o; curx = ppos->o_x; cury = ppos->o_y; at++; break; case INVIS: battr |= INVIS; break; case NOEDGE: battr |= NOEDGEBIT; break; case DOT: case DASH: battr |= ap->a_type==DOT ? DOTBIT : DASHBIT; if (ap->a_sub == DEFAULT) ddval = getfval("dashwid"); else ddval = ap->a_val.f; break; case FILL: battr |= FILLBIT; if (ap->a_sub == DEFAULT) fillval = getfval("fillval"); else fillval = ap->a_val.f; break; case TEXTATTR: savetext(ap->a_sub, ap->a_val.p); break; } } if (with) { switch (with) { case NORTH: ywith = -h / 2; break; case SOUTH: ywith = h / 2; break; case EAST: xwith = -w / 2; break; case WEST: xwith = w / 2; break; case NE: xwith = -w / 2; ywith = -h / 2; break; case SE: xwith = -w / 2; ywith = h / 2; break; case NW: xwith = w / 2; ywith = -h / 2; break; case SW: xwith = w / 2; ywith = h / 2; break; } curx += xwith; cury += ywith; } if (!at) { if (isright(hvmode)) curx += w / 2; else if (isleft(hvmode)) curx -= w / 2; else if (isup(hvmode)) cury += h / 2; else cury -= h / 2; } x0 = curx - w / 2; y0 = cury - h / 2; x1 = curx + w / 2; y1 = cury + h / 2; extreme(x0, y0); extreme(x1, y1); p = makenode(BOX, 2); p->o_val[0] = w; p->o_val[1] = h; p->o_attr = battr; p->o_ddval = ddval; p->o_fillval = fillval; dprintf("B %g %g %g %g at %g %g, h=%g, w=%g\n", x0, y0, x1, y1, curx, cury, h, w); if (isright(hvmode)) curx = x1; else if (isleft(hvmode)) curx = x0; else if (isup(hvmode)) cury = y1; else cury = y0; prevh = h; prevw = w; return(p); }