[cairo-commit] roadster/src Makefile.am, 1.23, 1.24 db.c, 1.32,
1.33 db.h, 1.14, 1.15 import_tiger.c, 1.21, 1.22 main.c, 1.32,
1.33 main.h, 1.5, 1.6 mainwindow.c, 1.48, 1.49 map.c, 1.51,
1.52 map.h, 1.25, 1.26 map_draw_cairo.c, 1.27,
1.28 map_draw_cairo.h, 1.1, 1.2 map_draw_gdk.c, 1.25,
1.26 map_draw_gdk.h, 1.1, 1.2 map_style.c, 1.4, 1.5 map_tile.c,
1.2, NONE map_tile.h, 1.1, NONE map_tilemanager.c, NONE,
1.1 map_tilemanager.h, NONE, 1.1 road.c, 1.8,
1.9 scenemanager.c, 1.15, 1.16 scenemanager.h, 1.7,
1.8 search_road.c, 1.28, 1.29
Ian McIntosh
commit at pdx.freedesktop.org
Tue Oct 4 23:09:38 PDT 2005
Committed by: ian
Update of /cvs/cairo/roadster/src
In directory gabe:/tmp/cvs-serv21001/src
Modified Files:
Makefile.am db.c db.h import_tiger.c main.c main.h
mainwindow.c map.c map.h map_draw_cairo.c map_draw_cairo.h
map_draw_gdk.c map_draw_gdk.h map_style.c road.c
scenemanager.c scenemanager.h search_road.c
Added Files:
map_tilemanager.c map_tilemanager.h
Removed Files:
map_tile.c map_tile.h
Log Message:
* src/import_tiger.c:
* src/search_road.c:
* src/db.c: Add level of detail concept.
* src/mainwindow.c: Add zoomtool.
* src/map_draw_gdk.c:
* src/map_draw_cairo.c: Calculate bounding box on load instead of draw. Update to tile drawing.
* src/map.c: Begin splitting this file up more. Add lots more zoom levels.
* src/scenemanager.c: Remove empty module init.
* src/main.c: Don't need to init scenemanager module.
Index: Makefile.am
===================================================================
RCS file: /cvs/cairo/roadster/src/Makefile.am,v
retrieving revision 1.23
retrieving revision 1.24
diff -u -d -r1.23 -r1.24
--- Makefile.am 1 Oct 2005 05:24:16 -0000 1.23
+++ Makefile.am 5 Oct 2005 06:09:36 -0000 1.24
@@ -25,11 +25,13 @@
mainwindow.c\
gotowindow.c\
map.c\
- map_tile.c\
- map_history.c\
- map_style.c\
map_draw_cairo.c\
map_draw_gdk.c\
+ map_history.c\
+ map_hittest.c\
+ map_math.c\
+ map_style.c\
+ map_tilemanager.c\
import.c\
import_tiger.c\
importwindow.c\
Index: db.c
===================================================================
RCS file: /cvs/cairo/roadster/src/db.c,v
retrieving revision 1.32
retrieving revision 1.33
diff -u -d -r1.32 -r1.33
--- db.c 1 Oct 2005 01:42:12 -0000 1.32
+++ db.c 5 Oct 2005 06:09:36 -0000 1.33
@@ -256,11 +256,6 @@
return uRows;
}
-gboolean db_is_empty()
-{
- return (db_count_table_rows(DB_ROADS_TABLENAME) == 0);
-}
-
/******************************************************
** data inserting
******************************************************/
@@ -285,9 +280,9 @@
return FALSE;
}
-gboolean db_insert_road(gint nRoadNameID, gint nLayerType, gint nAddressLeftStart, gint nAddressLeftEnd, gint nAddressRightStart, gint nAddressRightEnd, gint nCityLeftID, gint nCityRightID, const gchar* pszZIPCodeLeft, const gchar* pszZIPCodeRight, GPtrArray* pPointsArray, gint* pReturnID)
+gboolean db_insert_road(gint nLOD, gint nRoadNameID, gint nLayerType, gint nAddressLeftStart, gint nAddressLeftEnd, gint nAddressRightStart, gint nAddressRightEnd, gint nCityLeftID, gint nCityRightID, const gchar* pszZIPCodeLeft, const gchar* pszZIPCodeRight, GPtrArray* pPointsArray, gint* pReturnID)
{
- g_assert(pReturnID != NULL);
+// g_assert(pReturnID != NULL);
if(!db_is_connected()) return FALSE;
if(pPointsArray->len == 0) return TRUE; // skip 0-length
@@ -307,23 +302,32 @@
nCount++;
}
- gchar azQuery[MAX_SQLBUFFER_LEN];
- g_snprintf(azQuery, MAX_SQLBUFFER_LEN,
- "INSERT INTO %s SET RoadNameID=%d, TypeID=%d, Coordinates=GeometryFromText('LINESTRING(%s)')"
- ", AddressLeftStart=%d, AddressLeftEnd=%d, AddressRightStart=%d, AddressRightEnd=%d"
- ", CityLeftID=%d, CityRightID=%d"
- ", ZIPCodeLeft='%s', ZIPCodeRight='%s'",
- DB_ROADS_TABLENAME, nRoadNameID, nLayerType, azCoordinateList,
- nAddressLeftStart, nAddressLeftEnd, nAddressRightStart, nAddressRightEnd,
- nCityLeftID, nCityRightID,
- pszZIPCodeLeft, pszZIPCodeRight);
-
- if(MYSQL_RESULT_SUCCESS != mysql_query(g_pDB->pMySQLConnection, azQuery)) {
- g_warning("db_insert_road failed: %s (SQL: %s)\n", mysql_error(g_pDB->pMySQLConnection), azQuery);
- return FALSE;
+ gchar* pszQuery;
+
+ if(nLOD == 0) {
+ pszQuery = g_strdup_printf(
+ "INSERT INTO %s%d SET RoadNameID=%d, TypeID=%d, Coordinates=GeometryFromText('LINESTRING(%s)')"
+ ", AddressLeftStart=%d, AddressLeftEnd=%d, AddressRightStart=%d, AddressRightEnd=%d"
+ ", CityLeftID=%d, CityRightID=%d"
+ ", ZIPCodeLeft='%s', ZIPCodeRight='%s'",
+ DB_ROADS_TABLENAME, nLOD, nRoadNameID, nLayerType, azCoordinateList,
+ nAddressLeftStart, nAddressLeftEnd, nAddressRightStart, nAddressRightEnd,
+ nCityLeftID, nCityRightID,
+ pszZIPCodeLeft, pszZIPCodeRight);
}
+ else {
+ pszQuery = g_strdup_printf(
+ "INSERT INTO %s%d SET RoadNameID=%d, TypeID=%d, Coordinates=GeometryFromText('LINESTRING(%s)')",
+ DB_ROADS_TABLENAME, nLOD, nRoadNameID, nLayerType, azCoordinateList);
+ }
+
+ mysql_query(g_pDB->pMySQLConnection, pszQuery);
+ g_free(pszQuery);
+
// return the new ID
- *pReturnID = mysql_insert_id(g_pDB->pMySQLConnection);
+ if(pReturnID != NULL) {
+ *pReturnID = mysql_insert_id(g_pDB->pMySQLConnection);
+ }
return TRUE;
}
@@ -571,32 +575,43 @@
// db_query("ALTER TABLE RoadName ADD INDEX (NameSoundex);", NULL);
// Road
- db_query("CREATE TABLE IF NOT EXISTS Road("
- " ID INT4 UNSIGNED NOT NULL AUTO_INCREMENT," // XXX: can we get away with INT3 ?
+ db_query(
+ "CREATE TABLE IF NOT EXISTS Road0("
+// " ID INT4 UNSIGNED NOT NULL AUTO_INCREMENT," // XXX: can we get away with INT3 ?
" TypeID INT1 UNSIGNED NOT NULL,"
-
" RoadNameID INT3 UNSIGNED NOT NULL," // NOTE: 3 bytes
-
" AddressLeftStart INT2 UNSIGNED NOT NULL,"
" AddressLeftEnd INT2 UNSIGNED NOT NULL,"
" AddressRightStart INT2 UNSIGNED NOT NULL,"
" AddressRightEnd INT2 UNSIGNED NOT NULL,"
-
" CityLeftID INT3 UNSIGNED NOT NULL," // NOTE: 3 bytes
" CityRightID INT3 UNSIGNED NOT NULL," // NOTE: 3 bytes
-
" ZIPCodeLeft CHAR(6) NOT NULL,"
" ZIPCodeRight CHAR(6) NOT NULL,"
-
" Coordinates point NOT NULL,"
// lots of indexes:
- " PRIMARY KEY (ID)," // XXX: we'll probably want to keep a unique ID, but we don't use this for anything yet.
+// " PRIMARY KEY (ID)," // XXX: we'll probably want to keep a unique ID, but we don't use this for anything yet.
" INDEX(RoadNameID)," // to get roads when we've matched a RoadName
" SPATIAL KEY (Coordinates));", NULL);
+ db_query(
+ "CREATE TABLE IF NOT EXISTS Road1("
+ " TypeID INT1 UNSIGNED NOT NULL,"
+ " RoadNameID INT3 UNSIGNED NOT NULL," // NOTE: 3 bytes
+ " Coordinates point NOT NULL,"
+ " SPATIAL KEY (Coordinates));", NULL);
+
+ db_query(
+ "CREATE TABLE IF NOT EXISTS Road2("
+ " TypeID INT1 UNSIGNED NOT NULL,"
+ " RoadNameID INT3 UNSIGNED NOT NULL," // NOTE: 3 bytes
+ " Coordinates point NOT NULL,"
+ " SPATIAL KEY (Coordinates));", NULL);
+
// RoadName
- db_query("CREATE TABLE IF NOT EXISTS RoadName("
+ db_query(
+ "CREATE TABLE IF NOT EXISTS RoadName("
" ID INT3 UNSIGNED NOT NULL auto_increment," // NOTE: 3 bytes
" Name VARCHAR(30) NOT NULL,"
" NameSoundex CHAR(10) NOT NULL," // see soundex() function
@@ -607,8 +622,8 @@
,NULL);
// City
- db_query("CREATE TABLE IF NOT EXISTS City("
- // a unique ID for the value
+ db_query(
+ "CREATE TABLE IF NOT EXISTS City("
" ID INT3 UNSIGNED NOT NULL AUTO_INCREMENT," // NOTE: 3 bytes
" StateID INT2 UNSIGNED NOT NULL," // NOTE: 2 bytes
" Name CHAR(60) NOT NULL," // are city names ever 60 chars anyway?? TIGER think so
@@ -618,8 +633,8 @@
,NULL);
// State
- db_query("CREATE TABLE IF NOT EXISTS State("
- // a unique ID for the value
+ db_query(
+ "CREATE TABLE IF NOT EXISTS State("
" ID INT2 UNSIGNED NOT NULL AUTO_INCREMENT," // NOTE: 2 bytes (enough to go global..?)
" Name CHAR(40) NOT NULL,"
" Code CHAR(3) NOT NULL," // eg. "MA"
@@ -629,7 +644,8 @@
,NULL);
// Location
- db_query("CREATE TABLE IF NOT EXISTS Location("
+ db_query(
+ "CREATE TABLE IF NOT EXISTS Location("
" ID INT4 UNSIGNED NOT NULL AUTO_INCREMENT,"
" LocationSetID INT3 NOT NULL," // NOTE: 3 bytes
" Coordinates point NOT NULL,"
Index: db.h
===================================================================
RCS file: /cvs/cairo/roadster/src/db.h,v
retrieving revision 1.14
retrieving revision 1.15
diff -u -d -r1.14 -r1.15
--- db.h 1 Oct 2005 01:42:12 -0000 1.14
+++ db.h 5 Oct 2005 06:09:36 -0000 1.15
@@ -52,8 +52,6 @@
const gchar* db_get_connection_info(void);
// utility
-gboolean db_is_empty(void);
-
gboolean db_insert_roadname(const gchar* pszName, gint nSuffixID, gint* pnReturnID);
//~ gboolean db_create_points_db(const gchar* name);
@@ -86,12 +84,7 @@
void db_disable_keys(void);
gboolean db_insert_city(const gchar* pszName, gint nStateID, gint* pnReturnCityID);
-gboolean db_insert_road(gint nRoadNameID, gint nLayerType,
- gint nAddressLeftStart, gint nAddressLeftEnd,
- gint nAddressRightStart, gint nAddressRightEnd,
- gint nCityLeftID, gint nCityRightID,
- const gchar* pszZIPCodeLeft, const gchar* pszZIPCodeRight,
- GPtrArray* pPointsArray, gint* pReturnID);
+gboolean db_insert_road(gint nLOD, gint nRoadNameID, gint nLayerType, gint nAddressLeftStart, gint nAddressLeftEnd, gint nAddressRightStart, gint nAddressRightEnd, gint nCityLeftID, gint nCityRightID, const gchar* pszZIPCodeLeft, const gchar* pszZIPCodeRight, GPtrArray* pPointsArray, gint* pReturnID);
gboolean db_city_get_id(const gchar* pszName, gint nStateID, gint* pnReturnID);
gboolean db_state_get_id(const gchar* pszName, gint* pnReturnID);
Index: import_tiger.c
===================================================================
RCS file: /cvs/cairo/roadster/src/import_tiger.c,v
retrieving revision 1.21
retrieving revision 1.22
diff -u -d -r1.21 -r1.22
--- import_tiger.c 25 Sep 2005 19:02:37 -0000 1.21
+++ import_tiger.c 5 Oct 2005 06:09:36 -0000 1.22
@@ -155,6 +155,96 @@
gint nCityID; // a database ID, stored here after it is inserted
} tiger_record_rtc_t;
+// #define MAP_OBJECT_TYPE_NONE (0)
+// #define MAP_OBJECT_TYPE_MINORROAD (1)
+// #define MAP_OBJECT_TYPE_MAJORROAD (2)
+// #define MAP_OBJECT_TYPE_MINORHIGHWAY (3)
+// #define MAP_OBJECT_TYPE_MINORHIGHWAY_RAMP (4)
+// #define MAP_OBJECT_TYPE_MAJORHIGHWAY (5) // Unused
+// #define MAP_OBJECT_TYPE_MAJORHIGHWAY_RAMP (6) // Unused
+// #define MAP_OBJECT_TYPE_RAILROAD (7)
+// #define MAP_OBJECT_TYPE_PARK (8)
+// #define MAP_OBJECT_TYPE_RIVER (9)
+// #define MAP_OBJECT_TYPE_LAKE (10)
+// #define MAP_OBJECT_TYPE_MISC_AREA (11)
+// #define MAP_OBJECT_TYPE_URBAN_AREA (12)
+
+gdouble g_afPolygonMinSizeAtLODs[MAP_NUM_LEVELS_OF_DETAIL] = {0, 0.001, 0.01}; // in world degrees
+
+gint g_aaObjectTypeDetailAtLODs[MAP_NUM_OBJECT_TYPES][MAP_NUM_LEVELS_OF_DETAIL] = {
+ {0,0,0,0},
+ {1,0,0,0}, // minor rd
+ {1,6,0,0}, // major rd
+ {1,6,12,0}, // hw
+ {1,3,0,0}, // hw ramp
+ {0,0,0,0}, // (unused)
+ {0,0,0,0}, // (unused)
+ {1,8,0,0}, // rail
+ {1,1,1,1}, // park
+ {2,16,0,0}, // river
+ {1,1,1,1}, // lake
+ {1,1,1,1}, // misc area
+ {1,1,1,1}, // urban area
+};
+
+gboolean object_type_exists_at_lod(gint nRecordType, gint nLOD)
+{
+ if(nRecordType < 0) {
+ g_warning("nRecordType = %d\n", nRecordType);
+ }
+ g_assert(nRecordType >= 0);
+ g_assert(nRecordType < MAP_NUM_OBJECT_TYPES);
+ g_assert(nLOD >= 0);
+ g_assert(nLOD <= 3);
+ return (g_aaObjectTypeDetailAtLODs[nRecordType][nLOD] > 0);
+}
+
+gint object_type_detail_at_lod(gint nRecordType, gint nLOD)
+{
+ g_assert(nRecordType >= 0);
+ g_assert(nRecordType < MAP_NUM_OBJECT_TYPES);
+ g_assert(nLOD >= 0);
+ g_assert(nLOD <= 3);
+ return (g_aaObjectTypeDetailAtLODs[nRecordType][nLOD]);
+}
+
+void reduce_object_detail_for_lod(gint nRecordType, gint nLOD, GPtrArray* pSourceArray, GPtrArray* pDestArray)
+{
+ g_assert(pSourceArray);
+ g_assert(pDestArray);
+
+ if(!object_type_exists_at_lod(nRecordType, nLOD)) return;
+
+ gint nDetail = object_type_detail_at_lod(nRecordType, nLOD);
+ g_ptr_array_add(pDestArray, g_ptr_array_index(pSourceArray, 0));
+
+ // our super-hacky algorithm just steps N points at a time
+ gint i;
+ for(i = nDetail ; i < (pSourceArray->len-1) ; i+=nDetail) {
+ g_ptr_array_add(pDestArray, g_ptr_array_index(pSourceArray, i));
+ }
+ g_ptr_array_add(pDestArray, g_ptr_array_index(pSourceArray, pSourceArray->len-1));
+}
+
+void util_bounding_box_of_points_array(GPtrArray* pPointsArray, maprect_t* pReturnRect)
+{
+ pReturnRect->A.fLatitude = MAX_LATITUDE; // init to worst possible values
+ pReturnRect->A.fLongitude = MAX_LONGITUDE;
+
+ pReturnRect->B.fLatitude = MIN_LATITUDE;
+ pReturnRect->B.fLongitude = MIN_LONGITUDE;
+
+ gint i;
+ for(i=0 ; i<pPointsArray->len ; i++) {
+ mappoint_t* pPoint = g_ptr_array_index(pPointsArray, i);
+
+ pReturnRect->A.fLatitude = min(pReturnRect->A.fLatitude, pPoint->fLatitude);
+ pReturnRect->A.fLongitude = min(pReturnRect->A.fLongitude, pPoint->fLongitude);
+
+ pReturnRect->B.fLatitude = max(pReturnRect->B.fLatitude, pPoint->fLatitude);
+ pReturnRect->B.fLongitude = max(pReturnRect->B.fLongitude, pPoint->fLongitude);
+ }
+}
static gboolean import_tiger_read_lat(gint8* pBuffer, gdouble* pValue)
{
@@ -254,6 +344,8 @@
return TRUE;
}
+// NOTE: This function can return MAP_OBJECT_TYPE_NONE. Lines of this type shouldn't be saved, but they
+// might be used for polygons, so we have to keep them in memory.
static gboolean import_tiger_read_layer_type(gint8* pBuffer, gint* pValue)
{
//g_print("%c%c%c\n", *(pBuffer), *(pBuffer+1), *(pBuffer+2));
@@ -282,7 +374,6 @@
}
else if(chCode == '5') { // dirt roads
//*pValue = MAP_OBJECT_TYPE_TRAIL;
- return FALSE;
}
else if(chCode == '6') {
if(chSubCode == '1') {
@@ -294,7 +385,6 @@
}
else if(chSubCode == '5') {
//*pValue = MAP_OBJECT_TYPE_FERRY_ROUTE; // where a boat carrying cars goes
- return FALSE;
}
else if(chSubCode == '7') {
g_print("found code A67: toll booth!\n");
@@ -587,8 +677,8 @@
// 22-24 is a CFCC (
gint nRecordType;
-
import_tiger_read_layer_type(&pLine[22-1], &nRecordType);
+
pRecord = g_new0(tiger_record_rt7_t, 1);
pRecord->nRecordType = nRecordType;
@@ -832,16 +922,26 @@
db_insert_roadname(pRecordRT1->achName, pRecordRT1->nRoadNameSuffixID, &nRoadNameID);
}
- gint nRoadID;
- db_insert_road(nRoadNameID,
- pRecordRT1->nRecordType,
- pRecordRT1->nAddressLeftStart,
- pRecordRT1->nAddressLeftEnd,
- pRecordRT1->nAddressRightStart,
- pRecordRT1->nAddressRightEnd,
- nCityLeftID, nCityRightID,
- azZIPCodeLeft, azZIPCodeRight,
- pTempPointsArray, &nRoadID);
+ gint nLOD = MAP_LEVEL_OF_DETAIL_BEST;
+ db_insert_road(nLOD, nRoadNameID, pRecordRT1->nRecordType,
+ pRecordRT1->nAddressLeftStart, pRecordRT1->nAddressLeftEnd,
+ pRecordRT1->nAddressRightStart, pRecordRT1->nAddressRightEnd,
+ nCityLeftID, nCityRightID,
+ azZIPCodeLeft, azZIPCodeRight,
+ pTempPointsArray, NULL);
+
+ for(nLOD = MAP_LEVEL_OF_DETAIL_BEST+1 ; nLOD <= MAP_LEVEL_OF_DETAIL_WORST ; nLOD++) {
+ GPtrArray* pReducedPointsArray = g_ptr_array_new();
+
+ reduce_object_detail_for_lod(pRecordRT1->nRecordType, nLOD, pTempPointsArray, pReducedPointsArray);
+ if(pReducedPointsArray->len > 0) {
+ g_assert(pReducedPointsArray->len >= 2);
+
+ db_insert_road(nLOD, nRoadNameID, pRecordRT1->nRecordType, 0, 0, 0, 0, 0, 0, NULL, NULL,
+ pReducedPointsArray, NULL);
+ }
+ g_ptr_array_free(pReducedPointsArray, TRUE);
+ }
}
g_ptr_array_free(pTempPointsArray, TRUE);
}
@@ -1012,12 +1112,6 @@
g_print("Found a polygon that doesn't loop %s\n", pRecordRT7->achName);
}
- // XXX: looking up a city for a polygon? unimplemented.
- gint nCityLeftID = 0;
- gchar* pszZIPCodeLeft = "";
- gint nCityRightID = 0;
- gchar* pszZIPCodeRight = "";
-
// insert record
if(pRecordRT7->nRecordType != MAP_OBJECT_TYPE_NONE) {
gint nRoadNameID = 0;
@@ -1026,14 +1120,34 @@
db_insert_roadname(pRecordRT7->achName, 0, &nRoadNameID);
}
- gint nRoadID;
- db_insert_road(
- nRoadNameID,
- pRecordRT7->nRecordType,
- 0,0,0,0,
- nCityLeftID, nCityRightID,
- pszZIPCodeLeft, pszZIPCodeRight,
- pTempPointsArray, &nRoadID);
+ // Write LOD 0
+ gint nLOD = MAP_LEVEL_OF_DETAIL_BEST;
+ db_insert_road(nLOD, nRoadNameID, pRecordRT7->nRecordType, 0, 0, 0, 0, 0, 0, "", "",
+ pTempPointsArray, NULL);
+
+ // Write higher LODs
+ maprect_t rc;
+ util_bounding_box_of_points_array(pTempPointsArray, &rc);
+ gdouble fWidth = rc.B.fLongitude - rc.A.fLongitude;
+ gdouble fHeight = rc.B.fLatitude - rc.A.fLatitude;
+
+ for(nLOD = MAP_LEVEL_OF_DETAIL_BEST+1 ; nLOD <= MAP_LEVEL_OF_DETAIL_WORST ; nLOD++) {
+ if((fWidth < g_afPolygonMinSizeAtLODs[nLOD]) || (fHeight < g_afPolygonMinSizeAtLODs[nLOD])) {
+ g_print("object exluded at LOD %d\n", nLOD);
+ break; // not visible (nor at higher LODs, so break instead of continue)
+ }
+
+ GPtrArray* pReducedPointsArray = g_ptr_array_new();
+
+ reduce_object_detail_for_lod(pRecordRT7->nRecordType, nLOD, pTempPointsArray, pReducedPointsArray);
+ if(pReducedPointsArray->len > 0) {
+ g_assert(pReducedPointsArray->len >= 2);
+
+ db_insert_road(nLOD, nRoadNameID, pRecordRT7->nRecordType, 0, 0, 0, 0, 0, 0, NULL, NULL,
+ pReducedPointsArray, NULL);
+ }
+ g_ptr_array_free(pReducedPointsArray, TRUE);
+ }
}
}
Index: main.c
===================================================================
RCS file: /cvs/cairo/roadster/src/main.c,v
retrieving revision 1.32
retrieving revision 1.33
diff -u -d -r1.32 -r1.33
--- main.c 1 Oct 2005 05:24:16 -0000 1.32
+++ main.c 5 Oct 2005 06:09:36 -0000 1.33
@@ -31,7 +31,6 @@
#include "db.h"
#include "map.h"
#include "gpsclient.h"
-#include "scenemanager.h"
#include "locationset.h"
#include "location.h"
#include "search.h"
@@ -142,9 +141,6 @@
g_print("initializing map\n");
map_init();
- g_print("initializing scenemanager\n");
- scenemanager_init();
-
g_print("initializing gpsclient\n");
gpsclient_init();
Index: main.h
===================================================================
RCS file: /cvs/cairo/roadster/src/main.h,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -d -r1.5 -r1.6
--- main.h 25 Sep 2005 19:02:37 -0000 1.5
+++ main.h 5 Oct 2005 06:09:36 -0000 1.6
@@ -24,6 +24,8 @@
#ifndef _MAIN_H_
#define _MAIN_H_
+//#define G_DISABLE_ASSERT
+
#include <gtk/gtk.h>
#define USE_GNOME_VFS // comment this out to get a faster single-threaded compile (can't import, though)
Index: mainwindow.c
===================================================================
RCS file: /cvs/cairo/roadster/src/mainwindow.c,v
retrieving revision 1.48
retrieving revision 1.49
diff -u -d -r1.48 -r1.49
--- mainwindow.c 1 Oct 2005 19:09:05 -0000 1.48
+++ mainwindow.c 5 Oct 2005 06:09:36 -0000 1.49
@@ -27,7 +27,7 @@
#include <gtk/gtk.h>
#include <gtk/gtksignal.h>
-//#include <gdk/gdk.h>
+#include <gdk/gdkkeysyms.h>
//#include <gdk/gdkx.h>
//#include <cairo.h>
//#include <cairo-xlib.h>
@@ -39,6 +39,7 @@
#include "gotowindow.h"
#include "db.h"
#include "map.h"
+#include "map_hittest.h"
#include "map_style.h"
#include "importwindow.h"
#include "locationset.h"
@@ -89,6 +90,8 @@
#define LOCATIONSETLIST_COLUMN_COUNT (3)
#define LOCATIONSETLIST_COLUMN_PIXBUF (4)
+#define ZOOM_TOOL_THRESHOLD (5) // in pixels. a box less than AxA will be ignored
+
// Limits
#define MAX_SEARCH_TEXT_LENGTH (100)
#define SPEED_LABEL_FORMAT ("<span font_desc='32'>%.0f</span>")
@@ -107,20 +110,20 @@
#define MAX_DISTANCE_FOR_AUTO_SLIDE_IN_PIXELS (3500.0) // when selecting search results, we slide to them instead of jumping if they are within this distance
// Types
-typedef struct {
- GdkCursorType CursorType;
- GdkCursor* pGdkCursor;
-} cursor_t;
+// typedef struct {
+// GdkCursorType CursorType;
+// GdkCursor* pGdkCursor;
+// } cursor_t;
-typedef struct {
- char* szName;
- cursor_t Cursor;
-} toolsettings_t;
+// typedef struct {
+// char* szName;
+// cursor_t Cursor;
+// } toolsettings_t;
-typedef enum {
- kToolPointer = 0,
- kToolZoom = 1,
-} EToolType;
+// typedef enum {
+// MOUSE_TOOL_POINTER = 0,
+// MOUSE_TOOL_ZOOM = 1,
+// } EMouseToolType;
// Prototypes
static void mainwindow_setup_selected_tool(void);
@@ -169,8 +172,8 @@
// Toolbar
GtkHBox* pToolbar;
-// GtkToolButton* pPointerToolButton;
-// GtkToolButton* pZoomToolButton;
+ GtkRadioButton* pPointerToolRadioButton;
+ GtkRadioButton* pZoomToolRadioButton;
GtkHScale* pZoomScale;
GtkEntry* pSearchBox;
GtkImage* pStatusbarGPSIcon;
@@ -214,7 +217,7 @@
tooltip_t* pTooltip;
map_t* pMap;
- EToolType eSelectedTool;
+// EToolType eSelectedTool;
gboolean bScrolling;
EDirection eScrollDirection;
@@ -236,6 +239,10 @@
mappoint_t ptSlideEndLocation;
animator_t* pAnimator;
+ // Zoom Tool
+ gboolean bDrawingZoomRect;
+ screenrect_t rcZoomRect;
+
// History (forward / back)
maphistory_t* pMapHistory;
GtkButton* pForwardButton;
@@ -252,17 +259,17 @@
// XXX: Use GDK_HAND1 for the map
// Data
-toolsettings_t g_Tools[] = {
- {"Pointer Tool", {GDK_LEFT_PTR, NULL}},
- {"Zoom Tool", {GDK_CIRCLE, NULL}},
-};
-void cursor_init()
-{
- int i;
- for(i=0 ; i<G_N_ELEMENTS(g_Tools) ; i++) {
- g_Tools[i].Cursor.pGdkCursor = gdk_cursor_new(g_Tools[i].Cursor.CursorType);
- }
-}
+// toolsettings_t g_Tools[] = {
+// {"Pointer Tool", {GDK_LEFT_PTR, NULL}},
+// {"Zoom Tool", {GDK_CIRCLE, NULL}},
+// };
+// void cursor_init()
+// {
+// int i;
+// for(i=0 ; i<G_N_ELEMENTS(g_Tools) ; i++) {
+// g_Tools[i].Cursor.pGdkCursor = gdk_cursor_new(g_Tools[i].Cursor.CursorType);
+// }
+// }
static void util_set_image_to_stock(GtkImage* pImage, gchar* pszStockIconID, GtkIconSize nSize)
{
@@ -294,6 +301,11 @@
return pCursor;
}
+void mainwindow_draw_xor_rect(screenrect_t* pRect)
+{
+ map_draw_gdk_xor_rect(g_MainWindow.pMap, GTK_WIDGET(g_MainWindow.pDrawingArea)->window, pRect);
+}
+
void mainwindow_set_not_busy(void** ppCursor)
{
gdk_window_set_cursor(GTK_WIDGET(g_MainWindow.pWindow)->window, NULL);
@@ -365,6 +377,10 @@
GLADE_LINK_WIDGET(pGladeXML, g_MainWindow.pSidebarNotebook, GTK_NOTEBOOK, "sidebarnotebook");
GLADE_LINK_WIDGET(pGladeXML, g_MainWindow.pContentBox, GTK_VBOX, "mainwindowcontentsbox");
+// g_object_set(G_OBJECT(g_MainWindow.pSidebarNotebook), "show-border", FALSE, NULL);
+ g_object_set(G_OBJECT(g_MainWindow.pSidebarNotebook), "tab-border", 1, NULL);
+// g_object_set(G_OBJECT(g_MainWindow.pSidebarNotebook), "tab-hborder", 0, NULL);
+
// View menu
GLADE_LINK_WIDGET(pGladeXML, g_MainWindow.pViewSidebarMenuItem, GTK_CHECK_MENU_ITEM, "viewsidebarmenuitem");
GLADE_LINK_WIDGET(pGladeXML, g_MainWindow.pViewFullscreenMenuItem, GTK_CHECK_MENU_ITEM, "viewfullscreenmenuitem");
@@ -384,8 +400,8 @@
GLADE_LINK_WIDGET(pGladeXML, g_MainWindow.pMapPopupMenu, GTK_MENU, "mappopupmenu");
// Tools
- //GLADE_LINK_WIDGET(pGladeXML, g_MainWindow.pPointerToolButton, GTK_TOOL_BUTTON, "pointertoolbutton");
- //GLADE_LINK_WIDGET(pGladeXML, g_MainWindow.pZoomToolButton, GTK_TOOL_BUTTON, "zoomtoolbutton");
+ GLADE_LINK_WIDGET(pGladeXML, g_MainWindow.pPointerToolRadioButton, GTK_RADIO_BUTTON, "pointertoolradiobutton");
+ GLADE_LINK_WIDGET(pGladeXML, g_MainWindow.pZoomToolRadioButton, GTK_RADIO_BUTTON, "zoomtoolradiobutton");
// GPS Widgets
GLADE_LINK_WIDGET(pGladeXML, g_MainWindow.GPS.pShowPositionCheckButton, GTK_CHECK_BUTTON, "gpsshowpositioncheckbutton");
@@ -446,8 +462,7 @@
map_new(&g_MainWindow.pMap, GTK_WIDGET(g_MainWindow.pDrawingArea));
map_style_load(g_MainWindow.pMap, MAP_STYLE_FILENAME);
-
- cursor_init();
+// cursor_init();
mainwindow_configure_locationset_list();
mainwindow_refresh_locationset_list();
@@ -737,6 +752,13 @@
gtk_widget_set_sensitive(GTK_WIDGET(g_MainWindow.pZoomInMenuItem), map_can_zoom_in(g_MainWindow.pMap));
gtk_widget_set_sensitive(GTK_WIDGET(g_MainWindow.pZoomOutButton), map_can_zoom_out(g_MainWindow.pMap));
gtk_widget_set_sensitive(GTK_WIDGET(g_MainWindow.pZoomOutMenuItem), map_can_zoom_out(g_MainWindow.pMap));
+
+ // set zoomlevel scale but prevent it from calling handler (mainwindow_on_zoomscale_value_changed)
+ g_signal_handlers_block_by_func(g_MainWindow.pZoomScale, mainwindow_on_zoomscale_value_changed, NULL);
+ gtk_range_set_value(GTK_RANGE(g_MainWindow.pZoomScale), map_get_zoomlevel(g_MainWindow.pMap));
+ g_signal_handlers_unblock_by_func(g_MainWindow.pZoomScale, mainwindow_on_zoomscale_value_changed, NULL);
+
+ mainwindow_statusbar_update_zoomscale();
}
void mainwindow_set_zoomlevel(gint nZoomLevel)
@@ -744,11 +766,10 @@
map_set_zoomlevel(g_MainWindow.pMap, nZoomLevel);
// set zoomlevel scale but prevent it from calling handler (mainwindow_on_zoomscale_value_changed)
- g_signal_handlers_block_by_func(g_MainWindow.pZoomScale, mainwindow_on_zoomscale_value_changed, NULL);
- gtk_range_set_value(GTK_RANGE(g_MainWindow.pZoomScale), nZoomLevel);
- g_signal_handlers_unblock_by_func(g_MainWindow.pZoomScale, mainwindow_on_zoomscale_value_changed, NULL);
+// g_signal_handlers_block_by_func(g_MainWindow.pZoomScale, mainwindow_on_zoomscale_value_changed, NULL);
+// gtk_range_set_value(GTK_RANGE(g_MainWindow.pZoomScale), nZoomLevel);
+// g_signal_handlers_unblock_by_func(g_MainWindow.pZoomScale, mainwindow_on_zoomscale_value_changed, NULL);
- mainwindow_statusbar_update_zoomscale();
mainwindow_update_zoom_buttons();
}
@@ -771,11 +792,11 @@
//
//
//
-static void gui_set_tool(EToolType eTool)
-{
- g_MainWindow.eSelectedTool = eTool;
- gdk_window_set_cursor(GTK_WIDGET(g_MainWindow.pDrawingArea)->window, g_Tools[eTool].Cursor.pGdkCursor);
-}
+// static void gui_set_tool(EToolType eTool)
+// {
+// g_MainWindow.eSelectedTool = eTool;
+// gdk_window_set_cursor(GTK_WIDGET(g_MainWindow.pDrawingArea)->window, g_Tools[eTool].Cursor.pGdkCursor);
+// }
//
// Callbacks for About box
@@ -859,11 +880,18 @@
mainwindow_set_sidebox_visible(!mainwindow_get_sidebox_visible());
}
+#define ZOOM_MAJOR_TICK_SIZE (4)
+
// Zoom buttons / menu items (shared callbacks)
void mainwindow_on_zoomin_activate(GtkMenuItem *menuitem, gpointer user_data)
{
+ gint nNewZoomLevel = map_get_zoomlevel(g_MainWindow.pMap) - 1; // XXX: make zoomlevel 0-based and the -1 will go away
+ nNewZoomLevel -= (nNewZoomLevel % ZOOM_MAJOR_TICK_SIZE);
+ nNewZoomLevel += ZOOM_MAJOR_TICK_SIZE;
+ nNewZoomLevel += 1; // XXX: make zoomlevel 0-based and the +1 will go away
+
// tell the map
- map_set_zoomlevel(g_MainWindow.pMap, map_get_zoomlevel(g_MainWindow.pMap) + 1);
+ map_set_zoomlevel(g_MainWindow.pMap, nNewZoomLevel);
// update the gui
mainwindow_set_zoomlevel(map_get_zoomlevel(g_MainWindow.pMap));
@@ -874,7 +902,12 @@
void mainwindow_on_zoomout_activate(GtkMenuItem *menuitem, gpointer user_data)
{
- map_set_zoomlevel(g_MainWindow.pMap, map_get_zoomlevel(g_MainWindow.pMap) - 1);
+ gint nNewZoomLevel = map_get_zoomlevel(g_MainWindow.pMap) - 1;
+ if((nNewZoomLevel % ZOOM_MAJOR_TICK_SIZE) == 0) nNewZoomLevel -= ZOOM_MAJOR_TICK_SIZE;
+ else nNewZoomLevel -= (nNewZoomLevel % ZOOM_MAJOR_TICK_SIZE);
+ nNewZoomLevel += 1; // XXX: make zoomlevel 0-based and the +1 will go away
+
+ map_set_zoomlevel(g_MainWindow.pMap, nNewZoomLevel);
mainwindow_set_zoomlevel(map_get_zoomlevel(g_MainWindow.pMap));
mainwindow_draw_map(DRAWFLAG_GEOMETRY);
mainwindow_set_draw_pretty_timeout(DRAW_PRETTY_ZOOM_TIMEOUT_MS);
@@ -974,6 +1007,11 @@
gint nWidth = GTK_WIDGET(g_MainWindow.pDrawingArea)->allocation.width;
gint nHeight = GTK_WIDGET(g_MainWindow.pDrawingArea)->allocation.height;
+
+ // nX and nY clipped to screen
+ gint nClippedX = (nX < 0) ? 0 : (nX > nWidth) ? nWidth : nX;
+ gint nClippedY = (nY < 0) ? 0 : (nY > nHeight) ? nHeight : nY;
+
EDirection eScrollDirection = DIRECTION_NONE;
// get mouse position on screen
@@ -982,7 +1020,7 @@
map_windowpoint_to_mappoint(g_MainWindow.pMap, &screenpoint, &mappoint);
maphit_t* pHitStruct = NULL;
- map_hit_test(g_MainWindow.pMap, &mappoint, &pHitStruct);
+ map_hittest(g_MainWindow.pMap, &mappoint, &pHitStruct);
// hitstruct free'd far below
if(event->button == MOUSE_BUTTON_LEFT) {
@@ -1004,6 +1042,14 @@
mainwindow_set_scroll_timeout();
}
+ else if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(g_MainWindow.pZoomToolRadioButton))) {
+ //g_print("begin rect draw\n");
+ g_MainWindow.bDrawingZoomRect = TRUE;
+
+ // set both rect points to click point
+ g_MainWindow.rcZoomRect.A.nX = g_MainWindow.rcZoomRect.B.nX = nX;
+ g_MainWindow.rcZoomRect.A.nY = g_MainWindow.rcZoomRect.B.nY = nY;
+ }
else {
g_MainWindow.bMouseDragging = TRUE;
g_MainWindow.bMouseDragMovement = FALSE;
@@ -1048,6 +1094,27 @@
}
}
+ if(g_MainWindow.bDrawingZoomRect == TRUE) {
+ if((map_screenrect_width(&(g_MainWindow.rcZoomRect)) > ZOOM_TOOL_THRESHOLD) && (map_screenrect_height(&(g_MainWindow.rcZoomRect)) > ZOOM_TOOL_THRESHOLD)) {
+ map_zoom_to_screenrect(g_MainWindow.pMap, &(g_MainWindow.rcZoomRect));
+
+ // update GUI
+ mainwindow_update_zoom_buttons();
+ mainwindow_statusbar_update_position();
+
+ mainwindow_draw_map(DRAWFLAG_GEOMETRY);
+ mainwindow_set_draw_pretty_timeout(DRAW_PRETTY_ZOOM_TIMEOUT_MS);
+ mainwindow_add_history();
+ }
+ else {
+ // Since we're not redrawing the map, we need to erase the selection rectangle
+ mainwindow_draw_xor_rect(&(g_MainWindow.rcZoomRect));
+ }
+
+ // all done
+ g_MainWindow.bDrawingZoomRect = FALSE;
+ }
+
// end scrolling, if active
if(g_MainWindow.bScrolling == TRUE) {
// NOTE: don't restore cursor (mouse could *still* be over screen edge)
@@ -1086,7 +1153,7 @@
}
}
else if(event->type == GDK_2BUTTON_PRESS) {
- // can only double click in the middle (not on a scroll border)
+ // can only double-click in the middle (not on a scroll border)
eScrollDirection = match_border(nX, nY, nWidth, nHeight, BORDER_SCROLL_CLICK_TARGET_SIZE);
if(eScrollDirection == DIRECTION_NONE) {
animator_destroy(g_MainWindow.pAnimator);
@@ -1108,7 +1175,6 @@
if(event->type == GDK_BUTTON_PRESS) {
GtkMenu* pMenu = g_MainWindow.pMapPopupMenu; // default to generic map popup
- g_print("here %s\n", pHitStruct);
if(pHitStruct != NULL) {
if(pHitStruct->eHitType == MAP_HITTYPE_LOCATION) {
// Use POI specific popup menu
@@ -1134,7 +1200,7 @@
//gtk_menu_popup(pMenu, NULL, NULL, NULL, NULL, event->button, event->time);
}
}
- map_hitstruct_free(g_MainWindow.pMap, pHitStruct);
+ map_hittest_maphit_free(g_MainWindow.pMap, pHitStruct);
return TRUE;
}
@@ -1154,7 +1220,17 @@
gint nWidth = GTK_WIDGET(g_MainWindow.pDrawingArea)->allocation.width;
gint nHeight = GTK_WIDGET(g_MainWindow.pDrawingArea)->allocation.height;
- gint nCursor = GDK_LEFT_PTR;
+ // nX and nY clipped to screen
+ gint nClippedX = (nX < 0) ? 0 : ((nX > nWidth-1) ? nWidth-1 : nX);
+ gint nClippedY = (nY < 0) ? 0 : ((nY > nHeight-1) ? nHeight-1 : nY);
+
+ gint nCursor;
+ if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(g_MainWindow.pZoomToolRadioButton))) {
+ nCursor = GDK_SIZING;
+ }
+ else {
+ nCursor = GDK_LEFT_PTR;
+ }
if(g_MainWindow.bMouseDragging) {
g_MainWindow.bMouseDragMovement = TRUE;
@@ -1183,6 +1259,15 @@
// update direction if actively scrolling
g_MainWindow.eScrollDirection = eScrollDirection;
}
+ else if(g_MainWindow.bDrawingZoomRect) {
+ //g_print("updating rect\n");
+ mainwindow_draw_xor_rect(&g_MainWindow.rcZoomRect); // erase old rect (XOR operator rocks!)
+
+ g_MainWindow.rcZoomRect.B.nX = nClippedX;
+ g_MainWindow.rcZoomRect.B.nY = nClippedY;
+
+ mainwindow_draw_xor_rect(&g_MainWindow.rcZoomRect); // draw new rect
+ }
else {
// If not dragging or scrolling, user is just moving mouse around.
// Update tooltip and mouse cursor based on what we're pointing at.
@@ -1199,7 +1284,7 @@
// try to "hit" something on the map. a road, a location, whatever!
maphit_t* pHitStruct = NULL;
- if(map_hit_test(g_MainWindow.pMap, &mappoint, &pHitStruct)) {
+ if(map_hittest(g_MainWindow.pMap, &mappoint, &pHitStruct)) {
// A hit! Move the tooltip here, format the text, and show it.
tooltip_set_upper_left_corner(g_MainWindow.pTooltip, (gint)(event->x_root) + TOOLTIP_OFFSET_X, (gint)(event->y_root) + TOOLTIP_OFFSET_Y);
@@ -1240,7 +1325,7 @@
g_print("url: %s\n", pHitStruct->URLHit.pszURL);
}
- map_hitstruct_free(g_MainWindow.pMap, pHitStruct);
+ map_hittest_maphit_free(g_MainWindow.pMap, pHitStruct);
}
else {
// no hit. hide the tooltip
@@ -1293,14 +1378,27 @@
}
}
-static gboolean mainwindow_on_key_press(GtkWidget *widget, GdkEventKey *event, gpointer user_data)
+static gboolean mainwindow_on_key_press(GtkWidget *widget, GdkEventKey *pEvent, gpointer user_data)
{
- g_print("key_press\n");
+ //g_print("key_press\n");
+ if(pEvent->keyval == GDK_F1) {
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(g_MainWindow.pPointerToolRadioButton), TRUE);
+ }
+ else if(pEvent->keyval == GDK_F2) {
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(g_MainWindow.pZoomToolRadioButton), TRUE);
+ }
+ else if(pEvent->keyval == GDK_Escape) {
+ if(g_MainWindow.bDrawingZoomRect == TRUE) {
+ // cancel zoom-rect
+ mainwindow_draw_xor_rect(&(g_MainWindow.rcZoomRect));
+ g_MainWindow.bDrawingZoomRect = FALSE;
+ }
+ }
return FALSE;
}
static gboolean mainwindow_on_key_release(GtkWidget *widget, GdkEventKey *event, gpointer user_data)
{
- g_print("key_release\n");
+ //g_print("key_release\n");
return FALSE;
}
Index: map.c
===================================================================
RCS file: /cvs/cairo/roadster/src/map.c,v
retrieving revision 1.51
retrieving revision 1.52
diff -u -d -r1.51 -r1.52
--- map.c 1 Oct 2005 05:24:16 -0000 1.51
+++ map.c 5 Oct 2005 06:09:36 -0000 1.52
@@ -22,12 +22,12 @@
*/
#include <gdk/gdkx.h>
-//#include <cairo.h>
#include <gtk/gtk.h>
#include <math.h>
#include "main.h"
#include "map_style.h"
+#include "map_tilemanager.h"
#include "gui.h"
[...1286 lines suppressed...]
+ mappoint_t* pNewPoint = NULL;
+ callback_alloc_point(&pNewPoint);
+ gdouble fDistanceFromPoint1 = (j+1) * fDistanceBetweenPoints;
+
+ pNewPoint->fLongitude = pPoint1->fLongitude + (fDistanceFromPoint1 * fNormalizedX);
+ pNewPoint->fLatitude = pPoint1->fLatitude + (fDistanceFromPoint1 * fNormalizedY);
+
+ gdouble fRandomMovementLength = fMaxRandomDistance * g_random_double_range(-1.0, 1.0);
+ pNewPoint->fLongitude += (fPerpendicularNormalizedX * fRandomMovementLength); // move each component
+ pNewPoint->fLatitude += (fPerpendicularNormalizedY * fRandomMovementLength);
+
+ g_ptr_array_add(pDestArray, pNewPoint);
+ }
+ }
+ // add last point
+ g_ptr_array_add(pDestArray, g_ptr_array_index(pSourceArray, pSourceArray->len-1));
+//g_print("pDestArray->len = %d\n", pDestArray->len);
}
+*/
+#endif
Index: map.h
===================================================================
RCS file: /cvs/cairo/roadster/src/map.h,v
retrieving revision 1.25
retrieving revision 1.26
diff -u -d -r1.25 -r1.26
--- map.h 1 Oct 2005 01:42:12 -0000 1.25
+++ map.h 5 Oct 2005 06:09:36 -0000 1.26
@@ -24,6 +24,7 @@
#ifndef _MAP_H_
#define _MAP_H_
+#include <math.h>
#include "gfreelist.h"
//
@@ -48,6 +49,9 @@
#define MAP_OBJECT_TYPE_FIRST (1)
#define MAP_OBJECT_TYPE_LAST (12)
+#define MAP_LEVEL_OF_DETAIL_BEST (0)
+#define MAP_LEVEL_OF_DETAIL_WORST (3)
+#define MAP_NUM_LEVELS_OF_DETAIL (4)
//
// Line CAP styles
@@ -101,9 +105,9 @@
struct GtkWidget;
#define MIN_ZOOM_LEVEL (1)
-#define MAX_ZOOM_LEVEL (5)
-#define NUM_ZOOM_LEVELS (5)
-#define MIN_ZOOM_LEVEL_FOR_LOCATIONS (6) // don't show POI above this level
+#define MAX_ZOOM_LEVEL (41)
+#define NUM_ZOOM_LEVELS (41)
+#define MIN_ZOOM_LEVEL_FOR_LOCATIONS (25) // don't show POI above this level
#include "scenemanager.h"
@@ -153,7 +157,10 @@
EDistanceUnits eScaleMetricUnit;
gint nScaleMetricNumber;
- gchar* szName;
+ //gchar* szName;
+
+ gint nStyleZoomLevel; // pretend we're zoomlevel X because there are more real zoomlevels than in the map layer style definitions
+ gint nLevelOfDetail; // pretend we're zoomlevel X because there are more real zoomlevels than in the map layer style definitions
} zoomlevel_t;
extern zoomlevel_t g_sZoomLevels[];
@@ -173,19 +180,22 @@
maprect_t rWorldBoundingBox;
gint nWindowWidth;
gint nWindowHeight;
+ gint nLevelOfDetail;
} rendermetrics_t;
#define SCALE_X(p, x) ((((x) - (p)->rWorldBoundingBox.A.fLongitude) / (p)->fScreenLongitude) * (p)->nWindowWidth)
#define SCALE_Y(p, y) ((p)->nWindowHeight - ((((y) - (p)->rWorldBoundingBox.A.fLatitude) / (p)->fScreenLatitude) * (p)->nWindowHeight))
-typedef struct {
- GPtrArray* pRoadsArray;
-} maplayer_data_t;
+// typedef struct {
+// GPtrArray* pRoadsArray;
+// } maplayer_data_t;
typedef struct {
GPtrArray* pLocationsArray;
} maplayer_locations_t;
+#include "map_tilemanager.h"
+
typedef struct {
mappoint_t MapCenter;
dimensions_t MapDimensions;
@@ -195,7 +205,9 @@
// data
GArray *pTracksArray;
- maplayer_data_t *apLayerData[ MAP_NUM_OBJECT_TYPES + 1 ];
+// maplayer_data_t *apLayerData[ MAP_NUM_OBJECT_TYPES + 1 ];
+
+ maptilemanager_t* pTileManager;
// Locationsets
GHashTable *pLocationArrayHashTable;
@@ -209,42 +221,6 @@
} map_t;
typedef enum {
- MAP_HITTYPE_LOCATION,
- MAP_HITTYPE_ROAD,
-
- // the following all use LocationSelectionHit in the union below
- MAP_HITTYPE_LOCATIONSELECTION, // hit somewhere on a locationselection graphic (info balloon)
- MAP_HITTYPE_LOCATIONSELECTION_CLOSE, // hit locationselection graphic close graphic (info balloon [X])
- MAP_HITTYPE_LOCATIONSELECTION_EDIT, // hit locationselection graphic edit graphic (info balloon "edit")
-
- MAP_HITTYPE_URL,
-} EMapHitType;
-
-typedef struct {
- EMapHitType eHitType;
- gchar* pszText;
- union {
- struct {
- gint nLocationID;
- mappoint_t Coordinates;
- } LocationHit;
-
- struct {
- gint nRoadID;
- mappoint_t ClosestPoint;
- } RoadHit;
-
- struct {
- gint nLocationID;
- } LocationSelectionHit;
-
- struct {
- gchar* pszURL;
- } URLHit;
- };
-} maphit_t;
-
-typedef enum {
MAP_LAYER_RENDERTYPE_LINES,
MAP_LAYER_RENDERTYPE_POLYGONS,
MAP_LAYER_RENDERTYPE_LINE_LABELS,
@@ -287,8 +263,9 @@
#define DRAWFLAG_ALL (1|2)
-#define NUM_SUBLAYER_TO_DRAW (21) //(24)
-extern draworder_t layerdraworder[NUM_SUBLAYER_TO_DRAW]; //
+// #define NUM_SUBLAYER_TO_DRAW (21) //(24)
+// extern draworder_t layerdraworder[NUM_SUBLAYER_TO_DRAW]; //
+
void map_init(void);
gboolean map_new(map_t** ppMap, GtkWidget* pTargetWidget);
@@ -331,9 +308,6 @@
void map_draw(map_t* pMap, GdkPixmap* pTargetPixmap, gint nDrawFlags);
void map_add_track(map_t* pMap, gint hTrack);
-gboolean map_hit_test(map_t* pMap, mappoint_t* pMapPoint, maphit_t** ppReturnStruct);
-void map_hitstruct_free(map_t* pMap, maphit_t* pHitStruct);
-
gboolean map_location_selection_add(map_t* pMap, gint nLocationID);
gboolean map_location_selection_remove(map_t* pMap, gint nLocationID);
@@ -344,4 +318,9 @@
gboolean map_rects_overlap(const maprect_t* p1, const maprect_t* p2);
+void map_zoom_to_screenrect(map_t* pMap, const screenrect_t* pRect);
+gint map_screenrect_width(const screenrect_t* pRect);
+gint map_screenrect_height(const screenrect_t* pRect);
+void map_get_screenrect_centerpoint(const screenrect_t* pRect, screenpoint_t* pPoint);
+
#endif
Index: map_draw_cairo.c
===================================================================
RCS file: /cvs/cairo/roadster/src/map_draw_cairo.c,v
retrieving revision 1.27
retrieving revision 1.28
diff -u -d -r1.27 -r1.28
--- map_draw_cairo.c 1 Oct 2005 05:24:16 -0000 1.27
+++ map_draw_cairo.c 5 Oct 2005 06:09:36 -0000 1.28
@@ -99,7 +99,7 @@
cairo_set_source_rgba(pCairo, pColor->fRed, pColor->fGreen, pColor->fBlue, pColor->fAlpha);
}
-void map_draw_cairo(map_t* pMap, rendermetrics_t* pRenderMetrics, GdkPixmap* pPixmap, gint nDrawFlags)
+void map_draw_cairo(map_t* pMap, GPtrArray* pTiles, rendermetrics_t* pRenderMetrics, GdkPixmap* pPixmap, gint nDrawFlags)
{
// 1. Set draw target to X Drawable
Display* dpy;
@@ -143,32 +143,38 @@
for(i=pMap->pLayersArray->len-1 ; i>=0 ; i--) {
maplayer_t* pLayer = g_ptr_array_index(pMap->pLayersArray, i);
+ gint nStyleZoomLevel = g_sZoomLevels[pRenderMetrics->nZoomLevel-1].nStyleZoomLevel;
+
if(pLayer->nDrawType == MAP_LAYER_RENDERTYPE_LINES) {
if(nDrawFlags & DRAWFLAG_GEOMETRY) {
- map_draw_cairo_layer_roads(pMap, pCairo, pRenderMetrics,
- pMap->apLayerData[pLayer->nDataSource]->pRoadsArray,
- pLayer->paStylesAtZoomLevels[pRenderMetrics->nZoomLevel-1]);
+// map_draw_cairo_layer_roads(pMap, pCairo, pRenderMetrics,
+// pMap->apLayerData[pLayer->nDataSource]->pRoadsArray,
+// pLayer->paStylesAtZoomLevels[nStyleZoomLevel-1]);
}
}
else if(pLayer->nDrawType == MAP_LAYER_RENDERTYPE_POLYGONS) {
if(nDrawFlags & DRAWFLAG_GEOMETRY) {
- map_draw_cairo_layer_polygons(pMap, pCairo, pRenderMetrics,
- pMap->apLayerData[pLayer->nDataSource]->pRoadsArray,
- pLayer->paStylesAtZoomLevels[pRenderMetrics->nZoomLevel-1]);
+// map_draw_cairo_layer_polygons(pMap, pCairo, pRenderMetrics,
+// pMap->apLayerData[pLayer->nDataSource]->pRoadsArray,
+// pLayer->paStylesAtZoomLevels[nStyleZoomLevel-1]);
}
}
else if(pLayer->nDrawType == MAP_LAYER_RENDERTYPE_LINE_LABELS) {
if(nDrawFlags & DRAWFLAG_LABELS) {
- map_draw_cairo_layer_road_labels(pMap, pCairo, pRenderMetrics,
- pMap->apLayerData[pLayer->nDataSource]->pRoadsArray,
- pLayer->paStylesAtZoomLevels[pRenderMetrics->nZoomLevel-1]);
+ gint iTile;
+ for(iTile=0 ; iTile < pTiles->len ; iTile++) {
+ maptile_t* pTile = g_ptr_array_index(pTiles, iTile);
+ map_draw_cairo_layer_road_labels(pMap, pCairo, pRenderMetrics,
+ pTile->apMapObjectArrays[pLayer->nDataSource], // data
+ pLayer->paStylesAtZoomLevels[nStyleZoomLevel-1]);
+ }
}
}
else if(pLayer->nDrawType == MAP_LAYER_RENDERTYPE_POLYGON_LABELS) {
if(nDrawFlags & DRAWFLAG_LABELS) {
- map_draw_cairo_layer_polygon_labels(pMap, pCairo, pRenderMetrics,
- pMap->apLayerData[pLayer->nDataSource]->pRoadsArray,
- pLayer->paStylesAtZoomLevels[pRenderMetrics->nZoomLevel-1]);
+// map_draw_cairo_layer_polygon_labels(pMap, pCairo, pRenderMetrics,
+// pMap->apLayerData[pLayer->nDataSource]->pRoadsArray,
+// pLayer->paStylesAtZoomLevels[nStyleZoomLevel-1]);
}
}
}
@@ -246,6 +252,11 @@
for(i=0 ; i<pRoadsArray->len ; i++) {
road_t* pRoad = g_ptr_array_index(pRoadsArray, i);
+
+ if(!map_rects_overlap(&(pRoad->rWorldBoundingBox), &(pRenderMetrics->rWorldBoundingBox))) {
+ continue;
+ }
+
if(pRoad->pszName[0] != '\0') {
map_draw_cairo_road_label(pMap, pCairo, pLayerStyle, pRenderMetrics, pRoad->pMapPointsArray, pRoad->pszName);
}
@@ -480,26 +491,11 @@
mappoint_t* pTmp = pMapPoint1; pMapPoint1 = pMapPoint2; pMapPoint2 = pTmp;
}
- // find extents
- gdouble fMaxLat = max(pMapPoint1->fLatitude, pMapPoint2->fLatitude);
- gdouble fMinLat = min(pMapPoint1->fLatitude, pMapPoint2->fLatitude);
- gdouble fMaxLon = max(pMapPoint1->fLongitude, pMapPoint2->fLongitude);
- gdouble fMinLon = min(pMapPoint1->fLongitude, pMapPoint2->fLongitude);
-
gdouble fX1 = SCALE_X(pRenderMetrics, pMapPoint1->fLongitude);
gdouble fY1 = SCALE_Y(pRenderMetrics, pMapPoint1->fLatitude);
gdouble fX2 = SCALE_X(pRenderMetrics, pMapPoint2->fLongitude);
gdouble fY2 = SCALE_Y(pRenderMetrics, pMapPoint2->fLatitude);
- // rectangle overlap test
- if(fMaxLat < pRenderMetrics->rWorldBoundingBox.A.fLatitude
- || fMaxLon < pRenderMetrics->rWorldBoundingBox.A.fLongitude
- || fMinLat > pRenderMetrics->rWorldBoundingBox.B.fLatitude
- || fMinLon > pRenderMetrics->rWorldBoundingBox.B.fLongitude)
- {
- return;
- }
-
gdouble fRise = fY2 - fY1;
gdouble fRun = fX2 - fX1;
gdouble fLineLengthSquared = (fRun*fRun) + (fRise*fRise);
@@ -1276,7 +1272,7 @@
static void map_draw_cairo_map_scale(map_t* pMap, cairo_t *pCairo, rendermetrics_t* pRenderMetrics)
{
- zoomlevel_t* pZoomLevel = &g_sZoomLevels[pRenderMetrics->nZoomLevel];
+ zoomlevel_t* pZoomLevel = &g_sZoomLevels[pRenderMetrics->nZoomLevel-1];
// Imperial
gdouble fImperialLength = 0;
Index: map_draw_cairo.h
===================================================================
RCS file: /cvs/cairo/roadster/src/map_draw_cairo.h,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -d -r1.1 -r1.2
--- map_draw_cairo.h 4 Mar 2005 02:31:55 -0000 1.1
+++ map_draw_cairo.h 5 Oct 2005 06:09:36 -0000 1.2
@@ -26,6 +26,6 @@
#include <cairo.h>
-void map_draw_cairo(map_t* pMap, rendermetrics_t* pRenderMetrics, GdkPixmap* pPixmap, gint nDrawFlags);
+void map_draw_cairo(map_t* pMap, GPtrArray* pTiles, rendermetrics_t* pRenderMetrics, GdkPixmap* pPixmap, gint nDrawFlags);
#endif
Index: map_draw_gdk.c
===================================================================
RCS file: /cvs/cairo/roadster/src/map_draw_gdk.c,v
retrieving revision 1.25
retrieving revision 1.26
diff -u -d -r1.25 -r1.26
--- map_draw_gdk.c 1 Oct 2005 05:24:16 -0000 1.25
+++ map_draw_gdk.c 5 Oct 2005 06:09:36 -0000 1.26
@@ -1,5 +1,5 @@
/***************************************************************************
- * map_draw_cairo.c
+ * map_draw_gdk.c
*
* Copyright 2005 Ian McIntosh
* ian_mcintosh at linuxadvocate.org
@@ -69,7 +69,24 @@
gdk_gc_set_rgb_fg_color(pGC, &clr);
}
-void map_draw_gdk(map_t* pMap, rendermetrics_t* pRenderMetrics, GdkPixmap* pPixmap, gint nDrawFlags)
+void map_draw_gdk_xor_rect(map_t* pMap, GdkDrawable* pTargetDrawable, screenrect_t* pRect)
+{
+ GdkGC* pGC = pMap->pTargetWidget->style->fg_gc[GTK_WIDGET_STATE(pMap->pTargetWidget)];
+
+ GdkGCValues gcValues;
+ gdk_gc_get_values(pGC, &gcValues);
+
+ GdkColor clrWhite = {0, 32000, 32000, 32000};
+ gdk_gc_set_function(pGC, GDK_XOR);
+ gdk_gc_set_rgb_fg_color(pGC, &clrWhite);
+ gdk_draw_rectangle(pTargetDrawable, pGC, FALSE,
+ min(pRect->A.nX, pRect->B.nX), min(pRect->A.nY, pRect->B.nY), // x,y
+ map_screenrect_width(pRect), map_screenrect_height(pRect)); // w,h
+
+ gdk_gc_set_values(pGC, &gcValues, GDK_GC_FUNCTION | GDK_GC_FOREGROUND);
+}
+
+void map_draw_gdk(map_t* pMap, GPtrArray* pTiles, rendermetrics_t* pRenderMetrics, GdkPixmap* pPixmap, gint nDrawFlags)
{
TIMER_BEGIN(maptimer, "BEGIN RENDER MAP (gdk)");
@@ -86,29 +103,40 @@
// 2.1. Draw Background
// map_draw_gdk_background(pMap, pPixmap);
+ gint nStyleZoomLevel = g_sZoomLevels[pRenderMetrics->nZoomLevel-1].nStyleZoomLevel;
+
// 2.2. Draw layer list in reverse order (painter's algorithm: http://en.wikipedia.org/wiki/Painter's_algorithm )
for(i=pMap->pLayersArray->len-1 ; i>=0 ; i--) {
maplayer_t* pLayer = g_ptr_array_index(pMap->pLayersArray, i);
if(pLayer->nDrawType == MAP_LAYER_RENDERTYPE_FILL) {
map_draw_gdk_layer_fill(pMap, pPixmap, pRenderMetrics,
- pLayer->paStylesAtZoomLevels[pRenderMetrics->nZoomLevel-1]); // style
+ pLayer->paStylesAtZoomLevels[nStyleZoomLevel-1]); // style
}
else if(pLayer->nDrawType == MAP_LAYER_RENDERTYPE_LINES) {
- map_draw_gdk_layer_lines(pMap, pPixmap, pRenderMetrics,
- pMap->apLayerData[pLayer->nDataSource]->pRoadsArray, // data
- pLayer->paStylesAtZoomLevels[pRenderMetrics->nZoomLevel-1]); // style
+ gint iTile;
+ for(iTile=0 ; iTile < pTiles->len ; iTile++) {
+ maptile_t* pTile = g_ptr_array_index(pTiles, iTile);
+ map_draw_gdk_layer_lines(pMap, pPixmap, pRenderMetrics,
+ pTile->apMapObjectArrays[pLayer->nDataSource], // data
+ pLayer->paStylesAtZoomLevels[nStyleZoomLevel-1]); // style
+ }
}
else if(pLayer->nDrawType == MAP_LAYER_RENDERTYPE_POLYGONS) {
- map_draw_gdk_layer_polygons(pMap, pPixmap, pRenderMetrics,
- pMap->apLayerData[pLayer->nDataSource]->pRoadsArray, // data
- pLayer->paStylesAtZoomLevels[pRenderMetrics->nZoomLevel-1]); // style
+ gint iTile;
+ for(iTile=0 ; iTile < pTiles->len ; iTile++) {
+ maptile_t* pTile = g_ptr_array_index(pTiles, iTile);
+ map_draw_gdk_layer_polygons(pMap, pPixmap, pRenderMetrics,
+ pTile->apMapObjectArrays[pLayer->nDataSource], // data
+ pLayer->paStylesAtZoomLevels[nStyleZoomLevel-1]); // style
+ }
}
else if(pLayer->nDrawType == MAP_LAYER_RENDERTYPE_LOCATIONS) {
- map_draw_gdk_locations(pMap, pPixmap, pRenderMetrics);
+// map_draw_gdk_locations(pMap, pPixmap, pRenderMetrics);
}
- else if(pLayer->nDrawType == MAP_LAYER_RENDERTYPE_LOCATION_LABELS) {
- //map_draw_gdk_locations(pMap, pPixmap, pRenderMetrics);
+ else {
+// g_print("pLayer->nDrawType = %d\n", pLayer->nDrawType);
+// g_assert_not_reached();
}
}
}
@@ -148,7 +176,6 @@
map_draw_gdk_set_color(pGC, &(pLayerStyle->clrPrimary));
}
-
for(iString=0 ; iString<pRoadsArray->len ; iString++) {
pRoad = g_ptr_array_index(pRoadsArray, iString);
@@ -156,25 +183,27 @@
continue;
}
- if(pRoad->pMapPointsArray->len >= 2) {
- GdkPoint aPoints[MAX_GDK_LINE_SEGMENTS];
+ if(pRoad->pMapPointsArray->len < 3) {
+ //g_warning("not drawing polygon with < 3 points\n");
+ continue;
+ }
- if(pRoad->pMapPointsArray->len > MAX_GDK_LINE_SEGMENTS) {
- g_warning("not drawing line with > %d segments\n", MAX_GDK_LINE_SEGMENTS);
- continue;
- }
+ if(pRoad->pMapPointsArray->len > MAX_GDK_LINE_SEGMENTS) {
+ //g_warning("not drawing polygon with > %d points\n", MAX_GDK_LINE_SEGMENTS);
+ continue;
+ }
- // XXX: the bounding box should be pre-calculated!!!!
- for(iPoint=0 ; iPoint<pRoad->pMapPointsArray->len ; iPoint++) {
- pPoint = &g_array_index(pRoad->pMapPointsArray, mappoint_t, iPoint);
+ GdkPoint aPoints[MAX_GDK_LINE_SEGMENTS];
- aPoints[iPoint].x = pLayerStyle->nPixelOffsetX + (gint)SCALE_X(pRenderMetrics, pPoint->fLongitude);
- aPoints[iPoint].y = pLayerStyle->nPixelOffsetY + (gint)SCALE_Y(pRenderMetrics, pPoint->fLatitude);
- }
+ for(iPoint=0 ; iPoint<pRoad->pMapPointsArray->len ; iPoint++) {
+ pPoint = &g_array_index(pRoad->pMapPointsArray, mappoint_t, iPoint);
- gdk_draw_polygon(pPixmap, pMap->pTargetWidget->style->fg_gc[GTK_WIDGET_STATE(pMap->pTargetWidget)],
- TRUE, aPoints, pRoad->pMapPointsArray->len);
- }
+ aPoints[iPoint].x = pLayerStyle->nPixelOffsetX + (gint)SCALE_X(pRenderMetrics, pPoint->fLongitude);
+ aPoints[iPoint].y = pLayerStyle->nPixelOffsetY + (gint)SCALE_Y(pRenderMetrics, pPoint->fLatitude);
+ }
+
+ gdk_draw_polygon(pPixmap, pMap->pTargetWidget->style->fg_gc[GTK_WIDGET_STATE(pMap->pTargetWidget)],
+ TRUE, aPoints, pRoad->pMapPointsArray->len);
}
if(pLayerStyle->pGlyphFill != NULL) {
// Restore fill style
@@ -259,23 +288,26 @@
}
if(pRoad->pMapPointsArray->len > MAX_GDK_LINE_SEGMENTS) {
- //g_warning("not drawing line with > %d segments\n", MAX_GDK_LINE_SEGMENTS);
+ //g_warning("not drawing line with > %d points\n", MAX_GDK_LINE_SEGMENTS);
continue;
}
- if(pRoad->pMapPointsArray->len >= 2) {
- // Copy all points into this array. Yuuup this is slow. :)
- GdkPoint aPoints[MAX_GDK_LINE_SEGMENTS];
+ if(pRoad->pMapPointsArray->len < 2) {
+ //g_warning("not drawing line with < 2 points\n");
+ continue;
+ }
- for(iPoint=0 ; iPoint<pRoad->pMapPointsArray->len ; iPoint++) {
- pPoint = &g_array_index(pRoad->pMapPointsArray, mappoint_t, iPoint);
+ // Copy all points into this array. Yuuup this is slow. :)
+ GdkPoint aPoints[MAX_GDK_LINE_SEGMENTS];
- aPoints[iPoint].x = pLayerStyle->nPixelOffsetX + (gint)SCALE_X(pRenderMetrics, pPoint->fLongitude);
- aPoints[iPoint].y = pLayerStyle->nPixelOffsetY + (gint)SCALE_Y(pRenderMetrics, pPoint->fLatitude);
- }
+ for(iPoint=0 ; iPoint<pRoad->pMapPointsArray->len ; iPoint++) {
+ pPoint = &g_array_index(pRoad->pMapPointsArray, mappoint_t, iPoint);
- gdk_draw_lines(pPixmap, pMap->pTargetWidget->style->fg_gc[GTK_WIDGET_STATE(pMap->pTargetWidget)], aPoints, pRoad->pMapPointsArray->len);
- }
+ aPoints[iPoint].x = pLayerStyle->nPixelOffsetX + (gint)SCALE_X(pRenderMetrics, pPoint->fLongitude);
+ aPoints[iPoint].y = pLayerStyle->nPixelOffsetY + (gint)SCALE_Y(pRenderMetrics, pPoint->fLatitude);
+ }
+
+ gdk_draw_lines(pPixmap, pMap->pTargetWidget->style->fg_gc[GTK_WIDGET_STATE(pMap->pTargetWidget)], aPoints, pRoad->pMapPointsArray->len);
}
}
Index: map_draw_gdk.h
===================================================================
RCS file: /cvs/cairo/roadster/src/map_draw_gdk.h,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -d -r1.1 -r1.2
--- map_draw_gdk.h 4 Mar 2005 02:31:55 -0000 1.1
+++ map_draw_gdk.h 5 Oct 2005 06:09:36 -0000 1.2
@@ -26,6 +26,7 @@
#include <gdk/gdk.h>
-void map_draw_gdk(map_t* pMap, rendermetrics_t* pRenderMetrics, GdkPixmap* pPixmap, gint nDrawFlags);
+void map_draw_gdk(map_t* pMap, GPtrArray* pTiles, rendermetrics_t* pRenderMetrics, GdkPixmap* pPixmap, gint nDrawFlags);
+void map_draw_gdk_xor_rect(map_t* pMap, GdkDrawable* pTargetDrawable, screenrect_t* pRect);
#endif
Index: map_style.c
===================================================================
RCS file: /cvs/cairo/roadster/src/map_style.c,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -d -r1.4 -r1.5
--- map_style.c 1 Oct 2005 05:24:16 -0000 1.4
+++ map_style.c 5 Oct 2005 06:09:36 -0000 1.5
@@ -30,6 +30,9 @@
#include "glyph.h"
#include "map_style.h"
+#define MIN_STYLE_LEVEL (1)
+#define MAX_STYLE_LEVEL (10)
+
// utility functions for iterating through lists of XML things
#define EACH_ATTRIBUTE_OF_NODE(a,n) (a) = (n)->properties ; (a) != NULL ; (a) = (a)->next
#define EACH_CHILD_OF_NODE(c,n) (c) = (n)->children ; (c) != NULL ; (c) = (c)->next
@@ -127,12 +130,12 @@
nMin = nMax = atoi(pszStr);
}
- if(nMin < MIN_ZOOM_LEVEL || nMin > MAX_ZOOM_LEVEL) {
- g_warning("zoom-level '%s' out of valid range (%d to %d)\n", pszZoomLevel, MIN_ZOOM_LEVEL, MAX_ZOOM_LEVEL);
+ if(nMin < MIN_STYLE_LEVEL || nMin > MAX_STYLE_LEVEL) {
+ g_warning("zoom-level '%s' out of valid range (%d to %d)\n", pszZoomLevel, MIN_STYLE_LEVEL, MAX_STYLE_LEVEL);
bReturn = FALSE;
}
- else if(nMax < MIN_ZOOM_LEVEL || nMax > MAX_ZOOM_LEVEL) {
- g_warning("zoom-level '%s' out of valid range (%d to %d)\n", pszZoomLevel, MIN_ZOOM_LEVEL, MAX_ZOOM_LEVEL);
+ else if(nMax < MIN_STYLE_LEVEL || nMax > MAX_STYLE_LEVEL) {
+ g_warning("zoom-level '%s' out of valid range (%d to %d)\n", pszZoomLevel, MIN_STYLE_LEVEL, MAX_STYLE_LEVEL);
bReturn = FALSE;
}
else {
@@ -375,8 +378,8 @@
}
}
- gint nMinZoomLevel = MIN_ZOOM_LEVEL;
- gint nMaxZoomLevel = MAX_ZOOM_LEVEL;
+ gint nMinZoomLevel = MIN_STYLE_LEVEL;
+ gint nMaxZoomLevel = MAX_STYLE_LEVEL;
if(pszZoomLevel != NULL) {
map_style_parse_zoomlevel(pszZoomLevel, &nMinZoomLevel, &nMaxZoomLevel);
}
--- map_tile.c DELETED ---
--- map_tile.h DELETED ---
--- NEW FILE: map_tilemanager.c ---
/***************************************************************************
* map_tilemanager.c
*
* Copyright 2005 Ian McIntosh
* ian_mcintosh at linuxadvocate.org
****************************************************************************/
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* 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 Library 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include <gtk/gtk.h>
#include "util.h"
#include "map_tilemanager.h"
#include "db.h"
#include "road.h"
// Prototypes
static void _map_tilemanager_tile_load_map_objects(maptile_t* pTile, maprect_t* pRect, gint nLOD);
static maptile_t* map_tilemanager_tile_cache_lookup(maptilemanager_t* pTileManager, maprect_t* pRect, gint nLOD);
static maptile_t* map_tilemanager_tile_new(maptilemanager_t* pTileManager, maprect_t* pRect, gint nLOD);
struct {
gdouble fShift; // the units we care about (eg. 1000 = 1000ths of a degree)
gint nModulus; // how many of the above units each tile is on a side
gdouble fWidth; // width and height of a tile, in degrees
} g_aTileSizeAtLevelOfDetail[MAP_NUM_LEVELS_OF_DETAIL] = {
{1000.0, 70, 70.0 / 1000.0},
{100.0, 35, 35.0 / 100.0},
{10.0, 35, 35.0 / 10.0},
{1.0, 100, 100.0 / 1.0},
};
// Public API
maptilemanager_t* map_tilemanager_new()
{
maptilemanager_t* pNew = g_new0(maptilemanager_t, 1);
gint i;
for(i=0 ; i<MAP_NUM_LEVELS_OF_DETAIL ; i++) {
pNew->apTileCachedArrays[i] = g_ptr_array_new();
}
return pNew;
}
GPtrArray* map_tilemanager_load_tiles_for_worldrect(maptilemanager_t* pTileManager, maprect_t* pRect, gint nLOD)
{
//
// Break the worldrect up into the aligned squares that we load
//
gdouble fTileShift = g_aTileSizeAtLevelOfDetail[nLOD].fShift;
gint nTileModulus = g_aTileSizeAtLevelOfDetail[nLOD].nModulus;
gdouble fTileWidth = g_aTileSizeAtLevelOfDetail[nLOD].fWidth;
gint32 nLatStart = (gint32)(pRect->A.fLatitude * fTileShift);
// round it DOWN (south)
if(pRect->A.fLatitude > 0) {
nLatStart -= (nLatStart % nTileModulus);
}
else {
nLatStart -= (nLatStart % nTileModulus);
nLatStart -= nTileModulus;
}
gint32 nLonStart = (gint32)(pRect->A.fLongitude * fTileShift);
// round it DOWN (west)
if(pRect->A.fLongitude > 0) {
nLonStart -= (nLonStart % nTileModulus);
}
else {
nLonStart -= (nLonStart % nTileModulus);
nLonStart -= nTileModulus;
}
gint32 nLatEnd = (gint32)(pRect->B.fLatitude * fTileShift);
// round it UP (north)
if(pRect->B.fLatitude > 0) {
nLatEnd -= (nLatEnd % nTileModulus);
nLatEnd += nTileModulus;
}
else {
nLatEnd -= (nLatEnd % nTileModulus);
}
gint32 nLonEnd = (gint32)(pRect->B.fLongitude * fTileShift);
// round it UP (east)
if(pRect->B.fLongitude > 0) {
nLonEnd -= (nLonEnd % nTileModulus);
nLonEnd += nTileModulus;
}
else {
nLonEnd -= (nLonEnd % nTileModulus);
}
// how many tiles are we loading in each direction?
gint nLatNumTiles = (nLatEnd - nLatStart) / nTileModulus;
gint nLonNumTiles = (nLonEnd - nLonStart) / nTileModulus;
gdouble fLatStart = (gdouble)nLatStart / fTileShift;
gdouble fLonStart = (gdouble)nLonStart / fTileShift;
if(fLatStart > pRect->A.fLatitude) {
g_print("fLatStart %f > pRect->A.fLatitude %f\n", fLatStart, pRect->A.fLatitude);
g_assert(fLatStart <= pRect->A.fLatitude);
}
if(fLonStart > pRect->A.fLongitude) {
g_print("fLonStart %f > pRect->A.fLongitude %f!!\n", fLonStart, pRect->A.fLongitude);
g_assert_not_reached();
}
GPtrArray* pTileArray = g_ptr_array_new();
g_assert(pTileArray);
gint nLat,nLon;
for(nLat = 0 ; nLat < nLatNumTiles ; nLat++) {
for(nLon = 0 ; nLon < nLonNumTiles ; nLon++) {
maprect_t rect;
rect.A.fLatitude = fLatStart + ((gdouble)(nLat) * fTileWidth);
rect.A.fLongitude = fLonStart + ((gdouble)(nLon) * fTileWidth);
rect.B.fLatitude = fLatStart + ((gdouble)(nLat+1) * fTileWidth);
rect.B.fLongitude = fLonStart + ((gdouble)(nLon+1) * fTileWidth);
maptile_t* pTile = map_tilemanager_tile_cache_lookup(pTileManager, &rect, nLOD);
if(pTile) {
// cache hit
g_ptr_array_add(pTileArray, pTile);
}
else {
// cache miss
pTile = map_tilemanager_tile_new(pTileManager, &rect, nLOD);
g_ptr_array_add(pTileArray, pTile);
}
}
}
return pTileArray;
}
static maptile_t* map_tilemanager_tile_new(maptilemanager_t* pTileManager, maprect_t* pRect, gint nLOD)
{
//g_print("New tile for (%f,%f),(%f,%f)\n", pRect->A.fLongitude, pRect->A.fLatitude, pRect->B.fLongitude, pRect->B.fLatitude);
maptile_t* pNewTile = g_new0(maptile_t, 1);
memcpy(&(pNewTile->rcWorldBoundingBox), pRect, sizeof(maprect_t));
gint i;
for(i=0 ; i<MAP_NUM_OBJECT_TYPES ; i++) {
pNewTile->apMapObjectArrays[i] = g_ptr_array_new();
}
g_print("(");
_map_tilemanager_tile_load_map_objects(pNewTile, pRect, nLOD);
// _map_tilemanager_tile_load_locations(pNewTile, pRect);
g_print(")");
// Add to cache
g_ptr_array_add(pTileManager->apTileCachedArrays[nLOD], pNewTile);
return pNewTile;
}
//
// Private functions
//
static maptile_t* map_tilemanager_tile_cache_lookup(maptilemanager_t* pTileManager, maprect_t* pRect, gint nLOD)
{
// XXX: this should not match on rect, it should match on LOD and Tile ID only
GPtrArray* pArray = pTileManager->apTileCachedArrays[nLOD];
gint i;
for(i=0 ; i<pArray->len ; i++) {
maptile_t* pTile = g_ptr_array_index(pArray, i);
if(map_math_maprects_equal(&(pTile->rcWorldBoundingBox), pRect)) {
//g_print("Cache hit\n");
return pTile;
}
}
//g_print("cache miss for (%f,%f),(%f,%f)\n", pRect->A.fLongitude, pRect->A.fLatitude, pRect->B.fLongitude, pRect->B.fLatitude);
return NULL;
}
static void _map_tilemanager_tile_load_map_objects(maptile_t* pTile, maprect_t* pRect, gint nLOD)
{
db_resultset_t* pResultSet = NULL;
db_row_t aRow;
TIMER_BEGIN(mytimer, "BEGIN Geometry LOAD");
gchar* pszRoadTableName = g_strdup_printf("Road%d", nLOD);
// generate SQL
gchar azCoord1[20], azCoord2[20], azCoord3[20], azCoord4[20], azCoord5[20], azCoord6[20], azCoord7[20], azCoord8[20];
gchar* pszSQL;
pszSQL = g_strdup_printf(
"SELECT 0 AS ID, %s.TypeID, AsBinary(%s.Coordinates), RoadName.Name, RoadName.SuffixID %s"
" FROM %s "
" LEFT JOIN RoadName ON (%s.RoadNameID=RoadName.ID)"
" WHERE"
" MBRIntersects(GeomFromText('Polygon((%s %s,%s %s,%s %s,%s %s,%s %s))'), Coordinates)",
//pszRoadTableName, no ID column
pszRoadTableName, pszRoadTableName,
// Load all details for LOD 0
(nLOD == 0) ? ", AddressLeftStart, AddressLeftEnd, AddressRightStart, AddressRightEnd" : "",
pszRoadTableName, pszRoadTableName,
// upper left
g_ascii_dtostr(azCoord1, 20, pRect->A.fLatitude), g_ascii_dtostr(azCoord2, 20, pRect->A.fLongitude),
// upper right
g_ascii_dtostr(azCoord3, 20, pRect->A.fLatitude), g_ascii_dtostr(azCoord4, 20, pRect->B.fLongitude),
// bottom right
g_ascii_dtostr(azCoord5, 20, pRect->B.fLatitude), g_ascii_dtostr(azCoord6, 20, pRect->B.fLongitude),
// bottom left
g_ascii_dtostr(azCoord7, 20, pRect->B.fLatitude), g_ascii_dtostr(azCoord8, 20, pRect->A.fLongitude),
// upper left again
azCoord1, azCoord2);
//g_print("sql: %s\n", pszSQL);
db_query(pszSQL, &pResultSet);
g_free(pszSQL);
g_free(pszRoadTableName);
TIMER_SHOW(mytimer, "after query");
guint32 uRowCount = 0;
if(pResultSet) {
while((aRow = db_fetch_row(pResultSet))) {
uRowCount++;
// aRow[0] is ID
// aRow[1] is TypeID
// aRow[2] is Coordinates in mysql's text format
// aRow[3] is road name
// aRow[4] is road name suffix id
// aRow[5] is road address left start
// aRow[6] is road address left end
// aRow[7] is road address right start
// aRow[8] is road address right end
// Get layer type that this belongs on
gint nTypeID = atoi(aRow[1]);
if(nTypeID < MAP_OBJECT_TYPE_FIRST || nTypeID > MAP_OBJECT_TYPE_LAST) {
g_warning("geometry record '%s' has bad type '%s'\n", aRow[0], aRow[1]);
continue;
}
//road_t* pNewRoad = NULL;
//road_alloc(&pNewRoad);
road_t* pNewRoad = g_new0(road_t, 1);
// Build name by adding suffix, if one is present
if(aRow[3] != NULL && aRow[4] != NULL) {
const gchar* pszSuffix = road_suffix_itoa(atoi(aRow[4]), ROAD_SUFFIX_LENGTH_SHORT);
pNewRoad->pszName = g_strdup_printf("%s%s%s", aRow[3], (pszSuffix[0] != '\0') ? " " : "", pszSuffix);
}
else {
pNewRoad->pszName = g_strdup(""); // XXX: could we maybe not do this?
}
// We only load this st
if(nLOD == MAP_LEVEL_OF_DETAIL_BEST) {
pNewRoad->nAddressLeftStart = atoi(aRow[5]);
pNewRoad->nAddressLeftEnd = atoi(aRow[6]);
pNewRoad->nAddressRightStart = atoi(aRow[7]);
pNewRoad->nAddressRightEnd = atoi(aRow[8]);
}
// perhaps let the wkb parser create the array (at the perfect size)
pNewRoad->pMapPointsArray = g_array_new(FALSE, FALSE, sizeof(road_t));
db_parse_wkb_linestring(aRow[2], pNewRoad->pMapPointsArray, &(pNewRoad->rWorldBoundingBox));
#ifdef ENABLE_RIVER_TO_LAKE_LOADTIME_HACK // XXX: combine this and above hack and you get lakes with squiggly edges. whoops. :)
if(nTypeID == MAP_OBJECT_TYPE_RIVER) {
mappoint_t* pPointA = &g_array_index(pNewRoad->pMapPointsArray, mappoint_t, 0);
mappoint_t* pPointB = &g_array_index(pNewRoad->pMapPointsArray, mappoint_t, pNewRoad->pMapPointsArray->len-1);
if(pPointA->fLatitude == pPointB->fLatitude && pPointA->fLongitude == pPointB->fLongitude) {
nTypeID = MAP_OBJECT_TYPE_LAKE;
}
}
#endif
// Add this item to layer's list of pointstrings
g_ptr_array_add(pTile->apMapObjectArrays[nTypeID], pNewRoad);
} // end while loop on rows
//g_print("[%d rows]\n", uRowCount);
TIMER_SHOW(mytimer, "after rows retrieved");
db_free_result(pResultSet);
TIMER_SHOW(mytimer, "after free results");
TIMER_END(mytimer, "END Geometry LOAD");
}
}
// static gboolean map_data_load_locations(map_t* pMap, maprect_t* pRect)
// {
// g_return_val_if_fail(pMap != NULL, FALSE);
// g_return_val_if_fail(pRect != NULL, FALSE);
//
// // if(map_get_zoomlevel(pMap) < MIN_ZOOM_LEVEL_FOR_LOCATIONS) {
// // return TRUE;
// // }
//
// TIMER_BEGIN(mytimer, "BEGIN Locations LOAD");
//
// // generate SQL
// gchar* pszSQL;
// gchar azCoord1[20], azCoord2[20], azCoord3[20], azCoord4[20], azCoord5[20], azCoord6[20], azCoord7[20], azCoord8[20];
// pszSQL = g_strdup_printf(
// "SELECT Location.ID, Location.LocationSetID, AsBinary(Location.Coordinates), LocationAttributeValue_Name.Value" // LocationAttributeValue_Name.Value is the "Name" field of this Location
// " FROM Location"
// " LEFT JOIN LocationAttributeValue AS LocationAttributeValue_Name ON (LocationAttributeValue_Name.LocationID=Location.ID AND LocationAttributeValue_Name.AttributeNameID=%d)"
// " WHERE"
// " MBRIntersects(GeomFromText('Polygon((%s %s,%s %s,%s %s,%s %s,%s %s))'), Coordinates)",
// LOCATION_ATTRIBUTE_ID_NAME, // attribute ID for 'name'
// // upper left
// g_ascii_dtostr(azCoord1, 20, pRect->A.fLatitude), g_ascii_dtostr(azCoord2, 20, pRect->A.fLongitude),
// // upper right
// g_ascii_dtostr(azCoord3, 20, pRect->A.fLatitude), g_ascii_dtostr(azCoord4, 20, pRect->B.fLongitude),
// // bottom right
// g_ascii_dtostr(azCoord5, 20, pRect->B.fLatitude), g_ascii_dtostr(azCoord6, 20, pRect->B.fLongitude),
// // bottom left
// g_ascii_dtostr(azCoord7, 20, pRect->B.fLatitude), g_ascii_dtostr(azCoord8, 20, pRect->A.fLongitude),
// // upper left again
// azCoord1, azCoord2);
// //g_print("sql: %s\n", pszSQL);
//
// db_resultset_t* pResultSet = NULL;
// db_query(pszSQL, &pResultSet);
// g_free(pszSQL);
//
// TIMER_SHOW(mytimer, "after query");
//
// guint32 uRowCount = 0;
// if(pResultSet) {
// db_row_t aRow;
// while((aRow = db_fetch_row(pResultSet))) {
// uRowCount++;
//
// // aRow[0] is ID
// // aRow[1] is LocationSetID
// // aRow[2] is Coordinates in mysql's binary format
// // aRow[3] is Name
//
// // Get layer type that this belongs on
// gint nLocationSetID = atoi(aRow[1]);
//
// // Extract
// location_t* pNewLocation = NULL;
// location_alloc(&pNewLocation);
//
// pNewLocation->nID = atoi(aRow[0]);
//
// // Parse coordinates
// db_parse_wkb_point(aRow[2], &(pNewLocation->Coordinates));
//
// // make a copy of the name field, or "" (never leave it == NULL)
// pNewLocation->pszName = g_strdup(aRow[3] != NULL ? aRow[3] : "");
// map_store_location(pMap, pNewLocation, nLocationSetID);
// } // end while loop on rows
// //g_print("[%d rows]\n", uRowCount);
// TIMER_SHOW(mytimer, "after rows retrieved");
//
// db_free_result(pResultSet);
// TIMER_END(mytimer, "END Locations LOAD");
// return TRUE;
// }
// else {
// TIMER_END(mytimer, "END Locations LOAD (0 results)");
// return FALSE;
// }
// }
//
// static void map_data_clear(map_t* pMap)
// {
// // Clear layers
// gint i,j;
// for(i=0 ; i<G_N_ELEMENTS(pMap->apLayerData) ; i++) {
// maplayer_data_t* pLayerData = pMap->apLayerData[i];
//
// // Free each
// for(j = (pLayerData->pRoadsArray->len - 1) ; j>=0 ; j--) {
// road_t* pRoad = g_ptr_array_remove_index_fast(pLayerData->pRoadsArray, j);
// g_array_free(pRoad->pMapPointsArray, TRUE);
// g_free(pRoad);
// }
// g_assert(pLayerData->pRoadsArray->len == 0);
// }
//
// // Clear locations
// map_init_location_hash(pMap);
// }
--- NEW FILE: map_tilemanager.h ---
/***************************************************************************
* map_tilemanager.h
*
* Copyright 2005 Ian McIntosh
* ian_mcintosh at linuxadvocate.org
****************************************************************************/
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* 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 Library 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef _MAP_TILEMANAGER_H_
#define _MAP_TILEMANAGER_H_
#include <gtk/gtk.h>
typedef struct {
GPtrArray* apTileCachedArrays[4]; // MAP_NUM_LEVELS_OF_DETAIL
} maptilemanager_t;
#include "map.h"
typedef struct {
maprect_t rcWorldBoundingBox;
GPtrArray* apMapObjectArrays[ MAP_NUM_OBJECT_TYPES + 1 ];
} maptile_t;
maptilemanager_t* map_tilemanager_new();
// returns GArray containing maptile_t types
GPtrArray* map_tilemanager_load_tiles_for_worldrect(maptilemanager_t* pTileManager, maprect_t* pWorldRect, gint nLOD);
#endif
Index: road.c
===================================================================
RCS file: /cvs/cairo/roadster/src/road.c,v
retrieving revision 1.8
retrieving revision 1.9
diff -u -d -r1.8 -r1.9
--- road.c 1 Oct 2005 00:56:20 -0000 1.8
+++ road.c 5 Oct 2005 06:09:36 -0000 1.9
@@ -22,11 +22,7 @@
*/
#include <gtk/gtk.h>
-#include "main.h"
#include "road.h"
-#include "util.h"
-#include "map.h"
-#include "gfreelist.h"
struct {
gchar* pszLong;
Index: scenemanager.c
===================================================================
RCS file: /cvs/cairo/roadster/src/scenemanager.c,v
retrieving revision 1.15
retrieving revision 1.16
diff -u -d -r1.15 -r1.16
--- scenemanager.c 25 Sep 2005 19:02:37 -0000 1.15
+++ scenemanager.c 5 Oct 2005 06:09:36 -0000 1.16
@@ -21,23 +21,18 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
-#include <gtk/gtk.h>
-
-#include "main.h"
-#include "scenemanager.h"
-
-#define ENABLE_NO_DUPLICATE_LABELS
-
/*
Goals:
- Keep text labels and other screen objects from overlapping
- Prevent the same text from showing up too often (currently not more than once)
*/
-void scenemanager_init(void)
-{
-
-}
+#include <gtk/gtk.h>
+
+#include "main.h"
+#include "scenemanager.h"
+
+#define ENABLE_NO_DUPLICATE_LABELS
void scenemanager_new(scenemanager_t** ppReturn)
{
Index: scenemanager.h
===================================================================
RCS file: /cvs/cairo/roadster/src/scenemanager.h,v
retrieving revision 1.7
retrieving revision 1.8
diff -u -d -r1.7 -r1.8
--- scenemanager.h 25 Sep 2005 19:02:37 -0000 1.7
+++ scenemanager.h 5 Oct 2005 06:09:36 -0000 1.8
@@ -38,7 +38,6 @@
GHashTable* pLabelHash;
} scenemanager_t;
-void scenemanager_init(void);
void scenemanager_new(scenemanager_t** ppReturn);
void scenemanager_set_screen_dimensions(scenemanager_t* pSceneManager, gint nWindowWidth, gint nWindowHeight);
Index: search_road.c
===================================================================
RCS file: /cvs/cairo/roadster/src/search_road.c,v
retrieving revision 1.28
retrieving revision 1.29
diff -u -d -r1.28 -r1.29
--- search_road.c 1 Oct 2005 01:42:12 -0000 1.28
+++ search_road.c 5 Oct 2005 06:09:36 -0000 1.29
@@ -34,7 +34,7 @@
#include "glyph.h"
#include "searchwindow.h" // for defines about glyph size
-#define ROAD_RESULT_SUGGESTED_ZOOMLEVEL (4)
+#define ROAD_RESULT_SUGGESTED_ZOOMLEVEL (37)
#define FORMAT_ROAD_RESULT_WITHOUT_NUMBER ("%s %s\n%s")
#define FORMAT_ROAD_RESULT_WITH_NUMBER ("%d %s %s\n%s")
@@ -214,10 +214,10 @@
if(pRoadSearch->nNumber != ROADSEARCH_NUMBER_NONE) {
pszAddressClause = g_strdup_printf(
" AND ("
- "(%d BETWEEN Road.AddressLeftStart AND Road.AddressLeftEnd)"
- " OR (%d BETWEEN Road.AddressLeftEnd AND Road.AddressLeftStart)"
- " OR (%d BETWEEN Road.AddressRightStart AND Road.AddressRightEnd)"
- " OR (%d BETWEEN Road.AddressRightEnd AND Road.AddressRightStart)"
+ "(%d BETWEEN Road0.AddressLeftStart AND Road0.AddressLeftEnd)"
+ " OR (%d BETWEEN Road0.AddressLeftEnd AND Road0.AddressLeftStart)"
+ " OR (%d BETWEEN Road0.AddressRightStart AND Road0.AddressRightEnd)"
+ " OR (%d BETWEEN Road0.AddressRightEnd AND Road0.AddressRightStart)"
")", pRoadSearch->nNumber, pRoadSearch->nNumber,
pRoadSearch->nNumber, pRoadSearch->nNumber);
}
@@ -238,7 +238,7 @@
gchar* pszZIPClause;
if(pRoadSearch->pszZIPCode != NULL) {
gchar* pszSafeZIP = db_make_escaped_string(pRoadSearch->pszZIPCode);
- pszZIPClause = g_strdup_printf(" AND (Road.ZIPCodeLeft='%s' OR Road.ZIPCodeRight='%s')", pszSafeZIP, pszSafeZIP);
+ pszZIPClause = g_strdup_printf(" AND (Road0.ZIPCodeLeft='%s' OR Road0.ZIPCodeRight='%s')", pszSafeZIP, pszSafeZIP);
db_free_escaped_string(pszSafeZIP);
}
else {
@@ -247,7 +247,7 @@
gchar* pszCityClause;
if(pRoadSearch->nCityID != 0) {
- pszCityClause = g_strdup_printf(" AND (Road.CityLeftID=%d OR Road.CityRightID=%d)", pRoadSearch->nCityID, pRoadSearch->nCityID);
+ pszCityClause = g_strdup_printf(" AND (Road0.CityLeftID=%d OR Road0.CityRightID=%d)", pRoadSearch->nCityID, pRoadSearch->nCityID);
}
else {
pszCityClause = g_strdup("");
@@ -280,19 +280,19 @@
//pszRoadNameCondition = g_strdup_printf("RoadName.NameSoundex = SUBSTRING(SOUNDEX('%s') FROM 1 FOR 10)", pszSafeRoadName);
gchar* pszQuery = g_strdup_printf(
- "SELECT Road.ID, RoadName.Name, RoadName.SuffixID, AsBinary(Road.Coordinates), Road.AddressLeftStart, Road.AddressLeftEnd, Road.AddressRightStart, Road.AddressRightEnd, CityLeft.Name, CityRight.Name"
- ", StateLeft.Code, StateRight.Code, Road.ZIPCodeLeft, Road.ZIPCodeRight"
+ "SELECT 0 AS ID, RoadName.Name, RoadName.SuffixID, AsBinary(Road0.Coordinates), Road0.AddressLeftStart, Road0.AddressLeftEnd, Road0.AddressRightStart, Road0.AddressRightEnd, CityLeft.Name, CityRight.Name"
+ ", StateLeft.Code, StateRight.Code, Road0.ZIPCodeLeft, Road0.ZIPCodeRight"
" FROM RoadName"
- " LEFT JOIN Road ON (RoadName.ID=Road.RoadNameID%s)" // address # clause
+ " LEFT JOIN Road0 ON (RoadName.ID=Road0.RoadNameID%s)" // address # clause
// left side
- " LEFT JOIN City AS CityLeft ON (Road.CityLeftID=CityLeft.ID)"
+ " LEFT JOIN City AS CityLeft ON (Road0.CityLeftID=CityLeft.ID)"
" LEFT JOIN State AS StateLeft ON (CityLeft.StateID=StateLeft.ID)"
// right side
- " LEFT JOIN City AS CityRight ON (Road.CityRightID=CityRight.ID)"
+ " LEFT JOIN City AS CityRight ON (Road0.CityRightID=CityRight.ID)"
" LEFT JOIN State AS StateRight ON (CityRight.StateID=StateRight.ID)"
" WHERE %s"
// " WHERE RoadName.Name='%s'"
- " AND Road.ID IS NOT NULL" // don't include rows where the Road didn't match
+ " AND Road0.TypeID IS NOT NULL" // (any field will do) don't include rows where the Road didn't match
// begin clauses
"%s"
"%s"
@@ -353,7 +353,7 @@
db_parse_wkb_linestring(aRow[3], pMapPointsArray, &r);
search_road_filter_result(aRow[1], pRoadSearch->nNumber, atoi(aRow[2]), atoi(aRow[4]), atoi(aRow[5]), atoi(aRow[6]), atoi(aRow[7]), aRow[8], aRow[9], aRow[10], aRow[11], aRow[12], aRow[13], pMapPointsArray);
//g_print("%03d: Road.ID='%s' RoadName.Name='%s', Suffix=%s, L:%s-%s, R:%s-%s\n", nCount, aRow[0], aRow[1], aRow[3], aRow[4], aRow[5], aRow[6], aRow[7]);
-
+
g_array_free(pMapPointsArray, TRUE);
}
}
More information about the cairo-commit
mailing list