From: Sarah Hoffmann Date: Tue, 21 Jan 2020 20:57:07 +0000 (+0100) Subject: replace nominatim C program X-Git-Tag: v3.5.0~95^2~5 X-Git-Url: https://git.openstreetmap.org/nominatim.git/commitdiff_plain/b4e6d72fde248153207b0b311af4f46ee30e5e52 replace nominatim C program --- diff --git a/CMakeLists.txt b/CMakeLists.txt index d0b72a48..edad9bbc 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -53,6 +53,8 @@ if (NOT ONLY_DOCS) include_directories(${PostgreSQL_INCLUDE_DIRS}) link_directories(${PostgreSQL_LIBRARY_DIRS}) + find_package(PythonInterp 3) + find_program(PYOSMIUM pyosmium-get-changes) if (NOT EXISTS "${PYOSMIUM}") set(PYOSMIUM_PATH "") @@ -168,7 +170,6 @@ endif() if (NOT ONLY_DOCS) add_subdirectory(module) - add_subdirectory(nominatim) endif() add_subdirectory(docs) diff --git a/lib/setup/SetupClass.php b/lib/setup/SetupClass.php index bf44e04b..34ece8e0 100755 --- a/lib/setup/SetupClass.php +++ b/lib/setup/SetupClass.php @@ -10,6 +10,7 @@ class SetupFunctions protected $iInstances; protected $sModulePath; protected $aDSNInfo; + protected $bQuiet; protected $bVerbose; protected $sIgnoreErrors; protected $bEnableDiffUpdates; @@ -49,6 +50,7 @@ class SetupFunctions } // setting member variables based on command line options stored in $aCMDResult + $this->bQuiet = $aCMDResult['quiet']; $this->bVerbose = $aCMDResult['verbose']; //setting default values which are not set by the update.php array @@ -518,10 +520,16 @@ class SetupFunctions public function index($bIndexNoanalyse) { $sOutputFile = ''; - $sBaseCmd = CONST_InstallPath.'/nominatim/nominatim -i' + $sBaseCmd = CONST_BasePath.'/nominatim/nominatim.py' .' -d '.escapeshellarg($this->aDSNInfo['database']) .' -P '.escapeshellarg($this->aDSNInfo['port']) .' -t '.escapeshellarg($this->iInstances.$sOutputFile); + if (!$this->bQuiet) { + $sBaseCmd .= ' -v'; + } + if ($this->bVerbose) { + $sBaseCmd .= ' -v'; + } if (isset($this->aDSNInfo['hostspec'])) { $sBaseCmd .= ' -H '.escapeshellarg($this->aDSNInfo['hostspec']); } diff --git a/nominatim/CMakeLists.txt b/nominatim/CMakeLists.txt deleted file mode 100644 index b391a342..00000000 --- a/nominatim/CMakeLists.txt +++ /dev/null @@ -1,12 +0,0 @@ -add_executable(nominatim export.c geometry.cpp import.c index.c input.c nominatim.c postgresql.c sprompt.c) - -CHECK_SYMBOL_EXISTS(bswap_32 "byteswap.h" HAVE_BYTESWAP) -CHECK_SYMBOL_EXISTS(bswap32 "sys/endian.h" HAVE_SYS_ENDIAN) - -target_compile_definitions(nominatim - PRIVATE HAVE_BYTESWAP=$ - PRIVATE HAVE_SYS_ENDIAN=$ -) - -target_link_libraries(nominatim ${LIBXML2_LIBRARIES} ${ZLIB_LIBRARIES} ${BZIP2_LIBRARIES} ${PostgreSQL_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT}) - diff --git a/nominatim/README.txt b/nominatim/README.txt deleted file mode 100644 index e69de29b..00000000 diff --git a/nominatim/export.c b/nominatim/export.c deleted file mode 100644 index b9628e14..00000000 --- a/nominatim/export.c +++ /dev/null @@ -1,558 +0,0 @@ -/* -*/ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include "nominatim.h" -#include "export.h" -#include "postgresql.h" - -extern int verbose; - -int mode = 0; - -void nominatim_export(int rank_min, int rank_max, const char *conninfo, const char *structuredoutputfile) -{ - xmlTextWriterPtr writer; - - int rankTotalDone; - - PGconn *conn; - PGresult * res; - PGresult * resSectors; - PGresult * resPlaces; - - int rank; - int i; - int iSector; - int tuples; - - const char *paramValues[2]; - int paramLengths[2]; - int paramFormats[2]; - uint32_t paramRank; - uint32_t paramSector; - uint32_t sector; - - Oid pg_prepare_params[2]; - - conn = PQconnectdb(conninfo); - if (PQstatus(conn) != CONNECTION_OK) - { - fprintf(stderr, "Connection to database failed: %s\n", PQerrorMessage(conn)); - exit(EXIT_FAILURE); - } - - pg_prepare_params[0] = PG_OID_INT4; - res = PQprepare(conn, "index_sectors", - "select geometry_sector,count(*) from placex where rank_search = $1 and indexed_status = 0 group by geometry_sector order by geometry_sector", - 1, pg_prepare_params); - if (PQresultStatus(res) != PGRES_COMMAND_OK) exit(EXIT_FAILURE); - PQclear(res); - - pg_prepare_params[0] = PG_OID_INT4; - pg_prepare_params[1] = PG_OID_INT4; - res = PQprepare(conn, "index_sector_places", - "select place_id from placex where rank_search = $1 and geometry_sector = $2", - 2, pg_prepare_params); - if (PQresultStatus(res) != PGRES_COMMAND_OK) exit(EXIT_FAILURE); - PQclear(res); - - nominatim_exportCreatePreparedQueries(conn); - - // Create the output file - writer = nominatim_exportXMLStart(structuredoutputfile); - - for (rank = rank_min; rank <= rank_max; rank++) - { - printf("Starting rank %d\n", rank); - - paramRank = PGint32(rank); - paramValues[0] = (char *)¶mRank; - paramLengths[0] = sizeof(paramRank); - paramFormats[0] = 1; - resSectors = PQexecPrepared(conn, "index_sectors", 1, paramValues, paramLengths, paramFormats, 1); - if (PQresultStatus(resSectors) != PGRES_TUPLES_OK) - { - fprintf(stderr, "index_sectors: SELECT failed: %s", PQerrorMessage(conn)); - PQclear(resSectors); - exit(EXIT_FAILURE); - } - if (PQftype(resSectors, 0) != PG_OID_INT4) - { - fprintf(stderr, "Sector value has unexpected type\n"); - PQclear(resSectors); - exit(EXIT_FAILURE); - } - if (PQftype(resSectors, 1) != PG_OID_INT8) - { - fprintf(stderr, "Sector value has unexpected type\n"); - PQclear(resSectors); - exit(EXIT_FAILURE); - } - - rankTotalDone = 0; - for (iSector = 0; iSector < PQntuples(resSectors); iSector++) - { - sector = PGint32(*((uint32_t *)PQgetvalue(resSectors, iSector, 0))); - - // Get all the place_id's for this sector - paramRank = PGint32(rank); - paramValues[0] = (char *)¶mRank; - paramLengths[0] = sizeof(paramRank); - paramFormats[0] = 1; - paramSector = PGint32(sector); - paramValues[1] = (char *)¶mSector; - paramLengths[1] = sizeof(paramSector); - paramFormats[1] = 1; - resPlaces = PQexecPrepared(conn, "index_sector_places", 2, paramValues, paramLengths, paramFormats, 1); - if (PQresultStatus(resPlaces) != PGRES_TUPLES_OK) - { - fprintf(stderr, "index_sector_places: SELECT failed: %s", PQerrorMessage(conn)); - PQclear(resPlaces); - exit(EXIT_FAILURE); - } - if (PQftype(resPlaces, 0) != PG_OID_INT8) - { - fprintf(stderr, "Place_id value has unexpected type\n"); - PQclear(resPlaces); - exit(EXIT_FAILURE); - } - - tuples = PQntuples(resPlaces); - for (i = 0; i < tuples; i++) - { - nominatim_exportPlace(PGint64(*((uint64_t *)PQgetvalue(resPlaces, i, 0))), conn, writer, NULL, NULL); - rankTotalDone++; - if (rankTotalDone%1000 == 0) printf("Done %i (k)\n", rankTotalDone/1000); - } - PQclear(resPlaces); - } - PQclear(resSectors); - } - - nominatim_exportXMLEnd(writer); - - PQfinish(conn); -} - -void nominatim_exportCreatePreparedQueries(PGconn * conn) -{ - Oid pg_prepare_params[2]; - PGresult * res; - - pg_prepare_params[0] = PG_OID_INT8; - res = PQprepare(conn, "placex_details", - "select placex.osm_type, placex.osm_id, placex.class, placex.type, placex.name, placex.housenumber, placex.country_code, ST_AsText(placex.geometry), placex.admin_level, placex.rank_address, placex.rank_search, placex.parent_place_id, parent.osm_type, parent.osm_id, placex.indexed_status, placex.linked_place_id from placex left outer join placex as parent on (placex.parent_place_id = parent.place_id) where placex.place_id = $1", - 1, pg_prepare_params); - if (PQresultStatus(res) != PGRES_COMMAND_OK) - { - fprintf(stderr, "Error preparing placex_details: %s", PQerrorMessage(conn)); - exit(EXIT_FAILURE); - } - PQclear(res); - - pg_prepare_params[0] = PG_OID_INT8; - res = PQprepare(conn, "placex_address", - "select osm_type,osm_id,class,type,distance,cached_rank_address,isaddress from place_addressline join placex on (address_place_id = placex.place_id) where place_addressline.place_id = $1 and address_place_id != place_addressline.place_id order by cached_rank_address asc,osm_type,osm_id", - 1, pg_prepare_params); - if (PQresultStatus(res) != PGRES_COMMAND_OK) - { - fprintf(stderr, "Error preparing placex_address: %s", PQerrorMessage(conn)); - exit(EXIT_FAILURE); - } - PQclear(res); - - pg_prepare_params[0] = PG_OID_INT8; - res = PQprepare(conn, "placex_names", - "select (each(name)).key,(each(name)).value from (select name from placex where place_id = $1) as x order by (each(name)).key", - 1, pg_prepare_params); - if (PQresultStatus(res) != PGRES_COMMAND_OK) - { - fprintf(stderr, "Error preparing placex_names: %s", PQerrorMessage(conn)); - exit(EXIT_FAILURE); - } - PQclear(res); - - pg_prepare_params[0] = PG_OID_INT8; - res = PQprepare(conn, "placex_extratags", - "select (each(extratags)).key,(each(extratags)).value from (select extratags from placex where place_id = $1) as x order by (each(extratags)).key", - 1, pg_prepare_params); - if (PQresultStatus(res) != PGRES_COMMAND_OK) - { - fprintf(stderr, "Error preparing placex_extratags: %s", PQerrorMessage(conn)); - exit(EXIT_FAILURE); - } - PQclear(res); -} - -xmlTextWriterPtr nominatim_exportXMLStart(const char *structuredoutputfile) -{ - xmlTextWriterPtr writer; - - writer = xmlNewTextWriterFilename(structuredoutputfile, 0); - if (writer==NULL) - { - fprintf(stderr, "Unable to open %s\n", structuredoutputfile); - exit(EXIT_FAILURE); - } - xmlTextWriterSetIndent(writer, 1); - if (xmlTextWriterStartDocument(writer, NULL, "UTF8", NULL) < 0) - { - fprintf(stderr, "xmlTextWriterStartDocument failed\n"); - exit(EXIT_FAILURE); - } - if (xmlTextWriterStartElement(writer, BAD_CAST "osmStructured") < 0) - { - fprintf(stderr, "xmlTextWriterStartElement failed\n"); - exit(EXIT_FAILURE); - } - if (xmlTextWriterWriteAttribute(writer, BAD_CAST "version", BAD_CAST "0.1") < 0) - { - fprintf(stderr, "xmlTextWriterWriteAttribute failed\n"); - exit(EXIT_FAILURE); - } - if (xmlTextWriterWriteAttribute(writer, BAD_CAST "generator", BAD_CAST "Nominatim") < 0) - { - fprintf(stderr, "xmlTextWriterWriteAttribute failed\n"); - exit(EXIT_FAILURE); - } - - mode = 0; - - return writer; -} - -void nominatim_exportXMLEnd(xmlTextWriterPtr writer) -{ - nominatim_exportEndMode(writer); - - // End - if (xmlTextWriterEndElement(writer) < 0) - { - fprintf(stderr, "xmlTextWriterEndElement failed\n"); - exit(EXIT_FAILURE); - } - if (xmlTextWriterEndDocument(writer) < 0) - { - fprintf(stderr, "xmlTextWriterEndDocument failed\n"); - exit(EXIT_FAILURE); - } - xmlFreeTextWriter(writer); -} - -void nominatim_exportStartMode(xmlTextWriterPtr writer, int newMode) -{ - if (mode == newMode) return; - - nominatim_exportEndMode(writer); - - switch(newMode) - { - case 0: - break; - - case 1: - if (xmlTextWriterStartElement(writer, BAD_CAST "add") < 0) - { - fprintf(stderr, "xmlTextWriterStartElement failed\n"); - exit(EXIT_FAILURE); - } - break; - - case 2: - if (xmlTextWriterStartElement(writer, BAD_CAST "update") < 0) - { - fprintf(stderr, "xmlTextWriterStartElement failed\n"); - exit(EXIT_FAILURE); - } - break; - - case 3: - if (xmlTextWriterStartElement(writer, BAD_CAST "delete") < 0) - { - fprintf(stderr, "xmlTextWriterStartElement failed\n"); - exit(EXIT_FAILURE); - } - break; - } - mode = newMode; -} - -void nominatim_exportEndMode(xmlTextWriterPtr writer) -{ - if (!mode) return; - - if (xmlTextWriterEndElement(writer) < 0) - { - fprintf(stderr, "xmlTextWriterEndElement failed\n"); - exit(EXIT_FAILURE); - } -} - -void nominatim_exportPlaceQueries(uint64_t place_id, PGconn * conn, struct export_data * querySet) -{ - const char * paramValues[1]; - int paramLengths[1]; - int paramFormats[1]; - uint64_t paramPlaceID; - - paramPlaceID = PGint64(place_id); - paramValues[0] = (char *)¶mPlaceID; - paramLengths[0] = sizeof(paramPlaceID); - paramFormats[0] = 1; - - querySet->res = PQexecPrepared(conn, "placex_details", 1, paramValues, paramLengths, paramFormats, 0); - if (PQresultStatus(querySet->res) != PGRES_TUPLES_OK) - { - fprintf(stderr, "placex_details: SELECT failed: %s", PQerrorMessage(conn)); - PQclear(querySet->res); - exit(EXIT_FAILURE); - } - - querySet->resNames = PQexecPrepared(conn, "placex_names", 1, paramValues, paramLengths, paramFormats, 0); - if (PQresultStatus(querySet->resNames) != PGRES_TUPLES_OK) - { - fprintf(stderr, "placex_names: SELECT failed: %s", PQerrorMessage(conn)); - PQclear(querySet->resNames); - exit(EXIT_FAILURE); - } - - querySet->resAddress = PQexecPrepared(conn, "placex_address", 1, paramValues, paramLengths, paramFormats, 0); - if (PQresultStatus(querySet->resAddress) != PGRES_TUPLES_OK) - { - fprintf(stderr, "placex_address: SELECT failed: %s", PQerrorMessage(conn)); - PQclear(querySet->resAddress); - exit(EXIT_FAILURE); - } - - querySet->resExtraTags = PQexecPrepared(conn, "placex_extratags", 1, paramValues, paramLengths, paramFormats, 0); - if (PQresultStatus(querySet->resExtraTags) != PGRES_TUPLES_OK) - { - fprintf(stderr, "placex_extratags: SELECT failed: %s", PQerrorMessage(conn)); - PQclear(querySet->resExtraTags); - exit(EXIT_FAILURE); - } -} - -void nominatim_exportFreeQueries(struct export_data * querySet) -{ - PQclear(querySet->res); - PQclear(querySet->resNames); - PQclear(querySet->resAddress); - PQclear(querySet->resExtraTags); -} - -/* - * Requirements: the prepared queries must exist - */ -void nominatim_exportPlace(uint64_t place_id, PGconn * conn, - xmlTextWriterPtr writer, pthread_mutex_t * writer_mutex, struct export_data * prevQuerySet) -{ - struct export_data querySet; - - int i; - - nominatim_exportPlaceQueries(place_id, conn, &querySet); - - // Add, modify or delete? - if (prevQuerySet) - { - if ((PQgetvalue(prevQuerySet->res, 0, 14) && strcmp(PQgetvalue(prevQuerySet->res, 0, 14), "100") == 0) || PQntuples(querySet.res) == 0) - { - // Delete - if (writer_mutex) pthread_mutex_lock( writer_mutex ); - nominatim_exportStartMode(writer, 3); - xmlTextWriterStartElement(writer, BAD_CAST "feature"); - xmlTextWriterWriteFormatAttribute(writer, BAD_CAST "place_id", "%li", place_id); - xmlTextWriterWriteAttribute(writer, BAD_CAST "type", BAD_CAST PQgetvalue(prevQuerySet->res, 0, 0)); - xmlTextWriterWriteAttribute(writer, BAD_CAST "id", BAD_CAST PQgetvalue(prevQuerySet->res, 0, 1)); - xmlTextWriterWriteAttribute(writer, BAD_CAST "key", BAD_CAST PQgetvalue(prevQuerySet->res, 0, 2)); - xmlTextWriterWriteAttribute(writer, BAD_CAST "value", BAD_CAST PQgetvalue(prevQuerySet->res, 0, 3)); - xmlTextWriterEndElement(writer); - if (writer_mutex) pthread_mutex_unlock( writer_mutex ); - nominatim_exportFreeQueries(&querySet); - return; - } - if (PQgetvalue(prevQuerySet->res, 0, 14) && strcmp(PQgetvalue(prevQuerySet->res, 0, 14), "1") == 0) - { - // Add - if (writer_mutex) pthread_mutex_lock( writer_mutex ); - nominatim_exportStartMode(writer, 1); - } - else - { - // Update, but only if something has changed - - // TODO: detect changes - - if (writer_mutex) pthread_mutex_lock( writer_mutex ); - nominatim_exportStartMode(writer, 2); - } - } - else - { - // Add - if (writer_mutex) pthread_mutex_lock( writer_mutex ); - nominatim_exportStartMode(writer, 1); - } - - xmlTextWriterStartElement(writer, BAD_CAST "feature"); - xmlTextWriterWriteFormatAttribute(writer, BAD_CAST "place_id", "%li", place_id); - xmlTextWriterWriteAttribute(writer, BAD_CAST "type", BAD_CAST PQgetvalue(querySet.res, 0, 0)); - xmlTextWriterWriteAttribute(writer, BAD_CAST "id", BAD_CAST PQgetvalue(querySet.res, 0, 1)); - xmlTextWriterWriteAttribute(writer, BAD_CAST "key", BAD_CAST PQgetvalue(querySet.res, 0, 2)); - xmlTextWriterWriteAttribute(writer, BAD_CAST "value", BAD_CAST PQgetvalue(querySet.res, 0, 3)); - xmlTextWriterWriteAttribute(writer, BAD_CAST "rank", BAD_CAST PQgetvalue(querySet.res, 0, 9)); - xmlTextWriterWriteAttribute(writer, BAD_CAST "importance", BAD_CAST PQgetvalue(querySet.res, 0, 10)); - xmlTextWriterWriteAttribute(writer, BAD_CAST "parent_place_id", BAD_CAST PQgetvalue(querySet.res, 0, 11)); - xmlTextWriterWriteAttribute(writer, BAD_CAST "parent_type", BAD_CAST PQgetvalue(querySet.res, 0, 12)); - xmlTextWriterWriteAttribute(writer, BAD_CAST "parent_id", BAD_CAST PQgetvalue(querySet.res, 0, 13)); - xmlTextWriterWriteAttribute(writer, BAD_CAST "linked_place_id", BAD_CAST PQgetvalue(querySet.res, 0, 15)); - - if (PQntuples(querySet.resNames)) - { - xmlTextWriterStartElement(writer, BAD_CAST "names"); - - for (i = 0; i < PQntuples(querySet.resNames); i++) - { - xmlTextWriterStartElement(writer, BAD_CAST "name"); - xmlTextWriterWriteAttribute(writer, BAD_CAST "type", BAD_CAST PQgetvalue(querySet.resNames, i, 0)); - xmlTextWriterWriteString(writer, BAD_CAST PQgetvalue(querySet.resNames, i, 1)); - xmlTextWriterEndElement(writer); - } - - xmlTextWriterEndElement(writer); - } - - if (PQgetvalue(querySet.res, 0, 5) && strlen(PQgetvalue(querySet.res, 0, 5))) - { - xmlTextWriterStartElement(writer, BAD_CAST "houseNumber"); - xmlTextWriterWriteString(writer, BAD_CAST PQgetvalue(querySet.res, 0, 5)); - xmlTextWriterEndElement(writer); - } - - if (PQgetvalue(querySet.res, 0, 8) && strlen(PQgetvalue(querySet.res, 0, 8))) - { - xmlTextWriterStartElement(writer, BAD_CAST "adminLevel"); - xmlTextWriterWriteString(writer, BAD_CAST PQgetvalue(querySet.res, 0, 8)); - xmlTextWriterEndElement(writer); - } - - if (PQgetvalue(querySet.res, 0, 6) && strlen(PQgetvalue(querySet.res, 0, 6))) - { - xmlTextWriterStartElement(writer, BAD_CAST "countryCode"); - xmlTextWriterWriteString(writer, BAD_CAST PQgetvalue(querySet.res, 0, 6)); - xmlTextWriterEndElement(writer); - } - - if (PQntuples(querySet.resAddress) > 0) - { - xmlTextWriterStartElement(writer, BAD_CAST "address"); - for (i = 0; i < PQntuples(querySet.resAddress); i++) - { - xmlTextWriterStartElement(writer, BAD_CAST getRankLabel(atoi(PQgetvalue(querySet.resAddress, i, 5)))); - xmlTextWriterWriteAttribute(writer, BAD_CAST "rank", BAD_CAST PQgetvalue(querySet.resAddress, i, 5)); - xmlTextWriterWriteAttribute(writer, BAD_CAST "type", BAD_CAST PQgetvalue(querySet.resAddress, i, 0)); - xmlTextWriterWriteAttribute(writer, BAD_CAST "id", BAD_CAST PQgetvalue(querySet.resAddress, i, 1)); - xmlTextWriterWriteAttribute(writer, BAD_CAST "key", BAD_CAST PQgetvalue(querySet.resAddress, i, 2)); - xmlTextWriterWriteAttribute(writer, BAD_CAST "value", BAD_CAST PQgetvalue(querySet.resAddress, i, 3)); - xmlTextWriterWriteAttribute(writer, BAD_CAST "distance", BAD_CAST PQgetvalue(querySet.resAddress, i, 4)); - xmlTextWriterWriteAttribute(writer, BAD_CAST "isaddress", BAD_CAST PQgetvalue(querySet.resAddress, i, 6)); - xmlTextWriterEndElement(writer); - } - xmlTextWriterEndElement(writer); - } - - if (PQntuples(querySet.resExtraTags)) - { - xmlTextWriterStartElement(writer, BAD_CAST "tags"); - - for (i = 0; i < PQntuples(querySet.resExtraTags); i++) - { - xmlTextWriterStartElement(writer, BAD_CAST "tag"); - xmlTextWriterWriteAttribute(writer, BAD_CAST "type", BAD_CAST PQgetvalue(querySet.resExtraTags, i, 0)); - xmlTextWriterWriteString(writer, BAD_CAST PQgetvalue(querySet.resExtraTags, i, 1)); - xmlTextWriterEndElement(writer); - } - - xmlTextWriterEndElement(writer); - } - - - xmlTextWriterStartElement(writer, BAD_CAST "osmGeometry"); - xmlTextWriterWriteString(writer, BAD_CAST PQgetvalue(querySet.res, 0, 7)); - xmlTextWriterEndElement(writer); - - xmlTextWriterEndElement(writer); // - - if (writer_mutex) pthread_mutex_unlock( writer_mutex ); - - nominatim_exportFreeQueries(&querySet); -} - -const char * getRankLabel(int rank) -{ - switch (rank) - { - case 0: - case 1: - return "continent"; - case 2: - case 3: - return "sea"; - case 4: - case 5: - case 6: - case 7: - return "country"; - case 8: - case 9: - case 10: - case 11: - return "state"; - case 12: - case 13: - case 14: - case 15: - return "county"; - case 16: - return "city"; - case 17: - return "town"; - case 18: - return "village"; - case 19: - return "unknown"; - case 20: - return "suburb"; - case 21: - return "postcode"; - case 22: - return "neighborhood"; - case 23: - return "postcode"; - case 24: - return "unknown"; - case 25: - return "postcode"; - case 26: - return "street"; - case 27: - return "access"; - case 28: - return "building"; - case 29: - default: - return "other"; - } -} diff --git a/nominatim/export.h b/nominatim/export.h deleted file mode 100644 index c7a302c4..00000000 --- a/nominatim/export.h +++ /dev/null @@ -1,31 +0,0 @@ -#ifndef EXPORT_H -#define EXPORT_H - -#include -#include -#include - -struct export_data -{ - PGresult * res; - PGresult * resNames; - PGresult * resAddress; - PGresult * resExtraTags; -}; - -void nominatim_export(int rank_min, int rank_max, const char *conninfo, const char *structuredoutputfile); -void nominatim_exportCreatePreparedQueries(PGconn * conn); - -xmlTextWriterPtr nominatim_exportXMLStart(const char *structuredoutputfile); -void nominatim_exportXMLEnd(xmlTextWriterPtr writer); - -void nominatim_exportEndMode(xmlTextWriterPtr writer); - -void nominatim_exportPlaceQueries(uint64_t place_id, PGconn * conn, struct export_data * querySet); -void nominatim_exportFreeQueries(struct export_data * querySet); - -void nominatim_exportPlace(uint64_t place_id, PGconn * conn, - xmlTextWriterPtr writer, pthread_mutex_t * writer_mutex, struct export_data * prevQuerySet); -const char * getRankLabel(int rank); - -#endif diff --git a/nominatim/geometry.cpp b/nominatim/geometry.cpp deleted file mode 100644 index e69de29b..00000000 diff --git a/nominatim/import.c b/nominatim/import.c deleted file mode 100644 index 419ab6a5..00000000 --- a/nominatim/import.c +++ /dev/null @@ -1,856 +0,0 @@ -/* -*/ -#include -#include - -#include - -#include -#include -#include - -#include "nominatim.h" -#include "import.h" -#include "input.h" - -typedef enum { FILETYPE_NONE, FILETYPE_STRUCTUREDV0P1 } filetypes_t; -typedef enum { FILEMODE_NONE, FILEMODE_ADD, FILEMODE_UPDATE, FILEMODE_DELETE } filemodes_t; - -#define MAX_FEATUREADDRESS 5000 -#define MAX_FEATURENAMES 10000 -#define MAX_FEATUREEXTRATAGS 10000 -#define MAX_FEATURENAMESTRING 1000000 -#define MAX_FEATUREEXTRATAGSTRING 500000 - -struct feature_address -{ - int place_id; - int rankAddress; - char isAddress[2]; - xmlChar * type; - xmlChar * id; - xmlChar * key; - xmlChar * value; - xmlChar * distance; -}; - -struct feature_tag -{ - xmlChar * type; - xmlChar * value; -}; - -struct feature -{ - xmlChar * placeID; - xmlChar * type; - xmlChar * id; - xmlChar * key; - xmlChar * value; - xmlChar * rankAddress; - xmlChar * rankSearch; - xmlChar * countryCode; - xmlChar * parentPlaceID; - xmlChar * parentType; - xmlChar * parentID; - xmlChar * adminLevel; - xmlChar * houseNumber; - xmlChar * geometry; -} feature; - -int fileType = FILETYPE_NONE; -int fileMode = FILEMODE_ADD; -PGconn * conn; -struct feature_address featureAddress[MAX_FEATUREADDRESS]; -struct feature_tag featureName[MAX_FEATURENAMES]; -struct feature_tag featureExtraTag[MAX_FEATUREEXTRATAGS]; -struct feature feature; -int featureAddressLines = 0; -int featureNameLines = 0; -int featureExtraTagLines = 0; -int featureCount = 0; -xmlHashTablePtr partionTableTagsHash; -xmlHashTablePtr partionTableTagsHashDelete; -char featureNameString[MAX_FEATURENAMESTRING]; -char featureExtraTagString[MAX_FEATUREEXTRATAGSTRING]; - -extern int verbose; - -void StartElement(xmlTextReaderPtr reader, const xmlChar *name) -{ - char * value; - float version; - int isAddressLine; - - if (fileType == FILETYPE_NONE) - { - // Potential to handle other file types in the future / versions - if (xmlStrEqual(name, BAD_CAST "osmStructured")) - { - value = (char*)xmlTextReaderGetAttribute(reader, BAD_CAST "version"); - version = strtof(value, NULL); - xmlFree(value); - - if (version == (float)0.1) - { - fileType = FILETYPE_STRUCTUREDV0P1; - fileMode = FILEMODE_ADD; - } - else - { - fprintf( stderr, "Unknown osmStructured version %f (%s)\n", version, value ); - exit_nicely(); - } - } - else - { - fprintf( stderr, "Unknown XML document type: %s\n", name ); - exit_nicely(); - } - return; - } - - if (xmlStrEqual(name, BAD_CAST "add")) - { - fileMode = FILEMODE_ADD; - return; - } - if (xmlStrEqual(name, BAD_CAST "update")) - { - fileMode = FILEMODE_UPDATE; - return; - } - if (xmlStrEqual(name, BAD_CAST "delete")) - { - fileMode = FILEMODE_DELETE; - return; - } - if (fileMode == FILEMODE_NONE) - { - fprintf( stderr, "Unknown import mode in: %s\n", name ); - exit_nicely(); - } - - if (xmlStrEqual(name, BAD_CAST "feature")) - { - feature.placeID = xmlTextReaderGetAttribute(reader, BAD_CAST "place_id"); - feature.type = xmlTextReaderGetAttribute(reader, BAD_CAST "type"); - feature.id = xmlTextReaderGetAttribute(reader, BAD_CAST "id"); - feature.key = xmlTextReaderGetAttribute(reader, BAD_CAST "key"); - feature.value = xmlTextReaderGetAttribute(reader, BAD_CAST "value"); - feature.rankAddress = xmlTextReaderGetAttribute(reader, BAD_CAST "rank"); - feature.rankSearch = xmlTextReaderGetAttribute(reader, BAD_CAST "importance"); - - feature.parentPlaceID = xmlTextReaderGetAttribute(reader, BAD_CAST "parent_place_id"); -/* - if (strlen(feature.parentPlaceID) == 0) - { - xmlFree(feature.parentPlaceID); - feature.parentPlaceID = NULL; - } -*/ - feature.parentType = xmlTextReaderGetAttribute(reader, BAD_CAST "parent_type"); - feature.parentID = xmlTextReaderGetAttribute(reader, BAD_CAST "parent_id"); - - feature.countryCode = NULL; - feature.adminLevel = NULL; - feature.houseNumber = NULL; - feature.geometry = NULL; - featureAddressLines = 0; - featureNameLines = 0; - featureExtraTagLines = 0; - - return; - } - if (xmlStrEqual(name, BAD_CAST "names")) return; - if (xmlStrEqual(name, BAD_CAST "name")) - { - if (featureNameLines < MAX_FEATURENAMES) - { - featureName[featureNameLines].type = xmlTextReaderGetAttribute(reader, BAD_CAST "type"); - featureName[featureNameLines].value = xmlTextReaderReadString(reader); - featureNameLines++; - } - else - { - fprintf( stderr, "Too many name elements (%s%s)\n", feature.type, feature.id); -// exit_nicely(); - } - return; - } - if (xmlStrEqual(name, BAD_CAST "tags")) return; - if (xmlStrEqual(name, BAD_CAST "tag")) - { - if (featureExtraTagLines < MAX_FEATUREEXTRATAGS) - { - featureExtraTag[featureExtraTagLines].type = xmlTextReaderGetAttribute(reader, BAD_CAST "type"); - featureExtraTag[featureExtraTagLines].value = xmlTextReaderReadString(reader); - featureExtraTagLines++; - } - else - { - fprintf( stderr, "Too many extra tag elements (%s%s)\n", feature.type, feature.id); -// exit_nicely(); - } - return; - } - if (xmlStrEqual(name, BAD_CAST "osmGeometry")) - { - feature.geometry = xmlTextReaderReadString(reader); - return; - } - if (xmlStrEqual(name, BAD_CAST "adminLevel")) - { - feature.adminLevel = xmlTextReaderReadString(reader); - return; - } - if (xmlStrEqual(name, BAD_CAST "countryCode")) - { - feature.countryCode = xmlTextReaderReadString(reader); - return; - } - if (xmlStrEqual(name, BAD_CAST "houseNumber")) - { - feature.houseNumber = xmlTextReaderReadString(reader); - return; - } - if (xmlStrEqual(name, BAD_CAST "address")) - { - featureAddressLines = 0; - return; - } - isAddressLine = 0; - if (xmlStrEqual(name, BAD_CAST "continent")) - { - isAddressLine = 1; - } - else if (xmlStrEqual(name, BAD_CAST "sea")) - { - isAddressLine = 1; - } - else if (xmlStrEqual(name, BAD_CAST "country")) - { - isAddressLine = 1; - } - else if (xmlStrEqual(name, BAD_CAST "state")) - { - isAddressLine = 1; - } - else if (xmlStrEqual(name, BAD_CAST "county")) - { - isAddressLine = 1; - } - else if (xmlStrEqual(name, BAD_CAST "city")) - { - isAddressLine = 1; - } - else if (xmlStrEqual(name, BAD_CAST "town")) - { - isAddressLine = 1; - } - else if (xmlStrEqual(name, BAD_CAST "village")) - { - isAddressLine = 1; - } - else if (xmlStrEqual(name, BAD_CAST "unknown")) - { - isAddressLine = 1; - } - else if (xmlStrEqual(name, BAD_CAST "suburb")) - { - isAddressLine = 1; - } - else if (xmlStrEqual(name, BAD_CAST "postcode")) - { - isAddressLine = 1; - } - else if (xmlStrEqual(name, BAD_CAST "neighborhood")) - { - isAddressLine = 1; - } - else if (xmlStrEqual(name, BAD_CAST "street")) - { - isAddressLine = 1; - } - else if (xmlStrEqual(name, BAD_CAST "access")) - { - isAddressLine = 1; - } - else if (xmlStrEqual(name, BAD_CAST "building")) - { - isAddressLine = 1; - } - else if (xmlStrEqual(name, BAD_CAST "other")) - { - isAddressLine = 1; - } - if (isAddressLine) - { - if (featureAddressLines < MAX_FEATUREADDRESS) - { - value = (char*)xmlTextReaderGetAttribute(reader, BAD_CAST "rank"); - if (!value) - { - fprintf( stderr, "Address element missing rank\n"); - exit_nicely(); - } - featureAddress[featureAddressLines].rankAddress = atoi(value); - xmlFree(value); - - value = (char*)xmlTextReaderGetAttribute(reader, BAD_CAST "isaddress"); - if (!value) - { - fprintf( stderr, "Address element missing rank\n"); - exit_nicely(); - } - if (*value == 't') strcpy(featureAddress[featureAddressLines].isAddress, "t"); - else strcpy(featureAddress[featureAddressLines].isAddress, "f"); - xmlFree(value); - - featureAddress[featureAddressLines].type = xmlTextReaderGetAttribute(reader, BAD_CAST "type"); - featureAddress[featureAddressLines].id = xmlTextReaderGetAttribute(reader, BAD_CAST "id"); - featureAddress[featureAddressLines].key = xmlTextReaderGetAttribute(reader, BAD_CAST "key"); - featureAddress[featureAddressLines].value = xmlTextReaderGetAttribute(reader, BAD_CAST "value"); - featureAddress[featureAddressLines].distance = xmlTextReaderGetAttribute(reader, BAD_CAST "distance"); - - featureAddressLines++; - } - else - { - fprintf( stderr, "Too many address elements (%s%s)\n", feature.type, feature.id); -// exit_nicely(); - } - - return; - } - fprintf(stderr, "%s: Unknown element name: %s\n", __FUNCTION__, name); -} - -void EndElement(xmlTextReaderPtr reader, const xmlChar *name) -{ - PGresult * res; - const char * paramValues[14]; - char * place_id; - char * partionQueryName; - int i, namePos, lineTypeLen, lineValueLen; - - if (xmlStrEqual(name, BAD_CAST "feature")) - { - featureCount++; - if (featureCount % 1000 == 0) printf("feature %i(k)\n", featureCount/1000); -/* - if (fileMode == FILEMODE_ADD) - { - resPlaceID = PQexecPrepared(conn, "get_new_place_id", 0, NULL, NULL, NULL, 0); - if (PQresultStatus(resPlaceID) != PGRES_TUPLES_OK) - { - fprintf(stderr, "get_place_id: INSERT failed: %s", PQerrorMessage(conn)); - PQclear(resPlaceID); - exit(EXIT_FAILURE); - } - } - else - { - paramValues[0] = (const char *)feature.type; - paramValues[1] = (const char *)feature.id; - paramValues[2] = (const char *)feature.key; - paramValues[3] = (const char *)feature.value; - resPlaceID = PQexecPrepared(conn, "get_new_place_id", 4, paramValues, NULL, NULL, 0); - if (PQresultStatus(resPlaceID) != PGRES_TUPLES_OK) - { - fprintf(stderr, "index_placex: INSERT failed: %s", PQerrorMessage(conn)); - PQclear(resPlaceID); - exit(EXIT_FAILURE); - } - } -*/ - place_id = (char *)feature.placeID; - - if (fileMode == FILEMODE_UPDATE || fileMode == FILEMODE_DELETE || fileMode == FILEMODE_ADD) - { - paramValues[0] = (const char *)place_id; - if (verbose) fprintf(stderr, "placex_delete: %s\n", paramValues[0]); - res = PQexecPrepared(conn, "placex_delete", 1, paramValues, NULL, NULL, 0); - if (PQresultStatus(res) != PGRES_COMMAND_OK) - { - fprintf(stderr, "placex_delete: DELETE failed: %s", PQerrorMessage(conn)); - PQclear(res); - exit(EXIT_FAILURE); - } - PQclear(res); - - if (verbose) fprintf(stderr, "search_name_delete: %s\n", paramValues[0]); - res = PQexecPrepared(conn, "search_name_delete", 1, paramValues, NULL, NULL, 0); - if (PQresultStatus(res) != PGRES_COMMAND_OK) - { - fprintf(stderr, "search_name_delete: DELETE failed: %s", PQerrorMessage(conn)); - PQclear(res); - exit(EXIT_FAILURE); - } - PQclear(res); - - if (verbose) fprintf(stderr, "place_addressline_delete: %s\n", paramValues[0]); - res = PQexecPrepared(conn, "place_addressline_delete", 1, paramValues, NULL, NULL, 0); - if (PQresultStatus(res) != PGRES_COMMAND_OK) - { - fprintf(stderr, "place_addressline_delete: DELETE failed: %s", PQerrorMessage(conn)); - PQclear(res); - exit(EXIT_FAILURE); - } - PQclear(res); - - partionQueryName = xmlHashLookup2(partionTableTagsHashDelete, feature.key, feature.value); - if (partionQueryName) - { - res = PQexecPrepared(conn, partionQueryName, 1, paramValues, NULL, NULL, 0); - if (PQresultStatus(res) != PGRES_COMMAND_OK) - { - fprintf(stderr, "%s: DELETE failed: %s", partionQueryName, PQerrorMessage(conn)); - PQclear(res); - exit(EXIT_FAILURE); - } - PQclear(res); - } - } - - if (fileMode == FILEMODE_UPDATE || fileMode == FILEMODE_ADD) - { - // Insert into placex - paramValues[0] = (const char *)place_id; - paramValues[1] = (const char *)feature.type; - paramValues[2] = (const char *)feature.id; - paramValues[3] = (const char *)feature.key; - paramValues[4] = (const char *)feature.value; - - featureNameString[0] = 0; - if (featureNameLines) - { - namePos = 0; - lineTypeLen = 0; - lineValueLen = 0; - for (i = 0; i < featureNameLines; i++) - { - lineTypeLen = (int)strlen((char *) featureName[i].type); - lineValueLen = (int)strlen((char *) featureName[i].value); - if (namePos+lineTypeLen+lineValueLen+7 > MAX_FEATURENAMESTRING) - { - fprintf(stderr, "feature name too long: %s", (const char *)featureName[i].value); - break; - } - if (namePos) strcpy(featureNameString+(namePos++), ","); - strcpy(featureNameString+(namePos++), "\""); - strcpy(featureNameString+namePos, (char*) featureName[i].type); - namePos += lineTypeLen; - strcpy(featureNameString+namePos, "\"=>\""); - namePos += 4; - strcpy(featureNameString+namePos, (char *) featureName[i].value); - namePos += lineValueLen; - strcpy(featureNameString+(namePos++), "\""); - - xmlFree(featureName[i].type); - xmlFree(featureName[i].value); - } - } - paramValues[5] = (const char *)featureNameString; - - paramValues[6] = (const char *)feature.countryCode; - - featureExtraTagString[0] = 0; - if (featureExtraTagLines) - { - namePos = 0; - lineTypeLen = 0; - lineValueLen = 0; - for (i = 0; i < featureExtraTagLines; i++) - { - lineTypeLen = strlen((char *) featureExtraTag[i].type); - lineValueLen = strlen((char *) featureExtraTag[i].value); - if (namePos+lineTypeLen+lineValueLen+7 > MAX_FEATUREEXTRATAGSTRING) - { - fprintf(stderr, "feature extra tag too long: %s", (const char *)featureExtraTag[i].value); - break; - } - if (namePos) strcpy(featureExtraTagString+(namePos++),","); - strcpy(featureExtraTagString+(namePos++), "\""); - strcpy(featureExtraTagString+namePos, (char *) featureExtraTag[i].type); - namePos += lineTypeLen; - strcpy(featureExtraTagString+namePos, "\"=>\""); - namePos += 4; - strcpy(featureExtraTagString+namePos, (char *) featureExtraTag[i].value); - namePos += lineValueLen; - strcpy(featureExtraTagString+(namePos++), "\""); - - xmlFree(featureExtraTag[i].type); - xmlFree(featureExtraTag[i].value); - } - } - paramValues[7] = (const char *)featureExtraTagString; - - if (xmlStrlen(feature.parentPlaceID) == 0) - paramValues[8] = "0"; - else - paramValues[8] = (const char *)feature.parentPlaceID; - - paramValues[9] = (const char *)feature.adminLevel; - paramValues[10] = (const char *)feature.houseNumber; - paramValues[11] = (const char *)feature.rankAddress; - paramValues[12] = (const char *)feature.rankSearch; - paramValues[13] = (const char *)feature.geometry; - if (strlen(paramValues[3]) && strlen(paramValues[13])) - { - if (verbose) fprintf(stderr, "placex_insert: %s\n", paramValues[0]); - res = PQexecPrepared(conn, "placex_insert", 14, paramValues, NULL, NULL, 0); - if (PQresultStatus(res) != PGRES_COMMAND_OK) - { - fprintf(stderr, "index_placex: INSERT failed: %s", PQerrorMessage(conn)); - fprintf(stderr, "index_placex: INSERT failed: %s %s %s", paramValues[0], paramValues[1], paramValues[2]); - PQclear(res); - exit(EXIT_FAILURE); - } - PQclear(res); - } - - for (i = 0; i < featureAddressLines; i++) - { - // insert into place_address - paramValues[0] = (const char *)place_id; - paramValues[1] = (const char *)featureAddress[i].distance; - if (paramValues[1] == NULL || strlen(paramValues[1]) == 0) paramValues[1] = "0"; - paramValues[2] = (const char *)featureAddress[i].type; - paramValues[3] = (const char *)featureAddress[i].id; - paramValues[4] = (const char *)featureAddress[i].key; - paramValues[5] = (const char *)featureAddress[i].value; - paramValues[6] = (const char *)featureAddress[i].isAddress; - if (verbose) fprintf(stderr, "placex_insert: %s %s\n", paramValues[2], paramValues[3]); - res = PQexecPrepared(conn, "place_addressline_insert", 7, paramValues, NULL, NULL, 0); - if (PQresultStatus(res) != PGRES_COMMAND_OK) - { - fprintf(stderr, "place_addressline_insert: INSERT failed: %s", PQerrorMessage(conn)); - fprintf(stderr, "(%s,%s,%s,%s,%s,%s,%s)",paramValues[0],paramValues[1],paramValues[2],paramValues[3],paramValues[4],paramValues[5],paramValues[6]); - PQclear(res); - exit(EXIT_FAILURE); - } - PQclear(res); - - xmlFree(featureAddress[i].type); - xmlFree(featureAddress[i].id); - xmlFree(featureAddress[i].key); - xmlFree(featureAddress[i].value); - xmlFree(featureAddress[i].distance); - } - - if (featureNameLines) - { - if (xmlStrlen(feature.parentPlaceID) > 0 && featureAddressLines == 0) - { - paramValues[0] = (const char *)place_id; - paramValues[1] = (const char *)feature.parentPlaceID; - if (verbose) fprintf(stderr, "search_name_from_parent_insert: INSERT %s %s\n", paramValues[0], paramValues[1]); - res = PQexecPrepared(conn, "search_name_from_parent_insert", 2, paramValues, NULL, NULL, 0); - if (PQresultStatus(res) != PGRES_COMMAND_OK) - { - fprintf(stderr, "search_name_from_parent_insert: INSERT failed: %s", PQerrorMessage(conn)); - PQclear(res); - exit(EXIT_FAILURE); - } - PQclear(res); - } - else - { - paramValues[0] = (const char *)place_id; - if (verbose) fprintf(stderr, "search_name_insert: INSERT %s\n", paramValues[0]); - res = PQexecPrepared(conn, "search_name_insert", 1, paramValues, NULL, NULL, 0); - if (PQresultStatus(res) != PGRES_COMMAND_OK) - { - fprintf(stderr, "search_name_insert: INSERT failed: %s", PQerrorMessage(conn)); - PQclear(res); - exit(EXIT_FAILURE); - } - PQclear(res); - } - } - - partionQueryName = xmlHashLookup2(partionTableTagsHash, feature.key, feature.value); - if (partionQueryName) - { - // insert into partition table - paramValues[0] = (const char *)place_id; - paramValues[1] = (const char *)feature.geometry; - res = PQexecPrepared(conn, partionQueryName, 2, paramValues, NULL, NULL, 0); - if (PQresultStatus(res) != PGRES_COMMAND_OK) - { - fprintf(stderr, "%s: INSERT failed: %s", partionQueryName, PQerrorMessage(conn)); - PQclear(res); - exit(EXIT_FAILURE); - } - PQclear(res); - } - - } - else - { - for (i = 0; i < featureAddressLines; i++) - { - xmlFree(featureAddress[i].type); - xmlFree(featureAddress[i].id); - xmlFree(featureAddress[i].key); - xmlFree(featureAddress[i].value); - xmlFree(featureAddress[i].distance); - } - } - - xmlFree(feature.placeID); - xmlFree(feature.type); - xmlFree(feature.id); - xmlFree(feature.key); - xmlFree(feature.value); - xmlFree(feature.rankAddress); - xmlFree(feature.rankSearch); - if (feature.countryCode) xmlFree(feature.countryCode); - if (feature.parentPlaceID) xmlFree(feature.parentPlaceID); - if (feature.parentType) xmlFree(feature.parentType); - if (feature.parentID) xmlFree(feature.parentID); -// if (feature.name) xmlFree(feature.name); - if (feature.adminLevel) xmlFree(feature.adminLevel); - if (feature.houseNumber) xmlFree(feature.houseNumber); - if (feature.geometry) xmlFree(feature.geometry); - -// PQclear(resPlaceID); - } -} - -static void processNode(xmlTextReaderPtr reader) -{ - xmlChar *name; - name = xmlTextReaderName(reader); - if (name == NULL) - { - name = xmlStrdup(BAD_CAST "--"); - } - - switch (xmlTextReaderNodeType(reader)) - { - case XML_READER_TYPE_ELEMENT: - StartElement(reader, name); - if (xmlTextReaderIsEmptyElement(reader)) - EndElement(reader, name); /* No end_element for self closing tags! */ - break; - case XML_READER_TYPE_END_ELEMENT: - EndElement(reader, name); - break; - case XML_READER_TYPE_TEXT: - case XML_READER_TYPE_CDATA: - case XML_READER_TYPE_SIGNIFICANT_WHITESPACE: - /* Ignore */ - break; - default: - fprintf(stderr, "Unknown node type %d\n", xmlTextReaderNodeType(reader)); - break; - } - - xmlFree(name); -} - -int nominatim_import(const char *conninfo, const char *partionTagsFilename, const char *filename) -{ - xmlTextReaderPtr reader; - int ret = 0; - PGresult * res; - FILE * partionTagsFile; - char * partionQueryName; - char partionQuerySQL[1024]; - - conn = PQconnectdb(conninfo); - if (PQstatus(conn) != CONNECTION_OK) - { - fprintf(stderr, "Connection to database failed: %s\n", PQerrorMessage(conn)); - exit(EXIT_FAILURE); - } - - partionTableTagsHash = xmlHashCreate(200); - partionTableTagsHashDelete = xmlHashCreate(200); - - partionTagsFile = fopen(partionTagsFilename, "rt"); - if (!partionTagsFile) - { - fprintf(stderr, "Unable to read partition tags file: %s\n", partionTagsFilename); - exit(EXIT_FAILURE); - } - - char buffer[1024], osmkey[256], osmvalue[256]; - int fields; - while (fgets(buffer, sizeof(buffer), partionTagsFile) != NULL) - { - fields = sscanf( buffer, "%23s %63s", osmkey, osmvalue ); - - if ( fields <= 0 ) continue; - - if ( fields != 2 ) - { - fprintf( stderr, "Error partition file\n"); - exit_nicely(); - } - partionQueryName = malloc(strlen("partition_insert_")+strlen(osmkey)+strlen(osmvalue)+2); - strcpy(partionQueryName, "partition_insert_"); - strcat(partionQueryName, osmkey); - strcat(partionQueryName, "_"); - strcat(partionQueryName, osmvalue); - - strcpy(partionQuerySQL, "insert into place_classtype_"); - strcat(partionQuerySQL, osmkey); - strcat(partionQuerySQL, "_"); - strcat(partionQuerySQL, osmvalue); - strcat(partionQuerySQL, " (place_id, centroid) values ($1, ST_Centroid(st_setsrid($2, 4326)))"); - - res = PQprepare(conn, partionQueryName, partionQuerySQL, 2, NULL); - if (PQresultStatus(res) != PGRES_COMMAND_OK) - { - fprintf(stderr, "Failed to prepare %s: %s\n", partionQueryName, PQerrorMessage(conn)); - exit(EXIT_FAILURE); - } - - xmlHashAddEntry2(partionTableTagsHash, BAD_CAST osmkey, BAD_CAST osmvalue, BAD_CAST partionQueryName); - - partionQueryName = malloc(strlen("partition_delete_")+strlen(osmkey)+strlen(osmvalue)+2); - strcpy(partionQueryName, "partition_delete_"); - strcat(partionQueryName, osmkey); - strcat(partionQueryName, "_"); - strcat(partionQueryName, osmvalue); - - strcpy(partionQuerySQL, "delete from place_classtype_"); - strcat(partionQuerySQL, osmkey); - strcat(partionQuerySQL, "_"); - strcat(partionQuerySQL, osmvalue); - strcat(partionQuerySQL, " where place_id = $1::integer"); - - res = PQprepare(conn, partionQueryName, partionQuerySQL, 1, NULL); - if (PQresultStatus(res) != PGRES_COMMAND_OK) - { - fprintf(stderr, "Failed to prepare %s: %s\n", partionQueryName, PQerrorMessage(conn)); - exit(EXIT_FAILURE); - } - - xmlHashAddEntry2(partionTableTagsHashDelete, BAD_CAST osmkey, BAD_CAST osmvalue, BAD_CAST partionQueryName); - } - - res = PQprepare(conn, "get_new_place_id", - "select nextval('seq_place')", - 0, NULL); - if (PQresultStatus(res) != PGRES_COMMAND_OK) - { - fprintf(stderr, "Failed to prepare get_new_place_id: %s\n", PQerrorMessage(conn)); - exit(EXIT_FAILURE); - } - - res = PQprepare(conn, "get_place_id", - "select place_id from placex where osm_type = $1 and osm_id = $2 and class = $3 and type = $4", - 4, NULL); - if (PQresultStatus(res) != PGRES_COMMAND_OK) - { - fprintf(stderr, "Failed to prepare get_place_id: %s\n", PQerrorMessage(conn)); - exit(EXIT_FAILURE); - } - - res = PQprepare(conn, "placex_insert", - "insert into placex (place_id,osm_type,osm_id,class,type,name,country_code,extratags,parent_place_id,admin_level,housenumber,rank_address,rank_search,geometry) " - "values ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, st_setsrid($14, 4326))", - 12, NULL); - if (PQresultStatus(res) != PGRES_COMMAND_OK) - { - fprintf(stderr, "Failed to prepare placex_insert: %s\n", PQerrorMessage(conn)); - exit(EXIT_FAILURE); - } - - res = PQprepare(conn, "search_name_insert", - "insert into search_name (place_id, search_rank, address_rank, country_code, name_vector, nameaddress_vector, centroid) " - "select place_id, rank_search, rank_address, country_code, make_keywords(name), " - "(select uniq(sort(array_agg(parent_search_name.name_vector))) from search_name as parent_search_name where place_id in " - "(select distinct address_place_id from place_addressline where place_addressline.place_id = $1 limit 1000)" - "), st_centroid(geometry) from placex " - "where place_id = $1", - 1, NULL); - - if (PQresultStatus(res) != PGRES_COMMAND_OK) - { - fprintf(stderr, "Failed to prepare search_name_insert: %s\n", PQerrorMessage(conn)); - exit(EXIT_FAILURE); - } - - res = PQprepare(conn, "search_name_from_parent_insert", - "insert into search_name (place_id, search_rank, address_rank, country_code, name_vector, nameaddress_vector, centroid) " - "select place_id, rank_search, rank_address, country_code, make_keywords(name), " - "(select uniq(sort(name_vector+nameaddress_vector)) from search_name as parent_search_name " - "where parent_search_name.place_id = $2 ), st_centroid(geometry) from placex " - "where place_id = $1", - 2, NULL); - if (PQresultStatus(res) != PGRES_COMMAND_OK) - { - fprintf(stderr, "Failed to prepare search_name_insert: %s\n", PQerrorMessage(conn)); - exit(EXIT_FAILURE); - } - - res = PQprepare(conn, "place_addressline_insert", - "insert into place_addressline (place_id, address_place_id, fromarea, isaddress, distance, cached_rank_address) " - "select $1, place_id, false, $7, $2, rank_address from placex where osm_type = $3 and osm_id = $4 and class = $5 and type = $6", - 7, NULL); - if (PQresultStatus(res) != PGRES_COMMAND_OK) - { - fprintf(stderr, "Failed to prepare place_addressline_insert: %s\n", PQerrorMessage(conn)); - exit(EXIT_FAILURE); - } - - res = PQprepare(conn, "placex_delete", - "delete from placex where place_id = $1", - 1, NULL); - if (PQresultStatus(res) != PGRES_COMMAND_OK) - { - fprintf(stderr, "Failed to prepare placex_delete: %s\n", PQerrorMessage(conn)); - exit(EXIT_FAILURE); - } - - res = PQprepare(conn, "search_name_delete", - "delete from search_name where place_id = $1", - 1, NULL); - if (PQresultStatus(res) != PGRES_COMMAND_OK) - { - fprintf(stderr, "Failed to prepare search_name_delete: %s\n", PQerrorMessage(conn)); - exit(EXIT_FAILURE); - } - - res = PQprepare(conn, "place_addressline_delete", - "delete from place_addressline where place_id = $1", - 1, NULL); - if (PQresultStatus(res) != PGRES_COMMAND_OK) - { - fprintf(stderr, "Failed to prepare place_addressline_delete: %s\n", PQerrorMessage(conn)); - exit(EXIT_FAILURE); - } - - featureCount = 0; - - reader = inputUTF8(filename); - - if (reader == NULL) - { - fprintf(stderr, "Unable to open %s\n", filename); - return 1; - } - - ret = xmlTextReaderRead(reader); - while (ret == 1) - { - processNode(reader); - ret = xmlTextReaderRead(reader); - } - if (ret != 0) - { - fprintf(stderr, "%s : failed to parse\n", filename); - return ret; - } - - xmlFreeTextReader(reader); - xmlHashFree(partionTableTagsHash, NULL); - xmlHashFree(partionTableTagsHashDelete, NULL); - - return 0; -} diff --git a/nominatim/import.h b/nominatim/import.h deleted file mode 100644 index ae8c26c4..00000000 --- a/nominatim/import.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef IMPORT_H -#define IMPORT_H - -int nominatim_import(const char *conninfo, const char *partionTagsFilename, const char *filename); - -#endif diff --git a/nominatim/index.c b/nominatim/index.c deleted file mode 100644 index bb553f7e..00000000 --- a/nominatim/index.c +++ /dev/null @@ -1,547 +0,0 @@ -/* - * triggers indexing (reparenting etc.) through setting resetting indexed_status: update placex/osmline set indexed_status = 0 where indexed_status > 0 - * triggers placex_update and osmline_update -*/ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include "nominatim.h" -#include "index.h" -#include "export.h" -#include "postgresql.h" - -extern int verbose; - -void run_indexing(int rank, int interpolation, PGconn *conn, int num_threads, -struct index_thread_data * thread_data, const char *structuredoutputfile) -{ - int tuples, count, sleepcount; - pthread_mutex_t count_mutex = PTHREAD_MUTEX_INITIALIZER; - - time_t rankStartTime; - int rankTotalTuples; - int rankCountTuples; - float rankPerSecond; - - PGresult * resSectors; - PGresult * resPlaces; - PGresult * resNULL; - - int i; - int iSector; - int iResult; - - const char *paramValues[2]; - int paramLengths[2]; - int paramFormats[2]; - uint32_t paramRank; - uint32_t paramSector; - uint32_t sector; - - xmlTextWriterPtr writer; - pthread_mutex_t writer_mutex = PTHREAD_MUTEX_INITIALIZER; - - // Create the output file - writer = NULL; - if (structuredoutputfile) - { - writer = nominatim_exportXMLStart(structuredoutputfile); - } - - if (interpolation) - { - fprintf(stderr, "Starting interpolation lines (location_property_osmline)\n"); - } - else - { - fprintf(stderr, "Starting rank %d\n", rank); - } - - rankCountTuples = 0; - rankPerSecond = 0; - - paramRank = PGint32(rank); - paramValues[0] = (char *)¶mRank; - paramLengths[0] = sizeof(paramRank); - paramFormats[0] = 1; - - if (interpolation) - { - resSectors = PQexecPrepared(conn, "index_sectors_osmline", 0, NULL, 0, NULL, 1); - } - else - { - resSectors = PQexecPrepared(conn, "index_sectors", 1, paramValues, paramLengths, paramFormats, 1); - } - if (PQresultStatus(resSectors) != PGRES_TUPLES_OK) - { - fprintf(stderr, "index_sectors: SELECT failed: %s", PQerrorMessage(conn)); - PQclear(resSectors); - exit(EXIT_FAILURE); - } - if (PQftype(resSectors, 0) != PG_OID_INT4) - { - fprintf(stderr, "Sector value has unexpected type\n"); - PQclear(resSectors); - exit(EXIT_FAILURE); - } - if (PQftype(resSectors, 1) != PG_OID_INT8) - { - fprintf(stderr, "Sector value has unexpected type\n"); - PQclear(resSectors); - exit(EXIT_FAILURE); - } - - rankTotalTuples = 0; - for (iSector = 0; iSector < PQntuples(resSectors); iSector++) - { - rankTotalTuples += PGint64(*((uint64_t *)PQgetvalue(resSectors, iSector, 1))); - } - - rankStartTime = time(0); - for (iSector = 0; iSector <= PQntuples(resSectors); iSector++) - { - if (iSector > 0) - { - resPlaces = PQgetResult(conn); - if (PQresultStatus(resPlaces) != PGRES_TUPLES_OK) - { - fprintf(stderr, "index_sector_places: SELECT failed: %s", PQerrorMessage(conn)); - PQclear(resPlaces); - exit(EXIT_FAILURE); - } - if (PQftype(resPlaces, 0) != PG_OID_INT8) - { - fprintf(stderr, "Place_id value has unexpected type\n"); - PQclear(resPlaces); - exit(EXIT_FAILURE); - } - resNULL = PQgetResult(conn); - if (resNULL != NULL) - { - fprintf(stderr, "Unexpected non-null response\n"); - exit(EXIT_FAILURE); - } - } - - if (iSector < PQntuples(resSectors)) - { - sector = PGint32(*((uint32_t *)PQgetvalue(resSectors, iSector, 0))); -// fprintf(stderr, "\n Starting sector %d size %ld\n", sector, PGint64(*((uint64_t *)PQgetvalue(resSectors, iSector, 1)))); - - // Get all the place_id's for this sector - paramRank = PGint32(rank); - paramSector = PGint32(sector); - if (rankTotalTuples-rankCountTuples < num_threads*1000) - { - // no sectors - if (interpolation) - { - iResult = PQsendQueryPrepared(conn, "index_nosector_places_osmline", 0, NULL, 0, NULL, 1); - } - else - { - paramValues[0] = (char *)¶mRank; - paramLengths[0] = sizeof(paramRank); - paramFormats[0] = 1; - iResult = PQsendQueryPrepared(conn, "index_nosector_places", 1, paramValues, paramLengths, paramFormats, 1); - } - } - else - { - if (interpolation) - { - iResult = PQsendQueryPrepared(conn, "index_sector_places_osmline", 1, paramValues, paramLengths, paramFormats, 1); - paramValues[0] = (char *)¶mSector; - paramLengths[0] = sizeof(paramSector); - paramFormats[0] = 1; - } - else - { - paramValues[0] = (char *)¶mRank; - paramLengths[0] = sizeof(paramRank); - paramFormats[0] = 1; - paramValues[1] = (char *)¶mSector; - paramLengths[1] = sizeof(paramSector); - paramFormats[1] = 1; - iResult = PQsendQueryPrepared(conn, "index_sector_places", 2, paramValues, paramLengths, paramFormats, 1); - } - } - if (!iResult) - { - fprintf(stderr, "index_sector_places: SELECT failed: %s", PQerrorMessage(conn)); - PQclear(resPlaces); - exit(EXIT_FAILURE); - } - } - if (iSector > 0) - { - count = 0; - rankPerSecond = 0; - tuples = PQntuples(resPlaces); - - if (tuples > 0) - { - // Spawn threads - for (i = 0; i < num_threads; i++) - { - thread_data[i].res = resPlaces; - thread_data[i].tuples = tuples; - thread_data[i].count = &count; - thread_data[i].count_mutex = &count_mutex; - thread_data[i].writer = writer; - thread_data[i].writer_mutex = &writer_mutex; - if (interpolation) - { - thread_data[i].table = 0; // use interpolations table - } - else - { - thread_data[i].table = 1; // use placex table - } - pthread_create(&thread_data[i].thread, NULL, &nominatim_indexThread, (void *)&thread_data[i]); - } - - // Monitor threads to give user feedback - sleepcount = 0; - while (count < tuples) - { - usleep(1000); - - // Aim for one update per second - if (sleepcount++ > 1000) - { - rankPerSecond = ((float)rankCountTuples + (float)count) / MAX(difftime(time(0), rankStartTime),1); - if(interpolation) - { - fprintf(stderr, " Done %i in %i @ %f per second - Interpolation lines ETA (seconds): %f\n", (rankCountTuples + count), (int)(difftime(time(0), rankStartTime)), rankPerSecond, ((float)(rankTotalTuples - (rankCountTuples + count)))/rankPerSecond); - } - else - { - fprintf(stderr, " Done %i in %i @ %f per second - Rank %i ETA (seconds): %f\n", (rankCountTuples + count), (int)(difftime(time(0), rankStartTime)), rankPerSecond, rank, ((float)(rankTotalTuples - (rankCountTuples + count)))/rankPerSecond); - } - - sleepcount = 0; - } - } - - // Wait for everything to finish - for (i = 0; i < num_threads; i++) - { - pthread_join(thread_data[i].thread, NULL); - } - - rankCountTuples += tuples; - } - - // Finished sector - rankPerSecond = (float)rankCountTuples / MAX(difftime(time(0), rankStartTime),1); - fprintf(stderr, " Done %i in %i @ %f per second - ETA (seconds): %f\n", rankCountTuples, (int)(difftime(time(0), rankStartTime)), rankPerSecond, ((float)(rankTotalTuples - rankCountTuples))/rankPerSecond); - - PQclear(resPlaces); - } - if (rankTotalTuples-rankCountTuples < num_threads*20 && iSector < PQntuples(resSectors)) - { - iSector = PQntuples(resSectors) - 1; - } - } - // Finished rank - fprintf(stderr, "\r Done %i in %i @ %f per second - FINISHED\n\n", rankCountTuples, (int)(difftime(time(0), rankStartTime)), rankPerSecond); - - PQclear(resSectors); -} - -void nominatim_index(int rank_min, int rank_max, int num_threads, const char *conninfo, const char *structuredoutputfile) -{ - struct index_thread_data *thread_data; - - PGconn *conn; - PGresult *res; - int num_rows = 0, status_code = 0; - int db_has_locale = 0; - char *result_string = NULL; - - int rank; - - int i; - - xmlTextWriterPtr writer; - pthread_mutex_t writer_mutex = PTHREAD_MUTEX_INITIALIZER; - - Oid pg_prepare_params[2]; - - conn = PQconnectdb(conninfo); - if (PQstatus(conn) != CONNECTION_OK) - { - fprintf(stderr, "Connection to database failed: %s\n", PQerrorMessage(conn)); - exit(EXIT_FAILURE); - } - - res = PQexec(conn, "SHOW lc_messages"); - status_code = PQresultStatus(res); - if (status_code != PGRES_TUPLES_OK && status_code != PGRES_SINGLE_TUPLE) { - fprintf(stderr, "Failed determining database locale: %s\n", PQerrorMessage(conn)); - exit(EXIT_FAILURE); - } - num_rows = PQntuples(res); - if (num_rows > 0) - { - result_string = PQgetvalue(res, 0, 0); - if (result_string && (strlen(result_string) > 0) && (strcasecmp(result_string, "C") != 0)) - { - // non-default locale if the result exists, is non-empty, and is not "C" - db_has_locale = 1; - } - } - - pg_prepare_params[0] = PG_OID_INT4; - res = PQprepare(conn, "index_sectors", - "select geometry_sector,count(*) from placex where rank_search = $1 and indexed_status > 0 group by geometry_sector order by geometry_sector", - 1, pg_prepare_params); - if (PQresultStatus(res) != PGRES_COMMAND_OK) - { - fprintf(stderr, "Failed preparing index_sectors: %s\n", PQerrorMessage(conn)); - exit(EXIT_FAILURE); - } - PQclear(res); - - res = PQprepare(conn, "index_sectors_osmline", - "select geometry_sector,count(*) from location_property_osmline where indexed_status > 0 group by geometry_sector order by geometry_sector", - 0, NULL); - if (PQresultStatus(res) != PGRES_COMMAND_OK) - { - fprintf(stderr, "Failed preparing index_sectors: %s\n", PQerrorMessage(conn)); - exit(EXIT_FAILURE); - } - PQclear(res); - - pg_prepare_params[0] = PG_OID_INT4; - res = PQprepare(conn, "index_nosectors", - "select 0::integer,count(*) from placex where rank_search = $1 and indexed_status > 0", - 1, pg_prepare_params); - if (PQresultStatus(res) != PGRES_COMMAND_OK) - { - fprintf(stderr, "Failed preparing index_sectors: %s\n", PQerrorMessage(conn)); - exit(EXIT_FAILURE); - } - PQclear(res); - - pg_prepare_params[0] = PG_OID_INT4; - pg_prepare_params[1] = PG_OID_INT4; - res = PQprepare(conn, "index_sector_places", - "select place_id from placex where rank_search = $1 and geometry_sector = $2 and indexed_status > 0", - 2, pg_prepare_params); - if (PQresultStatus(res) != PGRES_COMMAND_OK) - { - fprintf(stderr, "Failed preparing index_sector_places: %s\n", PQerrorMessage(conn)); - exit(EXIT_FAILURE); - } - PQclear(res); - - pg_prepare_params[0] = PG_OID_INT4; - res = PQprepare(conn, "index_nosector_places", - "select place_id from placex where rank_search = $1 and indexed_status > 0 order by geometry_sector", - 1, pg_prepare_params); - if (PQresultStatus(res) != PGRES_COMMAND_OK) - { - fprintf(stderr, "Failed preparing index_nosector_places: %s\n", PQerrorMessage(conn)); - exit(EXIT_FAILURE); - } - PQclear(res); - - pg_prepare_params[0] = PG_OID_INT4; - res = PQprepare(conn, "index_sector_places_osmline", - "select place_id from location_property_osmline where geometry_sector = $1 and indexed_status > 0", - 1, pg_prepare_params); - if (PQresultStatus(res) != PGRES_COMMAND_OK) - { - fprintf(stderr, "Failed preparing index_sector_places: %s\n", PQerrorMessage(conn)); - exit(EXIT_FAILURE); - } - PQclear(res); - - res = PQprepare(conn, "index_nosector_places_osmline", - "select place_id from location_property_osmline where indexed_status > 0 order by geometry_sector", - 0, NULL); - if (PQresultStatus(res) != PGRES_COMMAND_OK) - { - fprintf(stderr, "Failed preparing index_nosector_places: %s\n", PQerrorMessage(conn)); - exit(EXIT_FAILURE); - } - PQclear(res); - - // Build the data for each thread - thread_data = (struct index_thread_data *)malloc(sizeof(struct index_thread_data)*num_threads); - for (i = 0; i < num_threads; i++) - { - thread_data[i].conn = PQconnectdb(conninfo); - if (PQstatus(thread_data[i].conn) != CONNECTION_OK) - { - fprintf(stderr, "Connection to database failed: %s\n", PQerrorMessage(thread_data[i].conn)); - exit(EXIT_FAILURE); - } - - pg_prepare_params[0] = PG_OID_INT8; - res = PQprepare(thread_data[i].conn, "index_placex", - "update placex set indexed_status = 0 where place_id = $1", - 1, pg_prepare_params); - if (PQresultStatus(res) != PGRES_COMMAND_OK) - { - fprintf(stderr, "Failed preparing index_placex: %s\n", PQerrorMessage(thread_data[i].conn)); - exit(EXIT_FAILURE); - } - PQclear(res); - - pg_prepare_params[0] = PG_OID_INT8; - res = PQprepare(thread_data[i].conn, "index_osmline", - "update location_property_osmline set indexed_status = 0 where place_id = $1", - 1, pg_prepare_params); - if (PQresultStatus(res) != PGRES_COMMAND_OK) - { - fprintf(stderr, "Failed preparing index_osmline: %s\n", PQerrorMessage(thread_data[i].conn)); - exit(EXIT_FAILURE); - } - PQclear(res); - - if (db_has_locale) - { - // Make sure the error message is not localized as we parse it later. - res = PQexec(thread_data[i].conn, "SET lc_messages TO 'C'"); - if (PQresultStatus(res) != PGRES_COMMAND_OK) - { - fprintf(stderr, "Failed to set langauge: %s\n", PQerrorMessage(thread_data[i].conn)); - exit(EXIT_FAILURE); - } - PQclear(res); - } - nominatim_exportCreatePreparedQueries(thread_data[i].conn); - } - - fprintf(stderr, "Starting indexing rank (%i to %i) using %i threads\n", rank_min, rank_max, num_threads); - - for (rank = rank_min; rank <= rank_max; rank++) - { - // OSMLINE: do reindexing (=> reparenting) for interpolation lines at rank 30, but before all other objects of rank 30 - // reason: houses (rank 30) depend on the updated interpolation line, when reparenting (see placex_update in functions.sql) - if (rank == 30) - { - run_indexing(rank, 1, conn, num_threads, thread_data, structuredoutputfile); - } - run_indexing(rank, 0, conn, num_threads, thread_data, structuredoutputfile); - } - // Close all connections - for (i = 0; i < num_threads; i++) - { - PQfinish(thread_data[i].conn); - } - PQfinish(conn); -} - -void *nominatim_indexThread(void * thread_data_in) -{ - struct index_thread_data * thread_data = (struct index_thread_data * )thread_data_in; - struct export_data querySet; - - PGresult *res; - - const char *paramValues[1]; - int paramLengths[1]; - int paramFormats[1]; - uint64_t paramPlaceID; - uint64_t place_id; - time_t updateStartTime; - unsigned table; - - table = thread_data->table; - - while (1) - { - pthread_mutex_lock( thread_data->count_mutex ); - if (*(thread_data->count) >= thread_data->tuples) - { - pthread_mutex_unlock( thread_data->count_mutex ); - break; - } - - place_id = PGint64(*((uint64_t *)PQgetvalue(thread_data->res, *thread_data->count, 0))); - (*thread_data->count)++; - - pthread_mutex_unlock( thread_data->count_mutex ); - - if (verbose) fprintf(stderr, " Processing place_id %ld\n", place_id); - - updateStartTime = time(0); - int done = 0; - - if (thread_data->writer) - { - nominatim_exportPlaceQueries(place_id, thread_data->conn, &querySet); - } - - while(!done) - { - paramPlaceID = PGint64(place_id); - paramValues[0] = (char *)¶mPlaceID; - paramLengths[0] = sizeof(paramPlaceID); - paramFormats[0] = 1; - if (table == 1) // table=1 for placex - { - res = PQexecPrepared(thread_data->conn, "index_placex", 1, paramValues, paramLengths, paramFormats, 1); - } - else // table=0 for osmline - { - res = PQexecPrepared(thread_data->conn, "index_osmline", 1, paramValues, paramLengths, paramFormats, 1); - } - if (PQresultStatus(res) == PGRES_COMMAND_OK) - done = 1; - else - { - if (!strncmp(PQerrorMessage(thread_data->conn), "ERROR: deadlock detected", 25)) - { - if (table == 1) - { - fprintf(stderr, "index_placex: UPDATE failed - deadlock, retrying (%ld)\n", place_id); - } - else - { - fprintf(stderr, "index_osmline: UPDATE failed - deadlock, retrying (%ld)\n", place_id); - } - PQclear(res); - sleep(rand() % 10); - } - else - { - if (table == 1) - { - fprintf(stderr, "index_placex: UPDATE failed: %s", PQerrorMessage(thread_data->conn)); - } - else - { - fprintf(stderr, "index_osmline: UPDATE failed: %s", PQerrorMessage(thread_data->conn)); - } - PQclear(res); - exit(EXIT_FAILURE); - } - } - } - PQclear(res); - if (difftime(time(0), updateStartTime) > 1) fprintf(stderr, " Slow place_id %ld\n", place_id); - - if (thread_data->writer) - { - nominatim_exportPlace(place_id, thread_data->conn, thread_data->writer, thread_data->writer_mutex, &querySet); - nominatim_exportFreeQueries(&querySet); - } - } - - return NULL; -} diff --git a/nominatim/index.h b/nominatim/index.h deleted file mode 100644 index e5759541..00000000 --- a/nominatim/index.h +++ /dev/null @@ -1,22 +0,0 @@ -#ifndef INDEX_H -#define INDEX_H - -#include -#include - -struct index_thread_data -{ - pthread_t thread; - PGconn * conn; - PGresult * res; - int tuples; - int * count; - pthread_mutex_t * count_mutex; - xmlTextWriterPtr writer; - pthread_mutex_t * writer_mutex; - unsigned table; -}; -void nominatim_index(int rank_min, int rank_max, int num_threads, const char *conninfo, const char *structuredoutputfile); -void *nominatim_indexThread(void * thread_data_in); - -#endif diff --git a/nominatim/input.c b/nominatim/input.c deleted file mode 100644 index 1d53b491..00000000 --- a/nominatim/input.c +++ /dev/null @@ -1,242 +0,0 @@ -#define _FILE_OFFSET_BITS 64 -#define _LARGEFILE64_SOURCE - -#ifdef __MINGW_H -# include -#else -#include -#include -#include -#include -#include -#include -#include -#include -#endif - -#include -#include - -#include "input.h" - -struct Input -{ - char *name; - enum { plainFile, gzipFile, bzip2File } type; - void *fileHandle; - // needed by bzip2 when decompressing from multiple streams. other - // decompressors must ignore it. - FILE *systemHandle; - int eof; - char buf[4096]; - int buf_ptr, buf_fill; -}; - -// tries to re-open the bz stream at the next stream start. -// returns 0 on success, -1 on failure. -int bzReOpen(struct Input *ctx, int *error) -{ - // for copying out the last unused part of the block which - // has an EOS token in it. needed for re-initialising the - // next stream. - unsigned char unused[BZ_MAX_UNUSED]; - void *unused_tmp_ptr = NULL; - int nUnused, i; - - BZ2_bzReadGetUnused(error, (BZFILE *)(ctx->fileHandle), &unused_tmp_ptr, &nUnused); - if (*error != BZ_OK) return -1; - - // when bzReadClose is called the unused buffer is deallocated, - // so it needs to be copied somewhere safe first. - for (i = 0; i < nUnused; ++i) - unused[i] = ((unsigned char *)unused_tmp_ptr)[i]; - - BZ2_bzReadClose(error, (BZFILE *)(ctx->fileHandle)); - if (*error != BZ_OK) return -1; - - // reassign the file handle - ctx->fileHandle = BZ2_bzReadOpen(error, ctx->systemHandle, 0, 0, unused, nUnused); - if (ctx->fileHandle == NULL || *error != BZ_OK) return -1; - - return 0; -} - -int readFile(void *context, char * buffer, int len) -{ - struct Input *ctx = context; - void *f = ctx->fileHandle; - int l = 0, error = 0; - - if (ctx->eof || (len == 0)) - return 0; - - switch (ctx->type) - { - case plainFile: - l = read(*(int *)f, buffer, len); - if (l <= 0) ctx->eof = 1; - break; - case gzipFile: - l = gzread((gzFile)f, buffer, len); - if (l <= 0) ctx->eof = 1; - break; - case bzip2File: - l = BZ2_bzRead(&error, (BZFILE *)f, buffer, len); - - // error codes BZ_OK and BZ_STREAM_END are both "OK", but the stream - // end means the reader needs to be reset from the original handle. - if (error != BZ_OK) - { - // for stream errors, try re-opening the stream before admitting defeat. - if (error != BZ_STREAM_END || bzReOpen(ctx, &error) != 0) - { - l = 0; - ctx->eof = 1; - } - } - break; - default: - fprintf(stderr, "Bad file type\n"); - break; - } - - if (l < 0) - { - fprintf(stderr, "File reader received error %d (%d)\n", l, error); - l = 0; - } - - return l; -} - -char inputGetChar(void *context) -{ - struct Input *ctx = context; - - if (ctx->buf_ptr == ctx->buf_fill) - { - ctx->buf_fill = readFile(context, &ctx->buf[0], sizeof(ctx->buf)); - ctx->buf_ptr = 0; - if (ctx->buf_fill == 0) - return 0; - if (ctx->buf_fill < 0) - { - perror("Error while reading file"); - exit(1); - } - } - //readFile(context, &c, 1); - return ctx->buf[ctx->buf_ptr++]; -} - -int inputEof(void *context) -{ - return ((struct Input *)context)->eof; -} - -void *inputOpen(const char *name) -{ - const char *ext = strrchr(name, '.'); - struct Input *ctx = malloc (sizeof(*ctx)); - - if (!ctx) - return NULL; - - memset(ctx, 0, sizeof(*ctx)); - - ctx->name = strdup(name); - - if (ext && !strcmp(ext, ".gz")) - { - ctx->fileHandle = (void *)gzopen(name, "rb"); - ctx->type = gzipFile; - } - else if (ext && !strcmp(ext, ".bz2")) - { - int error = 0; - ctx->systemHandle = fopen(name, "rb"); - if (!ctx->systemHandle) - { - fprintf(stderr, "error while opening file %s\n", name); - exit(10); - } - - ctx->fileHandle = (void *)BZ2_bzReadOpen(&error, ctx->systemHandle, 0, 0, NULL, 0); - ctx->type = bzip2File; - - } - else - { - int *pfd = malloc(sizeof(pfd)); - if (pfd) - { - if (!strcmp(name, "-")) - { - *pfd = STDIN_FILENO; - } - else - { - int flags = O_RDONLY; -#ifdef O_LARGEFILE - flags |= O_LARGEFILE; -#endif - *pfd = open(name, flags); - if (*pfd < 0) - { - free(pfd); - pfd = NULL; - } - } - } - ctx->fileHandle = (void *)pfd; - ctx->type = plainFile; - } - if (!ctx->fileHandle) - { - fprintf(stderr, "error while opening file %s\n", name); - exit(10); - } - ctx->buf_ptr = 0; - ctx->buf_fill = 0; - return (void *)ctx; -} - -int inputClose(void *context) -{ - struct Input *ctx = context; - void *f = ctx->fileHandle; - - switch (ctx->type) - { - case plainFile: - close(*(int *)f); - free(f); - break; - case gzipFile: - gzclose((gzFile)f); - break; - case bzip2File: - BZ2_bzclose((BZFILE *)f); - break; - default: - fprintf(stderr, "Bad file type\n"); - break; - } - - free(ctx->name); - free(ctx); - return 0; -} - -xmlTextReaderPtr inputUTF8(const char *name) -{ - void *ctx = inputOpen(name); - - if (!ctx) - { - fprintf(stderr, "Input reader create failed for: %s\n", name); - return NULL; - } - - return xmlReaderForIO(readFile, inputClose, (void *)ctx, NULL, NULL, 0); -} diff --git a/nominatim/input.h b/nominatim/input.h deleted file mode 100644 index de5f8028..00000000 --- a/nominatim/input.h +++ /dev/null @@ -1,11 +0,0 @@ -#ifndef INPUT_H -#define INPUT_H - -int readFile(void *context, char * buffer, int len); -int inputClose(void *context); -void *inputOpen(const char *name); -char inputGetChar(void *context); -int inputEof(void *context); -xmlTextReaderPtr inputUTF8(const char *name); - -#endif diff --git a/nominatim/nominatim.c b/nominatim/nominatim.c deleted file mode 100644 index 1771be2e..00000000 --- a/nominatim/nominatim.c +++ /dev/null @@ -1,255 +0,0 @@ -/* -#----------------------------------------------------------------------------- -# nominatim - [description] -#----------------------------------------------------------------------------- -# Copyright 2010, Brian Quinion -# Based on osm2pgsql -# -# 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 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. -#----------------------------------------------------------------------------- -*/ - -#define _GNU_SOURCE -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include "nominatim.h" -#include "postgresql.h" -#include "sprompt.h" -#include "index.h" -#include "export.h" -#include "import.h" - -int verbose; - -void exit_nicely(void) -{ - fprintf(stderr, "Error occurred, cleaning up\n"); - exit(1); -} - -void short_usage(char *arg0) -{ - const char *name = basename(arg0); - - fprintf(stderr, "Usage error. For further information see:\n"); - fprintf(stderr, "\t%s -h|--help\n", name); -} - -static void long_usage(char *arg0) -{ - const char *name = basename(arg0); - - fprintf(stderr, "Usage:\n"); - fprintf(stderr, "\t%s [options] planet.osms\n", name); - fprintf(stderr, "\nThis will import the structured osm data into a PostgreSQL database\n"); - fprintf(stderr, "suitable for nominatim search engine\n"); - fprintf(stderr, "\nOptions:\n"); - fprintf(stderr, " -d|--database\tThe name of the PostgreSQL database to connect\n"); - fprintf(stderr, " \tto (default: nominatim).\n"); - fprintf(stderr, " -U|--username\tPostgresql user name.\n"); - fprintf(stderr, " -W|--password\tForce password prompt.\n"); - fprintf(stderr, " -H|--host\t\tDatabase server hostname or socket location.\n"); - fprintf(stderr, " -P|--port\t\tDatabase server port.\n"); - fprintf(stderr, " -i|--index\t\tIndex the database.\n"); - fprintf(stderr, " -e|--export\t\tGenerate a structured file.\n"); - fprintf(stderr, " -I|--import\t\tImport a structured file.\n"); - fprintf(stderr, " -r|--minrank\t\tMinimum / starting rank. (default: 0))\n"); - fprintf(stderr, " -R|--maxrank\t\tMaximum / finishing rank. (default: 30)\n"); - fprintf(stderr, " -t|--threads\t\tNumber of threads to create for indexing.\n"); - fprintf(stderr, " -F|--file\t\tfile to use (either to import or export).\n"); - fprintf(stderr, " -T|--tagfile\t\tfile containing 'special' tag pairs\n"); - fprintf(stderr, " \t(default: partitionedtags.def).\n"); - fprintf(stderr, " -h|--help\t\tHelp information.\n"); - fprintf(stderr, " -v|--verbose\t\tVerbose output.\n"); - fprintf(stderr, "\n"); - - if (sizeof(int*) == 4) - { - fprintf(stderr, "\n\nYou are running this on 32bit system - this will not work\n"); - } -} - -int main(int argc, char *argv[]) -{ - int long_usage_bool=0; - int pass_prompt=0; - const char *db = "nominatim"; - const char *username=NULL; - const char *host=NULL; - const char *password=NULL; - const char *port = "5432"; - const char *conninfo = NULL; - int index = 0; - int export = 0; - int import = 0; - int minrank = 0; - int maxrank = 30; - int threads = 1; - const char *file = NULL; - const char *tagsfile = "partitionedtags.def"; - - //import = 1; - //structuredinputfile = "out.osms"; - - PGconn *conn; - - fprintf(stderr, "nominatim version %s\n\n", NOMINATIM_VERSION); - - while (1) - { - int c, option_index = 0; - static struct option long_options[] = - { - {"help", 0, 0, 'h'}, - - {"verbose", 0, 0, 'v'}, - - {"database", 1, 0, 'd'}, - {"username", 1, 0, 'U'}, - {"password", 0, 0, 'W'}, - {"host", 1, 0, 'H'}, - {"port", 1, 0, 'P'}, - - {"index", 0, 0, 'i'}, - {"export", 0, 0, 'e'}, - {"import", 1, 0, 'I'}, - {"threads", 1, 0, 't'}, - {"file", 1, 0, 'F'}, - {"tagsfile", 1, 0, 'T'}, - - {"minrank", 1, 0, 'r'}, - {"maxrank", 1, 0, 'R'}, - - - - {0, 0, 0, 0} - }; - - c = getopt_long(argc, argv, "vhd:U:WH:P:ieIt:F:T:r:R:", long_options, &option_index); - if (c == -1) - break; - - switch (c) - { - case 'v': - verbose=1; - break; - case 'd': - db=optarg; - break; - case 'U': - username=optarg; - break; - case 'W': - pass_prompt=1; - break; - case 'H': - host=optarg; - break; - case 'P': - port=optarg; - break; - case 'h': - long_usage_bool=1; - break; - case 'i': - index=1; - break; - case 'e': - export=1; - break; - case 'I': - import=1; - break; - case 't': - threads=atoi(optarg); - break; - case 'r': - minrank=atoi(optarg); - break; - case 'R': - maxrank=atoi(optarg); - break; - case 'F': - file=optarg; - break; - case 'T': - tagsfile=optarg; - break; - case '?': - default: - short_usage(argv[0]); - exit(EXIT_FAILURE); - } - } - - if (long_usage_bool) - { - long_usage(argv[0]); - exit(EXIT_FAILURE); - } - - if (threads < 1) threads = 1; - - /* - if (argc == optind) { // No non-switch arguments - short_usage(argv[0]); - exit(EXIT_FAILURE); - } - */ - if (index && import) - { - fprintf(stderr, "Error: --index and --import options can not be used on the same database!\n"); - exit(EXIT_FAILURE); - } - - if (pass_prompt) - password = simple_prompt("Password:", 100, 0); - else - { - password = getenv("PGPASS"); - } - - // Test the database connection - conninfo = build_conninfo(db, username, password, host, port); - conn = PQconnectdb(conninfo); - if (PQstatus(conn) != CONNECTION_OK) - { - fprintf(stderr, "Connection to database failed: %s\n", PQerrorMessage(conn)); - exit(EXIT_FAILURE); - } - PQfinish(conn); - - if (!index && !export && !import) - { - fprintf(stderr, "Please select index, export or import.\n"); - exit(EXIT_FAILURE); - } - if (index) nominatim_index(minrank, maxrank, threads, conninfo, file); - if (export) nominatim_export(minrank, maxrank, conninfo, file); - if (import) nominatim_import(conninfo, tagsfile, file); - - return 0; -} diff --git a/nominatim/nominatim.h b/nominatim/nominatim.h deleted file mode 100644 index a98f3bf9..00000000 --- a/nominatim/nominatim.h +++ /dev/null @@ -1,31 +0,0 @@ -#ifndef NOMINATIM_H -#define NOMINATIM_H - -#define MAX(x,y) (x > y?x:y) -#define MIN(x,y) (x < y?x:y) - -struct output_options -{ - const char *conninfo; /* Connection info string */ - const char *prefix; /* prefix for table names */ - int scale; /* scale for converting coordinates to fixed point */ - int projection; /* SRS of projection */ - int append; /* Append to existing data */ - int slim; /* In slim mode */ - int cache; /* Memory usable for cache in MB */ - struct middle_t *mid; /* Mid storage to use */ - const char *tblsindex; /* Pg Tablespace to store indexes */ - const char *style; /* style file to use */ - int expire_tiles_zoom; /* Zoom level for tile expiry list */ - int expire_tiles_zoom_min; /* Minimum zoom level for tile expiry list */ - const char *expire_tiles_filename; /* File name to output expired tiles list to */ - int enable_hstore; /* add an additional hstore column with objects key/value pairs */ - int enable_multi; /* Output multi-geometries instead of several simple geometries */ - char** hstore_columns; /* list of columns that should be written into their own hstore column */ - int n_hstore_columns; /* number of hstore columns */ -}; - -void exit_nicely(void); -void short_usage(char *arg0); - -#endif diff --git a/nominatim/nominatim.py b/nominatim/nominatim.py old mode 100644 new mode 100755 index 73456ff9..bbda4d7e --- a/nominatim/nominatim.py +++ b/nominatim/nominatim.py @@ -1,4 +1,4 @@ -#! /usr/bin/env python +#! /usr/bin/env python3 #----------------------------------------------------------------------------- # nominatim - [description] #----------------------------------------------------------------------------- diff --git a/nominatim/nominatim.spec.in b/nominatim/nominatim.spec.in deleted file mode 100644 index e7adf88f..00000000 --- a/nominatim/nominatim.spec.in +++ /dev/null @@ -1,55 +0,0 @@ - -%define svn @SVN@ - -Summary: Nominatim OpenStreetMap geocoding database -Name: @PACKAGE@ -Group: Applications/Text -Version: @VERSION@ -Release: 1.%{svn}%{?dist} - -License: GPL -URL: http://svn.openstreetmap.org/applications/utils/nominatim -Source0: %{name}-%{version}-%{svn}.tar.bz2 -Source1: nominatim-svn.sh -BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n) - -BuildRequires: geos-devel -BuildRequires: libxml2-devel -BuildRequires: postgresql-devel -BuildRequires: bzip2-devel -BuildRequires: proj-devel - -%description -Processes data imported using osm2pgsql from the communtiy mapping project -at http://www.openstreetmap.org. - -%prep -%setup -q -n %{name} - - -%build - -export CFLAGS="$RPM_OPT_FLAGS" -export CXXFLAGS="$RPM_OPT_FLAGS" - -make all - - -%install -rm -rf $RPM_BUILD_ROOT -install -D -p nominatim $RPM_BUILD_ROOT/usr/bin/nominatim - - -%clean -rm -rf $RPM_BUILD_ROOT - - -%files -%defattr(-,root,root) -%doc README.txt -%{_bindir}/nominatim - - -%changelog -* Fri Sep 09 2010 Brian Quinion 0.1-1.20070316svn -- Initial build diff --git a/nominatim/postgresql.c b/nominatim/postgresql.c deleted file mode 100644 index 30237e0a..00000000 --- a/nominatim/postgresql.c +++ /dev/null @@ -1,41 +0,0 @@ -/* -*/ -#include -#include "postgresql.h" - -const char *build_conninfo(const char *db, const char *username, const char *password, const char *host, const char *port) -{ - static char conninfo[1024]; - - conninfo[0]='\0'; - strcat(conninfo, "dbname='"); - strcat(conninfo, db); - strcat(conninfo, "'"); - - if (username) - { - strcat(conninfo, " user='"); - strcat(conninfo, username); - strcat(conninfo, "'"); - } - if (password) - { - strcat(conninfo, " password='"); - strcat(conninfo, password); - strcat(conninfo, "'"); - } - if (host) - { - strcat(conninfo, " host='"); - strcat(conninfo, host); - strcat(conninfo, "'"); - } - if (port) - { - strcat(conninfo, " port='"); - strcat(conninfo, port); - strcat(conninfo, "'"); - } - - return conninfo; -} diff --git a/nominatim/postgresql.h b/nominatim/postgresql.h deleted file mode 100644 index f30e7308..00000000 --- a/nominatim/postgresql.h +++ /dev/null @@ -1,40 +0,0 @@ -/* -*/ - -#ifndef POSTGRESQL_H -#define POSTGRESQL_H - -#define PG_OID_INT8 20 -#define PG_OID_INT4 23 - -#if HAVE_BYTESWAP -#include -#define PG_BSWAP32(x) bswap_32(x) -#define PG_BSWAP64(x) bswap_64(x) -#elif HAVE_SYS_ENDIAN -#include -#define PG_BSWAP32(x) bswap32(x) -#define PG_BSWAP64(x) bswap64(x) -#else -#error "No appropriate byteswap found for your system." -#endif - -#if defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__) -#define PGint32(x) (x) -#define PGint64(x) (x) -#elif defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__) -#define PGint32(x) PG_BSWAP32(x) -#define PGint64(x) PG_BSWAP64(x) -#elif defined(_BYTE_ORDER) && (_BYTE_ORDER == _BIG_ENDIAN) -#define PGint32(x) (x) -#define PGint64(x) (x) -#elif defined(_BYTE_ORDER) && (_BYTE_ORDER == _LITTLE_ENDIAN) -#define PGint32(x) PG_BSWAP32(x) -#define PGint64(x) PG_BSWAP64(x) -#else -#error "Cannot determine byte order." -#endif - -const char *build_conninfo(const char *db, const char *username, const char *password, const char *host, const char *port); - -#endif diff --git a/nominatim/sprompt.c b/nominatim/sprompt.c deleted file mode 100644 index 7666be5e..00000000 --- a/nominatim/sprompt.c +++ /dev/null @@ -1,200 +0,0 @@ -/*------------------------------------------------------------------------- - * - * sprompt.c - * simple_prompt() routine - * - * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group - * Portions Copyright (c) 1994, Regents of the University of California - * - * - * IDENTIFICATION - * $PostgreSQL: pgsql/src/port/sprompt.c,v 1.18 2006/10/04 00:30:14 momjian Exp $ - * - *------------------------------------------------------------------------- - * - * PostgreSQL Database Management System - * (formerly known as Postgres, then as Postgres95) - * - * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group - * - * Portions Copyright (c) 1994, The Regents of the University of California - * - * Permission to use, copy, modify, and distribute this software and its - * documentation for any purpose, without fee, and without a written agreement - * is hereby granted, provided that the above copyright notice and this - * paragraph and the following two paragraphs appear in all copies. - * - * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR - * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING - * LOST PROFITS, ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS - * DOCUMENTATION, EVEN IF THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS - * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATIONS TO - * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. - * - */ - - -/* - * simple_prompt - * - * Generalized function especially intended for reading in usernames and - * password interactively. Reads from /dev/tty or stdin/stderr. - * - * prompt: The prompt to print - * maxlen: How many characters to accept - * echo: Set to false if you want to hide what is entered (for passwords) - * - * Returns a malloc()'ed string with the input (w/o trailing newline). - */ - -#define DEVTTY "/dev/tty" - -#include -#include -#include -#include -#include - -#include - -#ifdef __MINGW_H -# include -#else -# define HAVE_TERMIOS_H -# include -#endif - -/* -extern char *simple_prompt(const char *prompt, int maxlen, int echo); -*/ - -char * -simple_prompt(const char *prompt, int maxlen, int echo) -{ - int length; - char *destination; - FILE *termin, - *termout; - -#ifdef HAVE_TERMIOS_H - struct termios t_orig, - t; -#else -#ifdef WIN32 - HANDLE t = NULL; - LPDWORD t_orig = NULL; -#endif -#endif - - destination = (char *) malloc(maxlen + 1); - if (!destination) - return NULL; - - /* - * Do not try to collapse these into one "w+" mode file. Doesn't work on - * some platforms (eg, HPUX 10.20). - */ - termin = fopen(DEVTTY, "r"); - termout = fopen(DEVTTY, "w"); - if (!termin || !termout -#ifdef WIN32 - /* See DEVTTY comment for msys */ - || (getenv("OSTYPE") && strcmp(getenv("OSTYPE"), "msys") == 0) -#endif - ) -{ - if (termin) - fclose(termin); - if (termout) - fclose(termout); - termin = stdin; - termout = stderr; - } - -#ifdef HAVE_TERMIOS_H - if (!echo) - { - tcgetattr(fileno(termin), &t); - t_orig = t; - t.c_lflag &= ~ECHO; - tcsetattr(fileno(termin), TCSAFLUSH, &t); - } -#else -#ifdef WIN32 - if (!echo) - { - /* get a new handle to turn echo off */ - t_orig = (LPDWORD) malloc(sizeof(DWORD)); - t = GetStdHandle(STD_INPUT_HANDLE); - - /* save the old configuration first */ - GetConsoleMode(t, t_orig); - - /* set to the new mode */ - SetConsoleMode(t, ENABLE_LINE_INPUT | ENABLE_PROCESSED_INPUT); - } -#endif -#endif - - if (prompt) - { - fputs(prompt, termout); - fflush(termout); - } - - if (fgets(destination, maxlen + 1, termin) == NULL) - destination[0] = '\0'; - - length = strlen(destination); - if (length > 0 && destination[length - 1] != '\n') - { - /* eat rest of the line */ - char buf[128]; - int buflen; - - do - { - if (fgets(buf, sizeof(buf), termin) == NULL) - break; - buflen = strlen(buf); - } - while (buflen > 0 && buf[buflen - 1] != '\n'); - } - - if (length > 0 && destination[length - 1] == '\n') - /* remove trailing newline */ - destination[length - 1] = '\0'; - -#ifdef HAVE_TERMIOS_H - if (!echo) - { - tcsetattr(fileno(termin), TCSAFLUSH, &t_orig); - fputs("\n", termout); - fflush(termout); - } -#else -#ifdef WIN32 - if (!echo) - { - /* reset to the original console mode */ - SetConsoleMode(t, *t_orig); - fputs("\n", termout); - fflush(termout); - free(t_orig); - } -#endif -#endif - - if (termin != stdin) - { - fclose(termin); - fclose(termout); - } - - return destination; -} diff --git a/nominatim/sprompt.h b/nominatim/sprompt.h deleted file mode 100644 index 5e684929..00000000 --- a/nominatim/sprompt.h +++ /dev/null @@ -1,4 +0,0 @@ -#ifndef SPROMPT_H -#define SPROMPT_H -char *simple_prompt(const char *prompt, int maxlen, int echo); -#endif diff --git a/nominatim/voronoi/VoronoiDiagramGenerator.cpp b/nominatim/voronoi/VoronoiDiagramGenerator.cpp deleted file mode 100644 index 196b1a81..00000000 --- a/nominatim/voronoi/VoronoiDiagramGenerator.cpp +++ /dev/null @@ -1,1276 +0,0 @@ -/* -* The author of this software is Steven Fortune. Copyright (c) 1994 by AT&T -* Bell Laboratories. -* Permission to use, copy, modify, and distribute this software for any -* purpose without fee is hereby granted, provided that this entire notice -* is included in all copies of any software which is or includes a copy -* or modification of this software and in all copies of the supporting -* documentation for such software. -* THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED -* WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR AT&T MAKE ANY -* REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY -* OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE. -*/ - -/* -* This code was originally written by Stephan Fortune in C code. I, Shane O'Sullivan, -* have since modified it, encapsulating it in a C++ class and, fixing memory leaks and -* adding accessors to the Voronoi Edges. -* Permission to use, copy, modify, and distribute this software for any -* purpose without fee is hereby granted, provided that this entire notice -* is included in all copies of any software which is or includes a copy -* or modification of this software and in all copies of the supporting -* documentation for such software. -* THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED -* WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR AT&T MAKE ANY -* REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY -* OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE. -*/ - -#include "VoronoiDiagramGenerator.h" -#include -#include - -VoronoiDiagramGenerator::VoronoiDiagramGenerator() -{ - siteidx = 0; - sites = 0; - - allMemoryList = new FreeNodeArrayList; - allMemoryList->memory = 0; - allMemoryList->next = 0; - currentMemoryBlock = allMemoryList; - allEdges = 0; - iteratorEdges = 0; - minDistanceBetweenSites = 0; -} - -VoronoiDiagramGenerator::~VoronoiDiagramGenerator() -{ - cleanup(); - cleanupEdges(); - - if(allMemoryList != 0) - delete allMemoryList; -} - -bool VoronoiDiagramGenerator::generateVoronoi(struct SourcePoint* srcPoints, int numPoints, float minX, float maxX, float minY, float maxY, float minDist) -{ - cleanup(); - cleanupEdges(); - int i; - - minDistanceBetweenSites = minDist; - - nsites = numPoints; - plot = 0; - triangulate = 0; - debug = 1; - sorted = 0; - freeinit(&sfl, sizeof (Site)); - - sites = (struct Site *) myalloc(nsites * sizeof(*sites)); - polygons = (struct Polygon *) myalloc(nsites * sizeof(*polygons)); - - if(sites == 0) return false; - - xmin = srcPoints[0].x; - ymin = srcPoints[0].y; - xmax = srcPoints[0].x; - ymax = srcPoints[0].y; - - for(i = 0; i < nsites; i++) - { - sites[i].coord.x = srcPoints[i].x; - sites[i].coord.y = srcPoints[i].y; - sites[i].weight = srcPoints[i].weight; - sites[i].sitenbr = i; - sites[i].refcnt = 0; // prevent reuse? - - if(sites[i].coord.x < xmin) - xmin = sites[i].coord.x; - else if(sites[i].coord.x > xmax) - xmax = sites[i].coord.x; - - if(sites[i].coord.y < ymin) - ymin = sites[i].coord.y; - else if(sites[i].coord.y > ymax) - ymax = sites[i].coord.y; - - polygons[i].coord.x = sites[i].coord.x; - polygons[i].coord.y = sites[i].coord.y; - polygons[i].numpoints = 0; - polygons[i].pointlist = NULL; - polygons[i].boundary = 0; - - //printf("\n%lf %lf\n", sites[i].coord.x, sites[i].coord.y); - } - - qsort(sites, nsites, sizeof (*sites), scomp); - - siteidx = 0; - geominit(); - float temp = 0; - if(minX > maxX) - { - temp = minX; - minX = maxX; - maxX = temp; - } - if(minY > maxY) - { - temp = minY; - minY = maxY; - maxY = temp; - } - borderMinX = minX; - borderMinY = minY; - borderMaxX = maxX; - borderMaxY = maxY; - - corners[0].x = borderMinX; - corners[0].y = borderMinY; - corners[1].x = borderMinX; - corners[1].y = borderMaxY; - corners[2].x = borderMaxX; - corners[2].y = borderMaxY; - corners[3].x = borderMaxX; - corners[3].y = borderMinY; - - siteidx = 0; - voronoi(triangulate); - - return true; -} - -bool VoronoiDiagramGenerator::ELinitialize() -{ - int i; - freeinit(&hfl, sizeof **ELhash); - ELhashsize = 2 * sqrt_nsites; - ELhash = (struct Halfedge **) myalloc ( sizeof *ELhash * ELhashsize); - - if(ELhash == 0) - return false; - - for(i=0; i ELleft = (struct Halfedge *)NULL; - ELleftend -> ELright = ELrightend; - ELrightend -> ELleft = ELleftend; - ELrightend -> ELright = (struct Halfedge *)NULL; - ELhash[0] = ELleftend; - ELhash[ELhashsize-1] = ELrightend; - - return true; -} - - -struct Halfedge* VoronoiDiagramGenerator::HEcreate(struct Edge *e,int pm) -{ - struct Halfedge *answer; - answer = (struct Halfedge *) getfree(&hfl); - answer -> ELedge = e; - answer -> ELpm = pm; - answer -> PQnext = (struct Halfedge *) NULL; - answer -> vertex = (struct Site *) NULL; - answer -> ELrefcnt = 0; - return(answer); -} - - -void VoronoiDiagramGenerator::ELinsert(struct Halfedge *lb, struct Halfedge *newHe) -{ - newHe -> ELleft = lb; - newHe -> ELright = lb -> ELright; - (lb -> ELright) -> ELleft = newHe; - lb -> ELright = newHe; -} - -/* Get entry from hash table, pruning any deleted nodes */ -struct Halfedge * VoronoiDiagramGenerator::ELgethash(int b) -{ - struct Halfedge *he; - - if(b<0 || b>=ELhashsize) - return((struct Halfedge *) NULL); - he = ELhash[b]; - if (he == (struct Halfedge *) NULL || he->ELedge != (struct Edge *) DELETED ) - return (he); - - /* Hash table points to deleted half edge. Patch as necessary. */ - ELhash[b] = (struct Halfedge *) NULL; - if ((he -> ELrefcnt -= 1) == 0) - makefree((Freenode*)he, &hfl); - return ((struct Halfedge *) NULL); -} - -struct Halfedge * VoronoiDiagramGenerator::ELleftbnd(struct Point *p) -{ - int i, bucket; - struct Halfedge *he; - - /* Use hash table to get close to desired halfedge */ - bucket = (int)((p->x - xmin)/deltax * ELhashsize); //use the hash function to find the place in the hash map that this HalfEdge should be - - if(bucket<0) bucket =0; //make sure that the bucket position in within the range of the hash array - if(bucket>=ELhashsize) bucket = ELhashsize - 1; - - he = ELgethash(bucket); - if(he == (struct Halfedge *) NULL) //if the HE isn't found, search backwards and forwards in the hash map for the first non-null entry - { - for(i=1; 1 ; i += 1) - { - if ((he=ELgethash(bucket-i)) != (struct Halfedge *) NULL) - break; - if ((he=ELgethash(bucket+i)) != (struct Halfedge *) NULL) - break; - }; - totalsearch += i; - }; - ntry += 1; - /* Now search linear list of halfedges for the correct one */ - if (he==ELleftend || (he != ELrightend && right_of(he,p))) - { - do - { - he = he -> ELright; - } while (he!=ELrightend && right_of(he,p)); //keep going right on the list until either the end is reached, or you find the 1st edge which the point - he = he -> ELleft; //isn't to the right of - } - else //if the point is to the left of the HalfEdge, then search left for the HE just to the left of the point - do - { - he = he -> ELleft; - } while (he!=ELleftend && !right_of(he,p)); - - /* Update hash table and reference counts */ - if(bucket > 0 && bucket ELrefcnt -= 1; - } - ELhash[bucket] = he; - ELhash[bucket] -> ELrefcnt += 1; - }; - return (he); -} - - -/* This delete routine can't reclaim node, since pointers from hash -table may be present. */ -void VoronoiDiagramGenerator::ELdelete(struct Halfedge *he) -{ - (he -> ELleft) -> ELright = he -> ELright; - (he -> ELright) -> ELleft = he -> ELleft; - he -> ELedge = (struct Edge *)DELETED; -} - - -struct Halfedge * VoronoiDiagramGenerator::ELright(struct Halfedge *he) -{ - return (he -> ELright); -} - -struct Halfedge * VoronoiDiagramGenerator::ELleft(struct Halfedge *he) -{ - return (he -> ELleft); -} - - -struct Site * VoronoiDiagramGenerator::leftreg(struct Halfedge *he) -{ - if(he -> ELedge == (struct Edge *)NULL) - return(bottomsite); - return( he -> ELpm == le ? - he -> ELedge -> reg[le] : he -> ELedge -> reg[re]); -} - -struct Site * VoronoiDiagramGenerator::rightreg(struct Halfedge *he) -{ - if(he -> ELedge == (struct Edge *)NULL) //if this halfedge has no edge, return the bottom site (whatever that is) - return(bottomsite); - - //if the ELpm field is zero, return the site 0 that this edge bisects, otherwise return site number 1 - return( he -> ELpm == le ? he -> ELedge -> reg[re] : he -> ELedge -> reg[le]); -} - -void VoronoiDiagramGenerator::geominit() -{ - float sn; - - freeinit(&efl, sizeof(Edge)); - nvertices = 0; - nedges = 0; - sn = (float)nsites+4; - sqrt_nsites = (int)sqrt(sn); - deltay = ymax - ymin; - deltax = xmax - xmin; -} - - -struct Edge * VoronoiDiagramGenerator::bisect(struct Site *s1,struct Site *s2) -{ - float dx,dy,adx,ady; - struct Edge *newedge; - - newedge = (struct Edge *) getfree(&efl); - - newedge -> reg[0] = s1; //store the sites that this edge is bisecting - newedge -> reg[1] = s2; - ref(s1); - ref(s2); - newedge -> ep[0] = (struct Site *) NULL; //to begin with, there are no endpoints on the bisector - it goes to infinity - newedge -> ep[1] = (struct Site *) NULL; - - dx = s2->coord.x - s1->coord.x; //get the difference in x dist between the sites - dy = s2->coord.y - s1->coord.y; - adx = dx>0 ? dx : -dx; //make sure that the difference in positive - ady = dy>0 ? dy : -dy; - newedge -> c = (float)(s1->coord.x * dx + s1->coord.y * dy + (dx*dx + dy*dy)*0.5);//get the slope of the line - - if (adx>ady) - { - newedge -> a = 1.0; newedge -> b = dy/dx; newedge -> c /= dx;//set formula of line, with x fixed to 1 - } - else - { - newedge -> b = 1.0; newedge -> a = dx/dy; newedge -> c /= dy;//set formula of line, with y fixed to 1 - }; - - newedge -> edgenbr = nedges; - - //printf("\nbisect(%d) ((%f,%f) and (%f,%f)",nedges,s1->coord.x,s1->coord.y,s2->coord.x,s2->coord.y); - - nedges += 1; - return(newedge); -} - -//create a new site where the HalfEdges el1 and el2 intersect - note that the Point in the argument list is not used, don't know why it's there -struct Site * VoronoiDiagramGenerator::intersect(struct Halfedge *el1, struct Halfedge *el2, struct Point *p) -{ - struct Edge *e1,*e2, *e; - struct Halfedge *el; - float d, xint, yint; - int right_of_site; - struct Site *v; - - e1 = el1 -> ELedge; - e2 = el2 -> ELedge; - if(e1 == (struct Edge*)NULL || e2 == (struct Edge*)NULL) - return ((struct Site *) NULL); - - //if the two edges bisect the same parent, return null - if (e1->reg[1] == e2->reg[1]) - return ((struct Site *) NULL); - - d = e1->a * e2->b - e1->b * e2->a; - if (-1.0e-10c*e2->b - e2->c*e1->b)/d; - yint = (e2->c*e1->a - e1->c*e2->a)/d; - - if( (e1->reg[1]->coord.y < e2->reg[1]->coord.y) || - (e1->reg[1]->coord.y == e2->reg[1]->coord.y && - e1->reg[1]->coord.x < e2->reg[1]->coord.x) ) - { - el = el1; - e = e1; - } - else - { - el = el2; - e = e2; - }; - - right_of_site = xint >= e -> reg[1] -> coord.x; - if ((right_of_site && el -> ELpm == le) || (!right_of_site && el -> ELpm == re)) - return ((struct Site *) NULL); - - //create a new site at the point of intersection - this is a new vector event waiting to happen - v = (struct Site *) getfree(&sfl); - v -> refcnt = 0; - v -> coord.x = xint; - v -> coord.y = yint; - return(v); -} - -/* returns 1 if p is to right of halfedge e */ -int VoronoiDiagramGenerator::right_of(struct Halfedge *el,struct Point *p) -{ - struct Edge *e; - struct Site *topsite; - int right_of_site, above, fast; - float dxp, dyp, dxs, t1, t2, t3, yl; - - e = el -> ELedge; - topsite = e -> reg[1]; - right_of_site = p -> x > topsite -> coord.x; - if(right_of_site && el -> ELpm == le) return(1); - if(!right_of_site && el -> ELpm == re) return (0); - if (e->a == 1.0) - { - dyp = p->y - topsite->coord.y; - dxp = p->x - topsite->coord.x; - fast = 0; - if ((!right_of_site & (e->b<0.0)) | (right_of_site & (e->b>=0.0)) ) - { - above = dyp>= e->b*dxp; - fast = above; - } - else - { - above = p->x + p->y*e->b > e-> c; - if(e->b<0.0) above = !above; - if (!above) fast = 1; - } - - if (!fast) - { - dxs = topsite->coord.x - (e->reg[0])->coord.x; - above = e->b * (dxp*dxp - dyp*dyp) < - dxs*dyp*(1.0+2.0*dxp/dxs + e->b*e->b); - if(e->b<0.0) above = !above; - } - } - else /*e->b==1.0 */ - { - yl = e->c - e->a*p->x; - t1 = p->y - yl; - t2 = p->x - topsite->coord.x; - t3 = yl - topsite->coord.y; - above = t1*t1 > t2*t2 + t3*t3; - } - return (el->ELpm==le ? above : !above); -} - - -void VoronoiDiagramGenerator::endpoint(struct Edge *e,int lr,struct Site * s) -{ - e -> ep[lr] = s; - ref(s); - return; - - if(e -> ep[re-lr]== (struct Site *) NULL) - return; - - clip_line(e); - - deref(e->reg[le]); - deref(e->reg[re]); - makefree((Freenode*)e, &efl); -} - -void VoronoiDiagramGenerator::endpoint(struct Edge *e1,int lr,struct Site * s, struct Edge *e2, struct Edge *e3) -{ - e1 -> ep[lr] = s; - ref(s); - - s->coordout.x = s->coord.x; - s->coordout.y = s->coord.y; - - if(e1 -> ep[le] != (struct Site *) NULL && e1 -> ep[re] != (struct Site *) NULL) - { - clip_line(e1); - deref(e1->reg[le]); - deref(e1->reg[re]); - makefree((Freenode*)e1, &efl); - } - - if(e2 -> ep[le] != (struct Site *) NULL && e2 -> ep[re] != (struct Site *) NULL) - { - clip_line(e2); - deref(e2->reg[le]); - deref(e2->reg[re]); - makefree((Freenode*)e2, &efl); - } - - if(e3 -> ep[le] != (struct Site *) NULL && e3 -> ep[re] != (struct Site *) NULL) - { - clip_line(e3); - deref(e3->reg[le]); - deref(e3->reg[re]); - makefree((Freenode*)e3, &efl); - } - - return; -} - - -float VoronoiDiagramGenerator::dist(struct Site *s,struct Site *t) -{ - float dx,dy; - dx = s->coord.x - t->coord.x; - dy = s->coord.y - t->coord.y; - return (float)(sqrt(dx*dx + dy*dy)); -} - - -void VoronoiDiagramGenerator::makevertex(struct Site *v) -{ - v -> sitenbr = nvertices; - nvertices += 1; - out_vertex(v); -} - - -void VoronoiDiagramGenerator::deref(struct Site *v) -{ - v -> refcnt -= 1; - if (v -> refcnt == 0 ) - makefree((Freenode*)v, &sfl); -} - -void VoronoiDiagramGenerator::ref(struct Site *v) -{ - v -> refcnt += 1; -} - -//push the HalfEdge into the ordered linked list of vertices -void VoronoiDiagramGenerator::PQinsert(struct Halfedge *he,struct Site * v, float offset) -{ - struct Halfedge *last, *next; - - he -> vertex = v; - ref(v); - he -> ystar = (float)(v -> coord.y + offset); - last = &PQhash[PQbucket(he)]; - while ((next = last -> PQnext) != (struct Halfedge *) NULL && - (he -> ystar > next -> ystar || - (he -> ystar == next -> ystar && v -> coord.x > next->vertex->coord.x))) - { - last = next; - } - he -> PQnext = last -> PQnext; - last -> PQnext = he; - PQcount += 1; -} - -//remove the HalfEdge from the list of vertices -void VoronoiDiagramGenerator::PQdelete(struct Halfedge *he) -{ - struct Halfedge *last; - - if(he -> vertex != (struct Site *) NULL) - { - last = &PQhash[PQbucket(he)]; - while (last -> PQnext != he) - last = last -> PQnext; - - last -> PQnext = he -> PQnext; - PQcount -= 1; - deref(he -> vertex); - he -> vertex = (struct Site *) NULL; - }; -} - -int VoronoiDiagramGenerator::PQbucket(struct Halfedge *he) -{ - int bucket; - - bucket = (int)((he->ystar - ymin)/deltay * PQhashsize); - if (bucket<0) bucket = 0; - if (bucket>=PQhashsize) bucket = PQhashsize-1 ; - if (bucket < PQmin) PQmin = bucket; - return(bucket); -} - -int VoronoiDiagramGenerator::PQempty() -{ - return(PQcount==0); -} - - -struct Point VoronoiDiagramGenerator::PQ_min() -{ - struct Point answer; - - while(PQhash[PQmin].PQnext == (struct Halfedge *)NULL) {PQmin += 1;}; - answer.x = PQhash[PQmin].PQnext -> vertex -> coord.x; - answer.y = PQhash[PQmin].PQnext -> ystar; - return (answer); -} - -struct Halfedge * VoronoiDiagramGenerator::PQextractmin() -{ - struct Halfedge *curr; - - curr = PQhash[PQmin].PQnext; - PQhash[PQmin].PQnext = curr -> PQnext; - PQcount -= 1; - return(curr); -} - - -bool VoronoiDiagramGenerator::PQinitialize() -{ - int i; - - PQcount = 0; - PQmin = 0; - PQhashsize = 4 * sqrt_nsites; - PQhash = (struct Halfedge *) myalloc(PQhashsize * sizeof *PQhash); - - if(PQhash == 0) - return false; - - for(i=0; i head = (struct Freenode *) NULL; - fl -> nodesize = size; -} - -char * VoronoiDiagramGenerator::getfree(struct Freelist *fl) -{ - int i; - struct Freenode *t; - - if(fl->head == (struct Freenode *) NULL) - { - t = (struct Freenode *) myalloc(sqrt_nsites * fl->nodesize); - - if(t == 0) - return 0; - - currentMemoryBlock->next = new FreeNodeArrayList; - currentMemoryBlock = currentMemoryBlock->next; - currentMemoryBlock->memory = t; - currentMemoryBlock->next = 0; - - for(i=0; inodesize), fl); - }; - t = fl -> head; - fl -> head = (fl -> head) -> nextfree; - return((char *)t); -} - - - -void VoronoiDiagramGenerator::makefree(struct Freenode *curr,struct Freelist *fl) -{ - curr -> nextfree = fl -> head; - fl -> head = curr; -} - -void VoronoiDiagramGenerator::cleanup() -{ - if(sites != 0) - { - free(sites); - sites = 0; - } - - FreeNodeArrayList* current=0, *prev = 0; - - current = prev = allMemoryList; - - while(current->next != 0) - { - prev = current; - current = current->next; - free(prev->memory); - delete prev; - prev = 0; - } - - if(current != 0 && current->memory != 0) - { - free(current->memory); - delete current; - } - - allMemoryList = new FreeNodeArrayList; - allMemoryList->next = 0; - allMemoryList->memory = 0; - currentMemoryBlock = allMemoryList; -} - -void VoronoiDiagramGenerator::cleanupEdges() -{ - GraphEdge* geCurrent = 0, *gePrev = 0; - geCurrent = gePrev = allEdges; - - while(geCurrent != 0 && geCurrent->next != 0) - { - gePrev = geCurrent; - geCurrent = geCurrent->next; - delete gePrev; - } - - allEdges = 0; - -} - -void VoronoiDiagramGenerator::pushGraphEdge(float x1, float y1, float x2, float y2) -{ - GraphEdge* newEdge = new GraphEdge; - newEdge->next = allEdges; - allEdges = newEdge; - newEdge->x1 = x1; - newEdge->y1 = y1; - newEdge->x2 = x2; - newEdge->y2 = y2; -} - - -char * VoronoiDiagramGenerator::myalloc(unsigned n) -{ - char *t=0; - t=(char*)malloc(n); - total_alloc += n; - return(t); -} - - -/* for those who don't have Cherry's plot */ -/* #include */ -void VoronoiDiagramGenerator::openpl(){} -void VoronoiDiagramGenerator::line(float x1, float y1, float x2, float y2) -{ - pushGraphEdge(x1,y1,x2,y2); - -} -void VoronoiDiagramGenerator::circle(float x, float y, float radius){} -void VoronoiDiagramGenerator::range(float minX, float minY, float maxX, float maxY){} - - - -void VoronoiDiagramGenerator::out_bisector(struct Edge *e) -{ - -} - - -void VoronoiDiagramGenerator::out_ep(struct Edge *e) -{ - -} - -void VoronoiDiagramGenerator::out_vertex(struct Site *v) -{ - -} - - -void VoronoiDiagramGenerator::out_site(struct Site *s) -{ - if(!triangulate & plot & !debug) - circle (s->coord.x, s->coord.y, cradius); -} - - -void VoronoiDiagramGenerator::out_triple(struct Site *s1, struct Site *s2,struct Site * s3) -{ - -} - - - -void VoronoiDiagramGenerator::plotinit() -{ - float dx,dy,d; - - dy = ymax - ymin; - dx = xmax - xmin; - d = (float)(( dx > dy ? dx : dy) * 1.1); - pxmin = (float)(xmin - (d-dx)/2.0); - pxmax = (float)(xmax + (d-dx)/2.0); - pymin = (float)(ymin - (d-dy)/2.0); - pymax = (float)(ymax + (d-dy)/2.0); - cradius = (float)((pxmax - pxmin)/350.0); - openpl(); - range(pxmin, pymin, pxmax, pymax); -} - -void VoronoiDiagramGenerator::pushpoint(int sitenbr, double x, double y, int boundary) -{ - Polygon *s; - - s = &polygons[sitenbr]; - - if (s->numpoints == 0) - { - s->pointlist = (PolygonPoint *)malloc(sizeof(struct PolygonPoint)*(s->numpoints+10)); - if (!s->pointlist) - { - printf("Out of mem\n"); - } - } - else if (s->numpoints % 10 == 0) - { - s->pointlist = (PolygonPoint *)realloc(s->pointlist, sizeof(struct PolygonPoint)*(s->numpoints+10)); - if (!s->pointlist) - { - printf("Out of remem\n"); - } - } - s->pointlist[s->numpoints].coord.x = x; - s->pointlist[s->numpoints].coord.y = y; - s->pointlist[s->numpoints].angle = atan2f(x-s->coord.x, y-s->coord.y); - s->pointlist[s->numpoints].boundary = boundary; - - if (boundary) s->boundary = 1; - - //printf("point #%d in %d (%lf, %lf) [%d] (%lf, %lf): %lf\n", s->numpoints, sitenbr, s->coord.x, s->coord.y, boundary, x, y, (s->pointlist[s->numpoints].angle/M_PI)*180); - - s->numpoints++; -} - -int VoronoiDiagramGenerator::ccw( Point p0, Point p1, Point p2 ) -{ - double dx1, dx2, dy1, dy2; - - dx1 = p1.x - p0.x; dy1 = p1.y - p0.y; - dx2 = p2.x - p0.x; dy2 = p2.y - p0.y; - - if (dx1*dy2 > dy1*dx2) - return +1; - if (dx1*dy2 < dy1*dx2) - return -1; - if ((dx1*dx2 < 0) || (dy1*dy2 < 0)) - return -1; - if ((dx1*dx1 + dy1*dy1) < (dx2*dx2 + dy2*dy2)) - return +1; - return 0; -} - -void VoronoiDiagramGenerator::getSitePoints(int sitenbr, int* numpoints, PolygonPoint** pS) -{ - int i, j, c, any, centrevalue, cornerinpolygon[4]; - - if (polygons[sitenbr].numpoints == 0) - { - for(c = 0; c < 4; c++) - { - pushpoint(sitenbr, corners[c].x, corners[c].y, 0); - } - } - - qsort(polygons[sitenbr].pointlist, polygons[sitenbr].numpoints, sizeof(PolygonPoint), anglecomp); - - if (polygons[sitenbr].boundary) - { -// printf("\nsite %d is boundary intersection\n", sitenbr); - - for(c = 0; c < 4; c++) cornerinpolygon[c] = 1; - - for(i = 0; i < polygons[sitenbr].numpoints; i++) - { -// printf("Point (%lf,%lf) %d\n", polygons[sitenbr].pointlist[i].coord.x,polygons[sitenbr].pointlist[i].coord.y,polygons[sitenbr].pointlist[i].boundary); - j = i > 0?i-1:polygons[sitenbr].numpoints-1; - if ( (!polygons[sitenbr].pointlist[i].boundary || !polygons[sitenbr].pointlist[j].boundary) && - (polygons[sitenbr].pointlist[i].coord.x != polygons[sitenbr].pointlist[j].coord.x || - polygons[sitenbr].pointlist[i].coord.y != polygons[sitenbr].pointlist[j].coord.y)) - { -// printf("line side test (%lf,%lf) => (%lf,%lf)\n",polygons[sitenbr].pointlist[i].coord.x,polygons[sitenbr].pointlist[i].coord.y,polygons[sitenbr].pointlist[j].coord.x,polygons[sitenbr].pointlist[j].coord.y); - any = 0; - centrevalue = ccw(polygons[sitenbr].pointlist[i].coord, polygons[sitenbr].pointlist[j].coord, polygons[sitenbr].coord); -//printf(" test against centre (%lf,%lf) %d\n", polygons[sitenbr].coord.x, polygons[sitenbr].coord.y, centrevalue); - for(c = 0; c < 4; c++) - { - if (cornerinpolygon[c]) - { - -//printf(" test against corner (%lf,%lf) %d\n", corners[c].x, corners[c].y, ccw(polygons[sitenbr].pointlist[i].coord, polygons[sitenbr].pointlist[j].coord, corners[c])); - - if (centrevalue == ccw(polygons[sitenbr].pointlist[i].coord, polygons[sitenbr].pointlist[j].coord, corners[c])) - { - any = 1; - } - else - { - cornerinpolygon[c] = 0; - } - } - } - if (!any) break; - } - } - if (any) - { - for(c = 0; c < 4; c++) - { - if (cornerinpolygon[c]) - { -// printf("adding corger (%lf,%lf) to %d\n", corners[c].x, corners[c].y, sitenbr); - pushpoint(sitenbr, corners[c].x, corners[c].y, 0); - } - } - } - qsort(polygons[sitenbr].pointlist, polygons[sitenbr].numpoints, sizeof(PolygonPoint), anglecomp); - - polygons[sitenbr].boundary = 0; - } - - *numpoints = polygons[sitenbr].numpoints; - *pS = polygons[sitenbr].pointlist; -} - - -void VoronoiDiagramGenerator::clip_line(struct Edge *e) -{ - struct Site *s1, *s2, *ts1, *ts2; - float x1=0,x2=0,y1=0,y2=0, temp = 0; - int boundary1 = 0, boundary2 = 0; - - - x1 = e->reg[0]->coord.x; - x2 = e->reg[1]->coord.x; - y1 = e->reg[0]->coord.y; - y2 = e->reg[1]->coord.y; - - if(sqrt(((x2 - x1) * (x2 - x1)) + ((y2 - y1) * (y2 - y1))) == 0) - { - return; - } - - pxmin = borderMinX; - pxmax = borderMaxX; - pymin = borderMinY; - pymax = borderMaxY; - - if(e -> a == 1.0 && e ->b >= 0.0) - { - s1 = e -> ep[1]; - s2 = e -> ep[0]; - - ts1 = e -> reg[1]; - ts2 = e -> reg[0]; - } - else - { - s1 = e -> ep[0]; - s2 = e -> ep[1]; - - ts1 = e -> reg[0]; - ts2 = e -> reg[1]; - - }; - - if(e -> a == 1.0) - { - if ( s1!=(struct Site *)NULL - && s1->coordout.y > pymin && s1->coordout.y < pymax - && s1->coordout.x > pxmin && s1->coordout.x < pxmax) - { - x1 = s1->coordout.x; - y1 = s1->coordout.y; - } - else - { - boundary1 = 1; - y1 = pymin; - if (s1!=(struct Site *)NULL && s1->coord.y > pymin) - { - y1 = s1->coord.y; - } - if(y1>pymax) - { - y1 = pymax; - } - x1 = e -> c - e -> b * y1; - } - - if ( s2!=(struct Site *)NULL - && s2->coordout.y > pymin && s2->coordout.y < pymax - && s2->coordout.x > pxmin && s2->coordout.x < pxmax) - { - x2 = s2->coordout.x; - y2 = s2->coordout.y; - } - else - { - boundary2 = 1; - y2 = pymax; - if (s2!=(struct Site *)NULL && s2->coord.y < pymax) - y2 = s2->coord.y; - if(y2c) - (e->b) * y2; - } - - if (((x1> pxmax) & (x2>pxmax)) | ((x1 pxmax) - { - x1 = pxmax; - y1 = (e -> c - x1)/e -> b; - } - if(x1 < pxmin) - { - x1 = pxmin; - y1 = (e -> c - x1)/e -> b; - } - if(x2 > pxmax) - { - x2 = pxmax; - y2 = (e -> c - x2)/e -> b; - } - if(x2 < pxmin) - { - x2 = pxmin; - y2 = (e -> c - x2)/e -> b; - } - } - else - { - if ( s1!=(struct Site *)NULL - && s1->coordout.y > pymin && s1->coordout.y < pymax - && s1->coordout.x > pxmin && s1->coordout.x < pxmax) - { - x1 = s1->coordout.x; - y1 = s1->coordout.y; - } - else - { - boundary1 = 1; - x1 = pxmin; - if (s1!=(struct Site *)NULL && s1->coord.x > pxmin) - x1 = s1->coord.x; - if(x1>pxmax) - { - //printf("\nClipped (3) x1 = %f to %f",x1,pxmin); - //return; - x1 = pxmax; - } - y1 = e -> c - e -> a * x1; - } - - if ( s2!=(struct Site *)NULL - && s2->coordout.y > pymin && s2->coordout.y < pymax - && s2->coordout.x > pxmin && s2->coordout.x < pxmax) - { - x2 = s2->coordout.x; - y2 = s2->coordout.y; - } - else - { - boundary2 = 1; - x2 = pxmax; - if (s2!=(struct Site *)NULL && s2->coord.x < pxmax) - x2 = s2->coord.x; - if(x2 c - e -> a * x2; - } - - if (((y1> pymax) & (y2>pymax)) | ((y1 pymax) - { y1 = pymax; x1 = (e -> c - y1)/e -> a;}; - if(y1 < pymin) - { y1 = pymin; x1 = (e -> c - y1)/e -> a;}; - if(y2 > pymax) - { y2 = pymax; x2 = (e -> c - y2)/e -> a;}; - if(y2 < pymin) - { y2 = pymin; x2 = (e -> c - y2)/e -> a;}; - }; - - if(sqrt(((x2 - x1) * (x2 - x1)) + ((y2 - y1) * (y2 - y1))) == 0) - { - return; - } - - pushpoint(ts1->sitenbr, x1, y1, boundary1); - pushpoint(ts2->sitenbr, x2, y2, boundary2); - pushpoint(ts1->sitenbr, x2, y2, boundary2); - pushpoint(ts2->sitenbr, x1, y1, boundary1); -} - - -/* implicit parameters: nsites, sqrt_nsites, xmin, xmax, ymin, ymax, -deltax, deltay (can all be estimates). -Performance suffers if they are wrong; better to make nsites, -deltax, and deltay too big than too small. (?) */ - -bool VoronoiDiagramGenerator::voronoi(int triangulate) -{ - struct Site *newsite, *bot, *top, *temp, *p; - struct Site *v; - struct Point newintstar; - int pm; - struct Halfedge *lbnd, *rbnd, *llbnd, *rrbnd, *bisector; - struct Edge *e, *e2, *e3; - - PQinitialize(); - bottomsite = nextone(); - out_site(bottomsite); - bool retval = ELinitialize(); - - if(!retval) - return false; - - newsite = nextone(); - while(1) - { - - if(!PQempty()) - newintstar = PQ_min(); - - //if the lowest site has a smaller y value than the lowest vector intersection, process the site - //otherwise process the vector intersection - - if (newsite != (struct Site *)NULL && (PQempty() || newsite -> coord.y < newintstar.y - || (newsite->coord.y == newintstar.y && newsite->coord.x < newintstar.x))) - {/* new site is smallest - this is a site event*/ - out_site(newsite); //output the site - lbnd = ELleftbnd(&(newsite->coord)); //get the first HalfEdge to the LEFT of the new site - rbnd = ELright(lbnd); //get the first HalfEdge to the RIGHT of the new site - bot = rightreg(lbnd); //if this halfedge has no edge, , bot = bottom site (whatever that is) - e = bisect(bot, newsite); //create a new edge that bisects - bisector = HEcreate(e, le); //create a new HalfEdge, setting its ELpm field to 0 - ELinsert(lbnd, bisector); //insert this new bisector edge between the left and right vectors in a linked list - - if ((p = intersect(lbnd, bisector)) != (struct Site *) NULL) //if the new bisector intersects with the left edge, remove the left edge's vertex, and put in the new one - { - PQdelete(lbnd); - PQinsert(lbnd, p, dist(p,newsite)); - }; - lbnd = bisector; - bisector = HEcreate(e, re); //create a new HalfEdge, setting its ELpm field to 1 - ELinsert(lbnd, bisector); //insert the new HE to the right of the original bisector earlier in the IF stmt - - if ((p = intersect(bisector, rbnd)) != (struct Site *) NULL) //if this new bisector intersects with the - { - PQinsert(bisector, p, dist(p,newsite)); //push the HE into the ordered linked list of vertices - }; - newsite = nextone(); - } - else if (!PQempty()) /* intersection is smallest - this is a vector event */ - { - lbnd = PQextractmin(); //pop the HalfEdge with the lowest vector off the ordered list of vectors - llbnd = ELleft(lbnd); //get the HalfEdge to the left of the above HE - rbnd = ELright(lbnd); //get the HalfEdge to the right of the above HE - rrbnd = ELright(rbnd); //get the HalfEdge to the right of the HE to the right of the lowest HE - bot = leftreg(lbnd); //get the Site to the left of the left HE which it bisects - top = rightreg(rbnd); //get the Site to the right of the right HE which it bisects - - out_triple(bot, top, rightreg(lbnd)); //output the triple of sites, stating that a circle goes through them - - v = lbnd->vertex; //get the vertex that caused this event - makevertex(v); //set the vertex number - couldn't do this earlier since we didn't know when it would be processed - e2 = lbnd->ELedge; - e3 = rbnd->ELedge; - endpoint(lbnd->ELedge,lbnd->ELpm,v); //set the endpoint of the left HalfEdge to be this vector - endpoint(rbnd->ELedge,rbnd->ELpm,v); //set the endpoint of the right HalfEdge to be this vector - ELdelete(lbnd); //mark the lowest HE for deletion - can't delete yet because there might be pointers to it in Hash Map - PQdelete(rbnd); //remove all vertex events to do with the right HE - ELdelete(rbnd); //mark the right HE for deletion - can't delete yet because there might be pointers to it in Hash Map - pm = le; //set the pm variable to zero - - if (bot->coord.y > top->coord.y) //if the site to the left of the event is higher than the Site - { //to the right of it, then swap them and set the 'pm' variable to 1 - temp = bot; - bot = top; - top = temp; - pm = re; - } - e = bisect(bot, top); //create an Edge (or line) that is between the two Sites. This creates - //the formula of the line, and assigns a line number to it - bisector = HEcreate(e, pm); //create a HE from the Edge 'e', and make it point to that edge with its ELedge field - ELinsert(llbnd, bisector); //insert the new bisector to the right of the left HE - endpoint(e, re-pm, v, e2, e3); //set one endpoint to the new edge to be the vector point 'v'. - //If the site to the left of this bisector is higher than the right - //Site, then this endpoint is put in position 0; otherwise in pos 1 - deref(v); //delete the vector 'v' - - //if left HE and the new bisector don't intersect, then delete the left HE, and reinsert it - if((p = intersect(llbnd, bisector)) != (struct Site *) NULL) - { - PQdelete(llbnd); - PQinsert(llbnd, p, dist(p,bot)); - }; - - //if right HE and the new bisector don't intersect, then reinsert it - if ((p = intersect(bisector, rrbnd)) != (struct Site *) NULL) - { - PQinsert(bisector, p, dist(p,bot)); - }; - } - else break; - }; - - for(lbnd=ELright(ELleftend); lbnd != ELrightend; lbnd=ELright(lbnd)) - { - e = lbnd -> ELedge; - - clip_line(e); - }; - - cleanup(); - - return true; -} - - -int scomp(const void *p1,const void *p2) -{ - struct Point *s1 = (Point*)p1, *s2=(Point*)p2; - if(s1 -> y < s2 -> y) return(-1); - if(s1 -> y > s2 -> y) return(1); - if(s1 -> x < s2 -> x) return(-1); - if(s1 -> x > s2 -> x) return(1); - return(0); -} - -int spcomp(const void *p1,const void *p2) -{ - struct SourcePoint *s1 = (SourcePoint*)p1, *s2=(SourcePoint*)p2; - if(s1 -> y < s2 -> y) return(-1); - if(s1 -> y > s2 -> y) return(1); - if(s1 -> x < s2 -> x) return(-1); - if(s1 -> x > s2 -> x) return(1); - return(0); -} - -int anglecomp(const void * p1, const void * p2) -{ - PolygonPoint * s1 = (PolygonPoint *)p1 ; - PolygonPoint * s2 = (PolygonPoint *)p2 ; - - if (s1->angle < s2->angle) { - return (-1) ; - } - if (s1->angle > s2->angle) { - return (1) ; - } - return (0) ; -} - -/* return a single in-storage site */ -struct Site * VoronoiDiagramGenerator::nextone() -{ - struct Site *s; - if(siteidx < nsites) - { - s = &sites[siteidx]; - siteidx += 1; - return(s); - } - else - return( (struct Site *)NULL); -} - diff --git a/nominatim/voronoi/VoronoiDiagramGenerator.h b/nominatim/voronoi/VoronoiDiagramGenerator.h deleted file mode 100644 index 2e1aefe1..00000000 --- a/nominatim/voronoi/VoronoiDiagramGenerator.h +++ /dev/null @@ -1,281 +0,0 @@ -/* -* The author of this software is Steven Fortune. Copyright (c) 1994 by AT&T -* Bell Laboratories. -* Permission to use, copy, modify, and distribute this software for any -* purpose without fee is hereby granted, provided that this entire notice -* is included in all copies of any software which is or includes a copy -* or modification of this software and in all copies of the supporting -* documentation for such software. -* THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED -* WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR AT&T MAKE ANY -* REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY -* OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE. -*/ - -/* -* This code was originally written by Stephan Fortune in C code. I, Shane O'Sullivan, -* have since modified it, encapsulating it in a C++ class and, fixing memory leaks and -* adding accessors to the Voronoi Edges. -* Permission to use, copy, modify, and distribute this software for any -* purpose without fee is hereby granted, provided that this entire notice -* is included in all copies of any software which is or includes a copy -* or modification of this software and in all copies of the supporting -* documentation for such software. -* THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED -* WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR AT&T MAKE ANY -* REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY -* OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE. -*/ - -#ifndef VORONOI_DIAGRAM_GENERATOR -#define VORONOI_DIAGRAM_GENERATOR - -#include -#include -#include - - -#ifndef NULL -#define NULL 0 -#endif -#define DELETED -2 - -#define le 0 -#define re 1 - -struct SourcePoint -{ - int id; - double weight; - double x; - double y; -}; - -struct Freenode -{ - struct Freenode *nextfree; -}; - -struct FreeNodeArrayList -{ - struct Freenode* memory; - struct FreeNodeArrayList* next; - -}; - -struct Freelist -{ - struct Freenode *head; - int nodesize; -}; - -struct Point -{ - float x,y; -}; - -struct PolygonPoint -{ - struct Point coord; - double angle; - int boundary; -}; - -struct Polygon -{ - int sitenbr; - struct Point coord; - int numpoints; - struct PolygonPoint * pointlist; - int boundary; -}; - - -// structure used both for sites and for vertices -struct Site -{ - struct Point coord; - struct Point coordout; - double weight; - int sitenbr; - int refcnt; -}; - - - -struct Edge -{ - float a,b,c; - struct Site *ep[2]; - struct Site *reg[2]; - int edgenbr; - -}; - -struct GraphEdge -{ - float x1,y1,x2,y2; - struct GraphEdge* next; -}; - - - - -struct Halfedge -{ - struct Halfedge *ELleft, *ELright; - struct Edge *ELedge; - int ELrefcnt; - char ELpm; - struct Site *vertex; - float ystar; - struct Halfedge *PQnext; -}; - - - - -class VoronoiDiagramGenerator -{ -public: - VoronoiDiagramGenerator(); - ~VoronoiDiagramGenerator(); - - bool generateVoronoi(struct SourcePoint* srcPoints, int numPoints, float minX, float maxX, float minY, float maxY, float minDist=0); - void getSitePoints(int sitenbr, int* numpoints, PolygonPoint** pS); - - void resetIterator() - { - iteratorEdges = allEdges; - } - - bool getNext(float& x1, float& y1, float& x2, float& y2) - { - if(iteratorEdges == 0) - return false; - - x1 = iteratorEdges->x1; - x2 = iteratorEdges->x2; - y1 = iteratorEdges->y1; - y2 = iteratorEdges->y2; - - iteratorEdges = iteratorEdges->next; - - return true; - } - - -private: - void cleanup(); - void cleanupEdges(); - char *getfree(struct Freelist *fl); - struct Halfedge *PQfind(); - int PQempty(); - - - - struct Halfedge **ELhash; - struct Halfedge *HEcreate(), *ELleft(), *ELright(), *ELleftbnd(); - struct Halfedge *HEcreate(struct Edge *e,int pm); - - - struct Point PQ_min(); - struct Halfedge *PQextractmin(); - void freeinit(struct Freelist *fl,int size); - void makefree(struct Freenode *curr,struct Freelist *fl); - void geominit(); - void plotinit(); - bool voronoi(int triangulate); - void ref(struct Site *v); - void deref(struct Site *v); - void endpoint(struct Edge *e,int lr,struct Site * s); - void endpoint(struct Edge *e1,int lr,struct Site * s, struct Edge *e2, struct Edge *e3); - - void ELdelete(struct Halfedge *he); - struct Halfedge *ELleftbnd(struct Point *p); - struct Halfedge *ELright(struct Halfedge *he); - void makevertex(struct Site *v); - void out_triple(struct Site *s1, struct Site *s2,struct Site * s3); - - void PQinsert(struct Halfedge *he,struct Site * v, float offset); - void PQdelete(struct Halfedge *he); - bool ELinitialize(); - void ELinsert(struct Halfedge *lb, struct Halfedge *newHe); - struct Halfedge * ELgethash(int b); - struct Halfedge *ELleft(struct Halfedge *he); - struct Site *leftreg(struct Halfedge *he); - void out_site(struct Site *s); - bool PQinitialize(); - int PQbucket(struct Halfedge *he); - void pushpoint(int sitenbr, double x, double y, int boundary); - int ccw( Point p0, Point p1, Point p2 ); - void clip_line(struct Edge *e); - char *myalloc(unsigned n); - int right_of(struct Halfedge *el,struct Point *p); - - struct Site *rightreg(struct Halfedge *he); - struct Edge *bisect(struct Site *s1,struct Site *s2); - float dist(struct Site *s,struct Site *t); - struct Site *intersect(struct Halfedge *el1, struct Halfedge *el2, struct Point *p=0); - - void out_bisector(struct Edge *e); - void out_ep(struct Edge *e); - void out_vertex(struct Site *v); - struct Site *nextone(); - - void pushGraphEdge(float x1, float y1, float x2, float y2); - - void openpl(); - void line(float x1, float y1, float x2, float y2); - void circle(float x, float y, float radius); - void range(float minX, float minY, float maxX, float maxY); - - - struct Freelist hfl; - struct Halfedge *ELleftend, *ELrightend; - int ELhashsize; - - int triangulate, sorted, plot, debug; - float xmin, xmax, ymin, ymax, deltax, deltay; - - struct Site *sites; - struct Polygon *polygons; - struct Point corners[4]; - int nsites; - int siteidx; - int sqrt_nsites; - int nvertices; - struct Freelist sfl; - struct Site *bottomsite; - - int nedges; - struct Freelist efl; - int PQhashsize; - struct Halfedge *PQhash; - int PQcount; - int PQmin; - - int ntry, totalsearch; - float pxmin, pxmax, pymin, pymax, cradius; - int total_alloc; - - float borderMinX, borderMaxX, borderMinY, borderMaxY; - - FreeNodeArrayList* allMemoryList; - FreeNodeArrayList* currentMemoryBlock; - - GraphEdge* allEdges; - GraphEdge* iteratorEdges; - - float minDistanceBetweenSites; - -}; - -int scomp(const void *p1,const void *p2); -int spcomp(const void *p1,const void *p2); -int anglecomp(const void * p1, const void * p2); - - -#endif - - diff --git a/nominatim/voronoi/voronoi_main.cpp b/nominatim/voronoi/voronoi_main.cpp deleted file mode 100644 index e55a1170..00000000 --- a/nominatim/voronoi/voronoi_main.cpp +++ /dev/null @@ -1,86 +0,0 @@ -/* -* The author of this software is Shane O'Sullivan. -* Permission to use, copy, modify, and distribute this software for any -* purpose without fee is hereby granted, provided that this entire notice -* is included in all copies of any software which is or includes a copy -* or modification of this software and in all copies of the supporting -* documentation for such software. -* THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED -* WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR AT&T MAKE ANY -* REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY -* OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE. -*/ - - -# -#include -#include -#include -#include "VoronoiDiagramGenerator.h" - - - -int main(int argc, char **argv) -{ - double xmin, xmax, ymin, ymax; - scanf("%lf %lf %lf %lf", &xmin, &xmax, &ymin, &ymax) ; - - SourcePoint * sites; - long nsites; - - nsites = 0; - sites = (SourcePoint *) malloc(4000 * sizeof(SourcePoint)); - while (scanf("%d %lf %lf %lf", &sites[nsites].id, &sites[nsites].weight, &sites[nsites].x, &sites[nsites].y) != EOF) - { - nsites++; - if (nsites % 4000 == 0) { - sites = (SourcePoint *)realloc(sites,(nsites+4000)*sizeof(SourcePoint)); - } - } - - VoronoiDiagramGenerator * pvdg; - pvdg = new VoronoiDiagramGenerator(); - pvdg->generateVoronoi(sites, nsites, xmin, xmax, ymin, ymax, 0); - -// printf("sites %ld\n-------------------------------\n", nsites); - PolygonPoint* pSitePoints; - int numpoints, i, j; - for(i = 0; i < nsites; i++) - { - pvdg->getSitePoints(i, &numpoints, &pSitePoints); - if (numpoints == 0) - { - printf("-- no points for %d\n", i); - } - else - { - - - printf("update temp_child_4076440_0 set resultgeom = st_setsrid('POLYGON(("); - for(j = 0; j < numpoints; j++) - { - printf("%.15lf %.15lf,", pSitePoints[j].coord.x, pSitePoints[j].coord.y, (pSitePoints[j].angle/M_PI)*180); - } - printf("%.15lf %.15lf", pSitePoints[0].coord.x, pSitePoints[0].coord.y, (pSitePoints[j].angle/M_PI)*180); - printf("))'::geometry,4326) where id = %d;\n", sites[i].id); - - } - } - - float x1,y1,x2,y2; -// printf("sites %ld\n-------------------------------\n", nsites); - pvdg->resetIterator(); - while(pvdg->getNext(x1,y1,x2,y2)) - { - printf("(%f %f,%f %f)\n",x1,y1,x2, y2); - - } - - delete pvdg; - free(sites); - - return 0; -} - - -