All Downloads are FREE. Search and download functionalities are using the official Maven repository.

sim.portrayal.grid.HexaValueGridPortrayal2D Maven / Gradle / Ivy

Go to download

MASON is a fast discrete-event multiagent simulation library core in Java, designed to be the foundation for large custom-purpose Java simulations, and also to provide more than enough functionality for many lightweight simulation needs. MASON contains both a model library and an optional suite of visualization tools in 2D and 3D.

The newest version!
/*
  Copyright 2006 by Sean Luke and George Mason University
  Licensed under the Academic Free License version 3.0
  See the file "LICENSE" for more information
*/

package sim.portrayal.grid;
import sim.portrayal.*;
import sim.field.grid.*;
import java.awt.*;
import java.awt.geom.*;
import sim.util.*;

/**
   Portrayal for hexagonal grids (each cell has six equally-distanced neighbors) with double-precision real values.
*/

public class HexaValueGridPortrayal2D extends ValueGridPortrayal2D
    {
    int[] xPoints = new int[6];
    int[] yPoints = new int[6];
    float[] xPointsf = new float[6];
    float[] yPointsf = new float[6];
        
    double[] xyC = new double[2];
    double[] xyC_ul = new double[2];
    double[] xyC_up = new double[2];
    double[] xyC_ur = new double[2];
    
    public HexaValueGridPortrayal2D()
        {
        super();
        }

    public HexaValueGridPortrayal2D(String valueName)
        {
        super(valueName);
        }

    final static void getxyC( final int x, final int y, final double xScale, final double yScale, final double tx, final double ty, final double[] xyC )
        {
        xyC[0] = tx + xScale * (1.5 * x + 1);
        xyC[1] = ty + yScale * (1.0 + 2.0 * y + (x<0?(-x)%2:x%2) );
        }


    public Double2D getScale(DrawInfo2D info)
        {
        synchronized(info.gui.state.schedule)
            {
            final Grid2D field = (Grid2D) this.field;
            if (field==null) return null;

            int maxX = field.getWidth(); 
            int maxY = field.getHeight();
            if (maxX == 0 || maxY == 0) return null;

            final double divideByX = ((maxX%2==0)?(3.0*maxX/2.0+0.5):(3.0*maxX/2.0+2.0));
            final double divideByY = (1.0+2.0*maxY);

            final double xScale = info.draw.width / divideByX;
            final double yScale = info.draw.height / divideByY;
            return new Double2D(xScale, yScale);
            }
        }


    public Object getPositionLocation(Point2D.Double position, DrawInfo2D info)
        {
        Double2D scale = getScale(info);
        double xScale = scale.x;
        double yScale = scale.y;
                
        int startx = (int)(((position.getX() - info.draw.x)/xScale-0.5)/1.5);
        int starty = (int)((position.getY() - info.draw.y)/(yScale*2.0));

        return new Int2D(startx, starty);
        }


    static final double HEXAGONAL_RATIO = 2/Math.sqrt(3);

    public Point2D.Double getLocationPosition(Object location, DrawInfo2D info)
        {
        synchronized(info.gui.state.schedule)
            {
            final Grid2D field = (Grid2D) this.field;
            if (field==null) return null;

            int maxX = field.getWidth(); 
            int maxY = field.getHeight();
            if (maxX == 0 || maxY == 0) return null;

            final double divideByX = ((maxX%2==0)?(3.0*maxX/2.0+0.5):(3.0*maxX/2.0+2.0));
            final double divideByY = (1.0+2.0*maxY);

            final double xScale = info.draw.width / divideByX;
            final double yScale = info.draw.height / divideByY;
            //int startx = (int)(((info.clip.x - info.draw.x)/xScale-0.5)/1.5)-2;
            //int starty = (int)((info.clip.y - info.draw.y)/(yScale*2.0))-2;
            //int endx = /*startx +*/ (int)(((info.clip.x - info.draw.x + info.clip.width)/xScale-0.5)/1.5) + 4;  // with rounding, width be as much as 1 off
            //int endy = /*starty +*/ (int)((info.clip.y - info.draw.y + info.clip.height)/(yScale*2.0)) + 4;  // with rounding, height be as much as 1 off

            DrawInfo2D newinfo = new DrawInfo2D(info.gui, info.fieldPortrayal, new Rectangle2D.Double(0,0, 
                    Math.ceil(info.draw.width / (HEXAGONAL_RATIO * ((maxX - 1) * 3.0 / 4.0 + 1))),
                    Math.ceil(info.draw.height / (maxY + 0.5))),
                info.clip/*, xPoints, yPoints*/);  // we don't do further clipping 
            newinfo.precise = info.precise;

            Int2D loc = (Int2D) location;
            if (loc == null) return null;

            final int x = loc.x;
            final int y = loc.y;

            getxyC( x, y, xScale, yScale, info.draw.x, info.draw.y, xyC );
            getxyC( field.ulx(x,y), field.uly(x,y), xScale, yScale, info.draw.x, info.draw.y, xyC_ul );
            getxyC( field.upx(x,y), field.upy(x,y), xScale, yScale, info.draw.x, info.draw.y, xyC_up );
            getxyC( field.urx(x,y), field.ury(x,y), xScale, yScale, info.draw.x, info.draw.y, xyC_ur );

            xPoints[0] = (int)(xyC_ur[0]-0.5*xScale);
            //yPoints[0] = (int)(xyC_ur[1]+yScale);
            //xPoints[1] = (int)(xyC_up[0]+0.5*xScale);
            yPoints[1] = (int)(xyC_up[1]+yScale);
            //xPoints[2] = (int)(xyC_up[0]-0.5*xScale);
            //yPoints[2] = (int)(xyC_up[1]+yScale);
            xPoints[3] = (int)(xyC_ul[0]+0.5*xScale);
            //yPoints[3] = (int)(xyC_ul[1]+yScale);
            //xPoints[4] = (int)(xyC[0]-0.5*xScale);
            yPoints[4] = (int)(xyC[1]+yScale);
            //xPoints[5] = (int)(xyC[0]+0.5*xScale);
            //yPoints[5] = (int)(xyC[1]+yScale);

            // compute the width of the object -- we tried computing the EXACT width each time, but
            // it results in weird-shaped circles etc, so instead we precomputed a standard width
            // and height, and just compute the x values here.
            newinfo.draw.x = xPoints[3];
            newinfo.draw.y = yPoints[1];
                    
            // adjust drawX and drawY to center
            newinfo.draw.x +=(xPoints[0]-xPoints[3]) / 2.0;
            newinfo.draw.y += (yPoints[4]-yPoints[1]) / 2.0;

            return new Point2D.Double(newinfo.draw.x, newinfo.draw.y);
            }
        }


    // 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;
        
        // first question: determine the range in which we need to draw.
        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 divideByY = (1.0+2.0*maxY);

        final double xScale = info.draw.width / divideByX;
        final double yScale = info.draw.height / divideByY;
        int startx = (int)(((info.clip.x - info.draw.x)/xScale-0.5)/1.5)-2;
        int starty = (int)((info.clip.y - info.draw.y)/(yScale*2.0))-2;
        int endx = /*startx +*/ (int)(((info.clip.x - info.draw.x + info.clip.width)/xScale-0.5)/1.5) + 4;  // with rounding, width be as much as 1 off
        int endy = /*starty +*/ (int)((info.clip.y - info.draw.y + info.clip.height)/(yScale*2.0)) + 4;  // with rounding, height be as much as 1 off

        //
        //
        // CAUTION!
        //
        // At some point we should triple check the math for rounding such
        // that the margins are drawn properly
        //
        //
        
        // next we determine if this is a DoubleGrid2D or an IntGrid2D
        
//        final Rectangle clip = (graphics==null ? null : graphics.getClipBounds());

        final boolean isDoubleGrid2D = (field instanceof DoubleGrid2D);
        final double[][] doubleField = (isDoubleGrid2D ? ((DoubleGrid2D) field).field : null);
        final int[][] intField = (isDoubleGrid2D ? null : ((IntGrid2D) field).field);

        double xyC_x, xyC_y, xyC_ulx, xyC_uly, xyC_upx, xyC_upy, xyC_urx, xyC_ury, x0, y0, tx, ty;

        if( startx < 0 ) startx = 0;
        if( starty < 0 ) starty = 0;
        if (endx > maxX) endx = maxX;
        if (endy > maxY) endy = maxY;

        for(int y=starty;y




© 2015 - 2025 Weber Informatics LLC | Privacy Policy