Package gml4u.recording

Source Code of gml4u.recording.GmlRecorder

package gml4u.recording;

import gml4u.model.Gml;
import gml4u.model.GmlBrush;
import gml4u.model.GmlClient;
import gml4u.model.GmlConstants;
import gml4u.model.GmlPoint;
import gml4u.model.GmlStroke;
import gml4u.utils.Vec3DUtils;

import java.util.ArrayList;
import java.util.Collection;
import java.util.concurrent.ConcurrentHashMap;
import java.util.logging.Level;
import java.util.logging.Logger;

import toxi.geom.AABB;
import toxi.geom.Vec3D;

public class GmlRecorder {
 
  private static final Logger LOGGER = Logger.getLogger(GmlRecorder.class.getName());
 
  public static final float DEFAULT_MIN_STROKE_LENGTH = 0.01f;
  public static final float DEFAULT_MIN_POINTS_DISTANCE = 0.001f;

  private Gml gml;
  private float minStrokeLength;
  private float minPointsDistance;
  private AABB boundingBox = AABB.fromMinMax(new Vec3D(0, 0, 0),new Vec3D(1, 1, 1));
  private ConcurrentHashMap<Integer, GmlStroke> strokes = new ConcurrentHashMap<Integer, GmlStroke>();
  private Vec3D normalizer;
 
  /**
   * Creates a new GmlRecorder using the given screen size, minimum stroke length and minimum points distance
   * @param screen - Vec3D (srceen dimensions)
   * @param minStrokeLength - int (minimum length of the stroke)
   * @param minPointsDistance - flaot (minimum distance between two points of the same stroke)
   */
  public GmlRecorder(final Vec3D screen, float minStrokeLength, float minPointsDistance) {
    gml = new Gml();
    initGml(screen);

    this.minStrokeLength = minStrokeLength;
    this.minPointsDistance = minPointsDistance;
  }
 
  /**
   * Creates a new GmlRecorder using the given screen size and default values for minimum stroke length and minimum points distance
   * @param screen (srceen dimensions)
   */
  public GmlRecorder(final Vec3D screen) {
    this(screen, DEFAULT_MIN_STROKE_LENGTH, DEFAULT_MIN_POINTS_DISTANCE);
  }
 
  /**
   * Initializes the Gml with default values
   * @param screen - Vec3D vector (screen dimensions)
   */
  private void initGml(Vec3D screen) {   
    normalizer = new Vec3D(Vec3DUtils.getNormalized(screen));
    gml.client.set(GmlClient.USERNAME, GmlConstants.DEFAULT_CLIENT_NAME);
    gml.environment.screenBounds = new Vec3D(screen);
  }
 
  /**
   * Returns the normalizer used to scale points
   * @return Vec3D
   */
  public Vec3D getNormalizer() {
    return new Vec3D(normalizer);
  }
 
  /**
   * Sets the client information to be used. Overrides the default values
   * @param client - GmlClient
   */
  public void setClient(GmlClient client) {
    gml.client = client;
  }
 
  // TODO setEnvironment(GmlEnvironment environment) Useful ?
  // Also resets the screen and normalizer values
 
  /**
   * Returns the minimum stroke length
   * @return float
   */
  public float getMinStrokeLength() {
    return minStrokeLength;
  }

  /**
   * Sets the min stroke length. If smaller, a stroke won't be added
   * @param length - float
   */
  public void setMinStrokeLength(float length) {
    this.minStrokeLength = length;
  }

  /**
   * Returns the minimum point distance
   * @return float
   */
  public float getMinPointDistance() {
    return minPointsDistance;
  }

  /**
   * Sets the min points distance. If below, a point won't be added
   * Used to minimise the number of points
   * @param distance - float
   */
  public void setMinPointsDistance(float distance) {
    this.minPointsDistance = distance;
  }
 
  /**
   * Clears strokes, including those under recording
   */
  public void clear() {   
    gml.removeStrokes();
    strokes.clear();
  }
 
  /**
   * Begins the recording of a new GmlStroke<br/>
   * Note: you must keep track of the sessionID and use the same ID to end the stroke<br/>
   * otherwise the stroke won't be added to the gml.
   * @param sessionID - int
   */
  public void beginStroke(int sessionID) {

    GmlBrush brush = new GmlBrush();
    int layer = 0;
    beginStroke(sessionID, layer, brush);
  }

  /**
   * Begins the recording of a new GmlStroke<br/>
   * Note: you must keep track of the sessionID and use the same ID to end the stroke<br/>
   * otherwise the stroke won't be added to the gml.
   * @param sessionID - int
   * @param layer - int
   */
  public void beginStroke(int sessionID, int layer) {

    GmlBrush brush = new GmlBrush();
    beginStroke(sessionID, layer, brush);
  }


  /**
   * Begins the recording of a new GmlStroke<br/>
   * Note: you must keep track of the sessionID and use the same ID to end the stroke<br/>
   * otherwise the stroke won't be added to the gml.
   * @param sessionID - int
   * @param layer - int
   * @param brush - GmlBrush
   */
  public void beginStroke(int sessionID, int layer, final GmlBrush brush) {
   
    LOGGER.log(Level.FINEST, "Start recording");
    GmlStroke stroke = new GmlStroke();
    stroke.setLayer(layer);
    stroke.setBrush(brush)
    strokes.put(sessionID, stroke);
  }

  /**
   * Adds a new point to a stroke
   * The point's coordinates shall be within 0-1 on every axis.
   * They'll be scaled automatically according to the screen's ratio
   * @param sessionID - int
   * @param v - Vec3D vetor (shall be within AABB (0,0,0) -> (1,1,1))
   */
  public void addPoint(int sessionID, Vec3D v) {
    addPoint(sessionID, v, 0);
  }
 
  /**
   * Adds a new point to a stroke
   * The point's coordinates shall be within 0-1 on every axis.
   * They'll be scaled automatically according to the screen's ratio
   * @param sessionID - int
   * @param v - Vec3D vetor (shall be within AABB (0,0,0) -> (1,1,1))
   * @param time - float
   */
  public void addPoint(int sessionID, Vec3D v, final float time) {
    addPoint(sessionID, v, time, GmlPoint.DEFAULT_PRESSURE, new Vec3D(), new Vec3D());
  }

 
  /**
   * Adds a new point to a stroke
   * The point's coordinates shall be within 0-1 on every axis.
   * They'll be scaled automatically according to the screen's ratio
   * @param sessionID - int
   * @param v - Vec3D vetor (shall be within AABB (0,0,0) -> (1,1,1))
   * @param time - float
   * @param pressure - float
   * @param rotation - Vec3D
   * @param direction - Vec3D
   */
  public void addPoint(int sessionID, Vec3D v, final float time, final float pressure, final Vec3D rotation, final Vec3D direction) {
    addPoint(sessionID, v, time, pressure, rotation, direction, GmlPoint.DEFAULT_THICKNESS);
  }
 
  /**
   * Adds a new point to a stroke
   * The point's coordinates shall be within 0-1 on every axis.
   * They'll be scaled automatically according to the screen's ratio
   * @param sessionID - int
   * @param v - Vec3D vetor (shall be within AABB (0,0,0) -> (1,1,1))
   * @param time - float
   * @param pressure - float
   * @param rotation - Vec3D
   * @param direction - Vec3D
   * @param thickness - float
   */
  public void addPoint(int sessionID, Vec3D v, final float time, final float pressure, final Vec3D rotation, final Vec3D direction, float thickness) {
    LOGGER.log(Level.FINEST, "Add point");

    // Check bounding box and do not add if outside
    /*
    if (!v.isInAABB(boundingBox)) {
      LOGGER.warn("point skipped : v "+ v + " is outside "+ boundingBox);
    }
    else {
    */
      v.scaleSelf(normalizer);
     
      // Check is sessionID exists (beginStroke has been called before)
      if (null != strokes.get(sessionID)) {
       
        // Check minimum distance from last point
        if (null != strokes.get(sessionID).getLastPoint()) {
          GmlPoint prev = new GmlPoint();
          prev.set(strokes.get(sessionID).getLastPoint());
          if (prev.distanceTo(v) > minPointsDistance) {
            strokes.get(sessionID).addPoint(new GmlPoint(v, time, pressure, rotation, direction, thickness));
          }
          else {
            LOGGER.log(Level.FINE, "Skipped, too close from previous point: "+prev.distanceTo(v));
          }
        }
        else { // First point, add it
          strokes.get(sessionID).addPoint(new GmlPoint(v, time, pressure, rotation, direction, thickness));
        }
      }
    //}
  }

  /**
   * Ends recording of a GmlStroke
   * @param sessionID - int
   */
  public void endStroke(int sessionID) {
    LOGGER.log(Level.FINEST, "Stop recording");
    GmlStroke stroke = strokes.get(sessionID);
    // Add the stroke only if significant (at least a certain length)
    if (null != stroke && stroke.getLength() > minStrokeLength) {
      gml.addStroke(stroke);
    }
    strokes.remove(sessionID);
  }

  /**
   * Ends recording of all GmlStroke
   */
  public void endStrokes() {
    LOGGER.log(Level.FINEST, "Stop recording");
    for (int sessionID : strokes.keySet()) {
      GmlStroke stroke = strokes.get(sessionID);
      // Add the stroke only if significant (at least a certain length)
      if (null != stroke && stroke.getLength() > minStrokeLength) {
        gml.addStroke(stroke);
      }     
    }
    strokes.clear();
  }

  /**
   * Removes the last GmlStroke from the given layer
   * @param layer
   */
  public void removeLastStroke(final int layer) {
    gml.removeLastStroke(layer);
  }
 
  /**
   * Returns  a copy of all GmlStrokes (including those under recording)
   * @return Collection<GmlStroke>
   */
  public Collection<GmlStroke> getStrokes() {
    Collection<GmlStroke> strokeList = new ArrayList<GmlStroke>();
    strokeList.addAll(gml.getStrokes());
    strokeList.addAll(strokes.values());
    return strokeList;
  }
 
  // REMOVE LAST STROKE any layer
 
  /**
   * Returns a copy of the Gml including the strokes under drawing
   * @return Gml
   */
  public Gml getGml() {
    Gml gmlCopy = gml.copy();
    gml.addStrokes(strokes.values());
    return gmlCopy;
  }

  /**
   * Sets the Gml to be used by the GmlRecorder
   * @param gml - Gml
   */
  public void setGml(Gml gml) {
    this.gml = gml;
    // TODO test screen or screenbounds consistency
    initGml(gml.environment.screenBounds);
  }
}
TOP

Related Classes of gml4u.recording.GmlRecorder

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.