[miio] add new map elements (#8637)
* [miio] add new map elements Add newly found mapelements for obstacles Signed-off-by: Marcel Verpaalen marcel@verpaalen.com
This commit is contained in:
parent
bd4528dcf3
commit
9c6c80d41f
|
@ -33,6 +33,10 @@ import java.io.IOException;
|
|||
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;
|
||||
|
||||
|
@ -78,8 +82,8 @@ public class RRMapDraw {
|
|||
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);
|
||||
|
@ -132,6 +136,7 @@ public class RRMapDraw {
|
|||
*/
|
||||
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++) {
|
||||
|
@ -160,7 +165,8 @@ public class RRMapDraw {
|
|||
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:
|
||||
|
@ -173,6 +179,13 @@ public class RRMapDraw {
|
|||
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());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -275,20 +288,44 @@ public class RRMapDraw {
|
|||
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) {
|
||||
|
@ -296,10 +333,10 @@ public class RRMapDraw {
|
|||
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 {
|
||||
|
@ -410,6 +447,7 @@ public class RRMapDraw {
|
|||
drawPath(g2d, scale);
|
||||
drawRobo(g2d, scale);
|
||||
drawGoTo(g2d, scale);
|
||||
drawObstacles(g2d, scale);
|
||||
g2d = bi.createGraphics();
|
||||
drawOpenHabRocks(g2d, width, height, scale);
|
||||
return bi;
|
||||
|
|
|
@ -52,6 +52,11 @@ public class RRMapFileParser {
|
|||
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;
|
||||
|
||||
|
@ -84,8 +89,9 @@ public class RRMapFileParser {
|
|||
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);
|
||||
|
||||
|
@ -192,12 +198,62 @@ public class RRMapFileParser {
|
|||
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:
|
||||
|
@ -285,7 +341,10 @@ public class RRMapFileParser {
|
|||
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()) {
|
||||
|
@ -301,7 +360,7 @@ public class RRMapFileParser {
|
|||
|
||||
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]);
|
||||
}
|
||||
|
@ -309,6 +368,16 @@ public class RRMapFileParser {
|
|||
});
|
||||
}
|
||||
|
||||
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
|
||||
*
|
||||
|
@ -416,11 +485,15 @@ public class RRMapFileParser {
|
|||
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;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue