InkUtils.java

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                 // calculate the bounds of the container stroke
00097                 Rectangle2D bounds = container.getBounds();
00098 
00099                 // return any stroke that falls completely within these bounds
00100                 // do not include the original container!
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                                         // the stroke is completely inside the containing stroke
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                 // calculate the bounds of the container stroke
00126                 Rectangle2D bounds = container.getBounds();
00127 
00128                 // return any stroke that falls completely outside these bounds
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                                         // the stroke is completely outside the containing stroke
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                                 // not marked as hidden? and...
00159                                 // TODO with a named shortcut?
00160                                 if (m.isAnnotationPresent(HideFromFlash.class)) {
00161                                         // do nothing for hidden methods
00162                                 } else {
00163                                         // DebugUtils.println(m.getName());
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                 // calculate the bounds of the container stroke
00220                 Rectangle2D bounds = container.getBounds();
00221 
00222                 // return any stroke that overlaps the container but is not contained
00223                 // by it
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                                         // the stroke is completely outside the containing stroke
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 }

Generated on Sat Apr 14 18:21:36 2007 for R3 Paper Toolkit by  doxygen 1.4.7