Class TrailedPortrayal2D

java.lang.Object
sim.portrayal.SimplePortrayal2D
sim.portrayal.simple.TrailedPortrayal2D
All Implemented Interfaces:
Serializable, Portrayal, Portrayal2D

public class TrailedPortrayal2D extends SimplePortrayal2D

TrailedPortrayal2D is a special SimplePortrayal wrapper which enables you to draw "trails" or "mouse tails" that drag behind objects and show where the've recently been. Unlike other "wrapper" style SimplePortrayals, like CircledPortrayal2D or LabelledPortrayal2D, TrailedPortrayal2D generally requires its own separate FieldPortrayal in which to draw the trails properly.

Let's say you have a 2D field called "field" (we strongly suggest only using trails in SparseGrid2D or in Continuous2D because of the costs involved in other spaces). That field is presently being portrayed by a FieldPortrayal2D called, say, "fieldPortrayal". fieldPortrayal2D is presently using a SimplePortrayal2D (we'll call it "simple") to draw those objects. It's possible for the objects to draw themselves if you like. fieldPortrayal is presently attached to a Display2D called "display".

To add trails, what you'll do is create a second FieldPortrayal2D, identical to fieldPortrayal, and which portrays the same field. Let's call this one trailfieldportrayal. Attach trailfieldportrayal to the display immediately *before* fieldPortrayal is attached, so the objects in fieldPortrayal get drawn on top of the trails.

Next you'll need to specify the SimplePortrayal2D for trailfieldportrayal. To do this, you'll use a TrailPortrayal2D wrapped around a child SimplePortrayal2D, specifically, the same kind of SimplePortrayal2D as "simple" was. In fact you can use "simple" itself if you like. If your objects portray themselves, pass in null as the child portrayal instead. This child portrayal won't be drawn and won't be inspected: it exists solely to enable the TrailPortrayal2D to determine whether an object has been SELECTED and if it should start drawing the trail. That is, it's used for hit testing.

It's important that you provide a SEPARATE TrailPortrayal2D for EVERY SINGLE object in trailfieldportrayal. That is, you register it using FieldPortrayal.setPortrayalForObject rather than FieldPortrayal.setPortrayalForAll or some-such. This is because TrailPortrayal2D only maintains one trail at a time, so if you select another object, the previous trail appears to be attached to that other object (which is wrong). If you use separate TrailPortrayal2Ds, each will manage the trail for the various objects in the field (which is right, but memory expensive and a bit slow).

Alternatively you can provide a single TrailPortrayal2D via FieldPortrayal.setPortrayalForAll but set onlyGrowTrailWhenSelected to FALSE. This will cause the TrailPortrayal2D to *begin* growing the trail each time a new object is selected. It uses a lot less memory and is faster but may not produce the effect you desire.

You can also cause all the TrailPortrayal2Ds to draw trails regardless of selection: just set onlyShowTrailWhenSelected to FALSE (and make sure you have separate TrailPortrayal2Ds for each object in the field). This is a rare need.

To draw the actual trail segements, TrailPortrayal2D relies on a SECOND subsidiary SimplePortrayal2D called "trail". You can either provide your own custom SimplePortrayal2D or use the default one, which draws half-thick line segments of different colors. Either way, this "trail" SimplePortrayal2D will be passed a TrailedPortrayal2D.TrailDrawInfo2D, which is a special version of DrawInfo2D which contains the previous point and also a value from 0.0 to 1.0 indicating how far back in time the segement is supposed to be -- you can use that to figure out what color to draw with, for example.

To handle big jumps (particularly toroidal wrap-arounds) elegantly, TrailedPortrayal2D has a maximumJump percentage. For a jump to be drawn, it must be LESS than this percentage of the total width or height of the underlying field.

See Also:
  • Field Details

    • child

      public SimplePortrayal2D child
      The Child portrayal of this portrayal: a SimplePortrayal2D used solely for determining hit testing.
    • trail

      public SimplePortrayal2D trail
      The SimplePortrayal2D used to draw line segments in the trail.
    • DEFAULT_MAXIMUM_JUMP

      public static final double DEFAULT_MAXIMUM_JUMP
      See Also:
    • maximumJump

      public double maximumJump
    • DEFAULT_MIN_COLOR

      public static final Color DEFAULT_MIN_COLOR
    • DEFAULT_MAX_COLOR

      public static final Color DEFAULT_MAX_COLOR
  • Constructor Details

    • TrailedPortrayal2D

      public TrailedPortrayal2D(GUIState state, SimplePortrayal2D child, FieldPortrayal2D fieldPortrayal, SimplePortrayal2D trail, double length)
      Creates a TrailedPortrayal2D for a given child portrayal, field portrayal for the trail, trail portrayal, and length in time.
    • TrailedPortrayal2D

      public TrailedPortrayal2D(GUIState state, SimplePortrayal2D child, FieldPortrayal2D fieldPortrayal, double length, Color minColor, Color maxColor)
      Creates a TrailedPortrayal2D for a given child portrayal, field portrayal for the trail, length in time, using a default trail portrayal going from minColor to maxColor through time.
    • TrailedPortrayal2D

      public TrailedPortrayal2D(GUIState state, SimplePortrayal2D child, FieldPortrayal2D fieldPortrayal, double length)
      Creates a TrailedPortrayal2D for a given child portrayal, field portrayal for the trail, length in time, using a default trail portrayal with default settings.
  • Method Details

    • setOnlyGrowTrailWhenSelected

      public void setOnlyGrowTrailWhenSelected(boolean val)
      Set this to grow the trail only after the objet has been selected, and delete it when the object has been deselected. By default this is FALSE. If you set this to TRUE, you can use the same TrailedPortrayal2D repeatedly for all objects in your field rather than providing separate ones for separate objects; furthermore only one trail will exist at a time, reducing memory costs.
    • setGrowTrailOnlyWhenSelected

      public void setGrowTrailOnlyWhenSelected(boolean val)
      Deprecated.
      use setOnlyGrowTrailWhenSelected
    • getOnlyGrowTrailWhenSelected

      public boolean getOnlyGrowTrailWhenSelected()
      Returns whether or not to grow the trail only after the objet has been selected, and delete it when the object has been deselected. By default this is FALSE. If you set this to TRUE, you can use the same TrailedPortrayal2D repeatedly for all objects in your field rather than providing separate ones for separate objects; furthermore only one trail will exist at a time, reducing memory costs.
    • getGrowTrailOnlyWhenSelected

      public boolean getGrowTrailOnlyWhenSelected()
      Deprecated.
      use getOnlyGrowTrailWhenSelected
    • setOnlyShowTrailWhenSelected

      public void setOnlyShowTrailWhenSelected(boolean val)
      Set this to draw the trail only when the object has been selected (or not). By default this is TRUE.
    • getOnlyShowTrailWhenSelected

      public boolean getOnlyShowTrailWhenSelected()
      Returns whether or not to draw the trail only when the object has been selected (or not). By default this is TRUE.
    • setLength

      public void setLength(double val)
      Sets the length of the trail in TIME. If an object was at a location further back than the length, the segment for that location won't be drawn any more.
    • getLength

      public double getLength()
      Returns the length of the trail in TIME. If an object was at a location further back than the length, the segment for that location won't be drawn any more.
    • setMaximumJump

      public void setMaximumJump(double val)
      Sets the maximum percentage of either the width or height of the field that can be jumped between two successive object locations before it's considered to be a huge leap and that segment won't be drawn. Huge leaps usually happen because of toroidal wrap-around. By default the value is 0.75. If you'd like all jumps to be drawn regardless of their size, set this to 1.0.
    • getMaximumJump

      public double getMaximumJump()
      Returns the maximum percentage of either the width or height of the field that can be jumped between two successive object locations before it's considered to be a huge leap and that segment won't be drawn. Huge leaps usually happen because of toroidal wrap-around. By default the value is 0.75. If you'd like all jumps to be drawn regardless of their size, set this to 1.0.
    • draw

      public void draw(Object object, Graphics2D graphics, DrawInfo2D info)
      Description copied from interface: Portrayal2D
      Draw a the given object with an origin at (info.draw.x, info.draw.y), and with the coordinate system scaled by so that 1 unit is in the x and y directions are equal to info.draw.width and info.draw.height respectively in pixels. The rectangle given by info.clip specifies the only region in which it is necessary to draw. If info.precise is true, try to draw using real-valued high-resolution drawing rather than faster integer drawing. It is possible that object is null. The location of the object in the field may (and may not) be stored in info.location. The form of that location varies depending on the kind of field used.
      Specified by:
      draw in interface Portrayal2D
      Overrides:
      draw in class SimplePortrayal2D
    • hitObject

      public boolean hitObject(Object object, DrawInfo2D range)
      Description copied from class: SimplePortrayal2D
      Return true if the given object, when drawn, intersects with a provided rectangle, for hit testing purposes. The object is drawn with an origin at (info.draw.x, info.draw.y), and with the coordinate system scaled by so that 1 unit is in the x and y directions are equal to info.draw.width and info.draw.height respectively in pixels. The rectangle given by info.clip specifies the region to do hit testing in; often this region is actually of 0 width or height, which might represent a single point. It is possible that object is null. The location of the object in the field may (and may not) be stored in info.location. The form of that location varies depending on the kind of field used.
      Overrides:
      hitObject in class SimplePortrayal2D
    • setSelected

      public boolean setSelected(LocationWrapper wrapper, boolean selected)
      Description copied from interface: Portrayal
      Change the portrayal state to reflect the fact that you've been selected or not selected. Always return true, except if you've received a setSelected(true) and in fact do not wish to be selectable, in which case return false in that sole situation.
      Specified by:
      setSelected in interface Portrayal
      Overrides:
      setSelected in class SimplePortrayal2D
    • getInspector

      public Inspector getInspector(LocationWrapper wrapper, GUIState state)
      Description copied from interface: Portrayal
      Provide an inspector for an object.
      Specified by:
      getInspector in interface Portrayal
      Overrides:
      getInspector in class SimplePortrayal2D
    • getName

      public String getName(LocationWrapper wrapper)
      Description copied from interface: Portrayal
      Returns a static, one-line name for the given object that is useful for a human to distinguish it from other objects. A simple default would be just to return "" + object.
      Specified by:
      getName in interface Portrayal
      Overrides:
      getName in class SimplePortrayal2D
    • handleMouseEvent

      public boolean handleMouseEvent(GUIState guistate, Manipulating2D manipulating, LocationWrapper wrapper, MouseEvent event, DrawInfo2D fieldPortrayalDrawInfo, int type)
      Description copied from class: SimplePortrayal2D
      Optionally handles a mouse event. At present, events are sent to SimplePortrayal2Ds representing objects which have been either selected or are presently hit by the event coordinates. The wrapper provides the field portrayal, object location, and object. Also provided are the display, event, the DrawInfo2D for the field portrayal, and the type of mouse event situation (either because the object was SELECTED or because it was HIT).

      To indicate that the event was handled, return true. The default blank implementation of this method simply returns false. Events are first sent to portrayals selected objects, until one of them handles the event. If none handled the event, then events are sent to portrayals of objects hit by the event, until one of *them* handles the event. If still no one has handled the event, then the Display2D will route the event to built-in mechanisms such selecting the object or inspecting it.

      If you're modifying or querying the model as a result of this event, be sure to lock on guistate.state.schedule before you do so.

      Overrides:
      handleMouseEvent in class SimplePortrayal2D