/** Computes a list of the valid locations in this cluster. */ public static List<SceneLocation> getClusterLocs(Cluster cluster) { List<SceneLocation> list = Lists.newArrayList(); // convert our tile coordinates into a cartesian coordinate system // with units equal to one fine coordinate in size int fx = cluster.x * _metrics.finegran + 1, fy = cluster.y * _metrics.finegran + 1; int fwid = cluster.width * _metrics.finegran - 2, fhei = cluster.height * _metrics.finegran - 2; int cx = fx + fwid / 2, cy = fy + fhei / 2; // if it's a 1x1 cluster, return one location in the center of the // cluster if (cluster.width == 1) { StageLocation loc = new StageLocation( MisoUtil.toFull(cluster.x, 2), MisoUtil.toFull(cluster.y, 2), (byte) DirectionCodes.SOUTHWEST); list.add(new SceneLocation(loc, 0)); return list; } double radius = (double) fwid / 2; int clidx = cluster.width - 2; if (clidx >= CLUSTER_METRICS.length / 2 || clidx < 0) { log.warning("Requested locs from invalid cluster " + cluster + ".", new Exception()); return list; } for (double angle = CLUSTER_METRICS[clidx * 2]; angle < Math.PI * 2; angle += CLUSTER_METRICS[clidx * 2 + 1]) { int sx = cx + (int) Math.round(Math.cos(angle) * radius); int sy = cy + (int) Math.round(Math.sin(angle) * radius); // obtain the orientation facing toward the center int orient = 2 * (int) (Math.round(angle / (Math.PI / 4)) % 8); orient = DirectionUtil.rotateCW(DirectionCodes.SOUTH, orient); orient = DirectionUtil.getOpposite(orient); // convert them back to full coordinates for the location int tx = MathUtil.floorDiv(sx, _metrics.finegran); sx = MisoUtil.toFull(tx, sx - (tx * _metrics.finegran)); int ty = MathUtil.floorDiv(sy, _metrics.finegran); sy = MisoUtil.toFull(ty, sy - (ty * _metrics.finegran)); StageLocation loc = new StageLocation(sx, sy, (byte) orient); list.add(new SceneLocation(loc, 0)); } return list; }
/** * Convert the given pixel coordinates, whose origin is at the top-left of a tile's containing * rectangle, to fine coordinates within that tile. Converted coordinates are placed in the given * point object. * * @param x the x-position pixel coordinate. * @param y the y-position pixel coordinate. * @param fpos the point object to place coordinates in. */ public static void pixelToFine(MisoSceneMetrics metrics, int x, int y, Point fpos) { // calculate line parallel to the y-axis (from the given // x/y-pos to the x-axis) float bY = y - (metrics.fineSlopeY * x); // determine intersection of x- and y-axis lines int crossx = (int) ((bY - metrics.fineBX) / (metrics.fineSlopeX - metrics.fineSlopeY)); int crossy = (int) ((metrics.fineSlopeY * crossx) + bY); // TODO: final position should check distance between our // position and the surrounding fine coords and return the // actual closest fine coord, rather than just dividing. // determine distance along the x-axis float xdist = MathUtil.distance(metrics.tilehwid, 0, crossx, crossy); fpos.x = (int) (xdist / metrics.finelen); // determine distance along the y-axis float ydist = MathUtil.distance(x, y, crossx, crossy); fpos.y = (int) (ydist / metrics.finelen); // Log.info("Pixel to fine " + StringUtil.coordsToString(x, y) + // " -> " + StringUtil.toString(fpos) + "."); }
protected final IntTuple blockKey(SceneBlock block) { Rectangle bounds = block.getBounds(); return new IntTuple( MathUtil.floorDiv(bounds.x, bounds.width), MathUtil.floorDiv(bounds.y, bounds.height)); }
/** Returns the tile coordinate of the given full coordinate. */ public static int fullToTile(int val) { return MathUtil.floorDiv(val, FULL_TILE_FACTOR); }