sim.portrayal.grid.HexaValueGridPortrayal2D Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of mason Show documentation
Show all versions of mason Show documentation
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