00001 package edu.stanford.hci.r3.pen.ink;
00002
00003 import java.awt.geom.Point2D;
00004 import java.awt.geom.Rectangle2D;
00005 import java.lang.reflect.Method;
00006 import java.util.ArrayList;
00007 import java.util.List;
00008
00009 import edu.stanford.hci.r3.pen.PenSample;
00010 import edu.stanford.hci.r3.tools.develop.inkapibrowser.HideFromFlash;
00011 import edu.stanford.hci.r3.util.DebugUtils;
00012
00025 public class InkUtils {
00026
00038 public static List<Ink> clusterStrokes(List<InkStroke> strokes, final double margin) {
00039
00040 class Cluster extends Ink {
00041 private Rectangle2D bounds;
00042
00043 void add(InkStroke stroke) {
00044 super.addStroke(stroke);
00045 Rectangle2D strokeBounds = expand(stroke.getBounds());
00046 if (bounds == null)
00047 bounds = strokeBounds;
00048 else
00049 bounds.add(strokeBounds);
00050 }
00051
00052 private Rectangle2D expand(Rectangle2D r) {
00053 double dx = r.getWidth() * margin / 2;
00054 double dy = r.getHeight() * margin / 2;
00055 return new Rectangle2D.Double(r.getX() - dx, r.getY() - dy, r.getWidth() + dx * 2, r
00056 .getHeight()
00057 + dy * 2);
00058 }
00059
00060 boolean matches(InkStroke stroke) {
00061 return expand(stroke.getBounds()).intersects(bounds);
00062 }
00063 }
00064
00065 List<Cluster> clusters = new ArrayList<Cluster>();
00066
00067 for (InkStroke stroke : strokes) {
00068 Cluster foundCluster = null;
00069 for (Cluster cluster : clusters) {
00070 if (cluster.matches(stroke)) {
00071 foundCluster = cluster;
00072 break;
00073 }
00074 }
00075 if (foundCluster == null) {
00076 foundCluster = new Cluster();
00077 clusters.add(foundCluster);
00078 }
00079 foundCluster.add(stroke);
00080 }
00081
00082 return new ArrayList<Ink>(clusters);
00083 }
00084
00094 public static List<InkStroke> getAllStrokesContainedWithin(List<Ink> inkWell, InkStroke container) {
00095
00096
00097 Rectangle2D bounds = container.getBounds();
00098
00099
00100
00101 List<InkStroke> matchingStrokes = new ArrayList<InkStroke>();
00102 for (Ink ink : inkWell) {
00103 List<InkStroke> strokes = ink.getStrokes();
00104 for (InkStroke stroke : strokes) {
00105 if (bounds.contains(stroke.getBounds()) && !container.equals(stroke)) {
00106
00107 matchingStrokes.add(stroke);
00108 }
00109 }
00110 }
00111 return matchingStrokes;
00112 }
00113
00123 public static List<InkStroke> getAllStrokesOutside(List<Ink> inkWell, InkStroke container) {
00124
00125
00126 Rectangle2D bounds = container.getBounds();
00127
00128
00129 List<InkStroke> matchingStrokes = new ArrayList<InkStroke>();
00130 for (Ink ink : inkWell) {
00131 List<InkStroke> strokes = ink.getStrokes();
00132 for (InkStroke stroke : strokes) {
00133 if (!bounds.intersects(stroke.getBounds())) {
00134
00135 matchingStrokes.add(stroke);
00136 }
00137 }
00138 }
00139 return matchingStrokes;
00140 }
00141
00147 @HideFromFlash()
00148 public static List<Method> getExposedMethods() {
00149 Method[] methods = InkUtils.class.getMethods();
00150 Class<InkUtils> c = InkUtils.class;
00151 Class<?> s = c.getSuperclass();
00152
00153 List<Method> methodsToReturn = new ArrayList<Method>();
00154
00155 for (Method m : methods) {
00156 Class<?> declaringClass = m.getDeclaringClass();
00157 if (c.equals(declaringClass)) {
00158
00159
00160 if (m.isAnnotationPresent(HideFromFlash.class)) {
00161
00162 } else {
00163
00164 methodsToReturn.add(m);
00165 }
00166 }
00167 }
00168 return methodsToReturn;
00169 }
00170
00182 public static Ink getInkNearPoint(List<Ink> inkWell, Point2D point, double range) {
00183
00184 Rectangle2D pointRange = new Rectangle2D.Double(point.getX() - range, point.getY() - range,
00185 range * 2, range * 2);
00186 for (Ink ink : inkWell)
00187 for (InkStroke stroke : ink.getStrokes())
00188 if (pointRange.intersects(stroke.getBounds()))
00189 return ink;
00190 return null;
00191 }
00192
00197 public static double getMaxDistanceBetweenSamples(InkStroke stroke) {
00198 List<PenSample> samples = stroke.getSamples();
00199 PenSample currSample = samples.get(0);
00200 double maxDistance = Double.MIN_VALUE;
00201 for (PenSample s : samples) {
00202 maxDistance = Math.max(s.getDistanceFrom(currSample), maxDistance);
00203 currSample = s;
00204 }
00205 return maxDistance;
00206 }
00207
00217 public static List<InkStroke> getStrokesPartlyOutside(List<Ink> inkWell, InkStroke container) {
00218
00219
00220 Rectangle2D bounds = container.getBounds();
00221
00222
00223
00224 List<InkStroke> matchingStrokes = new ArrayList<InkStroke>();
00225 for (Ink ink : inkWell) {
00226 List<InkStroke> strokes = ink.getStrokes();
00227 for (InkStroke stroke : strokes) {
00228 Rectangle2D strokeBounds = stroke.getBounds();
00229 if (bounds.intersects(strokeBounds) && !bounds.contains(strokeBounds)) {
00230
00231 matchingStrokes.add(stroke);
00232 }
00233 }
00234 }
00235 return matchingStrokes;
00236 }
00237
00245 public static InkStroke getStrokeWithLargestArea(List<Ink> inkWell) {
00246 InkStroke biggestStroke = null;
00247 double maxArea = Double.MIN_VALUE;
00248
00249 for (Ink ink : inkWell) {
00250 List<InkStroke> strokes = ink.getStrokes();
00251 for (InkStroke stroke : strokes) {
00252
00253 double area = stroke.getArea();
00254 if (area > maxArea) {
00255 biggestStroke = stroke;
00256 maxArea = area;
00257 }
00258 }
00259 }
00260
00261 DebugUtils.println(biggestStroke);
00262 return biggestStroke;
00263 }
00264
00271 public static Ink getStrokeWithMostSamples(Ink ink) {
00272 List<InkStroke> matchingStrokes = new ArrayList<InkStroke>();
00273 List<InkStroke> strokes = ink.getStrokes();
00274
00275 int maxNumSamples = 0;
00276 InkStroke longestStroke = null;
00277
00278 for (InkStroke stroke : strokes) {
00279 int numSamples = stroke.getNumSamples();
00280 DebugUtils.println(numSamples);
00281 if (numSamples > maxNumSamples) {
00282 DebugUtils.println("Longest");
00283 longestStroke = stroke;
00284 maxNumSamples = numSamples;
00285 }
00286 }
00287 if (longestStroke != null) {
00288 matchingStrokes.add(longestStroke);
00289 }
00290 return new Ink(matchingStrokes);
00291 }
00292
00296 @HideFromFlash
00297 public static void main(String[] args) {
00298 InkUtils.getExposedMethods();
00299 }
00300 }