I believe I send an answer to this already (I am not sure, due to our mailing system in the last few weeks is a bit unstable), but it might be interesting to others too.
First I recommend to use clipping whenever possible. I have an application (running on a 700 MHz linux machine using jdk1.3.1) that paints for one type of input data round 500.000 lines. The drawing time is around some seconds for a full screen repaint in zoomed fit mode. If the user zooms in, the amount of lines that have to be drawn are dramatically reduced. Now you could say: okay the java engine takes over and suppresses the lines that should not be drawn internally, but I found out that you can do much more there manually, just by checking the overlapping on your own before putting them in the graphics pipeline. My application draws much faster now then by using the clipping from the graphics engine - and the more I zoom in the faster it repaints (less objects to draw). I even can easily move around using the scrollbars and the screen is repainting immediately (no timeout is seen). According the problem you describing - do you really draw 110.000 lines on a screen? I believe this application has a huge usability problem then. Let me count: a typical screen for windows users is at around 1024x768 - which makes around 760.000 pixels. There you want to draw 110.000 lines - so any line can consume around 7 pixels (if they don't overlap each other) - and in that case you would see a black screen. I believe that is not a usefull way to represent data - even if you draw around 10.000 lines - it is usually becoming a usability problem (even if drawn in different colors). I would rather think in eliminating some of the objects to draw only the ones the user wants to see really (most important ones). If it is really required to draw 110.000 lines on a zoomed fit screen - then I would try to use some sort of overview window (that can be pre-computed and stored) additionally to your main drawing window (that is in zoomed in view). For detecting which elements has to be drawn in zoomed in view - there are multiple ways: a) walking over the list, checking boundaries and elimnating the lines that should not be drawn (slow, but working and easy to implement and doesn't consume additional memory) b) use a special four quadrant tree system to detect which line crosses these quadrants - and then first in which of them you are presently in ( O(long(n) operation I think) and then you get with O(1) the lines that has to be drawn - this is much faster, but consumes huge amount of memory. I think this is called quad-trees. method a) still produced good results - even for line-# of around 150.000...500.000 (I use this one) Btw. if memory is not a problem (and I speak of some hundred MB) and the data you want to draw are not changing while drawing/zooming/translating - you can speed up the drawing by using some 'dirty' tricks. Pre-compute some images in different zooming levels (perhaps even as some mosaics parts) and different locations and then use the following method for drawing depending on the zoom level: a) zoom fit - draw the pre-computed image directly on screen b) for zooming out larger then zoomed fit - use the zoomed fit image and scale it out and draw it. b) for small zoomed in level - use the pre-computed image tiles: +-----+-----+-----+-----+ | a | b | c | d | | | | | | +-----+-----+-----+-----+ | e | f | g | h | | | | | | +-----+-----+-----+-----+ | i | k | l | m | | | | | | +-----+-----+-----+-----+ | n | o | p | q | | | | | | +-----+-----+-----+-----+ I.e. lets assume this is pre-computed for zoom_in=2 and you need something for zoom_in=3 - then compute which tiles have to be drawn (and scaled) -- for this example lets say fgkl - then set the scaling value, set the correct translation for the tiles and draw the images (don't use a huge image for the zoom_ed in view, because then you would have to scale the full image all the time) d) for huge zoom in levels, use clipping (quad-tree?) and drawing the lines. if you combine all these four methods - you will get a blazingly fast applications. And noone will ever recognize that this is written in pure java. Hope this helps a bit. Karsten PS: you can try the opengl ports for java - I haven't used them, but I heared that they directly map the calls to the opengl engine, so you should get the benefit from the opengl graphics card and engine). PPS: you could try to use some native libraries to speed up drawing by drawing into a background buffer and then copy this background buffer over to the screen. You would loose the platform independency of java, but there is a workaround: if lib is available for you platform, use this one - should be available for your main target platform at least, and if lib is not available, use the std-java drawing functions as before - then it is slower, but still working) > Hi, > > I asked the question below on Oct 26 (thanks for the answers). In summery I am > drawing a large number of unconnected lines on a graph and zooming in on it. I > have since improved the performance, but it is still some 300 times slower than > equivalent code written in C using Open GL (see the times below). > > I was wondering if anyone can suggest ways of speeding up the drawing. I > include some relevant code and some times I have got. For the full code please > see my web page http://www.hgmp.mrc.ac.uk/~hmorgan2/my_files.html > > I am running it on a Sun Ultra 10 under solaris. > > Times (per screen redraw, in milliseconds) > > 10,000 lines > Java, not using GeneralPath ~185ms > Java, using GeneralPath ~300ms > C, inaccurate measure ~5ms > > 110,000 lines > Java, not using General Path ~1500ms > C, more accurate measure ~50ms > > Breakdown of times for Java, not using GeneralPath:- > clearRect - 30ms > prepareScale - ~55ms > drawLines - ~90ms > > public void update(Graphics oldGraphics) > { > g = (Graphics2D)oldGraphics; > g.drawImage(offImage, at, null); > } > > final void redrawImage() > { > offScreenGraphics.clearRect(0, 0, 1024, 1024); > prepareScale(); > drawLines(offScreenGraphics); > } > final void drawLines(Graphics2D g) > { > if(useGP) > { > g.setColor(Color.blue); > g.draw( polyLinePath ); > } else > { > g.setColor(Color.blue); > for(i = 0; i<Array.getLength(xNewValues1); ++i) > { > g.drawLine(xNewValues1[i], (size - yNewValues1[i]), > xNewValues2[i], (size - yNewValues2[i])); > } > } > } > > final void prepareScale() > { > at.setToTranslation(xPos, yPos); > at.scale((xfactor / imageXFactor), (yfactor / imageYFactor)); > at.translate(-xPos, -yPos); > } > > I have purposefully not used clipping because the worst case is most important, > ie. when the screen is zoomed out and all the lines are in view. Also the > sorting algorithm that would be needed would be for the preprocessing would be > built into the program that outputs the lines. > > Previous message:---------------------------------------------------- > > >>> > >>>Hi, > >>> > >>>I am drawing scientific graphs consisting of a large number (over 1000) of > >>>unconnected lines. The user can zoom in using a JSlider. It takes around 50 > >>>milliseconds to perform a zoom, and this flickers when the slider is dragged. > I > >>>tried double buffering and this increased the time it took to draw ten fold. > >>> > >>>Should I be able to get better performance with java 2D. Does anyone have > any > >>>suggestions about how to improve my code. Any help would be greatly > >>>appreciated. > >>> > >>> > >>>I include my code for doing the drawing. > >>> > >>>void drawGraph(Graphics g) > >>> { > >>> g2d = (Graphics2D)g; > >>> int i; > >>> at = new AffineTransform(); > >>> g2d.translate(xPos, yPos); > >>> at.setToScale(factor, factor); > >>> g2d.transform(at); > >>> g2d.translate(-xPos, -yPos); > >>> > >>>// Draw Grid > >>> g2d.setColor(Color.red); > >>> for(i=0; i<20; ++i) > >>> { > >>> j = i*size; > >>> g2d.drawLine(i*size,0,i*size,(19 * size)); > >>> } > >>> > >>> for(i=0; i<20; ++i) > >>> { > >>> j = i*size; > >>> g2d.drawLine(0,i*siz,(19 * size),i*size); > >>> } > >>> > >>> g2d.setColor(Color.blue); > >>> > >>>// Draw Line > >>> drawLineToPoints(g2d, xValues1, yValues1, xValues2, yValues2); > >>> } > >>> > >>>// Function to draw the line > >>> void drawLineToPoints(Graphics2D g2d, Vector xValues1, Vector yValues1, > Vector > >>>xValues2, Vector yValues2) > >>> { > >>> for(int a=0; a<xValues1.size(); ++a) > >>> { > >>> g2d.drawLine(getInt(xValues1, (a)),((19 * size + 1) - > >>>getInt(yValues1, (a))),getInt(xValues2, (a)),((19 * size + 1) - > getInt(yValues2, > >>>(a)))); > >>> } > >>> } > > =========================================================================== > To unsubscribe, send email to [EMAIL PROTECTED] and include in the body > of the message "signoff JAVA2D-INTEREST". For general help, send email to > [EMAIL PROTECTED] and include in the body of the message "help". =========================================================================== To unsubscribe, send email to [EMAIL PROTECTED] and include in the body of the message "signoff JAVA2D-INTEREST". For general help, send email to [EMAIL PROTECTED] and include in the body of the message "help".
