Java Source Code: org.opensourcephysics.displayejs.InteractiveParticle


   1: /*
   2:  * The display3D package contains 3D drawing classes and drawables
   3:  * @author F. Esquembre (http://fem.um.es).
   4:  * Last version : July 2003
   5:  */
   6: 
   7: package org.opensourcephysics.displayejs;
   8: 
   9: import java.awt.*;
  10: import java.awt.geom.*;
  11: import org.opensourcephysics.display.*;
  12: 
  13: /**
  14:  * An InteractiveParticle is an InteractiveElement that displays a RectangularShape
  15:  */
  16:	  public class InteractiveParticle extends AbstractInteractiveElement {
  17:  public final static int NONE             = 0;
  18:  public final static int ELLIPSE          = 1;
  19:  public final static int RECTANGLE        = 2;
  20:  public final static int ROUND_RECTANGLE  = 3;
  21:  public final static int WHEEL            = 4;
  22:
  23:  /* Configuration variables */
  24:  protected int shapeType = -1;  // Make sure an shape is created
  25:
  26:  /* Implementation variables */
  27:  protected double a1=0.0, b1=0.0; // the final coordinates for the Shape's origin
  28://  protected double a2=0.0, b2=0.0; // the final coordinates for the (other end) Shape's corner
  29://  protected double dx, dy; // The displacement from the center
  30:  protected double[] coordinates  = new double[6]; // the input for all projections
  31:  protected double[] pixelOrigin  = new double[5]; // The projection of the origin (and size)
  32:  protected Object3D[] objects    = new Object3D[] { new Object3D(this,0) };
  33:  protected AffineTransform transform = new AffineTransform();
  34:
  35:  /**
  36:   * Default constructor
  37:   */
  38:  public InteractiveParticle () { this(ELLIPSE); }
  39:
  40:  /**
  41:   * Constructor that accepts a given type. Either ELLIPSE, RECTANGLE, ROUND_RECTANGLE or NONE (a dot will be displayed)
  42:   */
  43:	    public InteractiveParticle (int _type) {
  44:    setShapeType(_type);
  45:  }
  46:
  47:// -------------------------------------
  48:// New configuration methods
  49:// -------------------------------------
  50:  /**
  51:   * Set the type of the marker
  52:   */
  53:	    public void setShapeType (int _type) {
  54:    if (shapeType==_type) return;
  55:    shapeType = _type;
  56:	      switch (shapeType) {
  57:      default :
  58:      case NONE            : style.displayObject = null; break;
  59:      case WHEEL           :
  60:      case ELLIPSE         : style.displayObject = new Ellipse2D.Float(); break;
  61:      case RECTANGLE       : style.displayObject = new Rectangle2D.Float(); break;
  62:      case ROUND_RECTANGLE : style.displayObject = new RoundRectangle2D.Float(); break;
  63:    }
  64:  }
  65:
  66:// ----------------------------------------------
  67:// Implementation of Interactive and Drawable3D
  68:// ----------------------------------------------
  69:
  70:  // method added by W. Christian
  71:  protected double[] getPixelOrigin(){ return pixelOrigin; }
  72:
  73:	    public org.opensourcephysics.display.Interactive findInteractive (DrawingPanel _panel, int _xpix, int _ypix) {
  74:    if (!visible) return null;
  75:    if (hasChanged || _panel!=panelWithValidProjection) projectPoints (_panel);
  76:    // In 3D it is not possible to change size interactively, due to the effect of style.position and style.angle
  77://    if (sizeEnabled      && Math.abs(a2-_xpix)<SENSIBILITY               && Math.abs(b2-_ypix)<SENSIBILITY)               return sizeTarget;
  78:    if (positionEnabled && Math.abs(pixelOrigin[0]-_xpix)<SENSIBILITY && Math.abs(pixelOrigin[1]-_ypix)<SENSIBILITY) return new InteractionTargetElementPosition(this);
  79:    return null;
  80:   }
  81:
  82:	    public Object3D[] getObjects3D(DrawingPanel3D _panel) {
  83:    if (!visible) return null;
  84:    if (hasChanged || _panel!=panelWithValidProjection) projectPoints (_panel);
  85:    return objects;
  86:  }
  87:
  88:  // No need to project, projection has already been computed in getObjects3D
  89:	    public void draw (DrawingPanel3D _panel, Graphics2D _g2, int _index) {
  90:    // Allow the panel to adjust color according to depth
  91:    Color theColor = ((DrawingPanel3D)_panel).projectColor(style.edgeColor,objects[0].distance);
  92:    Paint theFillPattern = style.fillPattern;
  93:    if (theFillPattern instanceof Color)
  94:      theFillPattern = ((DrawingPanel3D)_panel).projectColor((Color) theFillPattern,objects[0].distance);
  95:    drawIt (_g2,theColor,theFillPattern);
  96:  }
  97:
  98:	    public void drawQuickly (DrawingPanel3D _panel, Graphics2D _g2) {
  99:    if (!visible) return;
 100:    if (hasChanged || _panel!=panelWithValidProjection) projectPoints (_panel);
 101:    drawIt (_g2, style.edgeColor,style.fillPattern);
 102:  }
 103:
 104:	    public void draw (DrawingPanel _panel, Graphics _g) {
 105:    if (!visible) return;
 106://    if (hasChanged || _panel!=panelWithValidProjection)
 107:    projectPoints (_panel); // DrawingPanel still doesn't implement the call to needsToProject()
 108:    drawIt ((Graphics2D) _g, style.edgeColor,style.fillPattern);
 109:  }
 110:
 111:// -------------------------------------
 112://  Private methods
 113:// -------------------------------------
 114:
 115:	    protected void projectPoints (DrawingPanel _panel) {
 116:    // System.out.println("Projecting particle");
 117:	      if (group!=null) {
 118:      coordinates[0] = group.x + x*group.sizex;  coordinates[1] = group.y + y*group.sizey; coordinates[2] = group.z + z*group.sizez;
 119:      coordinates[3] = sizex*group.sizex;        coordinates[4] = sizey*group.sizey;       coordinates[5] = sizez*group.sizez;
 120:    }
 121:	      else {
 122:      coordinates[0] = x;     coordinates[1] = y;     coordinates[2] = z;
 123:      coordinates[3] = sizex; coordinates[4] = sizey; coordinates[5] = sizez;
 124:    }
 125:    _panel.project(coordinates,pixelOrigin);
 126:    objects[0].distance = pixelOrigin[4];
 127:    double dx, dy;
 128:	      switch (style.position) {
 129:      default :
 130:      case Style.CENTERED:   dx =pixelOrigin[2]/2.0; dy =pixelOrigin[3]/2.0; break;
 131:      case Style.NORTH:      dx =pixelOrigin[2]/2.0; dy = 0.0;               break;
 132:      case Style.SOUTH:      dx =pixelOrigin[2]/2.0; dy =pixelOrigin[3];     break;
 133:      case Style.EAST:       dx =pixelOrigin[2];     dy =pixelOrigin[3]/2.0; break;
 134:      case Style.SOUTH_EAST: dx =pixelOrigin[2];     dy =pixelOrigin[3];     break;
 135:      case Style.NORTH_EAST: dx =pixelOrigin[2];     dy = 0.0;               break;
 136:      case Style.WEST:       dx = 0.0;               dy =pixelOrigin[3]/2.0; break;
 137:      case Style.SOUTH_WEST: dx = 0.0;               dy =pixelOrigin[3];     break;
 138:      case Style.NORTH_WEST: dx = 0.0;               dy = 0.0;               break;
 139:    }
 140:    a1 = pixelOrigin[0] - dx;
 141:    b1 = pixelOrigin[1] - dy;
 142://    a2 = pixelOrigin[0] + dx*style.cosAngle - dy*style.sinAngle;
 143://    b2 = pixelOrigin[1] - dx*style.sinAngle - dy*style.cosAngle;
 144:    hasChanged = false;
 145:    panelWithValidProjection = _panel;
 146:  }
 147:
 148:	    private void drawIt (Graphics2D _g2, Color _color, Paint _fill) {
 149:    // System.out.println("Drawing particle ");
 150:	      if (! (style.displayObject instanceof RectangularShape) ) {
 151:      _g2.setColor(_color);
 152:      _g2.drawOval( (int) pixelOrigin[0], (int) pixelOrigin[1], 1, 1); // draw a point
 153:      return;
 154:    }
 155:    RectangularShape shape = (RectangularShape) style.displayObject;
 156:    AffineTransform originalTransform = _g2.getTransform();
 157:    transform.setTransform(originalTransform);
 158:    transform.rotate(-style.angle,pixelOrigin[0],pixelOrigin[1]);
 159:    _g2.setTransform(transform);
 160:    shape.setFrame(a1,b1,pixelOrigin[2],pixelOrigin[3]);
 161:	      if (_fill!=null) { // First fill the inside
 162:      _g2.setPaint(_fill);
 163:      _g2.fill(shape);
 164:    }
 165:    _g2.setColor (_color);
 166:    _g2.setStroke(style.edgeStroke);
 167:	      if (shapeType==WHEEL) {
 168:      int c = (int) (b1 + pixelOrigin[3]/2); // centerY
 169:      _g2.drawLine((int) a1, c, (int) (a1+pixelOrigin[2]), c);
 170:      c = (int) (a1 + pixelOrigin[2]/2);     // centerX
 171:      _g2.drawLine(c, (int) b1, c, (int) (b1+pixelOrigin[3]));
 172:    }
 173:    _g2.draw(shape); // Second, draw the edge
 174:    _g2.setTransform(originalTransform);
 175:  }
 176:}