All Downloads are FREE. Search and download functionalities are using the official Maven repository.

fr.umr.lastig.mapmatcher.util.Loaders Maven / Gradle / Ivy

Go to download

Map-matching of a track on a network with Hidden Markov Model. Based on popular Newson and Krumm paper

There is a newer version: 1.4
Show newest version
/*******************************************************************************
 * This software is released under the licence CeCILL
 * 
 * see Licence_CeCILL-C_fr.html see Licence_CeCILL-C_en.html
 * 
 * see http://www.cecill.info/a>
 * 
 * @copyright IGN
 *
 * @author Yann Méneroux
 ******************************************************************************/
package fr.umr.lastig.mapmatcher.util;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.Hashtable;
import java.util.NoSuchElementException;
import java.util.Scanner;
import java.util.StringTokenizer;

import org.locationtech.jts.geom.Coordinate;
import org.locationtech.jts.geom.Geometry;
import org.locationtech.jts.geom.GeometryFactory;
import org.locationtech.jts.geom.prep.PreparedGeometry;
import org.locationtech.jts.geom.prep.PreparedGeometryFactory;
import org.locationtech.jts.io.ParseException;
import org.locationtech.jts.io.WKTReader;
import org.locationtech.jts.simplify.DouglasPeuckerSimplifier;

import fr.umr.lastig.mapmatcher.network.Network;
import fr.umr.lastig.mapmatcher.core.MapMatching;
import fr.umr.lastig.mapmatcher.core.Track;




public class Loaders {

	// Network containers
	private static ArrayList SOURCES;
	private static ArrayList TARGETS;
	private static ArrayList WEIGHTS;
	private static ArrayList GEOMS;
	private static Hashtable> NODES;
	private static Hashtable EDGES;
	private static ArrayList EDGE_NAMES;
	private static ArrayList ONE_WAY;


	// Delimiters
	public static String columns_delimiter_network = "";
	public static String columns_delimiter_track = "";

	// Column indices for network
	public static int wkt_id = -1;
	public static int source_id = -1;
	public static int target_id = -1;
	public static int edge_id = -1;
	public static int oneway_id = -1;

	// Column names for network
	public static String geom_column_name = "";
	public static String source_column_name = "";
	public static String target_column_name = "";
	public static String edge_column_name = "";
	public static String oneway_column_name = "";

	// Columns indices for track
	public static int columns_x_id = -1;
	public static int columns_y_id = -1;
	public static int columns_t_id = -1;

	// Columns names for track
	public static String columns_x_name = "";
	public static String columns_y_name = "";
	public static String columns_t_name = "";

	// Headers
	public static boolean track_header = true;
	public static boolean network_header = true;

	// Date format in GPS trace
	public static String dateFmt = "";

	// GPS error code
	public static String gps_error_code = "";

	// Number of wrong points
	public static int excluded_points_number;

	// Excluded data
	public static ArrayList EXCLUDED_X;
	public static ArrayList EXCLUDED_Y;
	public static ArrayList EXCLUDED_T;
	public static ArrayList EXCLUDED_I;

	// Network bounding box
	public static double xmin = 0.0;
	public static double xmax = 0.0;
	public static double ymin = 0.0;
	public static double ymax = 0.0;

	// Network buffering
	private static PreparedGeometry buffer = null;

	// -------------------------------------------------------------------
	// Module for for setting map-matching parameters
	// -------------------------------------------------------------------
	public static void parameterize(){

		Loaders.columns_delimiter_network = Parameters.network_delimiter;
		Loaders.columns_delimiter_track = Parameters.track_delimiter;

		Loaders.wkt_id = Parameters.network_geom_id;
		Loaders.source_id = Parameters.network_source_id;
		Loaders.target_id = Parameters.network_target_id;
		Loaders.edge_id = Parameters.network_edge_id;
		Loaders.oneway_id = Parameters.network_oneway_id;

		Loaders.geom_column_name = Parameters.network_geom_name;
		Loaders.source_column_name = Parameters.network_source_name;
		Loaders.target_column_name = Parameters.network_target_name;
		Loaders.edge_column_name = Parameters.network_edge_name;
		Loaders.oneway_column_name = Parameters.network_oneway_name;

		Loaders.track_header = Parameters.track_header;
		Loaders.network_header = Parameters.network_header;

		Loaders.columns_x_id = Parameters.track_columns_x_id;
		Loaders.columns_y_id = Parameters.track_columns_y_id;
		Loaders.columns_t_id = Parameters.track_columns_t_id;

		Loaders.columns_x_name = Parameters.track_columns_x_name;
		Loaders.columns_y_name = Parameters.track_columns_y_name;
		Loaders.columns_t_name = Parameters.track_columns_t_name;

		Loaders.dateFmt = Parameters.track_date_fmt;

		Loaders.gps_error_code = Parameters.track_error_code;

		// Initialization

		excluded_points_number = 0;

		EXCLUDED_I = new ArrayList();
		EXCLUDED_T = new ArrayList();
		EXCLUDED_X = new ArrayList();
		EXCLUDED_Y = new ArrayList();

	}

	// ----------------------------------------------
	// Add buffer to loaders
	// ----------------------------------------------
	public static void setBuffer(Geometry buffer){

		Loaders.buffer = PreparedGeometryFactory.prepare(DouglasPeuckerSimplifier.simplify(buffer, 0.33*Parameters.buffer_radius));

	}


	// ----------------------------------------------
	// Reinitialize buffer
	// ----------------------------------------------
	public static void setBufferNull(){

		Loaders.buffer = null;

	}

	// ----------------------------------------------
	// Module to load GPS track without header
	// ----------------------------------------------
	@SuppressWarnings("resource")
	public static Track loadTrack(String path){

		Scanner scan = null;

		// Load data
		try {scan = new Scanner(new File(path));} 
		catch (FileNotFoundException e) {

			Tools.println("Error: no track file ["+path+"]");
			if (MapMatching.gui_mode){
				return null;
			}else{
				System.exit(6);
			}

		}

		// Initialize
		ArrayList X = new ArrayList();
		ArrayList Y = new ArrayList();
		ArrayList T = new ArrayList();
		ArrayList Tms = new ArrayList();

		// Date converter
		SimpleDateFormat df = new SimpleDateFormat(dateFmt);

		// Header
		if (track_header){

			String header = scan.nextLine();

			StringTokenizer st = new StringTokenizer(header, columns_delimiter_track);

			int counter = 1;

			while(st.hasMoreTokens()){

				String col_name = st.nextToken();

				if (col_name.equals(columns_x_name))    {columns_x_id = counter;}
				if (col_name.equals(columns_y_name))    {columns_y_id = counter;}
				if (col_name.equals(columns_t_name))    {columns_t_id = counter;}

				counter ++;

			}


			if (columns_x_id == -1){

				Tools.printError("Error : x coordinate column \""+columns_x_name+"\" has not been found in network input file");
				if (MapMatching.gui_mode){
					return null;
				}else{
					System.exit(1);
				}

			}

			if (columns_y_id == -1){

				Tools.printError("Error : y coordinate column \""+columns_y_name+"\" has not been found in network input file");
				if (MapMatching.gui_mode){
					return null;
				}else{
					System.exit(1);
				}

			}


			if ((columns_t_id == -1) && (!columns_t_name.equals(""))){

				if (!MapMatching.gui_mode){

					Tools.printError("Error : timestamp column \""+columns_t_name+"\" has not been found in network input file");
					System.exit(1);

				}

			}

		}


		// Reading file

		int counter = 0;

		while (scan.hasNextLine()){

			String line = scan.nextLine();


			if (line.equals("")){continue;}

			StringTokenizer st1 = new StringTokenizer(line, columns_delimiter_track);
			StringTokenizer st2 = new StringTokenizer(line, columns_delimiter_track);
			StringTokenizer st3 = new StringTokenizer(line, columns_delimiter_track);


			String x = "";
			String y = "";
			String t = "no_time_stamp";

			try{

				for (int i=0; i();
		TARGETS  = new ArrayList();
		WEIGHTS  = new ArrayList();
		GEOMS = new ArrayList();
		NODES = new Hashtable>();
		EDGES = new Hashtable();
		EDGE_NAMES = new ArrayList();
		ONE_WAY =  new ArrayList();

		// Load file
		try {scan = new Scanner(new File(path));} 
		catch (FileNotFoundException e) {

			Tools.printError("Error: no network file ["+path+"]");

			if (MapMatching.gui_mode){
				return null;
			}
			else{
				System.exit(6);
			}


		}

		// ------------------------------------------
		// Headline analysis
		// ------------------------------------------
		if (network_header) {


			int counter = 1;

			line = scan.nextLine();

			st = new StringTokenizer(line, columns_delimiter_network);

			while(st.hasMoreTokens()){

				String col_name = st.nextToken();
				
				if (col_name.equals(geom_column_name))   {wkt_id = counter;}
				if (col_name.equals(source_column_name)) {source_id = counter;}
				if (col_name.equals(target_column_name)) {target_id = counter;}
				if (col_name.equals(edge_column_name))   {edge_id = counter;}
				if (col_name.equals(oneway_column_name)) {oneway_id = counter;}


				counter ++;

			}


			if (wkt_id == -1){

				Tools.printError("Error : geometry column \""+geom_column_name+"\" has not been found in network input file");

				if (MapMatching.gui_mode){
					return null;
				}
				else{
					System.exit(1);
				}

			}

			if ((source_id == -1) && (!Parameters.make_topology)){

				Tools.printError("Error : source column \""+source_column_name+"\" has not been found in network input file");

				if (MapMatching.gui_mode){
					return null;
				}
				else{
					System.exit(1);
				}

			}

			if ((target_id == -1) && (!Parameters.make_topology)){

				Tools.printError("Error : target column \""+target_column_name+"\" has not been found in network input file");

				if (MapMatching.gui_mode){
					return null;
				}
				else{
					System.exit(1);
				}

			}

			if ((edge_id == -1) && (!edge_column_name.equals(""))){

				Tools.printError("Error : edge column \""+edge_column_name+"\" has not been found in network input file");

				if (MapMatching.gui_mode){
					return null;
				}
				else{
					System.exit(1);
				}

			}

			if ((oneway_id == -1) && (!oneway_column_name.equals(""))){

				Tools.printError("Error : one way column \""+oneway_column_name+"\" has not been found in network input file");

				if (MapMatching.gui_mode){
					return null;
				}
				else{
					System.exit(1);
				}

			}

		}


		// ------------------------------------------
		// File body analysis
		// ------------------------------------------


		wkt_id --;
		source_id --;
		target_id --;
		edge_id --;
		oneway_id --;

		Hashtable EDGE_ID_NAMES = new Hashtable();

		int max_id = Math.max(wkt_id, source_id);
		max_id = Math.max(max_id, target_id);
		max_id = Math.max(max_id, edge_id);
		max_id = Math.max(max_id, oneway_id);


		while(scan.hasNextLine()){

			line = scan.nextLine();

			if (line.equals("")){continue;}

			String[] values = line.replaceAll("^\"", "").split("\"?("+Parameters.network_delimiter+"|$)(?=(([^\"]*\"){2})*[^\"]*$) *\"?");

			if (max_id >= values.length){

				int ln = SOURCES.size()+1;

				if(network_header){ln ++;}

				Tools.printError("Error: line "+ln+" inconsistent with data specifications in network input file");
				return null;

			}



			if (!(buffer == null)){

				try {

					Geometry g = reader.read(values[wkt_id]);

					if (!Loaders.buffer.intersects(g)){continue;}

				} catch (Exception e1) {
					e1.printStackTrace();
				}
			}


			String source = "";
			String target = "";

			if (!Parameters.make_topology){

				source = values[source_id];
				target = values[target_id];

			}
			else{

				source = (2*SOURCES.size())+"";
				target = (2*SOURCES.size()+1)+"";	

			}

			SOURCES.add(source);
			TARGETS.add(target);


			if (oneway_id > -1){

				if ((values[oneway_id].equals("inverse"))||(values[oneway_id].equals("-1"))){
					
					ONE_WAY.add(0);
					
				}
				else if ((values[oneway_id].equals("direct"))||(values[oneway_id].equals("1"))){
					
					ONE_WAY.add(1);
					
				}
				else{
					
					ONE_WAY.add(0);
					
				}

			}
			else{

				ONE_WAY.add(0);

			}

			if (edge_id > -1){

				if (EDGE_ID_NAMES.containsKey(values[edge_id])){

					System.out.println(values[edge_id]);

					Tools.printError("Error: network edge id must be unique");

					if (MapMatching.gui_mode){
						return null;
					}
					else{
						System.exit(15);
					}

				}
				else{

					EDGE_NAMES.add(values[edge_id]);
					EDGE_ID_NAMES.put(values[edge_id], 0);

				}

			}

			// -------------------------------------------
			// Register source of edge
			// -------------------------------------------
			if (!NODES.containsKey(source)){

				nodeNumber ++;
				NODES.put(source, new ArrayList());

			}

			NODES.get(source).add(target);

			// -------------------------------------------
			// Register target of edge
			// -------------------------------------------
			if (!NODES.containsKey(target)){

				nodeNumber ++;
				NODES.put(target, new ArrayList());

			}

			NODES.get(target).add(source);


			// -------------------------------------------
			// Register geometry
			// -------------------------------------------

			Geometry geom = null;

			try {

				geom = reader.read(values[wkt_id]);

				WEIGHTS.add(geom.getLength());

			} catch (ParseException e) {

				Tools.printError("Error : geometry column is not in WKT format");

				if (MapMatching.gui_mode){
					return null;
				}
				else{
					System.exit(15);
				}

			}

			GEOMS.add(geom);

			// Updating bounding box
			for (int i=0; i"+target, GEOMS.size()-1);
			EDGES.put(target+"->"+source, GEOMS.size()-1);

		}

		// -------------------------------------------
		// Return output network
		// -------------------------------------------

		NETWORK.setSources(SOURCES);
		NETWORK.setTargets(TARGETS);
		NETWORK.setWeights(WEIGHTS);
		NETWORK.setGeometries(GEOMS);
		NETWORK.setNodes(NODES);
		NETWORK.setEdges(EDGES);
		NETWORK.setEdgeNames(EDGE_NAMES);
		NETWORK.setOneWay(ONE_WAY);

		NETWORK.setNodeNumber(nodeNumber);
		NETWORK.setVerticeNumber(verticeNumber);


		// -------------------------------------------
		// Build topology
		// -------------------------------------------
		NETWORK.makeGraph();


		return NETWORK;

	}


	// ----------------------------------------------
	// Module to load road network from OSM file
	// ----------------------------------------------
	@SuppressWarnings("resource")
	public static Network loadNetworkFromOSM(String path){

		Network NETWORK = new Network();

		GeometryFactory gf = new GeometryFactory();

		int nodeNumber = 0;
		int verticeNumber = 0;

		NETWORK.setPath(path);

		SOURCES = new ArrayList();
		TARGETS  = new ArrayList();
		WEIGHTS  = new ArrayList();
		GEOMS = new ArrayList();
		NODES = new Hashtable>();
		EDGES = new Hashtable();
		EDGE_NAMES = new ArrayList();
		ONE_WAY =  new ArrayList();

		Hashtable LIST_OF_NODES = new Hashtable();


		BufferedReader br = null;

		try {

			br = new BufferedReader(new FileReader(path));

		} catch (FileNotFoundException e2) {

			Tools.printError("Error: no network file ["+path+"]");

			if (MapMatching.gui_mode){

				return null;
			}
			else{

				System.exit(6);

			}
		}

		String line = null;

		try {
			line = br.readLine();
		} catch (IOException e1) {

		}

		ArrayList NODES_IN_WAY = new ArrayList();

		String edge_name = "";

		boolean road = false;

		while(line != null){

			if (line.startsWith("  ());
				LIST_OF_NODES.put(node_id, new Coordinate(x, y));

				nodeNumber ++;

			}


			if (line.startsWith("  ")){

				if (!road){

					try {line = br.readLine();}
					catch (IOException e) {}

					continue;

				}

				String source = NODES_IN_WAY.get(0);
				String target = NODES_IN_WAY.get(NODES_IN_WAY.size()-1);


				if (NODES.get(source) == null){

					try {line = br.readLine();}
					catch (IOException e) {}

					continue;

				}

				if (NODES.get(target) == null){

					try {line = br.readLine();}
					catch (IOException e) {}

					continue;

				}

				Coordinate[] coordinates = new Coordinate[NODES_IN_WAY.size()];

				for (int i=0; i"+target, GEOMS.size()-1);
				EDGES.put(target+"->"+source, GEOMS.size()-1);

				verticeNumber += (NODES_IN_WAY.size()-2);

			}

			try {line = br.readLine();}
			catch (IOException e) {}


		}


		// -------------------------------------------
		// Return output network
		// -------------------------------------------

		NETWORK.setSources(SOURCES);
		NETWORK.setTargets(TARGETS);
		NETWORK.setWeights(WEIGHTS);
		NETWORK.setGeometries(GEOMS);
		NETWORK.setNodes(NODES);
		NETWORK.setEdges(EDGES);
		NETWORK.setEdgeNames(EDGE_NAMES);
		NETWORK.setOneWay(ONE_WAY);

		NETWORK.setNodeNumber(nodeNumber);
		NETWORK.setVerticeNumber(verticeNumber);


		// -------------------------------------------
		// Build topology
		// -------------------------------------------
		NETWORK.makeGraph();

		return NETWORK;

	}


}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy