Example #1
0
  /**
   * Validate TMX Format,and pilot to Body XMLElement
   *
   * @param vg
   * @throws TmxReadException ;
   */
  private void validateTmxAndParseHeader(VTDGen vg) throws TmxReadException {
    VTDNav vn = vg.getNav();
    AutoPilot ap = new AutoPilot(vn);
    String rootPath = "/tmx";
    vu = new VTDUtils();
    try {
      vu.bind(vn);
      ap.selectXPath(rootPath);
      if (ap.evalXPath() == -1) {
        throw new TmxReadException(Messages.getString("document.TmxReader.validateTmxFileError"));
      }
      ap.resetXPath();
      ap.selectXPath("/tmx/header");
      if (ap.evalXPath() == -1) {
        throw new TmxReadException(Messages.getString("document.TmxReader.validateTmxFileError"));
      }
      int id = vu.getVTDNav().getAttrVal("srclang");
      if (id == -1) {
        throw new TmxReadException(Messages.getString("document.TmxReader.validateTmxFileError"));
      }
      header.setSrclang(vu.getVTDNav().toString(id).trim());

      if (vu.pilot("/tmx/body") == -1) {
        throw new TmxReadException(Messages.getString("document.TmxReader.validateTmxFileError"));
      }
      // compute total tu number
      this.totalTu = vu.getChildElementsCount();
    } catch (VTDException e) {
      logger.error("", e);
      throw new TmxReadException(
          Messages.getString("document.TmxReader.parseTmxFileError") + e.getMessage());
    } finally {
      vg.clear();
    }
  }
  /**
   * Requires vn to point to a relation element. From there it iterates over all matches of the ap.
   * Puts an empty list for each referenced way.
   */
  private List<Tuple2<WayRole, Long>> extractWayRefs(VTDNav vn, Hashtable<Long, List<Long>> ways)
      throws NavException, XPathEvalException {
    vn.push();

    List<Tuple2<WayRole, Long>> refs = new ArrayList<>();
    for (int j = MEMBER_WAY_PATH.evalXPath(); j != -1; j = MEMBER_WAY_PATH.evalXPath()) {
      long ref = Long.parseLong(vn.toString(vn.getAttrVal("ref")));
      String roleAsString = vn.toString(vn.getAttrVal("role")).toLowerCase();
      WayRole role;
      switch (roleAsString) {
        case "inner":
          role = WayRole.INNER;
          break;
        case "outer":
          role = WayRole.OUTER;
          break;
        default:
          continue;
      }
      refs.add(Tuple.tuple(role, ref));
      ways.put(ref, Collections.emptyList());
    }
    MEMBER_WAY_PATH.resetXPath();

    vn.pop();

    return refs;
  }
  public List<Triangle> parseFile(InputStream is) {
    try {
      VTDGen vg = new VTDGen();
      vg.setDoc(IOUtils.toByteArray(is));
      vg.parse(false);
      VTDNav vn = vg.getNav();
      NODE_PATH.resetXPath();
      NODE_PATH.bind(vn); // This is important state for the later method calls!
      NODE_REF_PATH.resetXPath();
      NODE_REF_PATH.bind(vn);
      BUILDING_WAY_PATH.resetXPath();
      BUILDING_WAY_PATH.bind(vn);
      BUILDING_MULTIPOLYGON_PATH.resetXPath();
      BUILDING_MULTIPOLYGON_PATH.bind(vn);
      MEMBER_WAY_PATH.resetXPath();
      MEMBER_WAY_PATH.bind(vn);
      WAY_PATH.resetXPath();
      WAY_PATH.bind(vn);

      // A hash from node ids to actual node positions
      Hashtable<Long, Point2D> nodes = new Hashtable<>();
      // A hash from way refs referenced from multipolygons to their actual list of node refs
      Hashtable<Long, List<Long>> multipolygonWays = new Hashtable<>();

      // The following call initializes accessed node refs in nodes to a dummy value.
      List<List<Long>> buildingWays = extractWaysOfBuildings(vn, nodes);
      // The following call initializes accessed way refs from multipolygons to a dummy value.
      List<List<Tuple2<WayRole, Long>>> multipolygonWayRefs =
          extractWayRefsOfMultipolygons(vn, multipolygonWays);
      // This will extract all referenced multipolygon multipolygonWays, excluding the building
      // multipolygonWays
      // Also adds referenced nodes to nodes
      extractReferencedWays(vn, multipolygonWays, nodes);
      // This will extract all referenced nodes, but no more.
      extractReferencedNodes(vn, nodes);
      // Finally build the polygon list by following the node refs in wayRefs.
      // Triangulate each polygon and return the flattened list of triangles.
      // This way, poly2tri's types will not leak out of this class and we operate
      // on triangles anyway.
      return buildPolygons(nodes, buildingWays, multipolygonWays, multipolygonWayRefs)
          .flatMap(
              p -> {
                try {
                  p.ComplexToSimplePolygon();
                  EarClipping ec = new EarClipping(p.SimplePolygon);
                  return ec.Triangulation().stream();
                } catch (RuntimeException ignored) {
                }
                return Stream.empty();
              })
          .toList();
    } catch (XPathEvalException | NavException | IOException | ParseException e) {
      e.printStackTrace();
      return new ArrayList<>();
    }
  }
  /**
   * Requires vn to point to a way element. From there it iterates over all matches of the ap. Puts
   * a dummy point into nodes for every node it finds.
   */
  private List<Long> extractNodeRefs(VTDNav vn, Hashtable<Long, Point2D> nodes)
      throws NavException, XPathEvalException {
    vn.push();

    List<Long> refs = new ArrayList<>();
    for (int j = NODE_REF_PATH.evalXPath(); j != -1; j = NODE_REF_PATH.evalXPath()) {
      long ref = Long.parseLong(vn.toString(j + 1));
      refs.add(ref);
      nodes.put(ref, new Point2D(0, 0));
    }
    NODE_REF_PATH.resetXPath();

    vn.pop();

    return refs;
  }
  private List<List<Long>> extractWaysOfBuildings(VTDNav vn, Hashtable<Long, Point2D> nodes)
      throws XPathEvalException, NavException {
    vn.push();

    List<List<Long>> ways = new ArrayList<>();
    for (int i = BUILDING_WAY_PATH.evalXPath(); i != -1; i = BUILDING_WAY_PATH.evalXPath()) {
      // The lambda will put in a dummy value for each encountered node,
      // so that we know later which nodes we need to parse.
      ways.add(extractNodeRefs(vn, nodes));
    }

    vn.pop();

    BUILDING_WAY_PATH.resetXPath();
    return ways;
  }
  private List<List<Tuple2<WayRole, Long>>> extractWayRefsOfMultipolygons(
      VTDNav vn, Hashtable<Long, List<Long>> ways) throws NavException, XPathEvalException {
    vn.push();

    List<List<Tuple2<WayRole, Long>>> multipolygons = new ArrayList<>();
    for (int i = BUILDING_MULTIPOLYGON_PATH.evalXPath();
        i != -1;
        i = BUILDING_MULTIPOLYGON_PATH.evalXPath()) {
      // For an explanation for the lambda see extractWaysOfBuildings
      multipolygons.add(extractWayRefs(vn, ways));
    }

    vn.pop();

    BUILDING_WAY_PATH.resetXPath();

    return multipolygons;
  }