/** * Extract and store relation information based on the relation member * * @param src The relation member to store information about */ public RelMember(RelationMember src) { role = src.getRole(); type = src.getType(); rel_id = 0; coor = new ArrayList<LatLon>(); if (src.isNode()) { Node r = src.getNode(); tags = r.getKeys(); coor = new ArrayList<LatLon>(1); coor.add(r.getCoor()); } if (src.isWay()) { Way r = src.getWay(); tags = r.getKeys(); List<Node> wNodes = r.getNodes(); coor = new ArrayList<LatLon>(wNodes.size()); for (Node wNode : wNodes) { coor.add(wNode.getCoor()); } } if (src.isRelation()) { Relation r = src.getRelation(); tags = r.getKeys(); rel_id = r.getId(); coor = new ArrayList<LatLon>(); } }
public static Route load(Relation left, Relation right, Way w) { left = left == null ? right : left; right = right == null ? left : right; if (left == null) { throw new IllegalArgumentException("At least one relation must not be null."); } final Route leftRoute = load(left); final Route rightRoute = load(right); int iLeft = 0; while (!w.equals(leftRoute.getSegments().get(iLeft++).getWay())) ; int iRight = 0; while (!w.equals(rightRoute.getSegments().get(iRight++).getWay())) ; final int min = Math.min(iLeft, iRight); final List<Segment> leftSegments = leftRoute.getSegments().subList(iLeft - min, iLeft); final List<Segment> rightSegments = rightRoute.getSegments().subList(iRight - min, iRight); if (!leftSegments.equals(rightSegments)) { throw new IllegalArgumentException("Routes are split across different ways."); } return new Route(iLeft == min ? rightSegments : leftSegments); }
@Override protected void parseWays(List<Osmformat.Way> osmWays) { if (exception == null) { try { for (Osmformat.Way w : osmWays) { final Info info = w.getInfo(); if (!info.hasVersion()) discourageUpload = true; final Way way = new Way(w.getId(), info.hasVersion() ? info.getVersion() : 1); setMetadata(way, info); Map<String, String> keys = new HashMap<>(); for (int i = 0; i < w.getKeysCount(); i++) { keys.put(getStringById(w.getKeys(i)), getStringById(w.getVals(i))); } way.setKeys(keys); long previousId = 0; // Node ids are delta coded Collection<Long> nodeIds = new ArrayList<>(); for (Long id : w.getRefsList()) { nodeIds.add(previousId += id); } ways.put(way.getUniqueId(), nodeIds); externalIdMap.put(way.getPrimitiveId(), way); } } catch (IllegalDataException e) { exception = e; } } }
/** * Remove all tags from the way * * @param x The Way to remove all tags from */ private void stripTags(Way x) { Way y = new Way(x); for (String key : x.keySet()) { y.remove(key); } cmds.add(new ChangeCommand(x, y)); }
@Override public boolean isFixable(TestError testError) { if (!(testError.getTester() instanceof DuplicateWay)) return false; // Do not automatically fix same ways with different tags if (testError.getCode() != DUPLICATE_WAY) return false; // We fix it only if there is no more than one way that is relation member. Collection<? extends OsmPrimitive> sel = testError.getPrimitives(); HashSet<Way> ways = new HashSet<Way>(); for (OsmPrimitive osm : sel) { if (osm instanceof Way) { ways.add((Way) osm); } } if (ways.size() < 2) return false; int waysWithRelations = 0; for (Way w : ways) { List<Relation> rel = OsmPrimitive.getFilteredList(w.getReferrers(), Relation.class); if (!rel.isEmpty()) { ++waysWithRelations; } } return (waysWithRelations <= 1); }
@Test public void testBackrefrenceForWay_Full() throws OsmTransferException { Way w = lookupWay(ds, 1); assertNotNull(w); // way with name "way-1" is referred to by two relations // OsmServerBackreferenceReader reader = new OsmServerBackreferenceReader(w); reader.setReadFull(true); DataSet referers = reader.parseOsm(NullProgressMonitor.INSTANCE); assertEquals(6, referers.getWays().size()); // 6 ways referred by two relations for (Way w1 : referers.getWays()) { assertEquals(false, w1.isIncomplete()); } assertEquals(2, referers.getRelations().size()); // two relations referring to Set<Long> expectedNodeIds = new HashSet<Long>(); for (Way way : referers.getWays()) { Way orig = (Way) ds.getPrimitiveById(way); for (Node n : orig.getNodes()) { expectedNodeIds.add(n.getId()); } } assertEquals(expectedNodeIds.size(), referers.getNodes().size()); for (Node n : referers.getNodes()) { assertEquals(true, expectedNodeIds.contains(n.getId())); } Relation r = lookupRelation(referers, 0); assertNotNull(r); assertEquals(false, r.isIncomplete()); r = lookupRelation(referers, 1); assertEquals(false, r.isIncomplete()); }
protected Way parseWay() throws XMLStreamException { WayData wd = new WayData(); readCommon(wd); Way w = new Way(wd.getId(), wd.getVersion()); w.setVisible(wd.isVisible()); w.load(wd); externalIdMap.put(wd.getPrimitiveId(), w); Collection<Long> nodeIds = new ArrayList<Long>(); while (true) { int event = parser.next(); if (event == XMLStreamConstants.START_ELEMENT) { if (parser.getLocalName().equals("nd")) { nodeIds.add(parseWayNode(w)); } else if (parser.getLocalName().equals("tag")) { parseTag(w); } else { parseUnknown(); } } else if (event == XMLStreamConstants.END_ELEMENT) { break; } } if (w.isDeleted() && nodeIds.size() > 0) { System.out.println(tr("Deleted way {0} contains nodes", w.getUniqueId())); nodeIds = new ArrayList<Long>(); } ways.put(wd.getUniqueId(), nodeIds); return w; }
void addWayNodes(Way w) { add(tr("{0} Nodes: ", w.getNodesCount())); for (Node n : w.getNodes()) { s.append(INDENT).append(INDENT); addNameAndId(n); s.append(NL); } }
/** * This method removes duplicate points (if any) from the input way. * * @param ways the ways to process * @return {@code true} if any changes where made */ private boolean removeDuplicateNodes(List<Way> ways) { // TODO: maybe join nodes with JoinNodesAction, rather than reconnect the ways. Map<Node, Node> nodeMap = new TreeMap<Node, Node>(new NodePositionComparator()); int totalNodesRemoved = 0; for (Way way : ways) { if (way.getNodes().size() < 2) { continue; } int nodesRemoved = 0; List<Node> newNodes = new ArrayList<Node>(); Node prevNode = null; for (Node node : way.getNodes()) { if (!nodeMap.containsKey(node)) { // new node nodeMap.put(node, node); // avoid duplicate nodes if (prevNode != node) { newNodes.add(node); } else { nodesRemoved++; } } else { // node with same coordinates already exists, substitute with existing node Node representator = nodeMap.get(node); if (representator != node) { nodesRemoved++; } // avoid duplicate node if (prevNode != representator) { newNodes.add(representator); } } prevNode = node; } if (nodesRemoved > 0) { if (newNodes.size() == 1) { // all nodes in the same coordinate - add one more node, to have closed way. newNodes.add(newNodes.get(0)); } Way newWay = new Way(way); newWay.setNodes(newNodes); cmds.add(new ChangeCommand(way, newWay)); totalNodesRemoved += nodesRemoved; } } return totalNodesRemoved > 0; }
/** * Determines which way chunk should reuse the old id and its history. Selects the one with the * highest node count. * * @param wayChunks the way chunks * @return the way to keep */ protected static Way determineWayToKeep(Iterable<Way> wayChunks) { Way wayToKeep = null; for (Way i : wayChunks) { if (wayToKeep == null || i.getNodesCount() > wayToKeep.getNodesCount()) { wayToKeep = i; } } return wayToKeep; }
/** * Check if a Way is correct. * * @param way The way. * @return <code>true</code> is valid. <code>false</code> is not valid. */ public boolean isvalidWay(Way way) { // if (!way.isTagged()) <---not needed me thinks // return false; String highway = way.get("highway"); return (highway != null && !excludedHighwayValues.contains(highway)) || way.get("junction") != null || way.get("service") != null; }
protected static void populateTestDataSetWithWays(DataSet ds) { for (int i = 0; i < 20; i++) { Way w = new Way(); for (int j = 0; j < 10; j++) { w.addNode(lookupNode(ds, i + j)); } w.put("name", "way-" + i); ds.addPrimitive(w); } }
/** * Creates new way objects for the way chunks and transfers the keys from the original way. * * @param way the original way whose keys are transferred * @param wayChunks the way chunks * @return the new way objects */ protected static List<Way> createNewWaysFromChunks(Way way, Iterable<List<Node>> wayChunks) { final List<Way> newWays = new ArrayList<>(); for (List<Node> wayChunk : wayChunks) { Way wayToAdd = new Way(); wayToAdd.setKeys(way.getKeys()); wayToAdd.setNodes(wayChunk); newWays.add(wayToAdd); } return newWays; }
/** * Determine which ways to split. * * @param selectedWays List of user selected ways. * @param selectedNodes List of user selected nodes. * @return List of ways to split */ private List<Way> getApplicableWays(List<Way> selectedWays, List<Node> selectedNodes) { if (selectedNodes.isEmpty()) return null; // Special case - one of the selected ways touches (not cross) way that we // want to split if (selectedNodes.size() == 1) { Node n = selectedNodes.get(0); List<Way> referedWays = OsmPrimitive.getFilteredList(n.getReferrers(), Way.class); Way inTheMiddle = null; for (Way w : referedWays) { // Need to look at all nodes see #11184 for a case where node n is // firstNode, lastNode and also in the middle if (selectedWays.contains(w) && w.isInnerNode(n)) { if (inTheMiddle == null) { inTheMiddle = w; } else { inTheMiddle = null; break; } } } if (inTheMiddle != null) return Collections.singletonList(inTheMiddle); } // List of ways shared by all nodes List<Way> result = new ArrayList<>( OsmPrimitive.getFilteredList(selectedNodes.get(0).getReferrers(), Way.class)); for (int i = 1; i < selectedNodes.size(); i++) { List<OsmPrimitive> ref = selectedNodes.get(i).getReferrers(); for (Iterator<Way> it = result.iterator(); it.hasNext(); ) { if (!ref.contains(it.next())) { it.remove(); } } } // Remove broken ways for (Iterator<Way> it = result.iterator(); it.hasNext(); ) { if (it.next().getNodesCount() <= 2) { it.remove(); } } if (selectedWays.isEmpty()) return result; else { // Return only selected ways for (Iterator<Way> it = result.iterator(); it.hasNext(); ) { if (!selectedWays.contains(it.next())) { it.remove(); } } return result; } }
/** * Collect all nodes with more than one referrer. * * @param ways Ways from witch nodes are selected * @return List of nodes with more than one referrer */ private static List<Node> collectNodesWithExternReferers(List<Way> ways) { List<Node> withReferrers = new ArrayList<>(); for (Way w : ways) { for (Node n : w.getNodes()) { if (n.getReferrers().size() > 1) { withReferrers.add(n); } } } return withReferrers; }
@Override public boolean hasEqualSemanticAttributes(OsmPrimitive other) { if (!(other instanceof Way)) return false; if (!super.hasEqualSemanticAttributes(other)) return false; Way w = (Way) other; if (getNodesCount() != w.getNodesCount()) return false; for (int i = 0; i < getNodesCount(); i++) { if (!getNode(i).hasEqualSemanticAttributes(w.getNode(i))) return false; } return true; }
public void visit(Way w) { if (w.isNewOrUndeleted() || w.isModified() || w.isDeleted()) { // upload new ways as well as modified and deleted ones hull.add(w); for (Node n : w.getNodes()) { // we upload modified nodes even if they aren't in the current // selection. n.visit(this); } } }
@Override public void cloneFrom(OsmPrimitive osm) { boolean locked = writeLock(); try { super.cloneFrom(osm); Way otherWay = (Way) osm; setNodes(otherWay.getNodes()); } finally { writeUnlock(locked); } }
protected void populate() { Way w1 = new Way(1); w1.addNode(new Node(10)); w1.addNode(new Node(11)); Way w2 = new Way(1); w2.addNode(new Node(10)); w2.addNode(new Node(11)); dialog.getConflictResolver().populate(new Conflict<OsmPrimitive>(w1, w2)); }
/** * Return a list of all objects in the selection, respecting the different modifier. * * @param alt Whether the alt key was pressed, which means select all objects that are touched, * instead those which are completely covered. * @return The collection of selected objects. */ public Collection<OsmPrimitive> getSelectedObjects(boolean alt) { Collection<OsmPrimitive> selection = new LinkedList<>(); // whether user only clicked, not dragged. boolean clicked = false; Rectangle bounding = lasso.getBounds(); if (bounding.height <= 2 && bounding.width <= 2) { clicked = true; } if (clicked) { Point center = new Point(lasso.xpoints[0], lasso.ypoints[0]); OsmPrimitive osm = nc.getNearestNodeOrWay(center, OsmPrimitive.isSelectablePredicate, false); if (osm != null) { selection.add(osm); } } else { // nodes for (Node n : nc.getCurrentDataSet().getNodes()) { if (n.isSelectable() && lasso.contains(nc.getPoint2D(n))) { selection.add(n); } } // ways for (Way w : nc.getCurrentDataSet().getWays()) { if (!w.isSelectable() || w.getNodesCount() == 0) { continue; } if (alt) { for (Node n : w.getNodes()) { if (!n.isIncomplete() && lasso.contains(nc.getPoint2D(n))) { selection.add(w); break; } } } else { boolean allIn = true; for (Node n : w.getNodes()) { if (!n.isIncomplete() && !lasso.contains(nc.getPoint(n))) { allIn = false; break; } } if (allIn) { selection.add(w); } } } } return selection; }
Segment(Node start, Way way, Node end) { this.start = start; this.way = way; this.end = end; final List<Node> ns = way.getNodes(); if (way.lastNode().equals(start)) { Collections.reverse(ns); } this.nodes = Collections.unmodifiableList(ns); }
@Override public void visit(Way w) { if (e.child == null && left.matches(new Environment(w))) { if (e.osm instanceof Way && Geometry.PolygonIntersection.FIRST_INSIDE_SECOND.equals( Geometry.polygonIntersection(w.getNodes(), ((Way) e.osm).getNodes())) || e.osm instanceof Relation && ((Relation) e.osm).isMultipolygon() && Geometry.isPolygonInsideMultiPolygon(w.getNodes(), (Relation) e.osm, null)) { e.child = w; } } }
@Override public void visit(Way w) { assert aNode != null; if (w.hasKey(tag)) { double dist = OsmUtils.getMinimumDistanceToWay(aNode.getCoor(), w); if (dist < minDist && dist < maxDist) { minDist = dist; currentValue = w.get(tag); srcNode = w; } } }
@Override public void visit(Way w) { if (!w.isUsable() || !w.isClosed()) return; String natural = w.get("natural"); if (natural == null) return; else if ("coastline".equals(natural) && Geometry.isClockwise(w)) { reportError(w, tr("Reversed coastline: land not on left side"), WRONGLY_ORDERED_COAST); } else if ("land".equals(natural) && Geometry.isClockwise(w)) { reportError(w, tr("Reversed land: land not on left side"), WRONGLY_ORDERED_LAND); } else return; }
@Override public void mouseMoved(MouseEvent e) { Way nearestWay = Main.map.mapView.getNearestWay(e.getPoint(), OsmPrimitive.isUsablePredicate); if (nearestWay != highlightedWay) { if (highlightedWay != null) { highlightedWay.setHighlighted(false); } if (nearestWay != null) { nearestWay.setHighlighted(true); } highlightedWay = nearestWay; Main.map.mapView.repaint(); } }
public static GpxData toGpxData(DataSet data, File file) { GpxData gpxData = new GpxData(); gpxData.storageFile = file; HashSet<Node> doneNodes = new HashSet<Node>(); for (Way w : data.ways) { if (w.incomplete || w.deleted) continue; ImmutableGpxTrack trk = new ImmutableGpxTrack( new LinkedList<Collection<WayPoint>>(), new HashMap<String, Object>()); gpxData.tracks.add(trk); if (w.get("name") != null) trk.attr.put("name", w.get("name")); ArrayList<WayPoint> trkseg = null; for (Node n : w.nodes) { if (n.incomplete || n.deleted) { trkseg = null; continue; } if (trkseg == null) { trkseg = new ArrayList<WayPoint>(); trk.trackSegs.add(trkseg); } if (!n.isTagged()) { doneNodes.add(n); } WayPoint wpt = new WayPoint(n.getCoor()); if (!n.isTimestampEmpty()) { wpt.attr.put("time", DateUtils.fromDate(n.getTimestamp())); wpt.setTime(); } trkseg.add(wpt); } } // what is this loop meant to do? it creates waypoints but never // records them? for (Node n : data.nodes) { if (n.incomplete || n.deleted || doneNodes.contains(n)) continue; WayPoint wpt = new WayPoint(n.getCoor()); if (!n.isTimestampEmpty()) { wpt.attr.put("time", DateUtils.fromDate(n.getTimestamp())); wpt.setTime(); } if (n.keys != null && n.keys.containsKey("name")) { wpt.attr.put("name", n.keys.get("name")); } } return gpxData; }
/** * Search by closed status. * * @throws ParseError if an error has been encountered while compiling */ @Test public void testClosed() throws ParseError { SearchContext sc = new SearchContext("closed"); // Closed sc.w1.addNode(sc.n1); for (Way w : new Way[] {sc.w1}) { assertTrue(w.toString(), w.isClosed()); sc.match(w, true); } // Unclosed for (OsmPrimitive p : new OsmPrimitive[] {sc.n1, sc.n2, sc.w2, sc.r1, sc.r2}) { sc.match(p, false); } }
@Override public ControllerState onMouseUp(MouseUpEvent evt, OsmPrimitive osm) { // if (evt.isShiftKeyDown()) { FIXME // // } else if (osm instanceof Node && osm.getReferrers().contains(parentWay)) { // select node within way boolean isFirst = parentWay.firstNode().equals(node); boolean isLast = parentWay.lastNode().equals(node); if (isFirst == isLast) return new SelectedWayNode(parentWay, node); else return new DrawWay(parentWay, isLast); } ControllerState cs = sharedOnMouseUp(evt, osm); return cs != null ? cs : this; }
public static Route create(List<Way> ws, Node end) { final List<Segment> segments = new ArrayList<Segment>(ws.size()); for (Way w : ws) { if (!w.isFirstLastNode(end)) { throw new IllegalArgumentException("Ways must be ordered."); } final Node start = Utils.getOppositeEnd(w, end); segments.add(0, new Segment(start, w, end)); end = start; } return new Route(segments); }
@Override public void visit(Way w) { if (!w.isUsable()) return; List<Node> wNodes = w.getNodes(); List<LatLon> wLat = new ArrayList<LatLon>(wNodes.size()); for (int i = 0; i < wNodes.size(); i++) { wLat.add(wNodes.get(i).getCoor()); } Map<String, String> wkeys = w.getKeys(); removeUninterestingKeys(wkeys); WayPair wKey = new WayPair(wLat, wkeys); ways.put(wKey, w); WayPairNoTags wKeyN = new WayPairNoTags(wLat); waysNoTags.put(wKeyN, w); }