improve minsk trans reader

git-svn-id: https://osmand.googlecode.com/svn/trunk@144 e29c36b1-1cfa-d876-8d93-3434fc2bb7b8
This commit is contained in:
Victor Shcherb 2010-06-08 18:29:38 +00:00
parent eec0c2a489
commit f338898513
4 changed files with 344 additions and 20 deletions

View file

@ -10,8 +10,15 @@ public class EntityInfo {
String visible;
String version;
String changeset;
String action;
public String getAction() {
return action;
}
public void setAction(String action) {
this.action = action;
}
public String getTimestamp() {
return timestamp;
}

View file

@ -195,6 +195,16 @@ public class MapUtils {
});
}
public static void sortListOfEntities(List<? extends Entity> list, final double lat, final double lon){
Collections.sort(list, new Comparator<Entity>() {
@Override
public int compare(Entity o1, Entity o2) {
return Double.compare(MapUtils.getDistance(o1.getLatLon(), lat, lon), MapUtils.getDistance(o2.getLatLon(),
lat, lon));
}
});
}
public static String getFormattedDistance(int meters){
if(meters >= 100000){

View file

@ -62,7 +62,6 @@ public class OsmStorageWriter {
// String indent = "{http://xml.apache.org/xslt}indent-amount";
// transformer.setOutputProperty(indent, "4");
XMLStreamWriter streamWriter = new XMLStreamWriterImpl(output, propertyManager);
List<Node> nodes = new ArrayList<Node>();
List<Way> ways = new ArrayList<Way>();
@ -99,7 +98,7 @@ public class OsmStorageWriter {
streamWriter.writeAttribute(ATTR_LAT, n.getLatitude()+"");
streamWriter.writeAttribute(ATTR_LON, n.getLongitude()+"");
streamWriter.writeAttribute(ATTR_ID, n.getId()+"");
writeEntityAttributes(streamWriter, entityInfo.get(n.getId()));
writeEntityAttributes(streamWriter, n, entityInfo.get(n.getId()));
writeTags(streamWriter, n);
writeEndElement(streamWriter, INDENT);
}
@ -107,7 +106,7 @@ public class OsmStorageWriter {
for(Way w : ways){
writeStartElement(streamWriter, ELEM_WAY, INDENT);
streamWriter.writeAttribute(ATTR_ID, w.getId()+"");
writeEntityAttributes(streamWriter, entityInfo.get(w.getId()));
writeEntityAttributes(streamWriter, w, entityInfo.get(w.getId()));
for(Long r : w.getNodeIds()){
writeStartElement(streamWriter, ELEM_ND, INDENT2);
streamWriter.writeAttribute(ATTR_REF, r+"");
@ -120,7 +119,7 @@ public class OsmStorageWriter {
for(Relation r : relations){
writeStartElement(streamWriter, ELEM_RELATION, INDENT);
streamWriter.writeAttribute(ATTR_ID, r.getId()+"");
writeEntityAttributes(streamWriter, entityInfo.get(r.getId()));
writeEntityAttributes(streamWriter, r, entityInfo.get(r.getId()));
for(Entry<Long, String> e : r.getMembersMap().entrySet()){
writeStartElement(streamWriter, ELEM_MEMBER, INDENT2);
streamWriter.writeAttribute(ATTR_REF, e.getKey()+"");
@ -141,8 +140,15 @@ public class OsmStorageWriter {
streamWriter.flush();
}
private void writeEntityAttributes(XMLStreamWriter writer, EntityInfo info) throws XMLStreamException{
private void writeEntityAttributes(XMLStreamWriter writer, Entity i, EntityInfo info) throws XMLStreamException{
if(i.getId() < 0 && (info == null || info.getAction() == null)){
writer.writeAttribute("action", "modify");
}
if(info != null){
// for josm editor
if(info.getAction() != null){
writer.writeAttribute("action", info.getAction());
}
if(info.getChangeset() != null){
writer.writeAttribute(ATTR_CHANGESET, info.getChangeset());
}

View file

@ -1,15 +1,48 @@
package com.osmand.osm.util;
import java.awt.BorderLayout;
import java.awt.Container;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.swing.JFrame;
import javax.swing.JMenuBar;
import javax.swing.UIManager;
import javax.xml.stream.XMLStreamException;
import org.xml.sax.SAXException;
import com.osmand.data.DataTileManager;
import com.osmand.impl.ConsoleProgressImplementation;
import com.osmand.osm.Entity;
import com.osmand.osm.EntityInfo;
import com.osmand.osm.LatLon;
import com.osmand.osm.MapUtils;
import com.osmand.osm.Node;
import com.osmand.osm.Relation;
import com.osmand.osm.Way;
import com.osmand.osm.OSMSettings.OSMTagKey;
import com.osmand.osm.io.IOsmStorageFilter;
import com.osmand.osm.io.OsmBaseStorage;
import com.osmand.osm.io.OsmStorageWriter;
import com.osmand.swing.DataExtractionSettings;
import com.osmand.swing.MapPanel;
public class MinskTransReader {
// Routes RouteNum; Authority; City; Transport; Operator; ValidityPeriods; SpecialDates;RouteTag;RouteType;Commercial;RouteName;Weekdays;RouteID;Entry;RouteStops;Datestart
@ -30,21 +63,283 @@ public class MinskTransReader {
public String name ; //4
}
public static void main(String[] args) throws IOException {
FileInputStream fis = new FileInputStream(new File("E:/routes.txt"));
BufferedReader reader = new BufferedReader(new InputStreamReader(fis, Charset.forName("cp1251")));
public static final int default_dist_to_stop = 60;
public static final String pathToRoutes = "E:/routes.txt";
public static final String pathToStops = "E:/stops.txt";
public static final String pathToMinsk = "E:\\Information\\OSM maps\\data.osm";
public static final String pathToSave = "E:\\Information\\OSM maps\\data_edit.osm";
public static void main(String[] args) throws IOException, SAXException, XMLStreamException {
FileInputStream fis = new FileInputStream(new File(pathToRoutes));
BufferedReader reader = new BufferedReader(new InputStreamReader(fis, Charset.forName("UTF-8")));
List<TransportRoute> routes = readRoutes(reader);
fis = new FileInputStream(new File("E:/stops.txt"));
reader = new BufferedReader(new InputStreamReader(fis, Charset.forName("cp1251")));
fis = new FileInputStream(new File(pathToStops));
reader = new BufferedReader(new InputStreamReader(fis, Charset.forName("UTF-8")));
List<TransportStop> stops = readStopes(reader);
OutputStreamWriter writer = new OutputStreamWriter(new FileOutputStream("E:/routes_out.txt"), Charset.forName("cp1251"));
for(TransportStop r : stops){
writer.write(r.stopId + " lat : " + r.latitude + " lon : " + r.longitude +" " + r.name + "\n");
Map<String, TransportStop> stopsMap = new LinkedHashMap<String, TransportStop>();
for(TransportStop s : stops){
stopsMap.put(s.stopId, s);
}
// checking that stops are good
for(TransportRoute r : routes){
writer.write(r.routeId +" " + r.routeNum +" " + r.routeType + " " + r.routeName+"\n");
for(String string : r.routeStops){
if(!stopsMap.containsKey(string)){
throw new IllegalArgumentException("Check stop " + string + " of route " + r.routeName);
}
}
}
// showMapPanelWithCorrelatedBusStops(stopsMap, busStops);
OsmBaseStorage storage = filterBusStops(stopsMap, routes);
OsmStorageWriter writer = new OsmStorageWriter();
writer.saveStorage(new FileOutputStream(pathToSave), storage, null, true);
}
public static void showMapPanelWithCorrelatedBusStops(Map<String, TransportStop> stopsMap, DataTileManager<Node> busStops) {
Map<String, Node> result = correlateExistingBusStopsWithImported(busStops, stopsMap);
DataTileManager<Entity> nodes = new DataTileManager<Entity>();
for (String trId : result.keySet()) {
TransportStop r = stopsMap.get(trId);
Way way = new Way(-1);
way.addNode(result.get(trId));
way.addNode(new Node(r.latitude, r.longitude, -1));
nodes.registerObject(r.latitude, r.longitude, way);
}
for(String trId : stopsMap.keySet()){
if(!result.containsKey(trId)){
TransportStop r = stopsMap.get(trId);
nodes.registerObject(r.latitude, r.longitude, new Node(r.latitude, r.longitude, -1));
}
}
showMapPanel(nodes);
}
public static Map<String, Node> correlateExistingBusStopsWithImported(DataTileManager<Node> busStops, Map<String, TransportStop> stopsMap){
Map<String, Node> correlated = new LinkedHashMap<String, Node>();
Map<Node, String> reverse = new LinkedHashMap<Node, String>();
List<TransportStop> stopsToCheck = new ArrayList<TransportStop>(stopsMap.values());
for(int k =0; k<stopsToCheck.size(); k++){
TransportStop r = stopsToCheck.get(k);
List<Node> closestObjects = busStops.getClosestObjects(r.latitude, r.longitude, 0, 1);
// filter closest objects
for(int i=0; i<closestObjects.size(); ){
if(MapUtils.getDistance(closestObjects.get(i), r.latitude, r.longitude) > default_dist_to_stop){
closestObjects.remove(i);
} else{
i++;
}
}
MapUtils.sortListOfEntities(closestObjects, r.latitude, r.longitude);
int ind = 0;
boolean ccorrelated = false;
while(ind < closestObjects.size() && !ccorrelated){
Node foundNode = closestObjects.get(ind);
if(!reverse.containsKey(foundNode)){
// all is good no one registered to that stop
reverse.put(foundNode, r.stopId);
correlated.put(r.stopId, foundNode);
ccorrelated = true;
} else {
// recorrelate existing node and add to todo list
String stopId = reverse.get(foundNode);
TransportStop st = stopsMap.get(stopId);
if(MapUtils.getDistance(foundNode, r.latitude, r.longitude) < MapUtils.getDistance(foundNode, st.latitude, st.longitude)){
// check that stop again
stopsToCheck.add(st);
reverse.put(foundNode, r.stopId);
correlated.put(r.stopId, foundNode);
correlated.remove(st.stopId);
ccorrelated = true;
}
}
ind++;
}
}
return correlated;
}
public static void showMapPanel(DataTileManager<? extends Entity> points){
JFrame frame = new JFrame("Map view");
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (Exception e) {
e.printStackTrace();
}
final MapPanel panel = new MapPanel(DataExtractionSettings.getSettings().getTilesDirectory());
panel.setPoints(points);
frame.addWindowListener(new WindowAdapter(){
@Override
public void windowClosing(WindowEvent e) {
DataExtractionSettings settings = DataExtractionSettings.getSettings();
settings.saveDefaultLocation(panel.getLatitude(), panel.getLongitude());
settings.saveDefaultZoom(panel.getZoom());
System.exit(0);
}
});
Container content = frame.getContentPane();
content.add(panel, BorderLayout.CENTER);
JMenuBar bar = new JMenuBar();
bar.add(MapPanel.getMenuToChooseSource(panel));
frame.setJMenuBar(bar);
frame.setSize(512, 512);
frame.setVisible(true);
}
protected static void removeGeneratedNotUsedBusStops(Map<String, Node> correlated,
Map<String, Relation> definedRoutes, DataTileManager<Node> busStops, OsmBaseStorage storage){
Set<Node> usedNodes = new LinkedHashSet<Node>(correlated.values());
for(Relation r : definedRoutes.values()){
for(Entity e : r.getMembers(null)){
if(e instanceof Node){
usedNodes.add((Node) e);
}
}
}
for(Node stop : busStops.getAllObjects()){
if(!usedNodes.contains(stop) && "yes".equals(stop.getTag("generated"))){
EntityInfo info = storage.getRegisteredEntityInfo().get(stop.getId());
info.setAction("delete");
System.out.println("[DEL] Remove generated not used stop " + stop.getId() + " " + stop.getTag("name"));
}
}
}
protected static OsmBaseStorage filterBusStops(Map<String, TransportStop> stopsMap, List<TransportRoute> routes) throws FileNotFoundException, IOException, SAXException{
long time = System.currentTimeMillis();
System.out.println("Start : ");
OsmBaseStorage storage = new OsmBaseStorage();
final Map<String, Relation> definedRoutes = new HashMap<String, Relation>();
final DataTileManager<Node> busStops = new DataTileManager<Node>();
busStops.setZoom(17);
storage.getFilters().add(new IOsmStorageFilter(){
@Override
public boolean acceptEntityToLoad(OsmBaseStorage storage, Entity entity) {
if(entity.getTag("route") != null){
definedRoutes.put(entity.getTag("route") + "_" + entity.getTag("ref"), (Relation) entity);
return true;
}
if(entity.getTag(OSMTagKey.HIGHWAY) != null && entity.getTag(OSMTagKey.HIGHWAY).equals("bus_stop")){
LatLon e = entity.getLatLon();
busStops.registerObject(e.getLatitude(), e.getLongitude(), (Node) entity);
}
return entity instanceof Node;
}
});
storage.parseOSM(new FileInputStream(pathToMinsk), new ConsoleProgressImplementation());
Map<String, Node> correlated = correlateExistingBusStopsWithImported(busStops, stopsMap);
removeGeneratedNotUsedBusStops(correlated, definedRoutes, busStops, storage);
registerNewRoutesAndEditExisting(stopsMap, routes, storage, definedRoutes, correlated);
System.out.println("End time : " + (System.currentTimeMillis() - time));
return storage;
}
protected static long id = -55000;
protected static void registerNewRoutesAndEditExisting(Map<String, TransportStop> stopsMap, List<TransportRoute> routes,
OsmBaseStorage storage, final Map<String, Relation> definedRoutes, Map<String, Node> correlated) {
Map<String, Relation> checkedRoutes = new LinkedHashMap<String, Relation>();
// because routes can changed on schedule that's why for 1 relation many routes.
Set<String> visitedRoutes = new HashSet<String>();
for (TransportRoute r : routes) {
// register only bus/trolleybus
if (!r.transport.equals("bus") && !r.transport.equals("trolleybus")) {
continue;
}
String s = r.transport + "_" + r.routeNum;
boolean reverse = r.routeType.equals("B>A");
boolean direct = r.routeType.equals("A>B");
if (!reverse && !direct) {
// that's additinal route skip it
continue;
}
if (!visitedRoutes.add(s + "_" + direct)) {
// skip it : duplicated route (schedule changed)
continue;
}
if (definedRoutes.containsKey(s)) {
checkedRoutes.put(s, definedRoutes.get(s));
// System.out.println("Already registered " + s);
} else {
if (!checkedRoutes.containsKey(s)) {
if(reverse){
System.err.println("Strange route skipped : " + s);
continue;
}
Relation relation = new Relation(id--);
relation.putTag("route", r.transport);
relation.putTag("ref", r.routeNum);
relation.putTag("name", r.routeName);
relation.putTag("operator", "КУП \"Минсктранс\"");
relation.putTag("type", "route");
relation.putTag("generated", "yes");
checkedRoutes.put(s, relation);
storage.getRegisteredEntities().put(relation.getId(), relation);
System.out.println("[ADD] Registered new route " + s);
}
Relation relation = checkedRoutes.get(s);
// correlating stops
for (int i = 0; i < r.routeStops.size(); i++) {
String stop = r.routeStops.get(i);
if (!stopsMap.containsKey(stop)) {
throw new IllegalArgumentException("Stops file is not corresponded to routes file");
}
if (!correlated.containsKey(stop)) {
TransportStop st = stopsMap.get(stop);
Node node = new Node(st.latitude, st.longitude, id--);
node.putTag("highway", "bus_stop");
if (st.name != null) {
node.putTag("name", st.name);
} else {
throw new IllegalArgumentException("Something wrong check " + st.stopId);
}
node.putTag("generated", "yes");
storage.getRegisteredEntities().put(node.getId(), node);
System.out.println("[ADD] Added new bus_stop : " + node.getId() + " " + st.name + " minsktrans_stop_id " + st.stopId);
correlated.put(stop, node);
}
if (i == 0 || i == r.routeStops.size() - 1) {
if (direct) {
relation.addMember(correlated.get(stop).getId(), "stop");
}
} else {
if (direct) {
relation.addMember(correlated.get(stop).getId(), "forward:stop");
} else {
relation.addMember(correlated.get(stop).getId(), "backward:stop");
}
}
}
}
}
// check relations that are not exist
for(String s : definedRoutes.keySet()){
if(!checkedRoutes.containsKey(s)){
Relation rel = definedRoutes.get(s);
storage.getRegisteredEntityInfo().get(rel.getId()).setAction("delete");
System.out.println("[DEL] Route is deprecated : " + rel.getTag("route")+"_"+rel.getTag("ref") + " " + rel.getTag("name"));
}
}
}
@ -113,6 +408,7 @@ public class MinskTransReader {
String st = null;
int line = 0;
List<TransportStop> stopes = new ArrayList<TransportStop>();
TransportStop previous = null;
while((st = reader.readLine()) != null){
if(line++ == 0){
continue;
@ -128,15 +424,20 @@ public class MinskTransReader {
if(i==0){
current.stopId = newS.trim();
} else if(i==4){
current.name = newS;
if(newS.length() == 0 && previous != null){
current.name = previous.name;
} else {
current.name = newS;
}
} else if(i==5){
current.latitude = Double.parseDouble(newS)/1e5;
current.longitude = Double.parseDouble(newS)/1e5;
} else if(i==6){
current.longitude = Double.parseDouble(newS)/1e5;
current.latitude = Double.parseDouble(newS)/1e5;
}
stI = endI + 1;
i++;
}
previous = current;
stopes.add(current);
}
return stopes;