/* XXL: The eXtensible and fleXible Library for data processing Copyright (C) 2000-2011 Prof. Dr. Bernhard Seeger Head of the Database Research Group Department of Mathematics and Computer Science University of Marburg Germany This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; If not, see <http://www.gnu.org/licenses/>. http://code.google.com/p/xxl/ */ package xxl.core.indexStructures; import java.awt.Color; import java.awt.Frame; import java.awt.Graphics; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import java.awt.image.BufferedImage; import java.util.Iterator; import xxl.core.cursors.SecureDecoratorCursor; import xxl.core.spatial.KPE; import xxl.core.spatial.points.DoublePoint; import xxl.core.spatial.points.Point; import xxl.core.spatial.rectangles.DoublePointRectangle; import xxl.core.spatial.rectangles.Rectangle; /** * This cursor draws the objects of the used iterator. */ public class ShowCursor<T> extends SecureDecoratorCursor<T> { /** * The frame showing the Ractangles. */ protected Frame f = null; /** * The <tt>Graphics</tt> Object of {link #f}. */ Graphics gr_frame = null; /** * An image used for drawing. */ protected BufferedImage image; /** * The <tt>Graphics</tt> Object of {link #image}. */ Graphics gr_im; /** * The width of {@link #f}. */ int sizeX; /** * The height of {@link #f}. */ int sizeY; /** * The delay between drawing the rectangles. */ int delay; /** * A counter for the rectangles. */ int rCount; /** * The universe all rectangle lie within. */ Rectangle universe; /** * Translation in x direction. */ double xt = 0.0; /** * Translation in y direction. */ double yt = 0.0; /** * Dilation in x direction. */ double wt = 1.0; /** * Dilation in y direction. */ double ht = 1.0; public static int DOUBLE_POINT_MODE = 0; public static int KPE_DOUBLE_POINT_RECTANGLE_MODE = 1; protected int mode; /** * Creates a new <tt>ShowKPERectanglesCursor</tt>. * * @param it an iterator providing the rectangles to display * @param universe a rectangle containing all rectangles in <tt>it</tt> * @param delay the delay between drawing the rectangles */ public ShowCursor(int mode, Iterator<T> it, Rectangle universe, int delay) { super(it); this.mode = mode; this.universe = universe; this.delay = delay; rCount=0; } /** * Creates the frame for displaying. * * @param sizeX width of the frame * @param sizeY height of the frame * @return the creates frame */ public Frame createFrame(int sizeX, int sizeY) { f = new Frame() { public void paint(Graphics gr) { super.paint(gr); if (gr_frame!=null) gr_frame.drawImage(image,0,0,f); } }; f.setSize(sizeX, sizeY); this.sizeX = f.getWidth(); this.sizeY = f.getHeight(); f.setVisible(true); f.addWindowListener( new WindowAdapter() { public void windowClosing(WindowEvent e) { f.dispose(); } } ); image = new BufferedImage(sizeX,sizeY,BufferedImage.TYPE_INT_RGB); gr_im = image.getGraphics(); gr_im.setColor(Color.white); gr_im.fillRect(0, 0, sizeX, sizeY); gr_im.setColor(Color.black); gr_frame = f.getGraphics(); return f; } /** Returns the next element in the iteration. * * @return the next element in the iteration. */ public T next() { T k = super.next(); if (mode==DOUBLE_POINT_MODE) draw((DoublePoint)k, Color.black, false); else if (mode==KPE_DOUBLE_POINT_RECTANGLE_MODE) draw((DoublePointRectangle)((KPE)k).getData(), Color.black); try { Thread.sleep(delay); } catch (InterruptedException e) {}; return k; } //TODO: Do the scaling in universe private int xRealToDraw(double x) { return ((int) (x*sizeX-1)); } //TODO: Do the scaling in universe private int yRealToDraw(double y) { return (sizeY-1-(int) (y*sizeY-1)); } public void drawVoronoiLine(DoublePoint a, DoublePoint b) { double ax = (a.getValue(0)-universe.getCorner(false).getValue(0))/universe.deltas()[0]; double ay = (a.getValue(1)-universe.getCorner(false).getValue(1))/universe.deltas()[1]; double bx = (b.getValue(0)-universe.getCorner(false).getValue(0))/universe.deltas()[0]; double by = (b.getValue(1)-universe.getCorner(false).getValue(1))/universe.deltas()[1]; //compute slope of AB //TODO: catch possible ArithmeticException double slopeAB = (by-ay)/(bx-ax); double slope_pb_AB = (-1)/slopeAB; double delta_pb_AB_x = 1; double slope_pb_AB_y = slope_pb_AB; double centerABx = Math.min(ax, bx)+(Math.abs(ax-bx)/2); double centerABy = Math.min(ay, by)+(Math.abs(ay-by)/2); //TODO: calculate intersection, draw only visible lines gr_im.drawLine(xRealToDraw(centerABx - 1), yRealToDraw(centerABy - slope_pb_AB_y), xRealToDraw(centerABx + 1), yRealToDraw(centerABy + slope_pb_AB_y) ); } /** * Draws a rectangle * @param rect The rectangle to draw */ public void drawRect(DoublePointRectangle rect) { DoublePoint[] corners = (DoublePoint[]) rect.getCorners(); DoublePoint[] scaledCornes = new DoublePoint[corners.length]; for (int i=0;i<scaledCornes.length;i++) { scaledCornes[i] = new DoublePoint(new double[]{ (corners[i].getValue(0)-universe.getCorner(false).getValue(0))/universe.deltas()[0], (corners[i].getValue(1)-universe.getCorner(false).getValue(1))/universe.deltas()[1] }); } DoublePoint temp = scaledCornes[2]; scaledCornes[2] = scaledCornes[3]; scaledCornes[3] = temp; gr_im.setColor(Color.GRAY); for (int i=0;i<scaledCornes.length;i++) { gr_im.drawLine( xRealToDraw(scaledCornes[i].getValue(0)), yRealToDraw(scaledCornes[i].getValue(1)), xRealToDraw(scaledCornes[(i+1)%4].getValue(0)), yRealToDraw(scaledCornes[(i+1)%4].getValue(1)) ); } } /** * Draws the given point in the given color. * * @param p the point to draw * @param color the color to use */ public void mark(DoublePoint p, Color color) { draw(p, color, true); } /** * Draws the given point and a horizontal and vertical line through it. * * @param p the point to draw */ public void drawQueryPoint(DoublePoint p) { double x = (p.getValue(0)-universe.getCorner(false).getValue(0))/universe.deltas()[0]; double y = (p.getValue(1)-universe.getCorner(false).getValue(1))/universe.deltas()[1]; gr_im.setColor(Color.red); gr_im.drawLine(0, (sizeY-1-(int) (y*sizeY-1)), sizeX-1, (sizeY-1-(int) (y*sizeY-1))); gr_im.drawLine(((int) (x*sizeX-1)), 0, ((int) (x*sizeX-1)), sizeY-1); } /** * Draws the given point in the given color. * * @param p the point to draw * @param color the color to use * @param mark if this flag is set, the point in drawn bigger */ protected void draw(DoublePoint p, Color color, boolean mark) { gr_im.setColor(color); double x = (p.getValue(0)-universe.getCorner(false).getValue(0))/universe.deltas()[0]; double y = (p.getValue(1)-universe.getCorner(false).getValue(1))/universe.deltas()[1]; x = (x-xt) / wt; y = (y-yt) / ht; if ((x>=0) && (x<1.0) && (y>=0) && (y<1.0)) { if (mark) gr_im.fillRect( (int) (x*sizeX-1) - 1, sizeY-1 - (int)(y*sizeY-1) - 1, 3, 3 ); else gr_im.drawRect( (int) (x*sizeX-1), sizeY-1 - (int)(y*sizeY-1), 0, 0); if (mark || (rCount++)>100*(delay+1)) { gr_frame.drawImage(image, 0, 0, f); rCount=0; } } } /** * Draws the given rectangle in the given color. * * @param r the rectangle to draw * @param color the color to use */ protected void draw(DoublePointRectangle r, Color color) { gr_im.setColor(color); Point left = r.getCorner(false); double deltas[] = r.deltas(); double x = (left.getValue(0)-universe.getCorner(false).getValue(0))/universe.deltas()[0]; double y = (left.getValue(1)-universe.getCorner(false).getValue(1))/universe.deltas()[1]; double w = deltas[0]/universe.deltas()[0]; double h = deltas[1]/universe.deltas()[1]; x = (x-xt) / wt; y = (y-yt) / ht; w = w/wt; h = h/ht; if ((x>=0) && (x<1.0) && (y>=0) && (y<1.0)) { gr_im.drawRect( (int) (x*sizeX), sizeY-1 - (int)(y*sizeY), (int) (w*sizeX), (int) (h*sizeY) ); if ((rCount++)>100*(delay+1)) { gr_frame.drawImage(image,0,0,f); rCount=0; } } } /* (non-Javadoc) * @see xxl.core.cursors.SecureDecoratorCursor#close() */ @Override public void close() { super.close(); flush(); } /** * Flushes the image. */ public void flush() { paint(f.getGraphics()); } /** * Paints the image to the frame. * * @param gr a Graphics object for painting to the frame */ public void paint(Graphics gr) { gr.drawImage(image, 0, 0, f); } /** * Return the frame. * * @return {@link #f} */ public Frame getFrame() { return f; } }