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 "")
if (NOT ONLY_DOCS)
add_subdirectory(module)
- add_subdirectory(nominatim)
endif()
add_subdirectory(docs)
protected $iInstances;
protected $sModulePath;
protected $aDSNInfo;
+ protected $bQuiet;
protected $bVerbose;
protected $sIgnoreErrors;
protected $bEnableDiffUpdates;
}
// 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
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']);
}
+++ /dev/null
-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=$<BOOL:${HAVE_BYTESWAP}>
- PRIVATE HAVE_SYS_ENDIAN=$<BOOL:${HAVE_SYS_ENDIAN}>
-)
-
-target_link_libraries(nominatim ${LIBXML2_LIBRARIES} ${ZLIB_LIBRARIES} ${BZIP2_LIBRARIES} ${PostgreSQL_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT})
-
+++ /dev/null
-/*
-*/
-
-#include <stdio.h>
-#include <unistd.h>
-#include <stdlib.h>
-#include <string.h>
-#include <assert.h>
-#include <time.h>
-#include <stdint.h>
-#include <pthread.h>
-
-#include <libpq-fe.h>
-
-#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 <osmStructured>
- 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); // </feature>
-
- 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";
- }
-}
+++ /dev/null
-#ifndef EXPORT_H
-#define EXPORT_H
-
-#include <libxml/encoding.h>
-#include <libxml/xmlwriter.h>
-#include <stdint.h>
-
-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
+++ /dev/null
-/*
-*/
-#include <stdlib.h>
-#include <string.h>
-
-#include <libpq-fe.h>
-
-#include <libxml/xmlstring.h>
-#include <libxml/xmlreader.h>
-#include <libxml/hash.h>
-
-#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;
-}
+++ /dev/null
-#ifndef IMPORT_H
-#define IMPORT_H
-
-int nominatim_import(const char *conninfo, const char *partionTagsFilename, const char *filename);
-
-#endif
+++ /dev/null
-/*
- * 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 <stdio.h>
-#include <unistd.h>
-#include <stdlib.h>
-#include <string.h>
-#include <assert.h>
-#include <pthread.h>
-#include <time.h>
-#include <stdint.h>
-
-#include <libpq-fe.h>
-
-#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;
-}
+++ /dev/null
-#ifndef INDEX_H
-#define INDEX_H
-
-#include <libxml/encoding.h>
-#include <libxml/xmlwriter.h>
-
-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
+++ /dev/null
-#define _FILE_OFFSET_BITS 64
-#define _LARGEFILE64_SOURCE
-
-#ifdef __MINGW_H
-# include <windows.h>
-#else
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <string.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <zlib.h>
-#endif
-
-#include <libxml/xmlreader.h>
-#include <bzlib.h>
-
-#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);
-}
+++ /dev/null
-#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
+++ /dev/null
-/*
-#-----------------------------------------------------------------------------
-# 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 <stdio.h>
-#include <unistd.h>
-#include <stdlib.h>
-#include <string.h>
-#include <assert.h>
-#include <getopt.h>
-#include <libgen.h>
-#include <pthread.h>
-#include <time.h>
-
-#include <libpq-fe.h>
-
-#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;
-}
+++ /dev/null
-#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
-#! /usr/bin/env python
+#! /usr/bin/env python3
#-----------------------------------------------------------------------------
# nominatim - [description]
#-----------------------------------------------------------------------------
+++ /dev/null
-
-%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 <nominatim@brian.quinion.co.uk> 0.1-1.20070316svn
-- Initial build
+++ /dev/null
-/*
-*/
-#include <string.h>
-#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;
-}
+++ /dev/null
-/*
-*/
-
-#ifndef POSTGRESQL_H
-#define POSTGRESQL_H
-
-#define PG_OID_INT8 20
-#define PG_OID_INT4 23
-
-#if HAVE_BYTESWAP
-#include <byteswap.h>
-#define PG_BSWAP32(x) bswap_32(x)
-#define PG_BSWAP64(x) bswap_64(x)
-#elif HAVE_SYS_ENDIAN
-#include <sys/endian.h>
-#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
+++ /dev/null
-/*-------------------------------------------------------------------------
- *
- * 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 <stdio.h>
-#include <unistd.h>
-#include <stdlib.h>
-#include <string.h>
-#include <assert.h>
-
-#include <libpq-fe.h>
-
-#ifdef __MINGW_H
-# include <windows.h>
-#else
-# define HAVE_TERMIOS_H
-# include <termios.h>
-#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;
-}
+++ /dev/null
-#ifndef SPROMPT_H
-#define SPROMPT_H
-char *simple_prompt(const char *prompt, int maxlen, int echo);
-#endif
+++ /dev/null
-/*\r
-* The author of this software is Steven Fortune. Copyright (c) 1994 by AT&T\r
-* Bell Laboratories.\r
-* Permission to use, copy, modify, and distribute this software for any\r
-* purpose without fee is hereby granted, provided that this entire notice\r
-* is included in all copies of any software which is or includes a copy\r
-* or modification of this software and in all copies of the supporting\r
-* documentation for such software.\r
-* THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED\r
-* WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR AT&T MAKE ANY\r
-* REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY\r
-* OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE.\r
-*/\r
-\r
-/* \r
-* This code was originally written by Stephan Fortune in C code. I, Shane O'Sullivan, \r
-* have since modified it, encapsulating it in a C++ class and, fixing memory leaks and \r
-* adding accessors to the Voronoi Edges.\r
-* Permission to use, copy, modify, and distribute this software for any\r
-* purpose without fee is hereby granted, provided that this entire notice\r
-* is included in all copies of any software which is or includes a copy\r
-* or modification of this software and in all copies of the supporting\r
-* documentation for such software.\r
-* THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED\r
-* WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR AT&T MAKE ANY\r
-* REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY\r
-* OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE.\r
-*/\r
-\r
-#include "VoronoiDiagramGenerator.h"\r
-#include <stdio.h>\r
-#include <sys/mman.h>\r
-\r
-VoronoiDiagramGenerator::VoronoiDiagramGenerator()\r
-{\r
- siteidx = 0;\r
- sites = 0;\r
-\r
- allMemoryList = new FreeNodeArrayList;\r
- allMemoryList->memory = 0;\r
- allMemoryList->next = 0;\r
- currentMemoryBlock = allMemoryList;\r
- allEdges = 0;\r
- iteratorEdges = 0;\r
- minDistanceBetweenSites = 0;\r
-}\r
-\r
-VoronoiDiagramGenerator::~VoronoiDiagramGenerator()\r
-{\r
- cleanup();\r
- cleanupEdges();\r
-\r
- if(allMemoryList != 0)\r
- delete allMemoryList;\r
-}\r
-\r
-bool VoronoiDiagramGenerator::generateVoronoi(struct SourcePoint* srcPoints, int numPoints, float minX, float maxX, float minY, float maxY, float minDist)\r
-{\r
- cleanup();\r
- cleanupEdges();\r
- int i;\r
-\r
- minDistanceBetweenSites = minDist;\r
-\r
- nsites = numPoints;\r
- plot = 0;\r
- triangulate = 0;\r
- debug = 1;\r
- sorted = 0;\r
- freeinit(&sfl, sizeof (Site));\r
-\r
- sites = (struct Site *) myalloc(nsites * sizeof(*sites));\r
- polygons = (struct Polygon *) myalloc(nsites * sizeof(*polygons));\r
-\r
- if(sites == 0) return false;\r
-\r
- xmin = srcPoints[0].x;\r
- ymin = srcPoints[0].y;\r
- xmax = srcPoints[0].x;\r
- ymax = srcPoints[0].y;\r
-\r
- for(i = 0; i < nsites; i++)\r
- {\r
- sites[i].coord.x = srcPoints[i].x;\r
- sites[i].coord.y = srcPoints[i].y;\r
- sites[i].weight = srcPoints[i].weight;\r
- sites[i].sitenbr = i;\r
- sites[i].refcnt = 0; // prevent reuse?\r
-\r
- if(sites[i].coord.x < xmin)\r
- xmin = sites[i].coord.x;\r
- else if(sites[i].coord.x > xmax)\r
- xmax = sites[i].coord.x;\r
-\r
- if(sites[i].coord.y < ymin)\r
- ymin = sites[i].coord.y;\r
- else if(sites[i].coord.y > ymax)\r
- ymax = sites[i].coord.y;\r
-\r
- polygons[i].coord.x = sites[i].coord.x;\r
- polygons[i].coord.y = sites[i].coord.y;\r
- polygons[i].numpoints = 0;\r
- polygons[i].pointlist = NULL;\r
- polygons[i].boundary = 0;\r
-\r
- //printf("\n%lf %lf\n", sites[i].coord.x, sites[i].coord.y);\r
- }\r
-\r
- qsort(sites, nsites, sizeof (*sites), scomp);\r
-\r
- siteidx = 0;\r
- geominit();\r
- float temp = 0;\r
- if(minX > maxX)\r
- {\r
- temp = minX;\r
- minX = maxX;\r
- maxX = temp;\r
- }\r
- if(minY > maxY)\r
- {\r
- temp = minY;\r
- minY = maxY;\r
- maxY = temp;\r
- }\r
- borderMinX = minX;\r
- borderMinY = minY;\r
- borderMaxX = maxX;\r
- borderMaxY = maxY;\r
-\r
- corners[0].x = borderMinX;\r
- corners[0].y = borderMinY;\r
- corners[1].x = borderMinX;\r
- corners[1].y = borderMaxY;\r
- corners[2].x = borderMaxX;\r
- corners[2].y = borderMaxY;\r
- corners[3].x = borderMaxX;\r
- corners[3].y = borderMinY;\r
-\r
- siteidx = 0;\r
- voronoi(triangulate);\r
-\r
- return true;\r
-}\r
-\r
-bool VoronoiDiagramGenerator::ELinitialize()\r
-{\r
- int i;\r
- freeinit(&hfl, sizeof **ELhash);\r
- ELhashsize = 2 * sqrt_nsites;\r
- ELhash = (struct Halfedge **) myalloc ( sizeof *ELhash * ELhashsize);\r
-\r
- if(ELhash == 0)\r
- return false;\r
-\r
- for(i=0; i<ELhashsize; i +=1) ELhash[i] = (struct Halfedge *)NULL;\r
- ELleftend = HEcreate( (struct Edge *)NULL, 0);\r
- ELrightend = HEcreate( (struct Edge *)NULL, 0);\r
- ELleftend -> ELleft = (struct Halfedge *)NULL;\r
- ELleftend -> ELright = ELrightend;\r
- ELrightend -> ELleft = ELleftend;\r
- ELrightend -> ELright = (struct Halfedge *)NULL;\r
- ELhash[0] = ELleftend;\r
- ELhash[ELhashsize-1] = ELrightend;\r
-\r
- return true;\r
-}\r
-\r
-\r
-struct Halfedge* VoronoiDiagramGenerator::HEcreate(struct Edge *e,int pm)\r
-{\r
- struct Halfedge *answer;\r
- answer = (struct Halfedge *) getfree(&hfl);\r
- answer -> ELedge = e;\r
- answer -> ELpm = pm;\r
- answer -> PQnext = (struct Halfedge *) NULL;\r
- answer -> vertex = (struct Site *) NULL;\r
- answer -> ELrefcnt = 0;\r
- return(answer);\r
-}\r
-\r
-\r
-void VoronoiDiagramGenerator::ELinsert(struct Halfedge *lb, struct Halfedge *newHe)\r
-{\r
- newHe -> ELleft = lb;\r
- newHe -> ELright = lb -> ELright;\r
- (lb -> ELright) -> ELleft = newHe;\r
- lb -> ELright = newHe;\r
-}\r
-\r
-/* Get entry from hash table, pruning any deleted nodes */\r
-struct Halfedge * VoronoiDiagramGenerator::ELgethash(int b)\r
-{\r
- struct Halfedge *he;\r
-\r
- if(b<0 || b>=ELhashsize)\r
- return((struct Halfedge *) NULL);\r
- he = ELhash[b];\r
- if (he == (struct Halfedge *) NULL || he->ELedge != (struct Edge *) DELETED )\r
- return (he);\r
-\r
- /* Hash table points to deleted half edge. Patch as necessary. */\r
- ELhash[b] = (struct Halfedge *) NULL;\r
- if ((he -> ELrefcnt -= 1) == 0) \r
- makefree((Freenode*)he, &hfl);\r
- return ((struct Halfedge *) NULL);\r
-}\r
-\r
-struct Halfedge * VoronoiDiagramGenerator::ELleftbnd(struct Point *p)\r
-{\r
- int i, bucket;\r
- struct Halfedge *he;\r
-\r
- /* Use hash table to get close to desired halfedge */\r
- bucket = (int)((p->x - xmin)/deltax * ELhashsize); //use the hash function to find the place in the hash map that this HalfEdge should be\r
-\r
- if(bucket<0) bucket =0; //make sure that the bucket position in within the range of the hash array\r
- if(bucket>=ELhashsize) bucket = ELhashsize - 1;\r
-\r
- he = ELgethash(bucket);\r
- 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\r
- {\r
- for(i=1; 1 ; i += 1)\r
- {\r
- if ((he=ELgethash(bucket-i)) != (struct Halfedge *) NULL)\r
- break;\r
- if ((he=ELgethash(bucket+i)) != (struct Halfedge *) NULL)\r
- break;\r
- };\r
- totalsearch += i;\r
- };\r
- ntry += 1;\r
- /* Now search linear list of halfedges for the correct one */\r
- if (he==ELleftend || (he != ELrightend && right_of(he,p)))\r
- {\r
- do \r
- {\r
- he = he -> ELright;\r
- } 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\r
- he = he -> ELleft; //isn't to the right of\r
- }\r
- else //if the point is to the left of the HalfEdge, then search left for the HE just to the left of the point\r
- do\r
- {\r
- he = he -> ELleft;\r
- } while (he!=ELleftend && !right_of(he,p));\r
-\r
- /* Update hash table and reference counts */\r
- if(bucket > 0 && bucket <ELhashsize-1)\r
- {\r
- if(ELhash[bucket] != (struct Halfedge *) NULL) \r
- {\r
- ELhash[bucket] -> ELrefcnt -= 1;\r
- }\r
- ELhash[bucket] = he;\r
- ELhash[bucket] -> ELrefcnt += 1;\r
- };\r
- return (he);\r
-}\r
-\r
-\r
-/* This delete routine can't reclaim node, since pointers from hash\r
-table may be present. */\r
-void VoronoiDiagramGenerator::ELdelete(struct Halfedge *he)\r
-{\r
- (he -> ELleft) -> ELright = he -> ELright;\r
- (he -> ELright) -> ELleft = he -> ELleft;\r
- he -> ELedge = (struct Edge *)DELETED;\r
-}\r
-\r
-\r
-struct Halfedge * VoronoiDiagramGenerator::ELright(struct Halfedge *he)\r
-{\r
- return (he -> ELright);\r
-}\r
-\r
-struct Halfedge * VoronoiDiagramGenerator::ELleft(struct Halfedge *he)\r
-{\r
- return (he -> ELleft);\r
-}\r
-\r
-\r
-struct Site * VoronoiDiagramGenerator::leftreg(struct Halfedge *he)\r
-{\r
- if(he -> ELedge == (struct Edge *)NULL)\r
- return(bottomsite);\r
- return( he -> ELpm == le ?\r
- he -> ELedge -> reg[le] : he -> ELedge -> reg[re]);\r
-}\r
-\r
-struct Site * VoronoiDiagramGenerator::rightreg(struct Halfedge *he)\r
-{\r
- if(he -> ELedge == (struct Edge *)NULL) //if this halfedge has no edge, return the bottom site (whatever that is)\r
- return(bottomsite);\r
-\r
- //if the ELpm field is zero, return the site 0 that this edge bisects, otherwise return site number 1\r
- return( he -> ELpm == le ? he -> ELedge -> reg[re] : he -> ELedge -> reg[le]);\r
-}\r
-\r
-void VoronoiDiagramGenerator::geominit()\r
-{\r
- float sn;\r
-\r
- freeinit(&efl, sizeof(Edge));\r
- nvertices = 0;\r
- nedges = 0;\r
- sn = (float)nsites+4;\r
- sqrt_nsites = (int)sqrt(sn);\r
- deltay = ymax - ymin;\r
- deltax = xmax - xmin;\r
-}\r
-\r
-\r
-struct Edge * VoronoiDiagramGenerator::bisect(struct Site *s1,struct Site *s2)\r
-{\r
- float dx,dy,adx,ady;\r
- struct Edge *newedge;\r
-\r
- newedge = (struct Edge *) getfree(&efl);\r
-\r
- newedge -> reg[0] = s1; //store the sites that this edge is bisecting\r
- newedge -> reg[1] = s2;\r
- ref(s1);\r
- ref(s2);\r
- newedge -> ep[0] = (struct Site *) NULL; //to begin with, there are no endpoints on the bisector - it goes to infinity\r
- newedge -> ep[1] = (struct Site *) NULL;\r
-\r
- dx = s2->coord.x - s1->coord.x; //get the difference in x dist between the sites\r
- dy = s2->coord.y - s1->coord.y;\r
- adx = dx>0 ? dx : -dx; //make sure that the difference in positive\r
- ady = dy>0 ? dy : -dy;\r
- newedge -> c = (float)(s1->coord.x * dx + s1->coord.y * dy + (dx*dx + dy*dy)*0.5);//get the slope of the line\r
-\r
- if (adx>ady)\r
- {\r
- newedge -> a = 1.0; newedge -> b = dy/dx; newedge -> c /= dx;//set formula of line, with x fixed to 1\r
- }\r
- else\r
- {\r
- newedge -> b = 1.0; newedge -> a = dx/dy; newedge -> c /= dy;//set formula of line, with y fixed to 1\r
- };\r
-\r
- newedge -> edgenbr = nedges;\r
-\r
- //printf("\nbisect(%d) ((%f,%f) and (%f,%f)",nedges,s1->coord.x,s1->coord.y,s2->coord.x,s2->coord.y);\r
-\r
- nedges += 1;\r
- return(newedge);\r
-}\r
-\r
-//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\r
-struct Site * VoronoiDiagramGenerator::intersect(struct Halfedge *el1, struct Halfedge *el2, struct Point *p)\r
-{\r
- struct Edge *e1,*e2, *e;\r
- struct Halfedge *el;\r
- float d, xint, yint;\r
- int right_of_site;\r
- struct Site *v;\r
-\r
- e1 = el1 -> ELedge;\r
- e2 = el2 -> ELedge;\r
- if(e1 == (struct Edge*)NULL || e2 == (struct Edge*)NULL)\r
- return ((struct Site *) NULL);\r
-\r
- //if the two edges bisect the same parent, return null\r
- if (e1->reg[1] == e2->reg[1])\r
- return ((struct Site *) NULL);\r
-\r
- d = e1->a * e2->b - e1->b * e2->a;\r
- if (-1.0e-10<d && d<1.0e-10)\r
- return ((struct Site *) NULL);\r
-\r
- xint = (e1->c*e2->b - e2->c*e1->b)/d;\r
- yint = (e2->c*e1->a - e1->c*e2->a)/d;\r
-\r
- if( (e1->reg[1]->coord.y < e2->reg[1]->coord.y) ||\r
- (e1->reg[1]->coord.y == e2->reg[1]->coord.y &&\r
- e1->reg[1]->coord.x < e2->reg[1]->coord.x) )\r
- {\r
- el = el1;\r
- e = e1;\r
- }\r
- else\r
- {\r
- el = el2;\r
- e = e2;\r
- };\r
-\r
- right_of_site = xint >= e -> reg[1] -> coord.x;\r
- if ((right_of_site && el -> ELpm == le) || (!right_of_site && el -> ELpm == re))\r
- return ((struct Site *) NULL);\r
-\r
- //create a new site at the point of intersection - this is a new vector event waiting to happen\r
- v = (struct Site *) getfree(&sfl);\r
- v -> refcnt = 0;\r
- v -> coord.x = xint;\r
- v -> coord.y = yint;\r
- return(v);\r
-}\r
-\r
-/* returns 1 if p is to right of halfedge e */\r
-int VoronoiDiagramGenerator::right_of(struct Halfedge *el,struct Point *p)\r
-{\r
- struct Edge *e;\r
- struct Site *topsite;\r
- int right_of_site, above, fast;\r
- float dxp, dyp, dxs, t1, t2, t3, yl;\r
-\r
- e = el -> ELedge;\r
- topsite = e -> reg[1];\r
- right_of_site = p -> x > topsite -> coord.x;\r
- if(right_of_site && el -> ELpm == le) return(1);\r
- if(!right_of_site && el -> ELpm == re) return (0);\r
- if (e->a == 1.0)\r
- {\r
- dyp = p->y - topsite->coord.y;\r
- dxp = p->x - topsite->coord.x;\r
- fast = 0;\r
- if ((!right_of_site & (e->b<0.0)) | (right_of_site & (e->b>=0.0)) )\r
- {\r
- above = dyp>= e->b*dxp;\r
- fast = above;\r
- }\r
- else\r
- {\r
- above = p->x + p->y*e->b > e-> c;\r
- if(e->b<0.0) above = !above;\r
- if (!above) fast = 1;\r
- }\r
-\r
- if (!fast)\r
- {\r
- dxs = topsite->coord.x - (e->reg[0])->coord.x;\r
- above = e->b * (dxp*dxp - dyp*dyp) <\r
- dxs*dyp*(1.0+2.0*dxp/dxs + e->b*e->b);\r
- if(e->b<0.0) above = !above;\r
- }\r
- }\r
- else /*e->b==1.0 */\r
- {\r
- yl = e->c - e->a*p->x;\r
- t1 = p->y - yl;\r
- t2 = p->x - topsite->coord.x;\r
- t3 = yl - topsite->coord.y;\r
- above = t1*t1 > t2*t2 + t3*t3;\r
- }\r
- return (el->ELpm==le ? above : !above);\r
-}\r
-\r
-\r
-void VoronoiDiagramGenerator::endpoint(struct Edge *e,int lr,struct Site * s)\r
-{\r
- e -> ep[lr] = s;\r
- ref(s);\r
- return;\r
-\r
- if(e -> ep[re-lr]== (struct Site *) NULL)\r
- return;\r
-\r
- clip_line(e);\r
-\r
- deref(e->reg[le]);\r
- deref(e->reg[re]);\r
- makefree((Freenode*)e, &efl);\r
-}\r
-\r
-void VoronoiDiagramGenerator::endpoint(struct Edge *e1,int lr,struct Site * s, struct Edge *e2, struct Edge *e3)\r
-{\r
- e1 -> ep[lr] = s;\r
- ref(s);\r
-\r
- s->coordout.x = s->coord.x;\r
- s->coordout.y = s->coord.y;\r
-\r
- if(e1 -> ep[le] != (struct Site *) NULL && e1 -> ep[re] != (struct Site *) NULL)\r
- {\r
- clip_line(e1);\r
- deref(e1->reg[le]);\r
- deref(e1->reg[re]);\r
- makefree((Freenode*)e1, &efl);\r
- }\r
-\r
- if(e2 -> ep[le] != (struct Site *) NULL && e2 -> ep[re] != (struct Site *) NULL)\r
- {\r
- clip_line(e2);\r
- deref(e2->reg[le]);\r
- deref(e2->reg[re]);\r
- makefree((Freenode*)e2, &efl);\r
- }\r
-\r
- if(e3 -> ep[le] != (struct Site *) NULL && e3 -> ep[re] != (struct Site *) NULL)\r
- {\r
- clip_line(e3);\r
- deref(e3->reg[le]);\r
- deref(e3->reg[re]);\r
- makefree((Freenode*)e3, &efl);\r
- }\r
-\r
- return; \r
-}\r
-\r
-\r
-float VoronoiDiagramGenerator::dist(struct Site *s,struct Site *t)\r
-{\r
- float dx,dy;\r
- dx = s->coord.x - t->coord.x;\r
- dy = s->coord.y - t->coord.y;\r
- return (float)(sqrt(dx*dx + dy*dy));\r
-}\r
-\r
-\r
-void VoronoiDiagramGenerator::makevertex(struct Site *v)\r
-{\r
- v -> sitenbr = nvertices;\r
- nvertices += 1;\r
- out_vertex(v);\r
-}\r
-\r
-\r
-void VoronoiDiagramGenerator::deref(struct Site *v)\r
-{\r
- v -> refcnt -= 1;\r
- if (v -> refcnt == 0 ) \r
- makefree((Freenode*)v, &sfl);\r
-}\r
-\r
-void VoronoiDiagramGenerator::ref(struct Site *v)\r
-{\r
- v -> refcnt += 1;\r
-}\r
-\r
-//push the HalfEdge into the ordered linked list of vertices\r
-void VoronoiDiagramGenerator::PQinsert(struct Halfedge *he,struct Site * v, float offset)\r
-{\r
- struct Halfedge *last, *next;\r
-\r
- he -> vertex = v;\r
- ref(v);\r
- he -> ystar = (float)(v -> coord.y + offset);\r
- last = &PQhash[PQbucket(he)];\r
- while ((next = last -> PQnext) != (struct Halfedge *) NULL &&\r
- (he -> ystar > next -> ystar ||\r
- (he -> ystar == next -> ystar && v -> coord.x > next->vertex->coord.x)))\r
- {\r
- last = next;\r
- }\r
- he -> PQnext = last -> PQnext;\r
- last -> PQnext = he;\r
- PQcount += 1;\r
-}\r
-\r
-//remove the HalfEdge from the list of vertices\r
-void VoronoiDiagramGenerator::PQdelete(struct Halfedge *he)\r
-{\r
- struct Halfedge *last;\r
-\r
- if(he -> vertex != (struct Site *) NULL)\r
- {\r
- last = &PQhash[PQbucket(he)];\r
- while (last -> PQnext != he)\r
- last = last -> PQnext;\r
-\r
- last -> PQnext = he -> PQnext;\r
- PQcount -= 1;\r
- deref(he -> vertex);\r
- he -> vertex = (struct Site *) NULL;\r
- };\r
-}\r
-\r
-int VoronoiDiagramGenerator::PQbucket(struct Halfedge *he)\r
-{\r
- int bucket;\r
-\r
- bucket = (int)((he->ystar - ymin)/deltay * PQhashsize);\r
- if (bucket<0) bucket = 0;\r
- if (bucket>=PQhashsize) bucket = PQhashsize-1 ;\r
- if (bucket < PQmin) PQmin = bucket;\r
- return(bucket);\r
-}\r
-\r
-int VoronoiDiagramGenerator::PQempty()\r
-{\r
- return(PQcount==0);\r
-}\r
-\r
-\r
-struct Point VoronoiDiagramGenerator::PQ_min()\r
-{\r
- struct Point answer;\r
-\r
- while(PQhash[PQmin].PQnext == (struct Halfedge *)NULL) {PQmin += 1;};\r
- answer.x = PQhash[PQmin].PQnext -> vertex -> coord.x;\r
- answer.y = PQhash[PQmin].PQnext -> ystar;\r
- return (answer);\r
-}\r
-\r
-struct Halfedge * VoronoiDiagramGenerator::PQextractmin()\r
-{\r
- struct Halfedge *curr;\r
-\r
- curr = PQhash[PQmin].PQnext;\r
- PQhash[PQmin].PQnext = curr -> PQnext;\r
- PQcount -= 1;\r
- return(curr);\r
-}\r
-\r
-\r
-bool VoronoiDiagramGenerator::PQinitialize()\r
-{\r
- int i;\r
-\r
- PQcount = 0;\r
- PQmin = 0;\r
- PQhashsize = 4 * sqrt_nsites;\r
- PQhash = (struct Halfedge *) myalloc(PQhashsize * sizeof *PQhash);\r
-\r
- if(PQhash == 0)\r
- return false;\r
-\r
- for(i=0; i<PQhashsize; i+=1) PQhash[i].PQnext = (struct Halfedge *)NULL;\r
-\r
- return true;\r
-}\r
-\r
-\r
-void VoronoiDiagramGenerator::freeinit(struct Freelist *fl,int size)\r
-{\r
- fl -> head = (struct Freenode *) NULL;\r
- fl -> nodesize = size;\r
-}\r
-\r
-char * VoronoiDiagramGenerator::getfree(struct Freelist *fl)\r
-{\r
- int i;\r
- struct Freenode *t;\r
-\r
- if(fl->head == (struct Freenode *) NULL)\r
- {\r
- t = (struct Freenode *) myalloc(sqrt_nsites * fl->nodesize);\r
-\r
- if(t == 0)\r
- return 0;\r
-\r
- currentMemoryBlock->next = new FreeNodeArrayList;\r
- currentMemoryBlock = currentMemoryBlock->next;\r
- currentMemoryBlock->memory = t;\r
- currentMemoryBlock->next = 0;\r
-\r
- for(i=0; i<sqrt_nsites; i+=1)\r
- makefree((struct Freenode *)((char *)t+i*fl->nodesize), fl);\r
- };\r
- t = fl -> head;\r
- fl -> head = (fl -> head) -> nextfree;\r
- return((char *)t);\r
-}\r
-\r
-\r
-\r
-void VoronoiDiagramGenerator::makefree(struct Freenode *curr,struct Freelist *fl)\r
-{\r
- curr -> nextfree = fl -> head;\r
- fl -> head = curr;\r
-}\r
-\r
-void VoronoiDiagramGenerator::cleanup()\r
-{\r
- if(sites != 0)\r
- {\r
- free(sites);\r
- sites = 0;\r
- }\r
-\r
- FreeNodeArrayList* current=0, *prev = 0;\r
-\r
- current = prev = allMemoryList;\r
-\r
- while(current->next != 0)\r
- {\r
- prev = current;\r
- current = current->next;\r
- free(prev->memory);\r
- delete prev;\r
- prev = 0;\r
- }\r
-\r
- if(current != 0 && current->memory != 0)\r
- {\r
- free(current->memory);\r
- delete current;\r
- }\r
-\r
- allMemoryList = new FreeNodeArrayList;\r
- allMemoryList->next = 0;\r
- allMemoryList->memory = 0;\r
- currentMemoryBlock = allMemoryList;\r
-}\r
-\r
-void VoronoiDiagramGenerator::cleanupEdges()\r
-{\r
- GraphEdge* geCurrent = 0, *gePrev = 0;\r
- geCurrent = gePrev = allEdges;\r
-\r
- while(geCurrent != 0 && geCurrent->next != 0)\r
- {\r
- gePrev = geCurrent;\r
- geCurrent = geCurrent->next;\r
- delete gePrev;\r
- }\r
-\r
- allEdges = 0;\r
-\r
-}\r
-\r
-void VoronoiDiagramGenerator::pushGraphEdge(float x1, float y1, float x2, float y2)\r
-{\r
- GraphEdge* newEdge = new GraphEdge;\r
- newEdge->next = allEdges;\r
- allEdges = newEdge;\r
- newEdge->x1 = x1;\r
- newEdge->y1 = y1;\r
- newEdge->x2 = x2;\r
- newEdge->y2 = y2;\r
-}\r
-\r
-\r
-char * VoronoiDiagramGenerator::myalloc(unsigned n)\r
-{\r
- char *t=0;\r
- t=(char*)malloc(n);\r
- total_alloc += n;\r
- return(t);\r
-}\r
-\r
-\r
-/* for those who don't have Cherry's plot */\r
-/* #include <plot.h> */\r
-void VoronoiDiagramGenerator::openpl(){}\r
-void VoronoiDiagramGenerator::line(float x1, float y1, float x2, float y2)\r
-{\r
- pushGraphEdge(x1,y1,x2,y2);\r
-\r
-}\r
-void VoronoiDiagramGenerator::circle(float x, float y, float radius){}\r
-void VoronoiDiagramGenerator::range(float minX, float minY, float maxX, float maxY){}\r
-\r
-\r
-\r
-void VoronoiDiagramGenerator::out_bisector(struct Edge *e)\r
-{\r
-\r
-}\r
-\r
-\r
-void VoronoiDiagramGenerator::out_ep(struct Edge *e)\r
-{\r
-\r
-}\r
-\r
-void VoronoiDiagramGenerator::out_vertex(struct Site *v)\r
-{\r
-\r
-}\r
-\r
-\r
-void VoronoiDiagramGenerator::out_site(struct Site *s)\r
-{\r
- if(!triangulate & plot & !debug)\r
- circle (s->coord.x, s->coord.y, cradius);\r
-}\r
-\r
-\r
-void VoronoiDiagramGenerator::out_triple(struct Site *s1, struct Site *s2,struct Site * s3)\r
-{\r
-\r
-}\r
-\r
-\r
-\r
-void VoronoiDiagramGenerator::plotinit()\r
-{\r
- float dx,dy,d;\r
-\r
- dy = ymax - ymin;\r
- dx = xmax - xmin;\r
- d = (float)(( dx > dy ? dx : dy) * 1.1);\r
- pxmin = (float)(xmin - (d-dx)/2.0);\r
- pxmax = (float)(xmax + (d-dx)/2.0);\r
- pymin = (float)(ymin - (d-dy)/2.0);\r
- pymax = (float)(ymax + (d-dy)/2.0);\r
- cradius = (float)((pxmax - pxmin)/350.0);\r
- openpl();\r
- range(pxmin, pymin, pxmax, pymax);\r
-}\r
-\r
-void VoronoiDiagramGenerator::pushpoint(int sitenbr, double x, double y, int boundary)\r
-{\r
- Polygon *s;\r
-\r
- s = &polygons[sitenbr];\r
-\r
- if (s->numpoints == 0)\r
- {\r
- s->pointlist = (PolygonPoint *)malloc(sizeof(struct PolygonPoint)*(s->numpoints+10));\r
- if (!s->pointlist)\r
- {\r
- printf("Out of mem\n");\r
- }\r
- }\r
- else if (s->numpoints % 10 == 0)\r
- {\r
- s->pointlist = (PolygonPoint *)realloc(s->pointlist, sizeof(struct PolygonPoint)*(s->numpoints+10));\r
- if (!s->pointlist)\r
- {\r
- printf("Out of remem\n");\r
- }\r
- }\r
- s->pointlist[s->numpoints].coord.x = x;\r
- s->pointlist[s->numpoints].coord.y = y;\r
- s->pointlist[s->numpoints].angle = atan2f(x-s->coord.x, y-s->coord.y);\r
- s->pointlist[s->numpoints].boundary = boundary;\r
-\r
- if (boundary) s->boundary = 1;\r
-\r
- //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);\r
-\r
- s->numpoints++;\r
-}\r
-\r
-int VoronoiDiagramGenerator::ccw( Point p0, Point p1, Point p2 )\r
-{\r
- double dx1, dx2, dy1, dy2;\r
-\r
- dx1 = p1.x - p0.x; dy1 = p1.y - p0.y;\r
- dx2 = p2.x - p0.x; dy2 = p2.y - p0.y;\r
-\r
- if (dx1*dy2 > dy1*dx2)\r
- return +1;\r
- if (dx1*dy2 < dy1*dx2)\r
- return -1;\r
- if ((dx1*dx2 < 0) || (dy1*dy2 < 0))\r
- return -1;\r
- if ((dx1*dx1 + dy1*dy1) < (dx2*dx2 + dy2*dy2))\r
- return +1;\r
- return 0;\r
-}\r
-\r
-void VoronoiDiagramGenerator::getSitePoints(int sitenbr, int* numpoints, PolygonPoint** pS)\r
-{\r
- int i, j, c, any, centrevalue, cornerinpolygon[4];\r
-\r
- if (polygons[sitenbr].numpoints == 0)\r
- {\r
- for(c = 0; c < 4; c++)\r
- {\r
- pushpoint(sitenbr, corners[c].x, corners[c].y, 0);\r
- }\r
- }\r
-\r
- qsort(polygons[sitenbr].pointlist, polygons[sitenbr].numpoints, sizeof(PolygonPoint), anglecomp);\r
-\r
- if (polygons[sitenbr].boundary)\r
- {\r
-// printf("\nsite %d is boundary intersection\n", sitenbr);\r
-\r
- for(c = 0; c < 4; c++) cornerinpolygon[c] = 1;\r
-\r
- for(i = 0; i < polygons[sitenbr].numpoints; i++)\r
- {\r
-// printf("Point (%lf,%lf) %d\n", polygons[sitenbr].pointlist[i].coord.x,polygons[sitenbr].pointlist[i].coord.y,polygons[sitenbr].pointlist[i].boundary);\r
- j = i > 0?i-1:polygons[sitenbr].numpoints-1;\r
- if ( (!polygons[sitenbr].pointlist[i].boundary || !polygons[sitenbr].pointlist[j].boundary) &&\r
- (polygons[sitenbr].pointlist[i].coord.x != polygons[sitenbr].pointlist[j].coord.x ||\r
- polygons[sitenbr].pointlist[i].coord.y != polygons[sitenbr].pointlist[j].coord.y))\r
- {\r
-// 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);\r
- any = 0;\r
- centrevalue = ccw(polygons[sitenbr].pointlist[i].coord, polygons[sitenbr].pointlist[j].coord, polygons[sitenbr].coord);\r
-//printf(" test against centre (%lf,%lf) %d\n", polygons[sitenbr].coord.x, polygons[sitenbr].coord.y, centrevalue);\r
- for(c = 0; c < 4; c++)\r
- {\r
- if (cornerinpolygon[c])\r
- {\r
-\r
-//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]));\r
-\r
- if (centrevalue == ccw(polygons[sitenbr].pointlist[i].coord, polygons[sitenbr].pointlist[j].coord, corners[c]))\r
- {\r
- any = 1;\r
- }\r
- else\r
- {\r
- cornerinpolygon[c] = 0;\r
- }\r
- }\r
- }\r
- if (!any) break;\r
- }\r
- }\r
- if (any)\r
- {\r
- for(c = 0; c < 4; c++)\r
- {\r
- if (cornerinpolygon[c])\r
- {\r
-// printf("adding corger (%lf,%lf) to %d\n", corners[c].x, corners[c].y, sitenbr);\r
- pushpoint(sitenbr, corners[c].x, corners[c].y, 0);\r
- }\r
- }\r
- }\r
- qsort(polygons[sitenbr].pointlist, polygons[sitenbr].numpoints, sizeof(PolygonPoint), anglecomp);\r
-\r
- polygons[sitenbr].boundary = 0;\r
- }\r
-\r
- *numpoints = polygons[sitenbr].numpoints;\r
- *pS = polygons[sitenbr].pointlist;\r
-}\r
-\r
-\r
-void VoronoiDiagramGenerator::clip_line(struct Edge *e)\r
-{\r
- struct Site *s1, *s2, *ts1, *ts2;\r
- float x1=0,x2=0,y1=0,y2=0, temp = 0;\r
- int boundary1 = 0, boundary2 = 0;\r
-\r
-\r
- x1 = e->reg[0]->coord.x;\r
- x2 = e->reg[1]->coord.x;\r
- y1 = e->reg[0]->coord.y;\r
- y2 = e->reg[1]->coord.y;\r
-\r
- if(sqrt(((x2 - x1) * (x2 - x1)) + ((y2 - y1) * (y2 - y1))) == 0)\r
- {\r
- return;\r
- }\r
-\r
- pxmin = borderMinX;\r
- pxmax = borderMaxX;\r
- pymin = borderMinY;\r
- pymax = borderMaxY;\r
-\r
- if(e -> a == 1.0 && e ->b >= 0.0)\r
- {\r
- s1 = e -> ep[1];\r
- s2 = e -> ep[0];\r
-\r
- ts1 = e -> reg[1];\r
- ts2 = e -> reg[0];\r
- }\r
- else\r
- {\r
- s1 = e -> ep[0];\r
- s2 = e -> ep[1];\r
-\r
- ts1 = e -> reg[0];\r
- ts2 = e -> reg[1];\r
-\r
- };\r
-\r
- if(e -> a == 1.0)\r
- {\r
- if ( s1!=(struct Site *)NULL\r
- && s1->coordout.y > pymin && s1->coordout.y < pymax\r
- && s1->coordout.x > pxmin && s1->coordout.x < pxmax)\r
- {\r
- x1 = s1->coordout.x;\r
- y1 = s1->coordout.y;\r
- }\r
- else\r
- {\r
- boundary1 = 1;\r
- y1 = pymin;\r
- if (s1!=(struct Site *)NULL && s1->coord.y > pymin)\r
- {\r
- y1 = s1->coord.y;\r
- }\r
- if(y1>pymax)\r
- {\r
- y1 = pymax;\r
- }\r
- x1 = e -> c - e -> b * y1;\r
- }\r
-\r
- if ( s2!=(struct Site *)NULL\r
- && s2->coordout.y > pymin && s2->coordout.y < pymax\r
- && s2->coordout.x > pxmin && s2->coordout.x < pxmax)\r
- {\r
- x2 = s2->coordout.x;\r
- y2 = s2->coordout.y;\r
- }\r
- else\r
- {\r
- boundary2 = 1;\r
- y2 = pymax;\r
- if (s2!=(struct Site *)NULL && s2->coord.y < pymax)\r
- y2 = s2->coord.y;\r
- if(y2<pymin)\r
- {\r
- y2 = pymin;\r
- }\r
- x2 = (e->c) - (e->b) * y2;\r
- }\r
-\r
- if (((x1> pxmax) & (x2>pxmax)) | ((x1<pxmin)&(x2<pxmin)))\r
- {\r
- // Line completely outside clipbox\r
- //printf("\nClipLine jumping out(3), x1 = %f, pxmin = %f, pxmax = %f",x1,pxmin,pxmax);\r
- return;\r
- }\r
- if(x1 > pxmax)\r
- {\r
- x1 = pxmax;\r
- y1 = (e -> c - x1)/e -> b;\r
- }\r
- if(x1 < pxmin)\r
- {\r
- x1 = pxmin;\r
- y1 = (e -> c - x1)/e -> b;\r
- }\r
- if(x2 > pxmax)\r
- {\r
- x2 = pxmax;\r
- y2 = (e -> c - x2)/e -> b;\r
- }\r
- if(x2 < pxmin)\r
- {\r
- x2 = pxmin;\r
- y2 = (e -> c - x2)/e -> b;\r
- }\r
- }\r
- else\r
- {\r
- if ( s1!=(struct Site *)NULL\r
- && s1->coordout.y > pymin && s1->coordout.y < pymax\r
- && s1->coordout.x > pxmin && s1->coordout.x < pxmax)\r
- {\r
- x1 = s1->coordout.x;\r
- y1 = s1->coordout.y;\r
- }\r
- else\r
- {\r
- boundary1 = 1;\r
- x1 = pxmin;\r
- if (s1!=(struct Site *)NULL && s1->coord.x > pxmin)\r
- x1 = s1->coord.x;\r
- if(x1>pxmax) \r
- {\r
- //printf("\nClipped (3) x1 = %f to %f",x1,pxmin);\r
- //return;\r
- x1 = pxmax;\r
- }\r
- y1 = e -> c - e -> a * x1;\r
- }\r
-\r
- if ( s2!=(struct Site *)NULL\r
- && s2->coordout.y > pymin && s2->coordout.y < pymax\r
- && s2->coordout.x > pxmin && s2->coordout.x < pxmax)\r
- {\r
- x2 = s2->coordout.x;\r
- y2 = s2->coordout.y;\r
- }\r
- else\r
- {\r
- boundary2 = 1;\r
- x2 = pxmax;\r
- if (s2!=(struct Site *)NULL && s2->coord.x < pxmax)\r
- x2 = s2->coord.x;\r
- if(x2<pxmin)\r
- {\r
- //printf("\nClipped (4) x2 = %f to %f",x2,pxmin);\r
- //return;\r
- x2 = pxmin;\r
- }\r
- y2 = e -> c - e -> a * x2;\r
- }\r
-\r
- if (((y1> pymax) & (y2>pymax)) | ((y1<pymin)&(y2<pymin)))\r
- {\r
- //printf("\nClipLine jumping out(6), y1 = %f, pymin = %f, pymax = %f",y2,pymin,pymax);\r
- return;\r
- }\r
- if(y1 > pymax)\r
- { y1 = pymax; x1 = (e -> c - y1)/e -> a;};\r
- if(y1 < pymin)\r
- { y1 = pymin; x1 = (e -> c - y1)/e -> a;};\r
- if(y2 > pymax)\r
- { y2 = pymax; x2 = (e -> c - y2)/e -> a;};\r
- if(y2 < pymin)\r
- { y2 = pymin; x2 = (e -> c - y2)/e -> a;};\r
- };\r
-\r
- if(sqrt(((x2 - x1) * (x2 - x1)) + ((y2 - y1) * (y2 - y1))) == 0)\r
- {\r
- return;\r
- }\r
-\r
- pushpoint(ts1->sitenbr, x1, y1, boundary1);\r
- pushpoint(ts2->sitenbr, x2, y2, boundary2);\r
- pushpoint(ts1->sitenbr, x2, y2, boundary2);\r
- pushpoint(ts2->sitenbr, x1, y1, boundary1);\r
-}\r
-\r
-\r
-/* implicit parameters: nsites, sqrt_nsites, xmin, xmax, ymin, ymax,\r
-deltax, deltay (can all be estimates).\r
-Performance suffers if they are wrong; better to make nsites,\r
-deltax, and deltay too big than too small. (?) */\r
-\r
-bool VoronoiDiagramGenerator::voronoi(int triangulate)\r
-{\r
- struct Site *newsite, *bot, *top, *temp, *p;\r
- struct Site *v;\r
- struct Point newintstar;\r
- int pm;\r
- struct Halfedge *lbnd, *rbnd, *llbnd, *rrbnd, *bisector;\r
- struct Edge *e, *e2, *e3;\r
-\r
- PQinitialize();\r
- bottomsite = nextone();\r
- out_site(bottomsite);\r
- bool retval = ELinitialize();\r
-\r
- if(!retval)\r
- return false;\r
-\r
- newsite = nextone();\r
- while(1)\r
- {\r
-\r
- if(!PQempty())\r
- newintstar = PQ_min();\r
-\r
- //if the lowest site has a smaller y value than the lowest vector intersection, process the site\r
- //otherwise process the vector intersection \r
-\r
- if (newsite != (struct Site *)NULL && (PQempty() || newsite -> coord.y < newintstar.y\r
- || (newsite->coord.y == newintstar.y && newsite->coord.x < newintstar.x)))\r
- {/* new site is smallest - this is a site event*/\r
- out_site(newsite); //output the site\r
- lbnd = ELleftbnd(&(newsite->coord)); //get the first HalfEdge to the LEFT of the new site\r
- rbnd = ELright(lbnd); //get the first HalfEdge to the RIGHT of the new site\r
- bot = rightreg(lbnd); //if this halfedge has no edge, , bot = bottom site (whatever that is)\r
- e = bisect(bot, newsite); //create a new edge that bisects \r
- bisector = HEcreate(e, le); //create a new HalfEdge, setting its ELpm field to 0 \r
- ELinsert(lbnd, bisector); //insert this new bisector edge between the left and right vectors in a linked list \r
-\r
- 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\r
- { \r
- PQdelete(lbnd);\r
- PQinsert(lbnd, p, dist(p,newsite));\r
- };\r
- lbnd = bisector; \r
- bisector = HEcreate(e, re); //create a new HalfEdge, setting its ELpm field to 1\r
- ELinsert(lbnd, bisector); //insert the new HE to the right of the original bisector earlier in the IF stmt\r
-\r
- if ((p = intersect(bisector, rbnd)) != (struct Site *) NULL) //if this new bisector intersects with the\r
- {\r
- PQinsert(bisector, p, dist(p,newsite)); //push the HE into the ordered linked list of vertices\r
- };\r
- newsite = nextone();\r
- }\r
- else if (!PQempty()) /* intersection is smallest - this is a vector event */\r
- {\r
- lbnd = PQextractmin(); //pop the HalfEdge with the lowest vector off the ordered list of vectors \r
- llbnd = ELleft(lbnd); //get the HalfEdge to the left of the above HE\r
- rbnd = ELright(lbnd); //get the HalfEdge to the right of the above HE\r
- rrbnd = ELright(rbnd); //get the HalfEdge to the right of the HE to the right of the lowest HE \r
- bot = leftreg(lbnd); //get the Site to the left of the left HE which it bisects\r
- top = rightreg(rbnd); //get the Site to the right of the right HE which it bisects\r
-\r
- out_triple(bot, top, rightreg(lbnd)); //output the triple of sites, stating that a circle goes through them\r
-\r
- v = lbnd->vertex; //get the vertex that caused this event\r
- makevertex(v); //set the vertex number - couldn't do this earlier since we didn't know when it would be processed\r
- e2 = lbnd->ELedge;\r
- e3 = rbnd->ELedge;\r
- endpoint(lbnd->ELedge,lbnd->ELpm,v); //set the endpoint of the left HalfEdge to be this vector\r
- endpoint(rbnd->ELedge,rbnd->ELpm,v); //set the endpoint of the right HalfEdge to be this vector\r
- ELdelete(lbnd); //mark the lowest HE for deletion - can't delete yet because there might be pointers to it in Hash Map \r
- PQdelete(rbnd); //remove all vertex events to do with the right HE\r
- ELdelete(rbnd); //mark the right HE for deletion - can't delete yet because there might be pointers to it in Hash Map \r
- pm = le; //set the pm variable to zero\r
-\r
- if (bot->coord.y > top->coord.y) //if the site to the left of the event is higher than the Site\r
- { //to the right of it, then swap them and set the 'pm' variable to 1\r
- temp = bot;\r
- bot = top;\r
- top = temp;\r
- pm = re;\r
- }\r
- e = bisect(bot, top); //create an Edge (or line) that is between the two Sites. This creates\r
- //the formula of the line, and assigns a line number to it\r
- bisector = HEcreate(e, pm); //create a HE from the Edge 'e', and make it point to that edge with its ELedge field\r
- ELinsert(llbnd, bisector); //insert the new bisector to the right of the left HE\r
- endpoint(e, re-pm, v, e2, e3); //set one endpoint to the new edge to be the vector point 'v'.\r
- //If the site to the left of this bisector is higher than the right\r
- //Site, then this endpoint is put in position 0; otherwise in pos 1\r
- deref(v); //delete the vector 'v'\r
-\r
- //if left HE and the new bisector don't intersect, then delete the left HE, and reinsert it\r
- if((p = intersect(llbnd, bisector)) != (struct Site *) NULL)\r
- {\r
- PQdelete(llbnd);\r
- PQinsert(llbnd, p, dist(p,bot));\r
- };\r
-\r
- //if right HE and the new bisector don't intersect, then reinsert it\r
- if ((p = intersect(bisector, rrbnd)) != (struct Site *) NULL)\r
- {\r
- PQinsert(bisector, p, dist(p,bot));\r
- };\r
- }\r
- else break;\r
- };\r
-\r
- for(lbnd=ELright(ELleftend); lbnd != ELrightend; lbnd=ELright(lbnd))\r
- {\r
- e = lbnd -> ELedge;\r
-\r
- clip_line(e);\r
- };\r
-\r
- cleanup();\r
-\r
- return true;\r
-}\r
-\r
-\r
-int scomp(const void *p1,const void *p2)\r
-{\r
- struct Point *s1 = (Point*)p1, *s2=(Point*)p2;\r
- if(s1 -> y < s2 -> y) return(-1);\r
- if(s1 -> y > s2 -> y) return(1);\r
- if(s1 -> x < s2 -> x) return(-1);\r
- if(s1 -> x > s2 -> x) return(1);\r
- return(0);\r
-}\r
-\r
-int spcomp(const void *p1,const void *p2)\r
-{\r
- struct SourcePoint *s1 = (SourcePoint*)p1, *s2=(SourcePoint*)p2;\r
- if(s1 -> y < s2 -> y) return(-1);\r
- if(s1 -> y > s2 -> y) return(1);\r
- if(s1 -> x < s2 -> x) return(-1);\r
- if(s1 -> x > s2 -> x) return(1);\r
- return(0);\r
-}\r
-\r
-int anglecomp(const void * p1, const void * p2)\r
-{\r
- PolygonPoint * s1 = (PolygonPoint *)p1 ;\r
- PolygonPoint * s2 = (PolygonPoint *)p2 ;\r
-\r
- if (s1->angle < s2->angle) {\r
- return (-1) ;\r
- }\r
- if (s1->angle > s2->angle) {\r
- return (1) ;\r
- }\r
- return (0) ;\r
-}\r
-\r
-/* return a single in-storage site */\r
-struct Site * VoronoiDiagramGenerator::nextone()\r
-{\r
- struct Site *s;\r
- if(siteidx < nsites)\r
- {\r
- s = &sites[siteidx];\r
- siteidx += 1;\r
- return(s);\r
- }\r
- else\r
- return( (struct Site *)NULL);\r
-}\r
-\r
+++ /dev/null
-/*\r
-* The author of this software is Steven Fortune. Copyright (c) 1994 by AT&T\r
-* Bell Laboratories.\r
-* Permission to use, copy, modify, and distribute this software for any\r
-* purpose without fee is hereby granted, provided that this entire notice\r
-* is included in all copies of any software which is or includes a copy\r
-* or modification of this software and in all copies of the supporting\r
-* documentation for such software.\r
-* THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED\r
-* WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR AT&T MAKE ANY\r
-* REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY\r
-* OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE.\r
-*/\r
-\r
-/* \r
-* This code was originally written by Stephan Fortune in C code. I, Shane O'Sullivan, \r
-* have since modified it, encapsulating it in a C++ class and, fixing memory leaks and \r
-* adding accessors to the Voronoi Edges.\r
-* Permission to use, copy, modify, and distribute this software for any\r
-* purpose without fee is hereby granted, provided that this entire notice\r
-* is included in all copies of any software which is or includes a copy\r
-* or modification of this software and in all copies of the supporting\r
-* documentation for such software.\r
-* THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED\r
-* WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR AT&T MAKE ANY\r
-* REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY\r
-* OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE.\r
-*/\r
-\r
-#ifndef VORONOI_DIAGRAM_GENERATOR\r
-#define VORONOI_DIAGRAM_GENERATOR\r
-\r
-#include <math.h>\r
-#include <stdlib.h>\r
-#include <string.h>\r
-\r
-\r
-#ifndef NULL\r
-#define NULL 0\r
-#endif\r
-#define DELETED -2\r
-\r
-#define le 0\r
-#define re 1\r
-\r
-struct SourcePoint\r
-{\r
- int id;\r
- double weight;\r
- double x;\r
- double y;\r
-};\r
-\r
-struct Freenode \r
-{\r
- struct Freenode *nextfree;\r
-};\r
-\r
-struct FreeNodeArrayList\r
-{\r
- struct Freenode* memory;\r
- struct FreeNodeArrayList* next;\r
-\r
-};\r
-\r
-struct Freelist \r
-{\r
- struct Freenode *head;\r
- int nodesize;\r
-};\r
-\r
-struct Point \r
-{\r
- float x,y;\r
-};\r
-\r
-struct PolygonPoint\r
-{\r
- struct Point coord;\r
- double angle;\r
- int boundary;\r
-};\r
-\r
-struct Polygon\r
-{\r
- int sitenbr;\r
- struct Point coord;\r
- int numpoints;\r
- struct PolygonPoint * pointlist;\r
- int boundary;\r
-};\r
-\r
-\r
-// structure used both for sites and for vertices \r
-struct Site \r
-{\r
- struct Point coord;\r
- struct Point coordout;\r
- double weight;\r
- int sitenbr;\r
- int refcnt;\r
-};\r
-\r
-\r
-\r
-struct Edge \r
-{\r
- float a,b,c;\r
- struct Site *ep[2];\r
- struct Site *reg[2];\r
- int edgenbr;\r
-\r
-};\r
-\r
-struct GraphEdge\r
-{\r
- float x1,y1,x2,y2;\r
- struct GraphEdge* next;\r
-};\r
-\r
-\r
-\r
-\r
-struct Halfedge \r
-{\r
- struct Halfedge *ELleft, *ELright;\r
- struct Edge *ELedge;\r
- int ELrefcnt;\r
- char ELpm;\r
- struct Site *vertex;\r
- float ystar;\r
- struct Halfedge *PQnext;\r
-};\r
-\r
-\r
-\r
-\r
-class VoronoiDiagramGenerator\r
-{\r
-public:\r
- VoronoiDiagramGenerator();\r
- ~VoronoiDiagramGenerator();\r
-\r
- bool generateVoronoi(struct SourcePoint* srcPoints, int numPoints, float minX, float maxX, float minY, float maxY, float minDist=0);\r
- void getSitePoints(int sitenbr, int* numpoints, PolygonPoint** pS);\r
-\r
- void resetIterator()\r
- {\r
- iteratorEdges = allEdges;\r
- }\r
-\r
- bool getNext(float& x1, float& y1, float& x2, float& y2)\r
- {\r
- if(iteratorEdges == 0)\r
- return false;\r
- \r
- x1 = iteratorEdges->x1;\r
- x2 = iteratorEdges->x2;\r
- y1 = iteratorEdges->y1;\r
- y2 = iteratorEdges->y2;\r
-\r
- iteratorEdges = iteratorEdges->next;\r
-\r
- return true;\r
- }\r
-\r
-\r
-private:\r
- void cleanup();\r
- void cleanupEdges();\r
- char *getfree(struct Freelist *fl); \r
- struct Halfedge *PQfind();\r
- int PQempty();\r
-\r
-\r
- \r
- struct Halfedge **ELhash;\r
- struct Halfedge *HEcreate(), *ELleft(), *ELright(), *ELleftbnd();\r
- struct Halfedge *HEcreate(struct Edge *e,int pm);\r
-\r
-\r
- struct Point PQ_min();\r
- struct Halfedge *PQextractmin(); \r
- void freeinit(struct Freelist *fl,int size);\r
- void makefree(struct Freenode *curr,struct Freelist *fl);\r
- void geominit();\r
- void plotinit();\r
- bool voronoi(int triangulate);\r
- void ref(struct Site *v);\r
- void deref(struct Site *v);\r
- void endpoint(struct Edge *e,int lr,struct Site * s);\r
- void endpoint(struct Edge *e1,int lr,struct Site * s, struct Edge *e2, struct Edge *e3);\r
-\r
- void ELdelete(struct Halfedge *he);\r
- struct Halfedge *ELleftbnd(struct Point *p);\r
- struct Halfedge *ELright(struct Halfedge *he);\r
- void makevertex(struct Site *v);\r
- void out_triple(struct Site *s1, struct Site *s2,struct Site * s3);\r
-\r
- void PQinsert(struct Halfedge *he,struct Site * v, float offset);\r
- void PQdelete(struct Halfedge *he);\r
- bool ELinitialize();\r
- void ELinsert(struct Halfedge *lb, struct Halfedge *newHe);\r
- struct Halfedge * ELgethash(int b);\r
- struct Halfedge *ELleft(struct Halfedge *he);\r
- struct Site *leftreg(struct Halfedge *he);\r
- void out_site(struct Site *s);\r
- bool PQinitialize();\r
- int PQbucket(struct Halfedge *he);\r
- void pushpoint(int sitenbr, double x, double y, int boundary);\r
- int ccw( Point p0, Point p1, Point p2 );\r
- void clip_line(struct Edge *e);\r
- char *myalloc(unsigned n);\r
- int right_of(struct Halfedge *el,struct Point *p);\r
-\r
- struct Site *rightreg(struct Halfedge *he);\r
- struct Edge *bisect(struct Site *s1,struct Site *s2);\r
- float dist(struct Site *s,struct Site *t);\r
- struct Site *intersect(struct Halfedge *el1, struct Halfedge *el2, struct Point *p=0);\r
-\r
- void out_bisector(struct Edge *e);\r
- void out_ep(struct Edge *e);\r
- void out_vertex(struct Site *v);\r
- struct Site *nextone();\r
-\r
- void pushGraphEdge(float x1, float y1, float x2, float y2);\r
-\r
- void openpl();\r
- void line(float x1, float y1, float x2, float y2);\r
- void circle(float x, float y, float radius);\r
- void range(float minX, float minY, float maxX, float maxY);\r
-\r
-\r
- struct Freelist hfl;\r
- struct Halfedge *ELleftend, *ELrightend;\r
- int ELhashsize;\r
-\r
- int triangulate, sorted, plot, debug;\r
- float xmin, xmax, ymin, ymax, deltax, deltay;\r
-\r
- struct Site *sites;\r
- struct Polygon *polygons;\r
- struct Point corners[4];\r
- int nsites;\r
- int siteidx;\r
- int sqrt_nsites;\r
- int nvertices;\r
- struct Freelist sfl;\r
- struct Site *bottomsite;\r
-\r
- int nedges;\r
- struct Freelist efl;\r
- int PQhashsize;\r
- struct Halfedge *PQhash;\r
- int PQcount;\r
- int PQmin;\r
-\r
- int ntry, totalsearch;\r
- float pxmin, pxmax, pymin, pymax, cradius;\r
- int total_alloc;\r
-\r
- float borderMinX, borderMaxX, borderMinY, borderMaxY;\r
-\r
- FreeNodeArrayList* allMemoryList;\r
- FreeNodeArrayList* currentMemoryBlock;\r
-\r
- GraphEdge* allEdges;\r
- GraphEdge* iteratorEdges;\r
-\r
- float minDistanceBetweenSites;\r
- \r
-};\r
-\r
-int scomp(const void *p1,const void *p2);\r
-int spcomp(const void *p1,const void *p2);\r
-int anglecomp(const void * p1, const void * p2);\r
-\r
-\r
-#endif\r
-\r
-\r
+++ /dev/null
-/*\r
-* The author of this software is Shane O'Sullivan. \r
-* Permission to use, copy, modify, and distribute this software for any\r
-* purpose without fee is hereby granted, provided that this entire notice\r
-* is included in all copies of any software which is or includes a copy\r
-* or modification of this software and in all copies of the supporting\r
-* documentation for such software.\r
-* THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED\r
-* WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR AT&T MAKE ANY\r
-* REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY\r
-* OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE.\r
-*/\r
-\r
-\r
-#\r
-#include <stdio.h>\r
-#include <search.h>\r
-#include <malloc.h>\r
-#include "VoronoiDiagramGenerator.h"\r
-\r
-\r
-\r
-int main(int argc, char **argv) \r
-{ \r
- double xmin, xmax, ymin, ymax;\r
- scanf("%lf %lf %lf %lf", &xmin, &xmax, &ymin, &ymax) ;\r
-\r
- SourcePoint * sites;\r
- long nsites;\r
-\r
- nsites = 0;\r
- sites = (SourcePoint *) malloc(4000 * sizeof(SourcePoint));\r
- while (scanf("%d %lf %lf %lf", &sites[nsites].id, &sites[nsites].weight, &sites[nsites].x, &sites[nsites].y) != EOF)\r
- {\r
- nsites++;\r
- if (nsites % 4000 == 0) {\r
- sites = (SourcePoint *)realloc(sites,(nsites+4000)*sizeof(SourcePoint));\r
- }\r
- }\r
-\r
- VoronoiDiagramGenerator * pvdg;\r
- pvdg = new VoronoiDiagramGenerator();\r
- pvdg->generateVoronoi(sites, nsites, xmin, xmax, ymin, ymax, 0);\r
-\r
-// printf("sites %ld\n-------------------------------\n", nsites);\r
- PolygonPoint* pSitePoints;\r
- int numpoints, i, j;\r
- for(i = 0; i < nsites; i++)\r
- {\r
- pvdg->getSitePoints(i, &numpoints, &pSitePoints);\r
- if (numpoints == 0)\r
- {\r
- printf("-- no points for %d\n", i);\r
- }\r
- else\r
- {\r
-\r
-\r
- printf("update temp_child_4076440_0 set resultgeom = st_setsrid('POLYGON((");\r
- for(j = 0; j < numpoints; j++)\r
- {\r
- printf("%.15lf %.15lf,", pSitePoints[j].coord.x, pSitePoints[j].coord.y, (pSitePoints[j].angle/M_PI)*180);\r
- }\r
- printf("%.15lf %.15lf", pSitePoints[0].coord.x, pSitePoints[0].coord.y, (pSitePoints[j].angle/M_PI)*180);\r
- printf("))'::geometry,4326) where id = %d;\n", sites[i].id);\r
-\r
- }\r
- }\r
-\r
- float x1,y1,x2,y2;\r
-// printf("sites %ld\n-------------------------------\n", nsites);\r
- pvdg->resetIterator();\r
- while(pvdg->getNext(x1,y1,x2,y2))\r
- {\r
- printf("(%f %f,%f %f)\n",x1,y1,x2, y2);\r
- \r
- }\r
-\r
- delete pvdg;\r
- free(sites);\r
-\r
- return 0;\r
-}\r
-\r
-\r
-\r