00001 package edu.stanford.hci.r3.pen.ink;
00002
00003 import java.awt.geom.Rectangle2D;
00004 import java.util.ArrayList;
00005 import java.util.Collection;
00006 import java.util.Date;
00007 import java.util.List;
00008
00009 import edu.stanford.hci.r3.pen.PenSample;
00010 import edu.stanford.hci.r3.units.PatternDots;
00011 import edu.stanford.hci.r3.units.Units;
00012 import edu.stanford.hci.r3.util.MathUtils;
00013
00034 public class InkStroke {
00035
00039 private static final PatternDots DEFAULT_REFERENCE_UNIT = new PatternDots();
00040
00044 private double maxX = Double.MIN_VALUE;
00045
00049 private double maxY = Double.MIN_VALUE;
00050
00054 private double minX = Double.MAX_VALUE;
00055
00059 private double minY = Double.MAX_VALUE;
00060
00064 private Units referenceUnit;
00065
00069 private List<PenSample> samples = new ArrayList<PenSample>();
00070
00074 private double strokeWidth = 1.2;
00075
00076 public InkStroke() {
00077 referenceUnit = DEFAULT_REFERENCE_UNIT;
00078 }
00079
00087 public InkStroke(Collection<PenSample> currentStrokeSamples, Units reference) {
00088 referenceUnit = reference;
00089 for (PenSample s : currentStrokeSamples) {
00090 addSample(s.x, s.y, s.force, s.timestamp);
00091 }
00092 }
00093
00097 public InkStroke(List<PenSample> stroke) {
00098 this(stroke, DEFAULT_REFERENCE_UNIT);
00099 }
00100
00107 public void addSample(double x, double y, int force, long ts) {
00108 samples.add(new PenSample(x, y, force, ts));
00109
00110
00111 minX = Math.min(x, minX);
00112 minY = Math.min(y, minY);
00113 maxX = Math.max(x, maxX);
00114 maxY = Math.max(y, maxY);
00115 }
00116
00120 public void addSample(PenSample penSample) {
00121 samples.add(penSample);
00122
00123
00124 minX = Math.min(penSample.x, minX);
00125 minY = Math.min(penSample.y, minY);
00126 maxX = Math.max(penSample.x, maxX);
00127 maxY = Math.max(penSample.y, maxY);
00128 }
00129
00133 public double getArea() {
00134 return (maxX - minX) * (maxY - minY);
00135 }
00136
00140 public Rectangle2D getBounds() {
00141 return new Rectangle2D.Double(minX, minY, maxX - minX, maxY - minY);
00142 }
00143
00147 public long getDuration() {
00148 return getLastTimestamp() - getFirstTimestamp();
00149 }
00150
00156 public PenSample getEnd() {
00157 return samples.get(samples.size() - 1);
00158 }
00159
00163 public long getFirstTimestamp() {
00164 return samples.get(0).timestamp;
00165 }
00166
00167 public Date getFirstTimestampAsDate() {
00168 return new Date(samples.get(0).timestamp);
00169 }
00170
00174 public int[] getForceSamples() {
00175 int numSamples = getNumSamples();
00176 int[] f = new int[numSamples];
00177 for (int i = 0; i < numSamples; i++) {
00178 f[i] = samples.get(i).force;
00179 }
00180 return f;
00181 }
00182
00186 public long getLastTimestamp() {
00187 return samples.get(samples.size() - 1).timestamp;
00188 }
00189
00193 public Date getLastTimestampAsDate() {
00194 return new Date(samples.get(samples.size() - 1).timestamp);
00195 }
00196
00200 public double getMaxX() {
00201 return maxX;
00202 }
00203
00207 public double getMaxY() {
00208 return maxY;
00209 }
00210
00214 public double getMinX() {
00215 return minX;
00216 }
00217
00221 public double getMinY() {
00222 return minY;
00223 }
00224
00228 public int getNumSamples() {
00229 return samples.size();
00230 }
00231
00235 public Units getReferenceUnit() {
00236 return referenceUnit;
00237 }
00238
00239 public List<PenSample> getSamples() {
00240 return samples;
00241 }
00242
00248 public PenSample getStart() {
00249 return samples.get(0);
00250 }
00251
00255 public long[] getTimeSamples() {
00256 int numSamples = getNumSamples();
00257 long[] t = new long[numSamples];
00258 for (int i = 0; i < numSamples; i++) {
00259 t[i] = samples.get(i).timestamp;
00260 }
00261 return t;
00262 }
00263
00264 public double getWidth() {
00265 return strokeWidth;
00266 }
00267
00271 public double[] getXSamples() {
00272 int numSamples = getNumSamples();
00273 double[] x = new double[numSamples];
00274 for (int i = 0; i < numSamples; i++) {
00275 x[i] = samples.get(i).x;
00276 }
00277 return x;
00278 }
00279
00283 public int[] getXSamplesAsInts() {
00284 int numSamples = getNumSamples();
00285 int[] xInts = new int[numSamples];
00286 for (int i = 0; i < numSamples; i++) {
00287 xInts[i] = MathUtils.rint(samples.get(i).x);
00288 }
00289 return xInts;
00290 }
00291
00295 public double[] getYSamples() {
00296 int numSamples = getNumSamples();
00297 double[] y = new double[numSamples];
00298 for (int i = 0; i < numSamples; i++) {
00299 y[i] = samples.get(i).y;
00300 }
00301 return y;
00302 }
00303
00307 public int[] getYSamplesAsInts() {
00308 int numSamples = getNumSamples();
00309 int[] yInts = new int[numSamples];
00310 for (int i = 0; i < numSamples; i++) {
00311 yInts[i] = MathUtils.rint(samples.get(i).y);
00312 }
00313 return yInts;
00314 }
00315
00322 public void setBounds(double minStrokeX, double minStrokeY, double maxStrokeX, double maxStrokeY) {
00323 minX = minStrokeX;
00324 minY = minStrokeY;
00325 maxX = maxStrokeX;
00326 maxY = maxStrokeY;
00327 }
00328
00333 public void setMaxX(float mxX) {
00334 maxX = mxX;
00335 }
00336
00341 public void setMaxY(float mxY) {
00342 maxY = mxY;
00343 }
00344
00349 public void setMinX(float mnX) {
00350 minX = mnX;
00351 }
00352
00357 public void setMinY(float mnY) {
00358 minY = mnY;
00359 }
00360
00361 public void setSamples(List<PenSample> newSamples) {
00362 samples = newSamples;
00363 }
00364
00365
00366
00367
00368
00369
00370 public String toString() {
00371 return "InkStroke: Bounds [" + minX + ", " + minY + " --> " + maxX + ", " + maxY + "] "
00372 + getNumSamples() + " Samples with timestamps from [" + getFirstTimestampAsDate() + " to "
00373 + getLastTimestampAsDate() + "]";
00374 }
00375
00376 }