📄 fasthexavaluegridportrayal2d.java
字号:
package sim.portrayal.grid;import sim.portrayal.*;import sim.field.grid.*;import java.awt.*;import java.awt.image.*;import sim.util.gui.ColorMap;import sim.util.*;// we don't benefit from being a subclass of HexaValueGridPortrayal2D, but// it makes us easily swappable in (see HexaBugs for example). And also// consistent with the subclass relationship between ValueGridPortrayal2D// and FastValueGridPortrayal2D.public class FastHexaValueGridPortrayal2D extends HexaValueGridPortrayal2D { /** If immutableField is true, we presume that the grid doesn't change. This allows us to just re-splat the buffer. */ public FastHexaValueGridPortrayal2D(String valueName, boolean immutableField) { super(valueName); setImmutableField(immutableField); } public FastHexaValueGridPortrayal2D(String valueName) { this(valueName,false); } /** If immutableField is true, we presume that the grid doesn't change. This allows us to just re-splat the buffer. */ public FastHexaValueGridPortrayal2D(boolean immutableField) { super(); setImmutableField(immutableField); } public FastHexaValueGridPortrayal2D() { this(false); } public void reset() { synchronized(this) { buffer = null; } } // Determines if we should buffer boolean shouldBuffer(Graphics2D graphics) { // We can either draw lots of rects, or we can pixels to a small bitmap, then // stretch the bitmap into rects using drawImage. Which technique is faster depends // on the OS unfortunately. Solaris prefers the bitmap. Linux prefers the rects // very much. Windows prefers the rects, // except for small draws where bitmaps have a slight edge (which we'll not consider). // MacOS X prefers bitmaps, but will not stretch and draw to an image buffer // without doing fancy-pants interpolation which looks horrible, so we have to check for that. // For now we'll do: // The user can override us if he likes in the options pane. Otherwise... // in Windows, only use the buffer if it's an immutable grid // in MacOS X, use the buffer for all non-image writes ONLY // in X Windows don't use the buffer ever // ...this puts Solaris at a disadvantage but given that Linux is more common... int buffering = getBuffering(); if (buffering==USE_BUFFER) return true; else if (buffering==DONT_USE_BUFFER) return false; else if (sim.display.Display2D.isMacOSX) return (graphics.getDeviceConfiguration(). getDevice().getType() != GraphicsDevice.TYPE_IMAGE_BUFFER); else if (sim.display.Display2D.isWindows) return (immutableField && !dirtyField); else // it's Linux or Solaris return false; } BufferedImage buffer; WritableRaster raster; DataBufferInt dbuffer; // our object to pass to the portrayal final MutableDouble valueToPass = new MutableDouble(0); protected void hitOrDraw(Graphics2D graphics, DrawInfo2D info, Bag putInHere) { final Grid2D field = (Grid2D)this.field; if (field==null) return; final boolean isDoubleGrid2D = (field instanceof DoubleGrid2D); final int maxX = field.getWidth(); final int maxY = field.getHeight(); if (maxX == 0 || maxY == 0) return; final double divideByX = ((maxX%2==0)?(3.0*maxX/2.0+0.5):(3.0*maxX/2.0+2.0)); final double scaleWidth = 1.5 * info.draw.width / ((maxX%2==0)?(3.0*maxX/2.0+0.5):(3.0*maxX/2.0+2.0)); final double translateWidth = info.draw.width / divideByX - scaleWidth/2.0; final double[][] doubleField = (isDoubleGrid2D ? ((DoubleGrid2D) field).field : null); final int[][] intField = (isDoubleGrid2D ? null : ((IntGrid2D) field).field); final double xScale = info.draw.width / maxX; final double yScale = info.draw.height / (2*maxY+1); int startx = (int)((info.clip.x - translateWidth - info.draw.x) / scaleWidth); int starty = (int)((info.clip.y - info.draw.y) / (2*yScale)) - 1; int endx = /*startx +*/ (int)((info.clip.x - translateWidth - info.draw.x + info.clip.width) / scaleWidth) + /*2*/ 1; // with rounding, width may be as much as 1 off int endy = /*starty +*/ (int)((info.clip.y - info.draw.y + info.clip.height) / (2*yScale)) + /*2*/ 1; // with rounding, height may be as much as 1 off // next we determine if this is a DoubleGrid2D or an IntGrid2D final Rectangle clip = (graphics==null ? null : graphics.getClipBounds()); if (graphics!=null && shouldBuffer(graphics)) { // create new buffer if needed boolean newBuffer = false; synchronized(this) { if (buffer==null || buffer.getWidth() != maxX || buffer.getHeight() != (2*maxY+1)) { // interestingly, this is not quite as fast as just making a BufferedImage directly! // at present, transparent images can't take advantage of new Sun efficiency improvements. // Perhaps we should have a new option for opaque images... //buffer = graphics.getDeviceConfiguration().createCompatibleImage(maxX,maxY,Transparency.TRANSLUCENT); // oops, it looks like createCompatibleImage has big-time HILARIOUS bugs on OS X Java 1.3.1! // So for the time being we're sticking with the (very slightly faster) // new BufferedImage(...) buffer = new BufferedImage(maxX,maxY,BufferedImage.TYPE_INT_ARGB); // transparency allowed // I had thought that TYPE_INT_ARGB_PRE would be faster because // it's natively supported by MacOS X CoreGraphics so no optimization needs to be done // in 1.4.1 -- but in fact it is SLOWER on 1.3.1 by 2/3. So for the time being we're // going to stay with the orgiginal. // see http://developer.apple.com/documentation/Java/Reference/Java14SysProperties/System_Properties/chapter_2_section_6.html newBuffer = true; raster = buffer.getRaster(); dbuffer = (DataBufferInt)(raster.getDataBuffer()); } } //WritableRaster _raster = raster; DataBufferInt _dbuffer = dbuffer; if (newBuffer || !immutableField || dirtyField) // we have to load the buffer { if (endx > maxX) endx = maxX; if (endy > maxY) endy = maxY; if( startx < 0 ) startx = 0; if( starty < 0 ) starty = 0; if (immutableField) { // must load ENTIRE buffer startx = 0; starty = 0; endx = maxX; endy = maxY; } final int ex = endx; final int ey = endy; final int sx = startx; final int sy = starty; final ColorMap map = this.map;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -