/** * Created by Nicholas Hallahan on 12/24/14. * nhallahan@spatialdev.com */ package com.spatialdev.osm.model; import com.mapbox.mapboxsdk.R; import com.mapbox.mapboxsdk.geometry.LatLng; import com.mapbox.mapboxsdk.overlay.ItemizedOverlay; import com.mapbox.mapboxsdk.overlay.Marker; import com.spatialdev.osm.marker.OSMMarker; import org.apache.commons.codec.binary.Hex; import org.apache.commons.codec.digest.DigestUtils; import org.xmlpull.v1.XmlSerializer; import java.io.IOException; import java.util.LinkedList; import java.util.List; import java.util.Timer; import java.util.TimerTask; public class OSMNode extends OSMElement { private double lat; private double lng; private LinkedList<OSMRelation> linkedRelations = new LinkedList<>(); // This is only for standalone nodes. private OSMMarker marker; /** * This constructor is used by OSMDataSet in the XML parsing process. */ public OSMNode(String idStr, String latStr, String lonStr, String versionStr, String timestampStr, String changesetStr, String uidStr, String userStr, String action) { super(idStr, versionStr, timestampStr, changesetStr, uidStr, userStr, action); lat = Double.valueOf(latStr); lng = Double.valueOf(lonStr); } /** * This constructor is used when we are creating an new OSMElement, * such as when a new Node is created. This constructor assumes * that we are creating a NEW element in the current survey. */ public OSMNode(LatLng latLng) { super(); // super sets the element to be modified lat = latLng.getLatitude(); lng = latLng.getLongitude(); } public LatLng getLatLng() { return new LatLng(lat, lng); } public double getLat() { return lat; } public double getLng() { return lng; } /** * This moves an OSMNode to a new location on the map. * * The LatLng in the node is reset, the LatLng in the * marker is reset, and the node is removed and replaced * in the JTSModel's spatial index. * * @param jtsModel - the model in which the node is spatially indexed * @param latLng - the new location to move the node to */ public void move(JTSModel jtsModel, LatLng latLng) { lat = latLng.getLatitude(); lng = latLng.getLongitude(); jtsModel.removeOSMElement(this); jtsModel.addOSMStandaloneNode(this); if (marker != null) { marker.setPoint(latLng); } } /** * Deletes this OSMNode from the JTSModel. * * @param jtsModel - the model in which the node is spatially indexed */ public void delete(JTSModel jtsModel) { jtsModel.removeOSMElement(this); if (marker != null) { // Because that marker is selected, it's also rendered as the focused item in addition // to being on the display list. The marker will still appear on the map if we // don't do this... marker.setVisibility(false); ItemizedOverlay overlay = marker.getParentHolder(); if (overlay != null) { overlay.setFocus(null); } } } public void addRelation(OSMRelation relation) { linkedRelations.push(relation); } public List<OSMRelation> getRelations() { return linkedRelations; } /** * We want a reference to a marker when the node is a standalone node. * This is a reference held when the marker is created * in OSMOverlay#renderMarker * * @param marker */ public void setMarker(OSMMarker marker) { this.marker = marker; } /** * We will get a marker only if the node is standalone. * This is a reference held when the marker is created * in OSMOverlay#renderMarker * * @return */ public Marker getMarker() { return marker; } public String preChecksum() { StringBuilder str = tagsAsSortedKVString(); str.append(lat); str.append(lng); return str.toString(); } /** * The checksum of an OSMNode is the sorted k,v of the tags * with the lat and long following. * * @return */ @Override public String checksum() { String str = preChecksum(); return new String(Hex.encodeHex(DigestUtils.sha1(str))); } @Override void xml(XmlSerializer xmlSerializer, String omkOsmUser) throws IOException { xmlSerializer.startTag(null, "node"); setOsmElementXmlAttributes(xmlSerializer, omkOsmUser); xmlSerializer.attribute(null, "lat", String.valueOf(lat)); xmlSerializer.attribute(null, "lon", String.valueOf(lng)); super.xml(xmlSerializer, omkOsmUser); // generates tags xmlSerializer.endTag(null, "node"); } @Override public void select() { super.select(); if (marker != null) { marker.setMarker(marker.getMapView().getContext().getResources().getDrawable(R.mipmap.maki_star_orange)); } else { // Very wretched hack. Something is wrong with Mapbox Android SDK (Deprecated). Satisfies #98 new Timer().schedule(new TimerTask() { @Override public void run() { if (marker != null) { marker.setMarker(marker.getMapView().getContext().getResources().getDrawable(R.mipmap.maki_star_orange)); } } }, 100); } } @Override public void deselect() { super.deselect(); if (marker != null) { marker.setMarker(marker.getMapView().getContext().getResources().getDrawable(R.mipmap.maki_star_blue)); } } }