summaryrefslogtreecommitdiff
path: root/navit/map/csv/csv.c
diff options
context:
space:
mode:
Diffstat (limited to 'navit/map/csv/csv.c')
-rw-r--r--navit/map/csv/csv.c348
1 files changed, 348 insertions, 0 deletions
diff --git a/navit/map/csv/csv.c b/navit/map/csv/csv.c
new file mode 100644
index 000000000..e7e415405
--- /dev/null
+++ b/navit/map/csv/csv.c
@@ -0,0 +1,348 @@
+/**
+ * Navit, a modular navigation system.
+ * Copyright (C) 2005-2011 Navit Team
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include <glib.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <math.h>
+#include "config.h"
+#include "debug.h"
+#include "plugin.h"
+#include "projection.h"
+#include "item.h"
+#include "map.h"
+#include "maptype.h"
+#include "attr.h"
+#include "transform.h"
+#include "file.h"
+#include "quadtree.h"
+
+#include "csv.h"
+
+static int map_id;
+
+
+struct quadtree_data
+{
+ struct item* item;
+ GList* attr_list;
+};
+
+static void
+map_destroy_csv(struct map_priv *m)
+{
+ dbg(1,"map_destroy_csv\n");
+ g_free(m);
+ g_hash_table_destroy(m->item_hash);
+ quadtree_destroy(m->tree_root);
+}
+
+static void
+csv_coord_rewind(void *priv_data)
+{
+}
+
+static int
+csv_coord_get(void *priv_data, struct coord *c, int count)
+{
+ struct map_rect_priv *mr=priv_data;
+ if(mr) {
+ *c = mr->c;
+ return 1;
+ }
+ else {
+ return 0;
+ }
+}
+
+static void
+csv_attr_rewind(void *priv_data)
+{
+ struct map_rect_priv *mr=priv_data;
+ //TODO implement if needed
+}
+
+static int
+csv_attr_get(void *priv_data, enum attr_type attr_type, struct attr *attr)
+{
+ struct map_rect_priv *mr=priv_data;
+
+ GList* attr_list = ((struct quadtree_data*)(((struct quadtree_item*)(mr->curr_item->data))->data))->attr_list;
+ if (attr_type == attr_any) {
+ }
+
+ while(attr_list) {
+ if(((struct attr*)attr_list->data)->type == attr_type) {
+ *attr = *(struct attr*)attr_list->data;
+ return 1;
+ }
+ attr_list = g_list_next(attr_list);
+ }
+ attr = NULL;
+ return 0;
+}
+
+static struct item_methods methods_csv = {
+ csv_coord_rewind,
+ csv_coord_get,
+ csv_attr_rewind,
+ csv_attr_get,
+};
+
+static struct map_rect_priv *
+map_rect_new_csv(struct map_priv *map, struct map_selection *sel)
+{
+ struct map_rect_priv *mr;
+
+ dbg(1,"map_rect_new_csv\n");
+ mr=g_new0(struct map_rect_priv, 1);
+ mr->m=map;
+ mr->bStarted = 0;
+ mr->sel=sel;
+ if (map->flags & 1)
+ mr->item.id_hi=1;
+ else
+ mr->item.id_hi=0;
+ mr->item.id_lo=0;
+ mr->item.meth=&methods_csv;
+ mr->item.priv_data=mr;
+
+ //convert selection to geo
+ struct coord_geo lu;
+ struct coord_geo rl;
+ transform_to_geo(projection_mg, &sel->u.c_rect.lu, &lu);
+ transform_to_geo(projection_mg, &sel->u.c_rect.rl, &rl);
+ GList*res = NULL;
+ quadtree_find_rect_items(map->tree_root, lu.lng, rl.lng, rl.lat, lu.lat, &res);
+ mr->query_result = res;
+ mr->curr_item = res;
+ return mr;
+}
+
+
+static void
+map_rect_destroy_csv(struct map_rect_priv *mr)
+{
+ g_free(mr);
+}
+
+static struct item *
+map_rect_get_item_csv(struct map_rect_priv *mr)
+{
+ if(mr->bStarted) {
+ mr->curr_item = g_list_next(mr->curr_item);
+ }
+ else {
+ mr->bStarted = 1;
+ }
+
+ if(mr->curr_item) {
+ struct item* ret;
+ ret = ((struct quadtree_data*)(((struct quadtree_item*)(mr->curr_item->data))->data))->item;
+ ret->priv_data=mr;
+ struct coord_geo cg;
+ if(mr->curr_item && mr->curr_item->data) {
+ cg.lng = ((struct quadtree_item*)(mr->curr_item->data))->longitude;
+ cg.lat = ((struct quadtree_item*)(mr->curr_item->data))->latitude;
+ transform_from_geo(projection_mg, &cg, &mr->c);
+ ret = ((struct quadtree_data*)(((struct quadtree_item*)(mr->curr_item->data))->data))->item;
+ return ret;
+ }
+
+ }
+ return NULL;
+}
+
+static struct item *
+map_rect_get_item_byid_csv(struct map_rect_priv *mr, int id_hi, int id_lo)
+{
+ //currently id_hi is ignored
+ return g_hash_table_lookup(mr->m->item_hash,id_lo);
+}
+
+static struct map_methods map_methods_csv = {
+ projection_mg,
+ "iso8859-1",
+ map_destroy_csv,
+ map_rect_new_csv,
+ map_rect_destroy_csv,
+ map_rect_get_item_csv,
+ map_rect_get_item_byid_csv,
+};
+
+static struct map_priv *
+map_new_csv(struct map_methods *meth, struct attr **attrs)
+{
+ struct map_priv *m = NULL;
+ m = g_new0(struct map_priv, 1);
+ m->id = ++map_id;
+ m->item_hash = g_hash_table_new(g_int_hash, g_int_equal);
+
+ struct attr *item_type = attr_search(attrs, NULL, attr_item_type);
+ struct attr *attr_types = attr_search(attrs, NULL, attr_attr_types);
+ int bLonFound = 0;
+ int bLatFound = 0;
+ int attr_cnt = 0;
+ enum attr_type* attr_type_list = NULL;
+ struct quadtree_node* tree_root = quadtree_node_new(NULL,-90,90,-90,90);
+ if(attr_types) {
+ enum attr_type* at = attr_types->u.attr_types;
+ while(*at != attr_none) {
+ attr_type_list = g_realloc(attr_type_list,sizeof(enum attr_type)*(attr_cnt+1));
+ attr_type_list[attr_cnt] = *at;
+ if(*at==attr_position_latitude) {
+ bLatFound = 1;
+ }
+ else if(*at==attr_position_longitude) {
+ bLonFound = 1;
+ }
+ ++attr_cnt;
+ ++at;
+ }
+ }
+ else {
+ return NULL;
+ }
+
+ if(bLonFound==0 || bLatFound==0) {
+ return NULL;
+ }
+
+ struct attr *item_type_attr=attr_search(attrs, NULL, attr_item_type);
+
+ if( !item_type_attr || item_type_attr->u.item_type==type_none) {
+ return NULL;
+ }
+
+ struct attr *data=attr_search(attrs, NULL, attr_data);
+
+ if(data) {
+ //load csv file into quadtree structure
+ //if column number is wrong skip
+ FILE*fp;
+ if((fp=fopen(data->u.str,"rt"))) {
+ int item_idx = 0;
+ while(!feof(fp)) {
+ const int max_line_len = 256;
+ char line[max_line_len];
+ if(fgets(line,max_line_len,fp)) {
+ char*line2 = g_strdup(line);
+ //count columns
+ //TODO make delimiter parameter
+ char* delim = ",";
+ int col_cnt=0;
+ char*tok;
+ while((tok=strtok( (col_cnt==0)?line:NULL , delim))) {
+ ++col_cnt;
+ }
+
+ if(col_cnt==attr_cnt) {
+ int cnt = 0; //idx of current attr
+ char*tok;
+ const int zoom_max = 18;
+ struct item *curr_item = item_new("",zoom_max);//does not use parameters
+ curr_item->type = item_type_attr->u.item_type;
+ curr_item->id_lo = item_idx;
+ if (m->flags & 1)
+ curr_item->id_hi=1;
+ else
+ curr_item->id_hi=0;
+ curr_item->meth=&methods_csv;
+
+ GList* attr_list = NULL;
+ int bAddSum = 1;
+ double longitude = 0.0, latitude=0.0;
+ while((tok=strtok( (cnt==0)?line2:NULL , delim))) {
+ struct attr*curr_attr = g_new0(struct attr,1);
+ curr_attr->type = attr_types->u.attr_types[cnt];
+ int bAdd = 1;
+ if(ATTR_IS_STRING(attr_types->u.attr_types[cnt])) {
+ curr_attr->u.str = g_strdup(tok);
+ }
+ else if(ATTR_IS_INT(attr_types->u.attr_types[cnt])) {
+ curr_attr->u.num = atoi(tok);
+ }
+ else if(ATTR_IS_DOUBLE(attr_types->u.attr_types[cnt])) {
+ double *d = g_new(double,1);
+ *d = atof(tok);
+ curr_attr->u.numd = d;
+ if(attr_types->u.attr_types[cnt] == attr_position_longitude) {
+ longitude = *d;
+ }
+ if(attr_types->u.attr_types[cnt] == attr_position_latitude) {
+ latitude = *d;
+ }
+ }
+ else {
+ //unknown attribute
+ bAddSum = bAdd = 0;
+ g_free(curr_attr);
+ }
+
+ if(bAdd) {
+ attr_list = g_list_prepend(attr_list, curr_attr);
+ }
+ ++cnt;
+ }
+ if(bAddSum) {
+ struct quadtree_data* qd = g_new0(struct quadtree_data,1);
+ qd->item = curr_item;
+ qd->attr_list = attr_list;
+ struct quadtree_item* qi =g_new(struct quadtree_item,1);
+ qi->data = qd;
+ qi->longitude = longitude;
+ qi->latitude = latitude;
+ quadtree_add(tree_root, qi);
+ g_hash_table_insert(m->item_hash, item_idx,curr_item);
+ ++item_idx;
+ }
+ else {
+ g_free(curr_item);
+ }
+
+ }
+ else {
+ //printf("ERROR: Non-matching attr count and column count: %d %d SKIPPING line: %s\n",col_cnt, attr_cnt,line);
+ }
+ g_free(line2);
+ }
+ }
+ fclose(fp);
+ }
+ else {
+ return NULL;
+ }
+ }
+
+ *meth = map_methods_csv;
+ m->tree_root = tree_root;
+ struct attr *flags=attr_search(attrs, NULL, attr_flags);
+ if (flags)
+ m->flags=flags->u.num;
+ return m;
+}
+
+void
+plugin_init(void)
+{
+ dbg(1,"csv: plugin_init\n");
+ plugin_register_map_type("csv", map_new_csv);
+}
+