public void deserializeMap(String map) {
   String[] areaList = map.split(";");
   if (areaList.length < 3) {
     return;
   }
   try {
     float metersPerUnit = Float.valueOf(areaList[0]);
     SimArea.setMetersPerUnit(metersPerUnit);
     String[] originTokens = areaList[1].trim().split(" ");
     if (originTokens.length > 1) {
       int originX = Integer.valueOf(originTokens[0].trim());
       int originY = Integer.valueOf(originTokens[1].trim());
       Point origin = new Point(originX, originY);
       SimArea.setImageOrigin(origin);
     }
   } catch (NumberFormatException e) {
     activity.showAlert("Invalid px per meter", Toast.LENGTH_SHORT);
   }
   for (int i = 2; i < areaList.length; ++i) {
     String area = areaList[i];
     if (area.trim().length() == 0) {
       continue;
     }
     System.out.println("Parsing area:\n" + area);
     AbridgedAreaDescription aad = AbridgedAreaDescriptions.parseArea(area);
     List<Double> xywh = aad.xywh;
     int x = (int) (double) xywh.get(0);
     int y = (int) (double) xywh.get(1);
     int w = (int) (double) xywh.get(2);
     int h = (int) (double) xywh.get(3);
     int left, right, top, bottom;
     if (w >= 0) {
       left = x;
       right = x + w;
     } else {
       left = x + w;
       right = x;
     }
     if (h >= 0) {
       top = -y;
       bottom = -(y + h);
     } else {
       top = -y;
       bottom = -(y - h);
     }
     synchronized (areas) {
       areas.put(aad.id, new SimArea(aad.id, new Rect(left, top, right, bottom), aad.type));
     }
   }
   makeWalls();
 }
  @Override
  public boolean onTouchEvent(MotionEvent event) {
    PointF screenTouch =
        new PointF(event.getX() / windowSize.x, 1.0f - event.getY() / windowSize.y);
    if (screenTouch.x < 0.0f) {
      screenTouch.x = 0.0f;
    }
    if (screenTouch.x > 1.0f) {
      screenTouch.x = 1.0f;
    }
    if (screenTouch.y < 0.0f) {
      screenTouch.y = 0.0f;
    }
    if (screenTouch.y >= 1.0f) {
      screenTouch.y = 1.0f;
    }
    PointF floorTouch = floorTouch(screenTouch);

    int action = event.getAction();
    if (action == MotionEvent.ACTION_MOVE) {
      if (fingerDown) {
        if (topDown) {
          synchronized (camera) {
            camera.x -= (floorTouch.x - lastFloorTouch.x);
            camera.y -= (floorTouch.y - lastFloorTouch.y);
            floorTouch = floorTouch(screenTouch);
          }
        } else {
          if (event.getPointerCount() > 1) {
            // followHeightFactor = 16.0f * (screenTouch.y + 0.1f);
          } else if (event.getPointerCount() == 1) {
            float deltaHeight = (screenTouch.y - lastScreenTouch.y);
            followHeightFactor += deltaHeight * followHeightFactor * 3.0f;

            if (followHeightFactor <= 1.0f) {
              followHeightFactor = 1.0f;
            } else if (followHeightFactor > 10.0f) {
              followHeightFactor = 10.0f;
            }

            // screenTouch is not being used because it is limited to 0 and 1
            // which leads to undesirable results. getX() is used instead.
            cameraOffsetX -= (event.getX() - lastX) / 200.0f;
            lastX = event.getX();
            if (cameraOffsetX > Math.PI * 2.0f) {
              cameraOffsetX -= Math.PI * 2.0f;
            } else if (cameraOffsetX < 0.0f) {
              cameraOffsetX += Math.PI * 2.0f;
            }
            // lastScreenTouch.y = screenTouch.y;
          }
        }
        if (event.getPointerCount() > 1) {
          PointF screenTouch2 =
              new PointF(event.getX(1) / windowSize.x, 1.0f - event.getY(1) / windowSize.y);
          float dx = screenTouch.x - screenTouch2.x;
          float dy = screenTouch.y - screenTouch2.y;
          zoom = -15.0f / (float) Math.sqrt(dx * dx + dy * dy) + 0.001f;
        }
      }
    } else if (action == MotionEvent.ACTION_DOWN) {
      fingerDown = true;
      lastX = event.getX();

      if (event.getEventTime() - lastTouchDownTime < 200) {
        resetCameraOffset();
      }
      lastTouchDownTime = event.getEventTime();

      if (nextObjectClass != null) {
        activity
            .getRobotSession()
            .sendMessage("object " + nextObjectClass + " " + floorTouch.x + " " + floorTouch.y);
        nextObjectClass = null;
      } else {
        try {
          boolean selected = false;
          synchronized (robots) {
            for (SimObject obj : robots.values()) {
              if (obj.intersectsPoint(floorTouch, 1.0f)) {
                activity.setSelectedObject(obj);
                selected = true;
                break;
              }
            }
          }
          if (!selected) {
            synchronized (objects) {
              for (SimObject obj : objects.values()) {
                if (obj.intersectsPoint(floorTouch, 1.0f)) {
                  activity.setSelectedObject(obj);
                  selected = true;
                  break;
                }
              }
            }
          }
          if (!selected) {
            synchronized (areas) {
              for (SimArea area : areas.values()) {
                if (area.intersectsPoint(floorTouch)) {
                  activity.setSelectedObject(area);
                  selected = true;
                  break;
                }
              }
            }
          }
          if (!selected) {
            activity.setSelectedObject(null);
          }
          draw();
        } catch (NullPointerException e) { // Don't know why this is happening
          e.printStackTrace();
        }
      }

    } else if (action == MotionEvent.ACTION_CANCEL || action == MotionEvent.ACTION_UP) {
      fingerDown = false;
    }
    synchronized (lastFloorTouch) {
      lastFloorTouch = floorTouch;
    }
    synchronized (lastScreenTouch) {
      lastScreenTouch = screenTouch;
    }
    // activity.propertiesTextView.setText(floorTouch.x + " " + floorTouch.y);
    return true;
  }