/**
* Copyright 2011 by Mark Coletti, Keith Sullivan, Sean Luke, and
* George Mason University Mason University Licensed under the Academic
* Free License version 3.0
*
* See the file "LICENSE" for more information
*
* $Id$
*
*/
package sim.util.geo;
import com.vividsolutions.jts.geom.Geometry;
import com.vividsolutions.jts.geom.prep.PreparedGeometry;
import com.vividsolutions.jts.geom.prep.PreparedGeometryFactory;
import java.awt.geom.AffineTransform;
import java.awt.geom.GeneralPath;
import java.util.HashMap;
import java.util.Map;
/**
* A MasonGeometry is a wrapper for a JTS geometry and an associated userData
* field. The userData field can be any MASON object, or general Java object,
* which will be included in the inspector by default.
*
* <p> MasonGeometry implements sim.util.Proxiable to allow the hiding of
* various getXXX and setXXX methods from the inspectors.
*
* TODO may have to move new AttributeValue convenience functions to inner
* proxy class.
*/
public class MasonGeometry implements sim.util.Proxiable, java.io.Serializable
{
private static final long serialVersionUID = 6290810736517692387L;
/** Internal JTS geometry object */
public Geometry geometry;
/** Optional attribute-value pairs associated with this geometry
*/
private Map<String,AttributeValue> attributes;
/**
* XXX This might be deprecated because no longer support hidden attributes
*
* @return true iff this.attributes contains any hidden attributes
*/
public boolean hasHiddenAttributes()
{
for (AttributeValue value : this.attributes.values())
{
if ( value.isHidden() )
{
return true;
}
}
return false;
}
/**
* @return true iff there are any attributes associated with this geometry
*/
public boolean hasAttributes()
{
return ! attributes.isEmpty();
}
/**
*
* @param name of attribute for which we're looking
* @return true if this geometry has an attribute of that name
*/
public boolean hasAttribute(final String name)
{
return this.attributes.containsKey(name);
}
/**
* @return attributes associated with this geometry
*/
public Map<String,AttributeValue> getAttributes()
{
// return Collections.unmodifiableMap(attributes);
return attributes;
}
/** Java2D shape corresponding to this Geometry. Used to
* speed up drawing.
*/
public GeneralPath shape;
/**
*
*/
public AffineTransform transform = new AffineTransform();
@Override
public int hashCode()
{
int hash = 5;
hash = 19 * hash + (this.geometry != null ? this.geometry.hashCode() : 0);
return hash;
}
@Override
public boolean equals(Object obj)
{
if (obj == null)
{
return false;
}
if (getClass() != obj.getClass())
{
return false;
}
final MasonGeometry other = (MasonGeometry) obj;
if (this.geometry != other.geometry && (this.geometry == null || !this.geometry.equals(other.geometry)))
{
return false;
}
if (this.attributes != other.attributes && (this.attributes == null || !this.attributes.equals(other.attributes)))
{
return false;
}
return true;
}
/** A cached, optimized version of my Geometry. Used for fast intersection, union, etc. operations */
public PreparedGeometry preparedGeometry;
/** Does this MasonGeometry move? i.e., dynamically change location */
public boolean isMovable = false;
/** Default constructors */
public MasonGeometry()
{
this(null, null);
}
public MasonGeometry(Geometry g)
{
this(g, null);
}
public MasonGeometry(Geometry g, Object o)
{
geometry = g;
shape = null;
transform = new AffineTransform();
preparedGeometry = null;
attributes = new HashMap<String,AttributeValue>();
if (geometry != null)
{
preparedGeometry = PreparedGeometryFactory.prepare(geometry);
}
if ( o != null )
{
setUserData(o);
}
}
// TODO add test for this in harness
public void addAttributes(final Map<String,AttributeValue> attributes )
{
this.attributes.putAll(attributes);
}
public void addAttribute(final String name, final Object value)
{
this.attributes.put(name, new AttributeValue(value));
}
public Object getAttribute(final String name)
{
return this.attributes.get(name);
}
public void addIntegerAttribute(final String name, int value)
{
this.attributes.put(name, new AttributeValue(value));
}
public Integer getIntegerAttribute(final String name)
{
return this.attributes.get(name).getInteger();
}
public void addDoubleAttribute(final String name, double value)
{
this.attributes.put(name, new AttributeValue(value));
}
public Double getDoubleAttribute(final String name)
{
return this.attributes.get(name).getDouble();
}
public void addStringAttribute(final String name, final String value)
{
this.attributes.put(name, new AttributeValue(value));
}
public String getStringAttribute(final String name)
{
return this.attributes.get(name).getString();
}
/** Set the userData field with an arbitrary object
*
* @param o is user supplied object to attach to this geometry
*/
final public void setUserData(Object o)
{
geometry.setUserData(o);
}
public Object getUserData()
{
return geometry.getUserData();
}
/**
* @return geometry type and coordinates
*/
@Override
public String toString()
{
return geometry.toString();
}
/** @return the JTS geometry object.
*/
public Geometry getGeometry()
{
return geometry;
}
/** Inner class allows us to prevent certain getXXX and setXXX methods from
* appearing in the Inspector
*/
public class GeomWrapperProxy
{
/**
* @return the area of the internal JTS geometry object. The units are
* the same as same as the internal JTS geometry object
*/
public double getArea()
{
return geometry.getArea();
}
/** @return the length of the perimeter of the internal JTS geometry
* object. The units are the same as same as the internal JTS geometry
* object
*/
public double getPerimeter()
{
return geometry.getLength();
}
/**
* @return the number of vertices which make up the geometry
*/
public int getNumVertices()
{
return geometry.getNumPoints();
}
}
public Object propertiesProxy()
{
return new GeomWrapperProxy();
}
}