PatternLocationToSheetLocationMapping.java

00001 package edu.stanford.hci.r3.pattern.coordinates;
00002 
00003 import java.io.File;
00004 import java.io.FileNotFoundException;
00005 import java.io.FileOutputStream;
00006 import java.util.HashMap;
00007 import java.util.List;
00008 import java.util.Map;
00009 import java.util.Set;
00010 
00011 import edu.stanford.hci.r3.PaperToolkit;
00012 import edu.stanford.hci.r3.paper.Region;
00013 import edu.stanford.hci.r3.paper.Sheet;
00014 import edu.stanford.hci.r3.pattern.coordinates.conversion.PatternCoordinateConverter;
00015 import edu.stanford.hci.r3.pattern.coordinates.conversion.TiledPatternCoordinateConverter;
00016 import edu.stanford.hci.r3.pen.PenSample;
00017 import edu.stanford.hci.r3.units.PatternDots;
00018 import edu.stanford.hci.r3.units.coordinates.PercentageCoordinates;
00019 import edu.stanford.hci.r3.units.coordinates.StreamedPatternCoordinates;
00020 import edu.stanford.hci.r3.util.DebugUtils;
00021 import edu.stanford.hci.r3.util.MathUtils;
00022 import edu.stanford.hci.r3.util.files.FileUtils;
00023 
00047 public class PatternLocationToSheetLocationMapping {
00048 
00049         // files end with .patternInfo.xml
00050         private static final String[] PATTERN_INFO_EXTENSION_FILTER = new String[] { "patternInfo.xml" };
00051 
00056         private Map<Region, PatternCoordinateConverter> regionToPatternBounds = new HashMap<Region, PatternCoordinateConverter>();
00057 
00061         private Sheet sheet;
00062 
00074         public PatternLocationToSheetLocationMapping(Sheet s) {
00075                 sheet = s;
00076                 final List<Region> regions = s.getRegions();
00077                 warnIfThereAreNoRegions(regions);
00078                 initializeMap(regions);
00079                 loadConfigurationFromAutomaticallyDiscoveredXMLFiles();
00080         }
00081 
00088         public PatternLocationToSheetLocationMapping(Sheet s, File patternInfoFile) {
00089                 sheet = s;
00090                 final List<Region> regions = s.getRegions();
00091                 warnIfThereAreNoRegions(regions);
00092                 initializeMap(regions);
00093                 loadConfigurationFromXML(patternInfoFile);
00094         }
00095 
00103         public PatternCoordinateConverter getCoordinateConverterForSample(PenSample sample) {
00104                 for (Region r : regionToPatternBounds.keySet()) {
00105                         PatternCoordinateConverter converter = regionToPatternBounds.get(r);
00106                         final StreamedPatternCoordinates coord = new StreamedPatternCoordinates(sample);
00107                         if (converter.contains(coord)) {
00108                                 // DebugUtils.println("Sample is on: " + r.getName());
00109 
00110                                 // where are we on this region?
00111                                 final PercentageCoordinates relativeLocation = converter.getRelativeLocation(coord);
00112 
00113                                 // currently, this is a FALLBACK HACK to check whether we are actually outside the
00114                                 // region later on, we must fix this and catch it earlier in the process
00115                                 if (relativeLocation.getPercentageInXDirection() > 100
00116                                                 || relativeLocation.getPercentageInYDirection() > 100) {
00117                                         DebugUtils.println("FALLBACK HACK. It's actually outside the bounds. "
00118                                                         + "Going on to check the next region...");
00119                                         continue;
00120                                 } else {
00121                                         return converter;
00122                                 }
00123                         }
00124                 }
00125                 return null; // couldn't find any
00126         }
00127 
00133         public PatternCoordinateConverter getPatternBoundsOfRegion(Region r) {
00134                 DebugUtils.println(regionToPatternBounds.size() + " " + r.getName() + " "
00135                                 + regionToPatternBounds);
00136 
00137                 return regionToPatternBounds.get(r);
00138         }
00139 
00146         public Map<Region, PatternCoordinateConverter> getRegionToPatternMapping() {
00147                 return regionToPatternBounds;
00148         }
00149 
00153         public Sheet getSheet() {
00154                 return sheet;
00155         }
00156 
00164         public void initializeMap(List<Region> regions) {
00165                 regionToPatternBounds.clear();
00166                 for (final Region r : regions) {
00167                         if (r.isActive()) {
00168                                 // put in an empty one for now. It should be updated later... otherwise,
00169                                 // this active region will not be accessible by the end user
00170                                 // note: I introduced a bug here a while back, by changing the name I gave to the
00171                                 // TiledPatternCoordinateConverter (_UninitializedMapping). Watch out if you want to
00172                                 // customize this name!
00173                                 regionToPatternBounds.put(r, new TiledPatternCoordinateConverter(r.getName()));
00174                         }
00175                 }
00176         }
00177 
00181         private void loadConfigurationFromAutomaticallyDiscoveredXMLFiles() {
00182                 // check to see if the pattern configuration file exists.
00183                 // if it does, load it automatically...
00184                 final Set<File> configurationPaths = sheet.getConfigurationPaths();
00185                 if (configurationPaths.size() == 0) {
00186                         DebugUtils.println("This Sheet does not have any pattern configuration paths. "
00187                                         + "Either add one so that we can automatically look for *.patternInfo.xml "
00188                                         + "files, or add patternInfo files explicitly.");
00189                         return;
00190                 }
00191 
00192                 DebugUtils.println("This Sheet has configuration paths for *.patternInfo.xml files.");
00193 
00194                 for (File path : configurationPaths) {
00195                         // System.out.println(path);
00196                         List<File> patternInfoFiles = FileUtils.listVisibleFiles(path,
00197                                         PATTERN_INFO_EXTENSION_FILTER);
00198                         // System.out.println(patternInfoFiles.size());
00199                         for (File f : patternInfoFiles) {
00200                                 DebugUtils.println("Trying to automatically load " + f.getName());
00201                                 loadConfigurationFromXML(f);
00202                         }
00203                 }
00204         }
00205 
00212         @SuppressWarnings("unchecked")
00213         public void loadConfigurationFromXML(File xmlFile) {
00214                 // for each region, there should be a specification of the pattern information
00215                 final HashMap<RegionID, PatternCoordinateConverter> regionIDToPattern = (HashMap<RegionID, PatternCoordinateConverter>) PaperToolkit
00216                                 .fromXML(xmlFile);
00217                 for (Region r : regionToPatternBounds.keySet()) {
00218                         final RegionID xmlKey = new RegionID(r);
00219                         // System.out.println("Found Key: " + regionIDToPattern.containsKey(xmlKey) + " for " +
00220                         // r.getName());
00221 
00222                         // loads the information into our map
00223                         if (regionIDToPattern.containsKey(xmlKey)) {
00224                                 DebugUtils.println("Loaded Pattern Configuration for " + xmlKey);
00225                                 regionToPatternBounds.put(r, regionIDToPattern.get(xmlKey));
00226                         }
00227                 }
00228         }
00229 
00233         public void printMapping() {
00234                 System.out.println(this);
00235         }
00236 
00243         public void saveConfigurationToXML(File xmlFile) {
00244                 try {
00245                         // create a new map that goes from name+origin to pattern bounds mapping
00246                         // only save active regions... because we don't render pattern for nonactive regions
00247                         final HashMap<RegionID, PatternCoordinateConverter> regionIDToPattern = new HashMap<RegionID, PatternCoordinateConverter>();
00248                         final Set<Region> regions = regionToPatternBounds.keySet();
00249                         for (Region r : regions) {
00250                                 if (!r.isActive()) {
00251                                         continue;
00252                                 }
00253                                 final RegionID rid = new RegionID(r);
00254                                 regionIDToPattern.put(rid, regionToPatternBounds.get(r));
00255                         }
00256                         if (xmlFile.exists()) {
00257                                 DebugUtils.println("Overwriting XML File: " + xmlFile.getName());
00258                                 xmlFile.delete();
00259                         }
00260                         PaperToolkit.toXML(regionIDToPattern, new FileOutputStream(xmlFile));
00261                 } catch (FileNotFoundException e) {
00262                         e.printStackTrace();
00263                 }
00264         }
00265 
00274         public void setPatternInformationOfRegion(Region r, PatternCoordinateConverter coordinateInfo) {
00275                 if (regionToPatternBounds.containsKey(r) || sheet.containsRegion(r)) {
00276                         // updating an already-known region OR
00277                         // adding a new region (probably added to the sheet after this object was constructed)
00278                         regionToPatternBounds.put(r, coordinateInfo);
00279                 } else {
00280                         System.err.println("PatternLocationToSheetLocationMapping.java: Region unknown. "
00281                                         + "Please add it to the sheet before updating this mapping.");
00282                 }
00283         }
00284 
00295         public void setPatternInformationOfRegion(Region region, //
00296                         PatternDots x, PatternDots y, PatternDots width, PatternDots height) {
00297                 setPatternInformationOfRegion(region, new TiledPatternCoordinateConverter(region.getName(),
00298                                 x.getValue(), y.getValue(), //
00299                                 MathUtils.rint(width.getValue()), MathUtils.rint(height.getValue())));
00300         }
00301 
00305         public void setSheet(Sheet s) {
00306                 sheet = s;
00307         }
00308 
00312         public String toString() {
00313                 final StringBuilder sb = new StringBuilder();
00314                 for (final Region r : regionToPatternBounds.keySet()) {
00315                         sb.append(r.getName() + " --> ");
00316                         final PatternCoordinateConverter bounds = regionToPatternBounds.get(r);
00317                         sb.append(bounds + ", ");
00318                 }
00319                 String string = sb.toString();
00320                 if (string.length() > 2) {
00321                         return string.substring(0, string.length() - 2); // chop off the last ", "
00322                 } else {
00323                         return string;
00324                 }
00325         }
00326 
00330         private void warnIfThereAreNoRegions(final List<Region> regions) {
00331                 // at this point, the sheet has to have regions...
00332                 // for now, warn, if there are no regions
00333                 if (regions.size() == 0) {
00334                         DebugUtils.println("There aren't any regions. Did you perhaps add the "
00335                                         + "regions _after_ you added the sheet to the application?");
00336                 }
00337         }
00338 }

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