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

sim.portrayal.grid.SparseGridPortrayal2D 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.portrayal.simple.*;
import sim.field.grid.*;
import sim.util.*;
import java.awt.*;
import java.util.*;
import java.awt.geom.*;
import sim.portrayal.inspector.*;

/**
   Can be used to draw both continuous and discrete sparse fields
*/

public class SparseGridPortrayal2D extends FieldPortrayal2D
    {
    public DrawPolicy policy;

    public SparseGridPortrayal2D()
        {
        super();
        }

    public SparseGridPortrayal2D (DrawPolicy policy)
        {
        super();
        this.policy = policy;
        }

    // a grey oval.  You should provide your own protrayals...
    SimplePortrayal2D defaultPortrayal = new OvalPortrayal2D();

    public Portrayal getDefaultPortrayal()
        {
        return defaultPortrayal;
        }

    public void setField(Object field)
        {
        dirtyField = true;
        if (field instanceof SparseGrid2D ) this.field = field;
        else throw new RuntimeException("Invalid field for Sparse2DPortrayal: " + field);
        }
    
    public Int2D getLocation(DrawInfo2D info)
        {
        final Grid2D field = (Grid2D) this.field;
        if (field==null) return null;

        int maxX = field.getWidth(); 
        int maxY = field.getHeight();

        final double xScale = info.draw.width / maxX;
        final double yScale = info.draw.height / maxY;
        final int startx = (int)((info.clip.x - info.draw.x) / xScale);
        final int starty = (int)((info.clip.y - info.draw.y) / yScale); // assume that the X coordinate is proportional -- and yes, it's _width_
        return new Int2D(startx, starty);
        }

    public Point2D.Double getPositionInFieldPortrayal(Object object, DrawInfo2D info)
        {
        final SparseGrid2D field = (SparseGrid2D) this.field;
        if (field==null) return null;

        int maxX = field.getWidth(); 
        int maxY = field.getHeight();

        final double xScale = info.draw.width / maxX;
        final double yScale = info.draw.height / maxY;

        DrawInfo2D newinfo = new DrawInfo2D(new Rectangle2D.Double(0,0, xScale, yScale), info.clip);  

        Int2D loc = field.getObjectLocation(object);
        if (loc == null) return null;

        // translate --- the   + newinfo.width/2.0  etc. moves us to the center of the object
        newinfo.draw.x = (int)(info.draw.x + (xScale) * loc.x);
        newinfo.draw.y = (int)(info.draw.y + (yScale) * loc.y);
        newinfo.draw.width = (int)(info.draw.x + (xScale) * (loc.x+1)) - newinfo.draw.x;
        newinfo.draw.height = (int)(info.draw.y + (yScale) * (loc.y+1)) - newinfo.draw.y;
        
        // adjust drawX and drawY to center
        newinfo.draw.x += newinfo.draw.width / 2.0;
        newinfo.draw.y += newinfo.draw.height / 2.0;

        return new Point2D.Double(newinfo.draw.x, newinfo.draw.y);
        }
        
        
    protected void hitOrDraw(Graphics2D graphics, DrawInfo2D info, Bag putInHere)
        {
        final SparseGrid2D field = (SparseGrid2D) this.field;
        if (field==null) return;

        boolean objectSelected = !selectedWrappers.isEmpty();

        int maxX = field.getWidth(); 
        int maxY = field.getHeight();

        final double xScale = info.draw.width / maxX;
        final double yScale = info.draw.height / maxY;
        final int startx = (int)((info.clip.x - info.draw.x) / xScale);
        final int starty = (int)((info.clip.y - info.draw.y) / yScale); // assume that the X coordinate is proportional -- and yes, it's _width_
        int endx = /*startx +*/ (int)((info.clip.x - info.draw.x + info.clip.width) / xScale) + /*2*/ 1;  // with rounding, width be as much as 1 off
        int endy = /*starty +*/ (int)((info.clip.y - info.draw.y + info.clip.height) / yScale) + /*2*/ 1;  // with rounding, height be as much as 1 off

        final Rectangle clip = (graphics==null ? null : graphics.getClipBounds());

        DrawInfo2D newinfo = new DrawInfo2D(new Rectangle2D.Double(0,0, xScale, yScale),
            info.clip);  // we don't do further clipping 

        // If the person has specified a policy, we have to iterate through the
        // bags.  At present we have to do this by using a hash table iterator
        // (yuck -- possibly expensive, have to search through empty locations).
        //
        // We never use the policy to determine hitting.  hence this only works if graphics != null
        if (policy != null && graphics != null)
            {
            Bag policyBag = new Bag();
            Iterator iterator = field.locationBagIterator();
            while(iterator.hasNext())
                {
                Bag objects = (Bag)(iterator.next());
                
                if (objects == null) continue;
                                
                // restrict the number of objects to draw
                policyBag.clear();  // fast
                if (policy.objectToDraw(objects,policyBag))  // if this function returns FALSE, we should use objects as is, else use the policy bag.
                    objects = policyBag;  // returned TRUE, so we're going to use the modified policyBag instead.
                                        
                // draw 'em
                for(int x=0;x= startx -2 && loc.x < endx + 4 &&
                        loc.y >= starty -2 && loc.y < endy + 4)
                        {
                        Portrayal p = getPortrayalForObject(portrayedObject);
                        if (!(p instanceof SimplePortrayal2D))
                            throw new RuntimeException("Unexpected Portrayal " + p + " for object " + 
                                portrayedObject + " -- expected a SimplePortrayal2D");
                        SimplePortrayal2D portrayal = (SimplePortrayal2D) p;
                        
                        // translate --- the   + newinfo.width/2.0  etc. moves us to the center of the object
                        newinfo.draw.x = (int)(info.draw.x + (xScale) * loc.x);
                        newinfo.draw.y = (int)(info.draw.y + (yScale) * loc.y);
                        newinfo.draw.width = (int)(info.draw.x + (xScale) * (loc.x+1)) - newinfo.draw.x;
                        newinfo.draw.height = (int)(info.draw.y + (yScale) * (loc.y+1)) - newinfo.draw.y;
                        
                        // adjust drawX and drawY to center
                        newinfo.draw.x += newinfo.draw.width / 2.0;
                        newinfo.draw.y += newinfo.draw.height / 2.0;

                        if (objectSelected &&  // there's something there
                            selectedWrappers.get(portrayedObject) != null)
                            {
                            LocationWrapper wrapper = (LocationWrapper)(selectedWrappers.get(portrayedObject));
                            portrayal.setSelected(wrapper,true);
                            portrayal.draw(portrayedObject, graphics, newinfo);
                            portrayal.setSelected(wrapper,false);
                            }
                        else portrayal.draw(portrayedObject, graphics, newinfo);
                        }
                    }
                }
            }
        else            // the easy way -- draw the objects one by one
            {
            Bag objects = field.getAllObjects();
            for(int x=0;x= startx -2 && loc.x < endx + 4 &&
                    loc.y >= starty -2 && loc.y < endy + 4)
                    {
                    Portrayal p = getPortrayalForObject(portrayedObject);
                    if (!(p instanceof SimplePortrayal2D))
                        throw new RuntimeException("Unexpected Portrayal " + p + " for object " + 
                            portrayedObject + " -- expected a SimplePortrayal2D");
                    SimplePortrayal2D portrayal = (SimplePortrayal2D) p;
                
                    // translate --- the   + newinfo.width/2.0  etc. moves us to the center of the object
                    newinfo.draw.x = (int)(info.draw.x + (xScale) * loc.x);
                    newinfo.draw.y = (int)(info.draw.y + (yScale) * loc.y);
                    newinfo.draw.width = (int)(info.draw.x + (xScale) * (loc.x+1)) - newinfo.draw.x;
                    newinfo.draw.height = (int)(info.draw.y + (yScale) * (loc.y+1)) - newinfo.draw.y;
                    
                    // adjust drawX and drawY to center
                    newinfo.draw.x += newinfo.draw.width / 2.0;
                    newinfo.draw.y += newinfo.draw.height / 2.0;

                    if (graphics == null)
                        {
                        if (portrayal.hitObject(portrayedObject, newinfo))
                            putInHere.add(getWrapper(portrayedObject));
                        }
                    else
                        {
                        // MacOS X 10.3 Panther has a bug which resets the clip, YUCK
                        // graphics.setClip(clip);
                        if (objectSelected &&  // there's something there
                            selectedWrappers.get(portrayedObject) != null)
                            {
                            LocationWrapper wrapper = (LocationWrapper)(selectedWrappers.get(portrayedObject));
                            portrayal.setSelected(wrapper,true);
                            portrayal.draw(portrayedObject, graphics, newinfo);
                            portrayal.setSelected(wrapper,false);
                            }
                        else portrayal.draw(portrayedObject, graphics, newinfo);
                        }
                    }
                }
            }
        }

    // The easiest way to make an inspector which gives the location of my objects
    public LocationWrapper getWrapper(Object object)
        {
        final SparseGrid2D field = (SparseGrid2D) this.field;
        final StableInt2D w = new StableInt2D(field, object);
        return new LocationWrapper( object, null, this )  // don't care about location
            {
            public Object getLocation()
                {
                w.update();
                return w;
                }
                
            public String getLocationName()
                {
                w.update();
                return w.toString();
                }
            };
        }

    HashMap selectedWrappers = new HashMap();
    public boolean setSelected(LocationWrapper wrapper, boolean selected)
        {
        if (wrapper == null) return true;
        if (wrapper.getFieldPortrayal() != this) return true;

        Object obj = wrapper.getObject();
        if (selected)
            {
            // first let's determine if the object WANTs to be selected
            boolean b = getPortrayalForObject(obj).setSelected(wrapper,selected);
                        
            // now we turn the selection back to regular
            getPortrayalForObject(obj).setSelected(wrapper,!selected);
                        
            // Okay, now we can tell whether or not to add to the wrapper collection
            if (b==false) return false;
            selectedWrappers.put(obj, wrapper);
            }
        else
            {
            selectedWrappers.remove(obj);
            }
        return true;
        }
    }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy