00001 package edu.stanford.hci.r3.pattern.calibrate;
00002
00003 import java.io.File;
00004 import java.util.List;
00005
00006 import javax.swing.JFileChooser;
00007
00008 import edu.stanford.hci.r3.PaperToolkit;
00009 import edu.stanford.hci.r3.pattern.coordinates.PageAddress;
00010 import edu.stanford.hci.r3.pen.ink.Ink;
00011 import edu.stanford.hci.r3.pen.ink.InkStroke;
00012 import edu.stanford.hci.r3.util.DebugUtils;
00013 import edu.stanford.hci.r3.util.files.FileUtils;
00014
00026 public class CalibrationEngine {
00027
00035 public static void main(String[] args) {
00036 PaperToolkit.initializeLookAndFeel();
00037
00038
00039 JFileChooser chooser = FileUtils.createNewFileChooser(new String[] { "xml" });
00040 chooser.setCurrentDirectory(new File("data/calibration/"));
00041 chooser.setMultiSelectionEnabled(true);
00042 int result = chooser.showDialog(null, "Align Two XML Files");
00043
00044
00045 if (result == JFileChooser.APPROVE_OPTION) {
00046 File[] selectedFiles = chooser.getSelectedFiles();
00047 if (selectedFiles.length < 2) {
00048 DebugUtils.println("Please select at least two XML files...");
00049 } else {
00050
00051 File streamed = null;
00052 File batched = null;
00053
00054 for (File f : selectedFiles) {
00055 final String fileName = f.getName();
00056 if (streamed == null && fileName.contains("streamed")) {
00057
00058 streamed = f;
00059 }
00060 if (batched == null && fileName.contains("batched")) {
00061
00062 batched = f;
00063 }
00064
00065 if ((streamed != null) && (batched != null)) {
00066
00067 new CalibrationEngine().alignInkStrokes(new Ink(streamed), new Ink(batched));
00068 }
00069 }
00070 }
00071 }
00072 }
00073
00078 public void alignInkStrokes(Ink streamedInk, Ink batchedInk) {
00079 final int numStreamedStrokes = streamedInk.getNumStrokes();
00080 final int numBatchedStrokes = batchedInk.getNumStrokes();
00081
00082 if (numStreamedStrokes != numBatchedStrokes) {
00083 DebugUtils
00084 .println("The number of strokes do not match. We will try our best to align the two...");
00085 }
00086
00087 DebugUtils.println(numStreamedStrokes + " streamed strokes.");
00088 DebugUtils.println(numBatchedStrokes + " batched strokes.");
00089
00090 final List<InkStroke> streamedStrokes = streamedInk.getStrokes();
00091 final List<InkStroke> batchedStrokes = batchedInk.getStrokes();
00092
00093 final PageAddress bPageAddress = batchedInk.getSourcePageAddress();
00094
00095 double avgMillisBehind = 0;
00096 double numSamples = 0;
00097
00098 for (int i = 0; i < streamedStrokes.size(); i++) {
00099 DebugUtils.println("Aligning Stroke");
00100 InkStroke sStroke = streamedStrokes.get(i);
00101 InkStroke bStroke = batchedStrokes.get(i);
00102
00103 int[] sForceSamples = sStroke.getForceSamples();
00104 int[] bForceSamples = bStroke.getForceSamples();
00105
00106 long[] sTimeSamples = sStroke.getTimeSamples();
00107 long[] bTimeSamples = bStroke.getTimeSamples();
00108
00109 double[] sSamplesX = sStroke.getXSamples();
00110 double[] bSamplesX = bStroke.getXSamples();
00111
00112 double[] sSamplesY = sStroke.getYSamples();
00113 double[] bSamplesY = bStroke.getYSamples();
00114
00115 for (int j = 0; j < sForceSamples.length; j++) {
00116 if (sForceSamples[j] == bForceSamples[j]) {
00117 final double millisBehind = (sTimeSamples[j] - bTimeSamples[j]);
00118 final String behindOrAhead = getBehindOrAheadString(millisBehind);
00119
00120 final double currStreamedX = sSamplesX[j];
00121 final double currStreamedY = sSamplesY[j];
00122 final double currBatchedY = bSamplesY[j];
00123 final double currBatchedX = bSamplesX[j];
00124
00125 DebugUtils.println("Streamed: " + currStreamedX + ", " + currStreamedY + " <--> "
00126 + currBatchedX + ", " + currBatchedY + " on page " + bPageAddress
00127 + " with the Pen's Clock" + behindOrAhead + "by " + Math.abs(millisBehind)
00128 + " milliseconds.");
00129
00130
00131 numSamples++;
00132 avgMillisBehind = (avgMillisBehind * ((numSamples - 1) / numSamples))
00133 + (millisBehind / numSamples);
00134
00135
00136 final double offsetX = currStreamedX - currBatchedX;
00137 final double offsetY = currStreamedY - currBatchedY;
00138
00139 DebugUtils.println(offsetX + " " + offsetY);
00140
00141 }
00142 }
00143 }
00144
00145 DebugUtils.println("After " + numSamples + " samples, we find that the Pen's Clock is"
00146 + getBehindOrAheadString(avgMillisBehind) + "by " + Math.abs(avgMillisBehind)
00147 + " milliseconds, on average.");
00148 }
00149
00154 private String getBehindOrAheadString(double millisBehind) {
00155 String behindOrAhead = (millisBehind < 0) ? " ahead " : " behind ";
00156 return behindOrAhead;
00157 }
00158 }