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

jadex.extension.envsupport.environment.space3d.Space3D 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.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

import jadex.commons.IFilter;
import jadex.extension.envsupport.environment.AbstractEnvironmentSpace;
import jadex.extension.envsupport.environment.ISpaceObject;
import jadex.extension.envsupport.math.IVector1;
import jadex.extension.envsupport.math.IVector3;
import jadex.extension.envsupport.math.Vector1Double;
import jadex.extension.envsupport.math.Vector3Double;
import jadex.extension.envsupport.math.Vector3Int;

/**
 *  General 3D space.
 */
public abstract class Space3D extends AbstractEnvironmentSpace
{
	//-------- constants --------
	
	/** The constant for the position property. */
	public static final String PROPERTY_POSITION = "position";
	
	/** The constant for the border property. */
	public static final String PROPERTY_BORDER = "border";
	
	/** Border strict mode. */
	public static final String BORDER_STRICT = "strict";

	/** Border relaxed mode. */
	public static final String BORDER_RELAXED = "relaxed";

	/** Border torus behavior. */
	public static final String BORDER_TORUS = "torus";

	//-------- attributes --------
	
	/** Area size. */
	protected IVector3 areasize;
	
	//-------- constructors --------
	
	/**
	 * Initializes the 3D-Space.
	 * @param spaceexecutor executor for the space
	 * @param actionexecutor executor for component actions
	 * @param areasize the size of the 2D area
	 */
	protected Space3D(IVector3 areasize)
	{	
		this.areasize = areasize;
	}
	
	//-------- methods --------
		
	/**
	 * Returns the size of the simulated area.
	 * @return size of the simulated area
	 */
	public IVector3 getAreaSize()
	{
		synchronized(monitor)
		{
			return areasize.copy();
		}
	}
	
	/**
	 *  Set the area size.
	 *  @param areasize The area size.
	 */
	public void setAreaSize(IVector3 areasize)
	{
		synchronized(monitor)
		{
			this.areasize = areasize;
		}
	}
	
	/**
	 *  Get the border mode.
	 *  @return the border_mode
	 */
	public String getBorderMode()
	{
		return getPropertyNames().contains(PROPERTY_BORDER)
		? (String)getProperty(PROPERTY_BORDER)
		: BORDER_TORUS;
	}

	/** 
	 * Init an object in this space.
	 */
	public void initSpaceObject(ISpaceObject ret)
	{
		super.initSpaceObject(ret);
		
		IVector3 pos = ret.getPropertyNames().contains(PROPERTY_POSITION)? 
			(IVector3)ret.getProperty(PROPERTY_POSITION): getRandomPosition(Vector3Int.ZERO);

		if(pos!=null)
		{
			ret.setProperty(PROPERTY_POSITION, null);
			setPosition(ret.getId(), pos);
		}
	}

	/**
	 *  Set the position of an object.
	 *  @param id The object id.
	 *  @param pos The object position.
	 */
	public void setPosition(Object id, IVector3 pos)
	{
//		System.out.println("POS POS: " + pos.getXAsDouble() + " " + pos.getYAsDouble() + " " + pos.getZAsDouble());
		synchronized(monitor)
		{
			ISpaceObject obj = getSpaceObject(id);
			if(obj==null)
				throw new RuntimeException("Space object not found: "+id);
			
			IVector3 newpos = adjustPosition(pos);
			obj.setProperty(PROPERTY_POSITION, newpos);
		}
	}

	/**
	 *  Get the distance between three positions.
	 *  @param pos1	The first position.
	 *  @param pos2	The second position.
	 *  @param pos3	The third position.
	 */
	public IVector1	getDistance(IVector3 pos1, IVector3 pos2)
	{
		synchronized(monitor)
		{
//			try
//			{
				IVector1 dx = getDistance(pos1.getX(), pos2.getX(), true);
				IVector1 dy = getDistance(pos1.getY(), pos2.getY(), false);
				IVector1 dz = getDistance(pos1.getZ(), pos2.getZ(), false);
				IVector1 ret = calculateDistance(dx, dy, dz);
//				System.out.println(ret);
				return ret;
//			}
//			catch(Exception e)
//			{
//				e.printStackTrace();
//				throw new RuntimeException();
//			}
		}
	}
	
	/**
	 *  Get the distance between two coordinates (x or y).
	 *  @param pos1	The first position.
	 *  @param pos2	The second position.
	 */
	public IVector1	getDistance(IVector1 pos1, IVector1 pos2, boolean isx)
	{
		synchronized(monitor)
		{
			IVector1 ret = null;
			
			if(BORDER_TORUS.equals(getBorderMode()))
			{
				IVector1 size = isx? areasize.getX(): areasize.getY();
				
				if(pos1.greater(pos2))
				{
					IVector1 tmp = pos1;
					pos1 = pos2;
					pos2 = tmp;
				}
				IVector1 d1 = pos2.copy().subtract(pos1);
				IVector1 d2 = pos1.copy().add(size).subtract(pos2);
				ret = d1.less(d2) ? d1 : d2;
			}
			else
			{
				ret = pos1.getDistance(pos2);
			}
			
			return ret;
		}
	}
	
	/**
	 *  Calculate the distance in the space.
	 *  @param dx The distance in x.
	 *  @param dy The distance in y.
	 *  @param dz The distance in z.
	 *  @return The distance according to the distance metrics of the space.
	 */
	public IVector1 calculateDistance(IVector1 dx, IVector1 dy, IVector1 dz)
	{
		IVector1 x2 = dx.copy().multiply(dx);
		IVector1 y2 = dy.copy().multiply(dy);
		IVector1 z2 = dz.copy().multiply(dz);
		return (x2.add(y2).add(z2)).sqrt();
	}
	
	/**
	 *  Calculate a position according to the space borders.
	 */
	public IVector3 adjustPosition(IVector3 pos)
	{
		IVector3 ret = null;
		
		if(pos!=null)
		{
			IVector1 sizex = areasize.getX();
			IVector1 sizey = areasize.getY();
			IVector1 sizez = areasize.getZ();
			
			if(BORDER_TORUS.equals(getBorderMode()))
			{
				IVector1 x = pos.getX().copy();
				IVector1 y = pos.getY().copy();
				IVector1 z = pos.getZ().copy();
				
				while(x.less(Vector1Double.ZERO))
					x.add(sizex);
				while(y.less(Vector1Double.ZERO))
					y.add(sizey);
				while(z.less(Vector1Double.ZERO))
					z.add(sizez);
				
				x = x.copy().mod(sizex);
				y = y.copy().mod(sizey);
				z = z.copy().mod(sizez);
				
				//TODO: verstehen was hier passiert
				ret = Vector3Double.getVector3(x.getAsDouble(), y.getAsDouble(), z.getAsDouble());
				//ret = x.createVector2(y);
			}
			else if(BORDER_STRICT.equals(getBorderMode()))
			{
				if(pos.getX().greater(sizex) || pos.getX().less(Vector1Double.ZERO)
					|| pos.getY().greater(sizey) || pos.getY().less(Vector1Double.ZERO)
					|| pos.getZ().greater(sizez) || pos.getZ().less(Vector1Double.ZERO))
				{
					throw new RuntimeException("Position out of areasize: "+pos+" "+areasize);
				}
				ret = pos;
			}
			else if(BORDER_RELAXED.equals(getBorderMode()))
			{
				ret = pos;
			}
			else
			{
				throw new RuntimeException("Unknown bordermode: "+getBorderMode());
			}
		}
		
		return ret;
	}
	
	/**
	 * Retrieves a random position within the simulation area with a minimum
	 * distance from the edge.
	 * @param distance minimum distance from the edge, null or zero for no distance
	 */
	public IVector3 getRandomPosition(IVector3 distance)
	{
		synchronized(monitor)
		{
			if(distance == null)
				distance = Vector3Double.ZERO;
			IVector3 position = areasize.copy();
			position.subtract(distance);
			position.randomX(distance.getX(), position.getX());
			position.randomY(distance.getY(), position.getY());
			position.randomZ(distance.getZ(), position.getZ());
			
			return position;
		}
	}
	
	/**
	 * Returns the nearest object to the given position within a
	 * maximum distance from the position.
	 * 
	 * @param position position the object should be nearest to
	 * @param maxdist maximum distance from the position, use null for unlimited distance
	 * @return nearest object's ID or null if none is found
	 */
	public ISpaceObject getNearestObject(IVector3 position, IVector1 maxdist, String type)
	{
		ISpaceObject ret = null;
		
		synchronized(monitor)
		{
			ISpaceObject nearest = null;
			IVector1 distance = null;
			ISpaceObject[] objects = type!=null ? getSpaceObjectsByType(type) : (ISpaceObject[])getSpaceObjects();
			for(int i=0; objects!=null && i




© 2015 - 2024 Weber Informatics LLC | Privacy Policy