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

sim.portrayal.simple.ShapePortrayal2D 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.simple;
import sim.portrayal.*;
import java.awt.*;
import java.awt.geom.*;

/**
   A simple portrayal for 2D visualization of java.awt.Shapes and java.awt.Polygons. It extends the SimplePortrayal2D and
   it manages the drawing and hit-testing for shapes.  Various X and Y point arrays for constructing
   different default shapes are also provided.
*/

public class ShapePortrayal2D extends AbstractShapePortrayal2D
    {
    static final Stroke defaultStroke = new BasicStroke();
    public Shape shape;
    public Stroke stroke;
    AffineTransform transform = new AffineTransform();

    double[] xPoints = null;
    double[] yPoints = null;
    double[] scaledXPoints = null;
    double[] scaledYPoints = null;
    int[] translatedXPoints = null;
    int[] translatedYPoints = null;
    double scaling;

    double bufferedWidth;
    double bufferedHeight;
    Shape bufferedShape;
    
    public static final double[] X_POINTS_TRIANGLE_DOWN = new double[] {-0.5, 0, 0.5};
    public static final double[] Y_POINTS_TRIANGLE_DOWN = new double[] {-0.5, 0.5, -0.5};
    public static final double[] X_POINTS_TRIANGLE_UP = new double[] {-0.5, 0, 0.5};
    public static final double[] Y_POINTS_TRIANGLE_UP = new double[] {0.5, -0.5, 0.5};
    public static final double[] X_POINTS_TRIANGLE_RIGHT = new double[] {-0.5, -0.5, 0.5};
    public static final double[] Y_POINTS_TRIANGLE_RIGHT = new double[] {-0.5, 0.5, 0};
    public static final double[] X_POINTS_TRIANGLE_LEFT = new double[] {-0.5, 0.5, 0.5};
    public static final double[] Y_POINTS_TRIANGLE_LEFT = new double[] {0, 0.5, -0.5};
    public static final double[] X_POINTS_DIAMOND = new double[] {-0.5, 0, 0.5, 0};
    public static final double[] Y_POINTS_DIAMOND = new double[] {0, 0.5, 0, -0.5};
    public static final double[] X_POINTS_SQUARE = new double[] {-0.5, -0.5, 0.5, 0.5};
    public static final double[] Y_POINTS_SQUARE = new double[] {-0.5, 0.5, 0.5, -0.5};
    public static final double[] X_POINTS_BOWTIE = new double[] {-0.5, 0.5, 0.5, -0.5};
    public static final double[] Y_POINTS_BOWTIE = new double[] {-0.5, 0.5, -0.5, 0.5};
    public static final double[] X_POINTS_HOURGLASS = new double[] {-0.5, 0.5, -0.5, 0.5};
    public static final double[] Y_POINTS_HOURGLASS = new double[] {-0.5, 0.5, 0.5, -0.5};
    
    static final double OCT_COORD = (1.0 / (1.0 + Math.sqrt(2))) / 2.0;  // About .2071067811, derived from Wikipedia's Octogon article :-)
    public static final double[] X_POINTS_OCTAGON = new double[] {-0.5, -0.5, -OCT_COORD, OCT_COORD, 0.5, 0.5, OCT_COORD, -OCT_COORD};
    public static final double[] Y_POINTS_OCTAGON = new double[] {-OCT_COORD, OCT_COORD, 0.5, 0.5, OCT_COORD, -OCT_COORD, -0.5, -0.5};

    // This hexagon, unlike HexagonalPortrayal2D, fits inside a 1x1 square centered at (0,0) and so looks somewhat stretched
    public static final double[] X_POINTS_HEXAGON = new double[] {-0.5, -0.25, 0.25, 0.5, 0.25, -0.25};
    public static final double[] Y_POINTS_HEXAGON = new double[] {0, 0.5, 0.5, 0, -0.5, -0.5};
    public static final double[] X_POINTS_HEXAGON_ROTATED = new double[] {0, 0.5, 0.5, 0, -0.5, -0.5};
    public static final double[] Y_POINTS_HEXAGON_ROTATED = new double[] {-0.5, -0.25, 0.25, 0.5, 0.25, -0.25};
    
    Shape buildPolygon(double[] xpoints, double[] ypoints)
        {
        GeneralPath path = new GeneralPath();
        // general paths are only floats and not doubles in Java 1.4, 1.5
        // in 1.6 it's been changed to doubles finally but we're not there yet.
        if (xpoints.length > 0) path.moveTo((float)xpoints[0], (float)ypoints[0]);
        for(int i=xpoints.length-1; i >= 0; i--)
            path.lineTo((float)xpoints[i], (float)ypoints[i]);
        return path;
        }
    
    public ShapePortrayal2D(double[] xpoints, double[] ypoints) { this(xpoints, ypoints, Color.gray,1.0,true); }
    public ShapePortrayal2D(double[] xpoints, double[] ypoints, Paint paint) { this(xpoints, ypoints,paint,1.0,true); }
    public ShapePortrayal2D(double[] xpoints, double[] ypoints, double scale) { this(xpoints, ypoints,Color.gray,scale,true); }
    public ShapePortrayal2D(double[] xpoints, double[] ypoints, Paint paint, double scale) { this(xpoints, ypoints, paint,scale,true); }
    public ShapePortrayal2D(double[] xpoints, double[] ypoints, boolean filled) { this(xpoints, ypoints,Color.gray,1.0,filled); }
    public ShapePortrayal2D(double[] xpoints, double[] ypoints, Paint paint, boolean filled) { this(xpoints, ypoints,paint,1.0,filled); }
    public ShapePortrayal2D(double[] xpoints, double[] ypoints, double scale, boolean filled) { this(xpoints, ypoints,Color.gray,scale,filled); }
    public ShapePortrayal2D(double[] xpoints, double[] ypoints, Paint paint, double scale, boolean filled)
        {
        this(null, paint, scale, filled);
        this.shape = buildPolygon(xpoints,ypoints);
        this.xPoints = xpoints;
        this.yPoints = ypoints;
        this.scaledXPoints = new double[xpoints.length];
        this.scaledYPoints = new double[ypoints.length];
        this.translatedXPoints = new int[xpoints.length];
        this.translatedYPoints = new int[ypoints.length];
        }

    public ShapePortrayal2D(Shape shape) { this(shape,Color.gray,1.0,true); }
    public ShapePortrayal2D(Shape shape, Paint paint) { this(shape,paint,1.0,true); }
    public ShapePortrayal2D(Shape shape, double scale) { this(shape,Color.gray,scale,true); }
    public ShapePortrayal2D(Shape shape, Paint paint, double scale) { this(shape, paint,scale,true); }
    public ShapePortrayal2D(Shape shape, boolean filled) { this(shape,Color.gray,1.0,filled); }
    public ShapePortrayal2D(Shape shape, Paint paint, boolean filled) { this(shape,paint,1.0,filled); }
    public ShapePortrayal2D(Shape shape, double scale, boolean filled) { this(shape,Color.gray,scale,filled); }
    public ShapePortrayal2D(Shape shape, Paint paint, double scale, boolean filled)
        {
        this.shape = shape;
        this.paint = paint;
        this.scale = scale;
        this.filled = filled;
        setStroke(null);
        }
    
    public void setStroke(Stroke s)
        {
        stroke = s;
        }
        
    // assumes the graphics already has its color set
    public void draw(Object object, Graphics2D graphics, DrawInfo2D info)
        {
        graphics.setPaint(paint);
        if (true)  //  We turn this off because it's no longer much slower (only 1% slower).     info.precise || xPoints == null || stroke != null)
            {   
            final double width = info.draw.width*scale;
            final double height = info.draw.height*scale;
            if (bufferedShape == null || width != bufferedWidth || height != bufferedHeight)
                {
                transform.setToScale(bufferedWidth = width, bufferedHeight = height);
                bufferedShape = transform.createTransformedShape(shape);
                }

            // we are doing a simple draw, so we ignore the info.clip

            // draw centered on the origin
            transform.setToTranslation(info.draw.x,info.draw.y);
            if (filled)
                {
                graphics.fill(transform.createTransformedShape(bufferedShape));
                }
            else
                {
                graphics.setStroke(stroke == null ? defaultStroke : stroke);
                graphics.draw(transform.createTransformedShape(bufferedShape));
                }
            }
        else   // faster by far         // NOTE:  Not any more.  On the Mac it's about 1% faster, not enough to worry about.
            {
            int len = xPoints.length;
            double[] scaledXPoints = this.scaledXPoints;
            double[] scaledYPoints = this.scaledYPoints;
            int[] translatedXPoints = this.translatedXPoints;
            int[] translatedYPoints = this.translatedYPoints;
            double x = info.draw.x;
            double y = info.draw.y;
            double width = scale * info.draw.width;

            // do we need to scale?
            if (scaling != width)
                {
                double[] xPoints = this.xPoints;
                double[] yPoints = this.yPoints;
                double height = scale * info.draw.height;
                for(int i=0;i




© 2015 - 2025 Weber Informatics LLC | Privacy Policy