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

jadex.extension.envsupport.environment.space3d.Grid3D Maven / Gradle / Ivy

Go to download

The Jadex kernel extension envsupport allows for using 2D spaces in concert with components.

There is a newer version: 3.0.117
Show newest version
package jadex.extension.envsupport.environment.space3d;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;

import jadex.commons.collection.MultiCollection;
import jadex.extension.envsupport.environment.ISpaceObject;
import jadex.extension.envsupport.environment.space2d.ContinuousSpace2D;
import jadex.extension.envsupport.math.IVector1;
import jadex.extension.envsupport.math.IVector2;
import jadex.extension.envsupport.math.IVector3;
import jadex.extension.envsupport.math.Vector1Double;
import jadex.extension.envsupport.math.Vector1Int;
import jadex.extension.envsupport.math.Vector3Int;

/**
 *  2D grid environment.
 */
public class Grid3D extends Space3D
{
	//-------- constants --------

	/** The default ID for this space. */
	public static final String DEFAULT_NAME = Grid3D.class.getName();
	
	/** The moore neighborhood. */
	public static final String NEIGHBORHOOD_MOORE = "moore";
	
	/** The von neumann neighborhood. */
	public static final String NEIGHBORHOOD_VON_NEUMANN = "von_neumann";

	/** The neighborhood property. */
	public static final String PROPERTY_NEIGHBORHOOD = "neighborhood";
	
	//-------- attributes --------
	
	/** All simobject id's accessible per position. */
	protected MultiCollection objectsygridpos;
	
	//-------- constructors --------
	
	/**
	 * Creates a new {@link ContinuousSpace2D} with the default name.
	 * 
	 * @param clockService the clock service
	 * @param timeCoefficient the time coefficient for time differences.
	 * @param areaSize the size of the 2D area
	 */
	public Grid3D()
	{
		this(null);
	}
	
	/**
	 * Creates a new {@link ContinuousSpace2D} with the default name.
	 * 
	 * @param actionexecutor executor for component actions
	 * @param areasize the size of the 2D area
	 */
	public Grid3D(IVector3 areasize)
	{
		this(DEFAULT_NAME, areasize);
	}
	
	/**
	 * Creates a new {@link ContinuousSpace2D} with a special ID.
	 * @param name the name of this space
	 * @param areasize the size of the 2D area
	 * @param actionexecutor executor for component actions
	 */
	public Grid3D(Object name, IVector3 areasize)
	{
		super(areasize==null? null: new Vector3Int(areasize.getXAsInteger(), areasize.getYAsInteger(), areasize.getZAsInteger()));
		this.setProperty("name", name);	
		this.objectsygridpos = new MultiCollection();
	}
	
	//-------- grid specific methods --------
		
	/**
	 *  Set the area size.
	 *  @param areasize The area size.
	 */
	public void setAreaSize(IVector3 areasize)
	{
		synchronized(monitor)
		{
			this.areasize = areasize==null? null: new Vector3Int(areasize.getXAsInteger(), areasize.getYAsInteger(), areasize.getZAsInteger());
		}
	}
	
	/**
	 *  Get the neighborhood.
	 *  @return Set the neighborhood.
	 */
	public String getNeighborhood()
	{
		return getPropertyNames().contains(PROPERTY_NEIGHBORHOOD)
			? (String)getProperty(PROPERTY_NEIGHBORHOOD)
			: NEIGHBORHOOD_VON_NEUMANN;
	}

	/**
	 * Get all SimObjects from a specific type at a specific grid position
	 */
	public Collection getSpaceObjectsByGridPosition(IVector3 position, Object type)
	{
		Collection ret = null;
		synchronized(monitor)
		{
			if(position!=null)
			{
				position = adjustPosition(position);
				IVector3 fieldpos = new Vector3Int(position.getXAsInteger(), position.getYAsInteger(), position.getZAsInteger());
			
				Collection simobjs = objectsygridpos.getCollection(fieldpos);
				if(null == type)
				{
					ret = simobjs;
				}
				else
				{
					ArrayList tmp = new ArrayList();
					for(Iterator objs = simobjs.iterator(); objs.hasNext();)
					{
						ISpaceObject curobj = (ISpaceObject)objs.next();
						if(type.equals(curobj.getType()))
						{
							tmp.add(curobj);
						}
					}
					if(tmp.size()>0)
						ret = tmp;
				}
			}
//			System.out.println("getSpaceObs: "+position+" "+type+" "+ret+" "+simobjs);
			
		}
		return ret;
	}
		
	/**
	 *  Get an empty position in the grid.
	 *  @return Empty {@link IVector2} position.
	 */
	public IVector3 getEmptyGridPosition()
	{
		synchronized(monitor)
		{
			IVector3 ret = null;

			// Problem of efficiently finding an empty field
			// Enumerating all empty fields would cause big
			// memory consumption on big grids
			
			// first try n times random value 
			int n = 5;
			for(int i=0; iobject mapping, for fast operation.
	 *  @param position	The position.
	 *  @param distance	The distance.
	 *  @param type	The type (or null for all objects).
	 */
	public Set getNearObjects(IVector3 position, IVector1 distance, String type)
	{
		synchronized(monitor)
		{
			Set ret = new HashSet();
			
			int sizex = areasize.getXAsInteger();
			int sizey = areasize.getYAsInteger();
			int sizez = areasize.getZAsInteger();
	
			int x = position.getXAsInteger();
			int y = position.getYAsInteger();
			int z = position.getYAsInteger();
			IVector3 pos = new Vector3Int(x, y, z);
			
			int range = distance.getAsInteger();
			
			int minx = x - range >= 0 || getBorderMode().equals(BORDER_TORUS) ? x - range : 0;
			int maxx = x + range <= sizex || getBorderMode().equals(BORDER_TORUS) ? x + range : sizex;

			int miny = y - range >= 0 || getBorderMode().equals(BORDER_TORUS) ? y - range : 0;
			int maxy = y + range <= sizey || getBorderMode().equals(BORDER_TORUS) ? y + range : sizey;
			
			int minz = z - range >= 0 || getBorderMode().equals(BORDER_TORUS) ? z - range : 0;
			int maxz = z + range <= sizez || getBorderMode().equals(BORDER_TORUS) ? z + range : sizez;

			for(int i = minx; i <= maxx; i++)
			{
				for(int j = miny; j <= maxy; j++)
				{
					for(int k = minz; k <= maxz; k++)
					{
						Vector3Int testpos = new Vector3Int((i + sizex) % sizex, (j + sizey) % sizey, (k + sizez) % sizez);
						if(!getDistance(testpos, pos).greater(distance))
						{
							Collection tmp = objectsygridpos.getCollection(testpos);
							if(tmp != null)
							{
								if(type==null)
								{
									ret.addAll(tmp);
								}
								else
								{
									for(Iterator it=tmp.iterator(); it.hasNext(); )
									{
										ISpaceObject obj = (ISpaceObject)it.next();
										if(obj.getType().equals(type))
											ret.add(obj);
									}
									
								}
							}
						}
					}
				}
			}
			
			return ret;
		}
	}
	
	
	/**
	 *  Calculate the distance in the space.
	 *  @param dx The distance in x.
	 *  @param dy The distance in y.
	 *  @return The distance according to the distance metrics of the space.
	 */
	public IVector1 calculateDistance(IVector1 dx, IVector1 dy)
	{
		if(NEIGHBORHOOD_MOORE.equals(getNeighborhood()))
		{
			return dx.greater(dy)? dx: dy;
		}
		else if(NEIGHBORHOOD_VON_NEUMANN.equals(getNeighborhood()))
		{
			if(dx.less(Vector1Double.ZERO))
				dx	= dx.copy().negate();
			if(dy.less(Vector1Double.ZERO))
				dy	= dy.copy().negate();
		}
		return dx.add(dy);
	}
	
	/**
	 *  Get the shortest (direct) direction between two coordinates.
	 *  @param pos1 The first position.
	 *  @param pos2 The second position.
	 *  @param isx The flag indicating if x or y).
	 *  @return -1: left/down, +1: right/up, 0: no move
	 */
	public IVector1 getShortestDirection(IVector1 pos1, IVector1 pos2, boolean isx)
	{
		IVector1 ret = Vector1Int.ZERO;
		
		if(getBorderMode().equals(BORDER_TORUS))
		{
			IVector1 size = isx? areasize.getX(): areasize.getY();
			
			if(pos1.less(pos2))
			{
				IVector1 d1 = pos2.copy().subtract(pos1);
				IVector1 d2 = pos1.copy().add(size).subtract(pos2);
				
				if(d1.less(d2))
					ret = new Vector1Int(1);
				else 
					ret = new Vector1Int(-1);
			}
			else if(pos1.greater(pos2))
			{
				IVector1 d1 = pos1.copy().subtract(pos2);
				IVector1 d2 = pos2.copy().add(size).subtract(pos1);
				
				if(d1.less(d2))
					ret = new Vector1Int(-1);
				else
					ret = new Vector1Int(1);
			}
		}
		else
		{
			if(pos1.less(pos2))
				ret = new Vector1Int(1);
			else if(pos1.greater(pos2))
				ret = new Vector1Int(-1);
		}
		
		return ret;
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy