/** * 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; }