00001 package edu.stanford.hci.r3.pen.ink;
00002
00003 import java.util.ArrayList;
00004 import java.util.LinkedList;
00005 import java.util.List;
00006
00007 import edu.stanford.hci.r3.pen.PenSample;
00008 import edu.stanford.hci.r3.util.DebugUtils;
00009 import edu.stanford.hci.r3.util.MathUtils;
00010
00032 public class InkSimplification {
00033
00034 private int maxNumSamples = 3;
00035
00036 private LinkedList<PenSample> recentSamples = new LinkedList<PenSample>();
00037
00038 public InkSimplification() {
00039
00040 }
00041
00047 public boolean processNewSample(PenSample sample) {
00048 recentSamples.add(sample);
00049 if (recentSamples.size() <= maxNumSamples) {
00050
00051 return true;
00052 } else {
00053
00054
00055
00056 double maxDR = Double.MIN_VALUE;
00057 double maxDT = Double.MIN_VALUE;
00058
00059
00060 PenSample firstSample = recentSamples.getFirst();
00061 double firstX = firstSample.x;
00062 double firstY = firstSample.y;
00063
00064 double firstTS = firstSample.timestamp;
00065
00066 List<Double> dThetas = new ArrayList<Double>();
00067
00068 for (PenSample s : recentSamples) {
00069
00070 if (s.equals(firstSample)) {
00071 continue;
00072 }
00073
00074 double dX = s.getX() - firstX;
00075 double dY = s.getY() - firstY;
00076 double dT = s.getTimestamp() - firstTS;
00077
00078 double dR = Math.sqrt(dX * dX + dY * dY);
00079 double dTheta = Math.atan2(dY, dX);
00080 dThetas.add(dTheta);
00081
00082 maxDR = Math.max(dR, maxDR);
00083 maxDT = Math.max(dT, maxDT);
00084 }
00085
00086
00087 boolean shouldKeepNewSample = true;
00088
00089
00090
00091 if (maxDR < 30) {
00092 shouldKeepNewSample = false;
00093 }
00094
00095
00096 double stdevTheta = MathUtils.standardDeviation(dThetas.toArray(new Double[0]));
00097
00098 if (stdevTheta > 1) {
00099 shouldKeepNewSample = true;
00100 }
00101
00102
00103
00104 if (maxDT > 100) {
00105 shouldKeepNewSample = true;
00106 }
00107
00108
00109 if (maxDR < 5) {
00110 shouldKeepNewSample = false;
00111 }
00112
00113 if (shouldKeepNewSample) {
00114
00115 recentSamples.removeFirst();
00116 } else {
00117
00118 recentSamples.removeLast();
00119 }
00120
00121 return shouldKeepNewSample;
00122 }
00123 }
00124
00128 public void reset() {
00129 recentSamples.clear();
00130 }
00131
00135 public void simplifyStroke(InkStroke currentStroke) {
00136 reset();
00137
00138 List<PenSample> samples = currentStroke.getSamples();
00139 List<PenSample> newSamples = new ArrayList<PenSample>();
00140
00141 for (PenSample s : samples) {
00142 boolean shouldKeep = processNewSample(s);
00143 if (shouldKeep) {
00144 newSamples.add(s);
00145 }
00146 }
00147
00148
00149 PenSample lastSample = samples.get(samples.size() - 1);
00150 if (!newSamples.contains(lastSample)) {
00151 newSamples.add(lastSample);
00152 }
00153
00154 currentStroke.setSamples(newSamples);
00155 }
00156 }