00001 package edu.stanford.hci.r3.pattern.coordinates.conversion;
00002
00003 import edu.stanford.hci.r3.pattern.TiledPattern;
00004 import edu.stanford.hci.r3.units.PatternDots;
00005 import edu.stanford.hci.r3.units.Percentage;
00006 import edu.stanford.hci.r3.units.coordinates.PercentageCoordinates;
00007 import edu.stanford.hci.r3.units.coordinates.StreamedPatternCoordinates;
00008 import edu.stanford.hci.r3.util.DebugUtils;
00009
00021 public class TiledPatternCoordinateConverter implements PatternCoordinateConverter {
00022
00023 private int bottomMostVoidSpaceInDots;
00024
00028 private int dotsPerTileHorizontal;
00029
00033 private int dotsPerTileVertical;
00034
00048 private double maxX;
00049
00053 private double maxY;
00054
00058 private double numDotsHorizontalBetweenTiles;
00059
00063 private double numDotsVerticalBetweenTiles;
00064
00068 private int numTiles;
00069
00078 private int numTilesAcross;
00079
00083 private int numTilesDown;
00084
00088 private double numTotalDotsAcross;
00089
00093 private PatternDots numTotalDotsAcrossObj;
00094
00098 private double numTotalDotsDown;
00099
00103 private PatternDots numTotalDotsDownObj;
00104
00108 private double originX;
00109
00113 private double originY;
00114
00118 private String regionName;
00119
00123 private int rightMostVoidSpaceInDots;
00124
00128 private int startingTile;
00129
00133 private double tileHeightIncludingPadding;
00134
00138 private double tileWidthIncludingPadding;
00139
00149 public TiledPatternCoordinateConverter(String regionName) {
00150 this(regionName, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
00151 }
00152
00156 public TiledPatternCoordinateConverter(String theRegionName,
00157 double leftMostPatternXCoord, double topMostPatternYCoord, int dotsAcross, int dotsDown) {
00158 setRegionName(theRegionName);
00159 setStartingTile(0);
00160 setTileConfiguration(1, 1);
00161 setTileSizeInDots(dotsAcross, dotsDown);
00162 setOriginInDots(leftMostPatternXCoord, topMostPatternYCoord);
00163 setTotalSizeInDots(dotsAcross, dotsDown);
00164 setTileToTileOffsetInDots(0, 0);
00165 }
00166
00205 public TiledPatternCoordinateConverter(String theRegionName, int startTile, int nTilesAcross,
00206 int nTilesDown, int dotsPerTileHoriz, int dotsPerTileVert,
00207 double numHorizDotsBetweenTiles, double numVertDotsBetweenTiles,
00208 double leftMostPatternX, double topMostPatternY, double numDotsAcross,
00209 double numDotsDown) {
00210 setRegionName(theRegionName);
00211 setStartingTile(startTile);
00212 setTileConfiguration(nTilesAcross, nTilesDown);
00213 setTileSizeInDots(dotsPerTileHoriz, dotsPerTileVert);
00214 setOriginInDots(leftMostPatternX, topMostPatternY);
00215 setTotalSizeInDots(numDotsAcross, numDotsDown);
00216 setTileToTileOffsetInDots(numHorizDotsBetweenTiles, numVertDotsBetweenTiles);
00217 }
00218
00234 private void calculateCachedDimensions() {
00235
00236
00237 if (numTilesAcross == 1) {
00238 tileWidthIncludingPadding = numTotalDotsAcross;
00239 maxX = originX + numTotalDotsAcross;
00240 } else if (numDotsHorizontalBetweenTiles < dotsPerTileHorizontal) {
00241 tileWidthIncludingPadding = dotsPerTileHorizontal;
00242 maxX = originX + dotsPerTileHorizontal - rightMostVoidSpaceInDots;
00243
00244
00245 } else {
00246 tileWidthIncludingPadding = numDotsHorizontalBetweenTiles;
00247 maxX = originX + numDotsHorizontalBetweenTiles * numTiles - rightMostVoidSpaceInDots;
00248 }
00249
00250
00251 if (numTilesDown == 1) {
00252 tileHeightIncludingPadding = numTotalDotsDown;
00253 maxY = originY + numTotalDotsDown;
00254 } else if (numDotsVerticalBetweenTiles < dotsPerTileVertical) {
00255
00256 tileHeightIncludingPadding = dotsPerTileVertical;
00257 maxY = originY + dotsPerTileVertical - bottomMostVoidSpaceInDots;
00258 } else {
00259 tileHeightIncludingPadding = numDotsVerticalBetweenTiles;
00260 maxY = originY + numDotsVerticalBetweenTiles * numTiles - bottomMostVoidSpaceInDots;
00261 }
00262
00263
00264
00265
00266 }
00267
00285 public boolean contains(final double xValPatternDots, final double yValPatternDots) {
00286
00287 final boolean insideLeftBoundary = xValPatternDots >= originX;
00288
00289
00290 final boolean insideTopBoundary = yValPatternDots >= originY;
00291
00292
00293 final boolean insideRightBoundary = xValPatternDots < maxX;
00294
00295
00296 final boolean insideBottomBoundary = yValPatternDots < maxY;
00297
00298
00299 final boolean notInHorizontalGap = ((xValPatternDots - originX) % tileWidthIncludingPadding) < dotsPerTileHorizontal;
00300 final boolean notInVerticalGap = ((yValPatternDots - originY) % tileHeightIncludingPadding) < dotsPerTileVertical;
00301
00302 return insideLeftBoundary && insideTopBoundary && insideRightBoundary
00303 && insideBottomBoundary && notInHorizontalGap && notInVerticalGap;
00304 }
00305
00313 public boolean contains(StreamedPatternCoordinates location) {
00314 final double xTestVal = location.getXVal();
00315 final double yTestVal = location.getYVal();
00316
00317 return contains(xTestVal, yTestVal);
00318 }
00319
00320
00321
00322
00323
00324
00325 @Override
00326 public double getArea() {
00327 return numTotalDotsAcross * numTotalDotsDown;
00328 }
00329
00333 public String getRegionName() {
00334 return regionName;
00335 }
00336
00343 public PercentageCoordinates getRelativeLocation(StreamedPatternCoordinates coord) {
00344
00345 final double xOffset = coord.getXVal() - originX;
00346 final double yOffset = coord.getYVal() - originY;
00347
00348 final double xRelativeToTile = xOffset
00349 - (getTileNumHorizontal(coord) * numDotsHorizontalBetweenTiles);
00350 final double yRelativeToTile = yOffset
00351 - (getTileNumVertical(coord) * numDotsVerticalBetweenTiles);
00352
00353 final int tileOffset = getTileNumber(coord) - startingTile;
00354
00355 final int tileRow = tileOffset / numTilesAcross;
00356 final int tileCol = tileOffset % numTilesAcross;
00357
00358
00359 final double totalDotsX = tileCol * dotsPerTileHorizontal + xRelativeToTile;
00360 final double totalDotsY = tileRow * dotsPerTileVertical + yRelativeToTile;
00361
00362 final double pctX = totalDotsX / numTotalDotsAcross * 100;
00363 final double pctY = totalDotsY / numTotalDotsDown * 100;
00364
00365 return new PercentageCoordinates(
00366 new Percentage(pctX, numTotalDotsAcrossObj),
00367 new Percentage(pctY, numTotalDotsDownObj));
00368 }
00369
00384 public int getTileNumber(StreamedPatternCoordinates coord) {
00385 if (!contains(coord)) {
00386 return -1;
00387 }
00388
00389
00390
00391
00392 final int tileNumHoriz = getTileNumHorizontal(coord);
00393 final int tileNumVert = getTileNumVertical(coord);
00394
00395 return startingTile + Math.max(tileNumHoriz, tileNumVert);
00396 }
00397
00402 private int getTileNumHorizontal(StreamedPatternCoordinates coord) {
00403 return (int) Math.floor((coord.getXVal() - originX) / tileWidthIncludingPadding);
00404 }
00405
00410 private int getTileNumVertical(StreamedPatternCoordinates coord) {
00411 return (int) Math.floor((coord.getYVal() - originY) / tileHeightIncludingPadding);
00412 }
00413
00417 private void setNumDotsFromBottomMostTilesThatAreNotIncluded(int numDots) {
00418 bottomMostVoidSpaceInDots = numDots;
00419 calculateCachedDimensions();
00420 }
00421
00425 private void setNumDotsFromRightMostTilesThatAreNotIncluded(int numDots) {
00426 rightMostVoidSpaceInDots = numDots;
00427 calculateCachedDimensions();
00428 }
00429
00436 public void setOriginInDots(double leftMostPatternX, double topMostPatternY) {
00437 originX = leftMostPatternX;
00438 originY = topMostPatternY;
00439
00440
00441 calculateCachedDimensions();
00442 }
00443
00450 public void setPatternInformationByReadingItFrom(TiledPattern p) {
00451 final int voidX = p.getNumDotsXPerFullTile() - p.getNumDotsXFromRightMostTiles();
00452 final int voidY = p.getNumDotsYPerFullTile() - p.getNumDotsYFromBottomMostTiles();
00453
00454 setNumDotsFromRightMostTilesThatAreNotIncluded(voidX);
00455 setNumDotsFromBottomMostTilesThatAreNotIncluded(voidY);
00456
00457 setOriginInDots(p.getOriginXInDots(), p.getOriginYInDots());
00458 setStartingTile(p.getInitialPatternFileNumber());
00459 setTileConfiguration(p.getNumTilesX(), p.getNumTilesY());
00460 setTileSizeInDots(p.getNumDotsXPerFullTile(), p.getNumDotsYPerFullTile());
00461 setTileToTileOffsetInDots(p.getNumHorizDotsBetweenTiles(), p.getNumVertDotsBetweenTiles());
00462 setTotalSizeInDots(p.getNumTotalColumns(), p.getNumTotalRows());
00463
00464 DebugUtils.println("");
00465 System.out.println("=========================");
00466 System.out.println(p);
00467 System.out.println(this);
00468 System.out.println("=========================");
00469
00470 }
00471
00477 public void setRegionName(String rName) {
00478 regionName = rName;
00479 }
00480
00489 public void setStartingTile(int startTile) {
00490 startingTile = startTile;
00491 }
00492
00501 public void setTileConfiguration(int nTilesAcross, int nTilesDown) {
00502 numTilesAcross = nTilesAcross;
00503 numTilesDown = nTilesDown;
00504 numTiles = numTilesAcross * numTilesDown;
00505 }
00506
00514 public void setTileSizeInDots(int dotsPerTileHoriz, int dotsPerTileVert) {
00515 dotsPerTileHorizontal = dotsPerTileHoriz;
00516 dotsPerTileVertical = dotsPerTileVert;
00517
00518
00519 calculateCachedDimensions();
00520 }
00521
00526 public void setTileToTileOffsetInDots(double numHorizDotsBetweenTiles,
00527 double numVertDotsBetweenTiles) {
00528
00529
00530
00531 numDotsHorizontalBetweenTiles = numHorizDotsBetweenTiles;
00532
00533
00534 numDotsVerticalBetweenTiles = numVertDotsBetweenTiles;
00535
00536
00537 calculateCachedDimensions();
00538 }
00539
00547 public void setTotalSizeInDots(double numDotsAcross, double numDotsDown) {
00548
00549 numTotalDotsAcross = numDotsAcross;
00550 numTotalDotsDown = numDotsDown;
00551
00552
00553 numTotalDotsAcrossObj = new PatternDots(numTotalDotsAcross);
00554 numTotalDotsDownObj = new PatternDots(numTotalDotsDown);
00555
00556 calculateCachedDimensions();
00557 }
00558
00562 public String toString() {
00563 return "TiledPatternCoordinateConverter {" + "x=" + originX + ", y=" + originY + " w="
00564 + numTotalDotsAcrossObj + ", h=" + numTotalDotsDownObj + "}";
00565 }
00566 }