import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
import javax.imageio.ImageIO;
private static final Color ROOM9 = new Color(0xFc, 0xD4, 0x51);
private static final Color ROOM10 = new Color(72, 201, 176);
private static final Color ROOM11 = new Color(84, 153, 199);
- private static final Color ROOM12 = new Color(133, 193, 233);
- private static final Color ROOM13 = new Color(245, 176, 65);
+ private static final Color ROOM12 = new Color(255, 213, 209);
+ private static final Color ROOM13 = new Color(228, 228, 215);
private static final Color ROOM14 = new Color(82, 190, 128);
private static final Color ROOM15 = new Color(72, 201, 176);
private static final Color ROOM16 = new Color(165, 105, 189);
*/
private void drawMap(Graphics2D g2d, float scale) {
Stroke stroke = new BasicStroke(1.1f * scale);
+ Set<Integer> roomIds = new HashSet<Integer>();
g2d.setStroke(stroke);
for (int y = 0; y < rmfp.getImgHeight() - 1; y++) {
for (int x = 0; x < rmfp.getImgWidth() + 1; x++) {
g2d.setColor(Color.BLACK);
break;
case 7:
- g2d.setColor(ROOM_COLORS[Math.round(mapId / 2)]);
+ g2d.setColor(ROOM_COLORS[mapId % 15]);
+ roomIds.add(mapId);
multicolor = true;
break;
default:
g2d.draw(new Line2D.Float(xPos, yP, xPos, yP));
}
}
+ if (logger.isDebugEnabled() && roomIds.size() > 0) {
+ StringBuilder sb = new StringBuilder();
+ for (Integer r : roomIds) {
+ sb.append(" " + r.toString());
+ }
+ logger.debug("Identified rooms in map:{}", sb.toString());
+ }
}
/**
g2d.setColor(COLOR_CHARGER_HALO);
final float chargerX = toXCoord(rmfp.getChargerX()) * scale;
final float chargerY = toYCoord(rmfp.getChargerY()) * scale;
- drawCircle(g2d, chargerX, chargerY, radius);
+ drawCircle(g2d, chargerX, chargerY, radius, false);
drawCenteredImg(g2d, scale / 8, "charger.png", chargerX, chargerY);
radius = 3 * scale;
g2d.setColor(COLOR_ROBO);
final float roboX = toXCoord(rmfp.getRoboX()) * scale;
final float roboY = toYCoord(rmfp.getRoboY()) * scale;
- drawCircle(g2d, roboX, roboY, radius);
+ drawCircle(g2d, roboX, roboY, radius, false);
if (scale > 1.5) {
drawCenteredImg(g2d, scale / 15, "robo.png", roboX, roboY);
}
}
- private void drawCircle(Graphics2D g2d, float x, float y, float radius) {
- g2d.draw(new Ellipse2D.Double(x - radius, y - radius, 2.0 * radius, 2.0 * radius));
+ private void drawObstacles(Graphics2D g2d, float scale) {
+ float radius = 2 * scale;
+ Stroke stroke = new BasicStroke(3 * scale);
+ g2d.setStroke(stroke);
+ g2d.setColor(Color.MAGENTA);
+
+ Map<Integer, ArrayList<int[]>> obstacleMap = rmfp.getObstacles();
+ for (ArrayList<int[]> obstacles : obstacleMap.values()) {
+ obstacles.forEach(obstacle -> {
+ final float obstacleX = toXCoord(obstacle[0]) * scale;
+ final float obstacleY = toYCoord(obstacle[1]) * scale;
+ drawCircle(g2d, obstacleX, obstacleY, radius, true);
+ if (scale > 1.0) {
+ drawCenteredImg(g2d, scale / 3, "obstacle-" + obstacle[2] + ".png", obstacleX, obstacleY + 15);
+ }
+ });
+ }
+ }
+
+ private void drawCircle(Graphics2D g2d, float x, float y, float radius, boolean fill) {
+ Ellipse2D.Double circle = new Ellipse2D.Double(x - radius, y - radius, 2.0 * radius, 2.0 * radius);
+ if (fill) {
+ g2d.fill(circle);
+ } else {
+ g2d.draw(circle);
+ }
}
private void drawCenteredImg(Graphics2D g2d, float scale, String imgFile, float x, float y) {
try {
if (image != null) {
BufferedImage addImg = ImageIO.read(image);
- int xpos = Math.round(x - (addImg.getWidth() / 2 * scale));
- int ypos = Math.round(y - (addImg.getHeight() / 2 * scale));
+ int xpos = Math.round(x + (addImg.getWidth() / 2 * scale));
+ int ypos = Math.round(y + (addImg.getHeight() / 2 * scale));
AffineTransform at = new AffineTransform();
- at.scale(scale, scale);
+ at.scale(-scale, -scale);
AffineTransformOp scaleOp = new AffineTransformOp(at, AffineTransformOp.TYPE_BILINEAR);
g2d.drawImage(addImg, scaleOp, xpos, ypos);
} else {
drawPath(g2d, scale);
drawRobo(g2d, scale);
drawGoTo(g2d, scale);
+ drawObstacles(g2d, scale);
g2d = bi.createGraphics();
drawOpenHabRocks(g2d, width, height, scale);
return bi;
public static final int BLOCKS = 11;
public static final int MFBZS_AREA = 12;
public static final int OBSTACLES = 13;
+ public static final int IGNORED_OBSTACLES = 14;
+ public static final int OBSTACLES2 = 15;
+ public static final int IGNORED_OBSTACLES2 = 16;
+ public static final int CARPET_MAP = 17;
+
public static final int DIGEST = 1024;
public static final int HEADER = 0x7272;
private Map<Integer, ArrayList<float[]>> areas = new HashMap<>();
private ArrayList<float[]> walls = new ArrayList<>();
private ArrayList<float[]> zones = new ArrayList<>();
- private ArrayList<int[]> obstacles = new ArrayList<>();
+ private Map<Integer, ArrayList<int[]>> obstacles = new HashMap<>();
private byte[] blocks = new byte[0];
+ private int[] carpetMap = {};
private final Logger logger = LoggerFactory.getLogger(RRMapFileParser.class);
areas.put(Integer.valueOf(blocktype & 0xFF), area);
break;
case OBSTACLES:
+ case IGNORED_OBSTACLES:
int obstaclePairs = getUInt16(header, 0x08);
+ ArrayList<int[]> obstacle = new ArrayList<>();
for (int obstaclePair = 0; obstaclePair < obstaclePairs; obstaclePair++) {
int x0 = getUInt16(data, obstaclePair * 5 + 0);
int y0 = getUInt16(data, obstaclePair * 5 + 2);
int u = data[obstaclePair * 5 + 0] & 0xFF;
- obstacles.add(new int[] { x0, y0, u });
+ obstacle.add(new int[] { x0, y0, u });
+ }
+ obstacles.put(Integer.valueOf(blocktype & 0xFF), obstacle);
+ break;
+ case OBSTACLES2:
+ int obstacle2Pairs = getUInt16(header, 0x08);
+ if (obstacle2Pairs == 0) {
+ break;
+ }
+ int obstacleDataLenght = blockDataLength / obstacle2Pairs;
+ logger.trace("block 15 records lenght: {}", obstacleDataLenght);
+ ArrayList<int[]> obstacle2 = new ArrayList<>();
+ for (int obstaclePair = 0; obstaclePair < obstacle2Pairs; obstaclePair++) {
+ int x0 = getUInt16(data, obstaclePair * obstacleDataLenght + 0);
+ int y0 = getUInt16(data, obstaclePair * obstacleDataLenght + 2);
+ int u0 = getUInt16(data, obstaclePair * obstacleDataLenght + 4);
+ int u1 = getUInt16(data, obstaclePair * obstacleDataLenght + 6);
+ int u2 = getUInt32LE(data, obstaclePair * obstacleDataLenght + 8);
+ if (obstacleDataLenght == 28) {
+ if ((data[obstaclePair * obstacleDataLenght + 12] & 0xFF) == 0) {
+ logger.trace("obstacle with photo: No text");
+ } else {
+ byte[] txt = getBytes(data, obstaclePair * obstacleDataLenght + 12, 16);
+ logger.trace("obstacle with photo: {}", new String(txt));
+ }
+ obstacle2.add(new int[] { x0, y0, u0, u1, u2 });
+ } else {
+ int u3 = getUInt32LE(data, obstaclePair * obstacleDataLenght + 12);
+ obstacle2.add(new int[] { x0, y0, u0, u1, u2, u3 });
+ logger.trace("obstacle without photo.");
+ }
+ }
+ obstacles.put(Integer.valueOf(blocktype & 0xFF), obstacle2);
+ break;
+ case IGNORED_OBSTACLES2:
+ int ignoredObstaclePairs = getUInt16(header, 0x08);
+ ArrayList<int[]> ignoredObstacle = new ArrayList<>();
+ for (int obstaclePair = 0; obstaclePair < ignoredObstaclePairs; obstaclePair++) {
+ int x0 = getUInt16(data, obstaclePair * 6 + 0);
+ int y0 = getUInt16(data, obstaclePair * 6 + 2);
+ int u = getUInt16(data, obstaclePair * 6 + 4);
+ ignoredObstacle.add(new int[] { x0, y0, u });
+ }
+ obstacles.put(Integer.valueOf(blocktype & 0xFF), ignoredObstacle);
+ break;
+ case CARPET_MAP:
+ carpetMap = new int[blockDataLength];
+ for (int carpetNode = 0; carpetNode < blockDataLength; carpetNode++) {
+ carpetMap[carpetNode] = data[carpetNode] & 0xFF;
}
break;
case BLOCKS:
printAreaDetails(walls, pw);
pw.printf("Zones:\t%d\r\n", zones.size());
printAreaDetails(zones, pw);
- pw.printf("Obstacles:\t%d\r\n", obstacles.size());
+ for (Integer obstacleType : obstacles.keySet()) {
+ pw.printf("Obstacles Type (%d):\t%d\r\n", obstacleType, obstacles.get(obstacleType).size());
+ printObstacleDetails(obstacles.get(obstacleType), pw);
+ }
pw.printf("Blocks:\t%d\r\n", blocks.length);
pw.print("Paths:");
for (Integer p : pathsDetails.keySet()) {
private void printAreaDetails(ArrayList<float[]> areas, PrintWriter pw) {
areas.forEach(area -> {
- pw.printf("\tArea coordinates:");
+ pw.print("\tArea coordinates:");
for (int i = 0; i < area.length; i++) {
pw.printf("\t%.0f", area[i]);
}
});
}
+ private void printObstacleDetails(ArrayList<int[]> obstacle, PrintWriter pw) {
+ obstacle.forEach(area -> {
+ pw.print("\tObstacle coordinates:");
+ for (int i = 0; i < area.length; i++) {
+ pw.printf("\t%d", area[i]);
+ }
+ pw.println();
+ });
+ }
+
/**
* Compute SHA-1 hash value for the byte array
*
return areas;
}
- public ArrayList<int[]> getObstacles() {
+ public Map<Integer, ArrayList<int[]>> getObstacles() {
return obstacles;
}
public byte[] getBlocks() {
return blocks;
}
+
+ public final int[] getCarpetMap() {
+ return carpetMap;
+ }
}