/* * Paul Garrett, garrett@math.umn.edu * 29 June 1999 revision * * Invoke this to draw Axes and Grid */ //package lib; import java.awt.*; import java.util.*; public class AxesAndGrid { // extends Printable { //__EDIT__ int height; // "width" is implicit: from Printable double heightD, widthD; double xLeft, xRight; double yBottom, yTop; int leftInset = 2, rightInset = 2, bottomInset = 2, topInset = 2; // defaults double xinc = .1, yinc = .1; // defaults for grid Color bg_color = new Color(0xbaaaaa); Color axes_color = new Color(0x201020); Color grid_color = new Color(0x907090); Color secondary_grid_color = new Color(0xa0a0a0); boolean queryShimek = false; // initial value int shx = -1000; int shy = -1000; // initial values are out of range Point nw; // location in some larger panel: NW corner int ascent; int width; int xoffset = 0; int yoffset = 0; /**********************************************************************/ public AxesAndGrid (int nwx, int nwy, int width, int height, double xLeft, double xRight) { this.ascent = height; nw = new Point(nwx, nwy); this.width = width; widthD = (double) width; this.height = height; heightD = (double) height; this.xLeft = Math.min(xLeft, -0.2); // always include axes!? this.xRight = Math.max(xRight, 0.2); setDefaultRange(); } // no baseline; default values of nw corner: (0,0) public AxesAndGrid(int width, int height, double xLeft, double xRight) { this(0, 0, width, height, xLeft, xRight); // NW corner is at (0,0), baseline = height } void setDefaultRange() { // pixels per unit: double scale = ((double) (width - topInset - bottomInset))/(xRight - xLeft); // in absolute units: double yRange = ((double) (height - topInset - bottomInset)) / scale; // default: yBottom = - yRange/3D; yTop = 2D*yRange/3D; } public final void setHorizontalRange(double left, double right) { xLeft = left; xRight = right; } public final void setVerticalRange(double bottom, double top) { yTop = top; yBottom = bottom; } public final void setRange(double left, double right, double bottom, double top) { xLeft = left; xRight = right; yTop = top; yBottom = bottom; } /**************************************************/ final synchronized double affineMap(double leftSource, double rightSource, double leftTarget, double rightTarget, double input) { return (leftTarget + ((input-leftSource)*(rightTarget-leftTarget) / (rightSource-leftSource))); } public final synchronized int xVirtualToScreen(double x) { return xoffset + (int) Math.round(affineMap(xLeft, xRight, (double) (nw.x+leftInset), (double) (nw.x+widthD-rightInset), x)); } public final synchronized double xScreenToVirtual(int x) { return affineMap((double) (nw.x+leftInset), (double) (nw.x+widthD - rightInset), xLeft, xRight, (double) x-xoffset); } public final synchronized int yVirtualToScreen(double y) { return yoffset+(int) Math.round(affineMap(yBottom, yTop, (double) (nw.y+heightD-bottomInset), (double) (nw.y+topInset), y)); } public final synchronized double yScreenToVirtual(int y) { return affineMap((double) (nw.y+heightD - bottomInset), (double) (nw.y+topInset), yBottom, yTop, (double) y-yoffset); } /**********************************************/ public void subPrint(Graphics g, int nwx, int nwy) { nw = new Point(nwx, nwy); draw(g); } /**********************************************************************/ public final void drawLine(Graphics g, double x1, double y1, double x2, double y2) { g.drawLine( xVirtualToScreen( x1 ), yVirtualToScreen( y1 ), xVirtualToScreen( x2 ), yVirtualToScreen( y2 )); } public final void drawRect(Graphics g, double nwx, double nwy, double width, double height) { g.drawRect( xVirtualToScreen( nwx ), yVirtualToScreen( nwy ), xVirtualToScreen( nwx + width ) - xVirtualToScreen( nwx ), xVirtualToScreen( nwy + height ) - xVirtualToScreen( nwy )); } public final void fillRect(Graphics g, double nwx, double nwy, double width, double height) { g.fillRect( xVirtualToScreen( nwx ), yVirtualToScreen( nwy ), xVirtualToScreen( nwx + width ) - xVirtualToScreen( nwx ), xVirtualToScreen( nwy + height ) - xVirtualToScreen( nwy )); } /**********************************************************************/ public synchronized void draw(Graphics g) { g.setColor(bg_color); g.fillRect(nw.x, nw.y, width, height); int iL = xVirtualToScreen(xLeft); int iR = xVirtualToScreen(xRight); int iB = yVirtualToScreen(yBottom); // watch out: y "upside down" int iT = yVirtualToScreen(yTop); // finest grid lines g.setColor(secondary_grid_color); for (int i=0; xVirtualToScreen(i * xinc) > iL; i--) { g.drawLine(xVirtualToScreen(i * xinc), nw.y+topInset, xVirtualToScreen(i * xinc), nw.y+height - bottomInset); } for (int i=1; xVirtualToScreen(i * xinc) < iR; i++) { g.drawLine(xVirtualToScreen(i * xinc), nw.y+topInset, xVirtualToScreen(i * xinc), nw.y+height - bottomInset); } for (int i=0; yVirtualToScreen(i * yinc) < iB; i--) { g.drawLine(nw.x+leftInset, yVirtualToScreen(i * yinc), nw.x+width-rightInset, yVirtualToScreen(i * yinc)); } for (int i=1; yVirtualToScreen(i * yinc) > iT; i++) { g.drawLine(nw.x+leftInset, yVirtualToScreen(i * yinc), nw.x+width-rightInset, yVirtualToScreen(i * yinc)); } // now draw gridlines at integers..... g.setColor(grid_color); for (int i=0; xVirtualToScreen(i) > iL; i--) { g.drawLine(xVirtualToScreen(i), nw.y+topInset, xVirtualToScreen(i), nw.y+height - bottomInset); } for (int i=1; xVirtualToScreen(i) < iR; i++) { g.drawLine(xVirtualToScreen(i), nw.y+topInset, xVirtualToScreen(i), nw.y+height - bottomInset); } for (int i=0; yVirtualToScreen(i) < iB; i--) { g.drawLine(nw.x+leftInset, yVirtualToScreen(i), nw.x+width-rightInset, yVirtualToScreen(i)); } for (int i=1; yVirtualToScreen(i) > iT; i++) { g.drawLine(nw.x+leftInset, yVirtualToScreen(i), nw.x+width-rightInset, yVirtualToScreen(i)); } // end of drawing of gridlines // make axes g.setColor(axes_color); g.fillRect( xVirtualToScreen(0.0)-1, nw.y+topInset, 2 , height - bottomInset - topInset); // y-axis g.fillRect( nw.x+leftInset, yVirtualToScreen(0.0), width - rightInset - leftInset, 2 ); // x-axis // arrow on y-axis int[] xs = {xVirtualToScreen(0.0), xVirtualToScreen(0.0) - 5 - 1, xVirtualToScreen(0.0), xVirtualToScreen(0.0) + 5 + 1}; int[] ys = { nw.y+topInset-2, nw.y+topInset+11, nw.y+topInset+7, nw.y+topInset+11 }; g.fillPolygon(new Polygon(xs, ys, 4)); // arrow on x-axis int[] xs2 = {nw.x+width - rightInset + 2, nw.x+width - rightInset - 10, nw.x+width - rightInset - 6, nw.x+width - rightInset - 10}; int[] ys2 = {yVirtualToScreen(0.0), yVirtualToScreen(0.0) - 6, yVirtualToScreen(0.0), yVirtualToScreen(0.0) + 6}; g.fillPolygon(new Polygon(xs2, ys2, 4)); } // end of draw() // // public void labelPoint(Graphics g) { // if (queryShimek == false) { // return; // don't draw anything // } // double factor = 100; // should divide 100... // double xcoord = Math.round(xScreenToVirtual(shx) * factor) / factor; // double ycoord = Math.round(yScreenToVirtual(shy) * factor) / factor; // // int hoffset = 10; // int voffset = -8; // measured _up_, so in negative screen direction // int crosshair = 8; // half of size of crosshair // // // draw cross-hairs // g.setColor(Color.red); // g.drawLine(shx - crosshair, shy, shx + crosshair, shy); // g.drawLine(shx , shy - crosshair, shx, shy + crosshair); // g.setColor(Color.yellow); // g.fillOval(shx-2, shy-2, 4, 4); // // make a nice background area on which to write coordinates: // g.setColor(new Color(0xbbaabb)); // String out = "(" + xcoord + ", " + ycoord + ")"; // // Font theFont = g.getFont(); // int wd = 6 + 20; //g.getFontMetrics(theFont).stringWidth(out); // int ht = 4 + 15; //g.getFontMetrics(theFont).getHeight(); // if (shx + 2 + hoffset + wd > nw.x + width - rightInset) { // hoffset = - wd - hoffset - 2; // move to the left, instead of right // } // if (shy - ht + voffset < nw.y) { // voffset = - voffset + ht; // move down instead of up // } // g.fillRect(shx + 2 + hoffset, shy - ht + voffset, wd, ht); // // finally write the coordinates of the point // g.setColor(Color.black); // g.drawString(out, shx + 6 + hoffset, shy - 6 + voffset); // } // // public void showPoint(int x, int y) { // queryShimek = !queryShimek; // shx = x; // shy = y; // } // // public void setLocation(Point nw) { // this.nw = new Point(nw); // } public void setBackgroundColor(Color c) { this.bg_color = c; } public void setAxesColor(Color c) { this.axes_color = c; } public void setGridColor(Color c) { this.grid_color = c; } public void setSecondaryGridColor(Color c) { this.secondary_grid_color = c; } public void setIncrements(double inc) { this.xinc = inc; this.yinc = inc; } public void setInsets(int lft, int rt, int bot, int top) { leftInset = lft; rightInset = rt; bottomInset = bot; topInset = top; } } // end of class /**************************************************/