├── .gitignore ├── LICENSE ├── README.markdown ├── STYLE ├── core ├── Makefile ├── contraction.c ├── contraction.h ├── edgepayload.c ├── edgepayload.h ├── edgetypes │ ├── combination.c │ ├── combination.h │ ├── crossing.c │ ├── crossing.h │ ├── custompayload.c │ ├── custompayload.h │ ├── egress.c │ ├── egress.h │ ├── elapsehelpers.c │ ├── elapsehelpers.h │ ├── elapsetime.c │ ├── elapsetime.h │ ├── headway.c │ ├── headway.h │ ├── headwayalight.c │ ├── headwayalight.h │ ├── headwayboard.c │ ├── headwayboard.h │ ├── link.c │ ├── link.h │ ├── street.c │ ├── street.h │ ├── tripalight.c │ ├── tripalight.h │ ├── tripboard.c │ ├── tripboard.h │ ├── wait.c │ └── wait.h ├── fibheap │ ├── dirfibheap.c │ ├── dirfibheap.h │ ├── fibheap.c │ └── fibheap.h ├── graph.c ├── graph.h ├── graphserver.h ├── hashtable │ ├── hashtable.c │ ├── hashtable.h │ ├── hashtable_gs.c │ ├── hashtable_gs.h │ ├── hashtable_itr.c │ ├── hashtable_itr.h │ ├── hashtable_private.h │ ├── hashtable_utility.c │ └── hashtable_utility.h ├── heap.c ├── heap.h ├── list.c ├── list.h ├── path.c ├── path.h ├── router.c ├── servicecalendar.c ├── servicecalendar.h ├── state.c ├── state.h ├── test │ ├── README │ ├── deadend.c │ ├── hops.c │ ├── hopslines │ ├── init_prio_queue.c │ ├── makefile │ ├── map.csv │ ├── nodes.csv │ ├── streetprofile.c │ ├── test_ch.c │ ├── test_crossing.c │ ├── testdestroystates.c │ ├── testheap.c │ └── testsetparent.c ├── timezone.c ├── timezone.h ├── vector.c ├── vector.h ├── walkoptions.c └── walkoptions.h └── pygs ├── README ├── graphserver ├── __init__.py ├── compiler │ ├── __init__.py │ ├── dedupe.py │ ├── gdb_import_gtfs.py │ ├── gdb_import_ned.py │ ├── gdb_import_osm.py │ ├── gdb_link_gtfs_gtfs.py │ ├── gdb_link_osm_gtfs.py │ ├── gdb_new.py │ └── tools.py ├── core.py ├── ext │ ├── __init__.py │ ├── graphcrawler.py │ ├── gtfs │ │ ├── __init__.py │ │ ├── gtfsdb.py │ │ ├── gtfsdb_stats.py │ │ └── process_gtfs.py │ ├── ned │ │ ├── __init__.py │ │ ├── elevation │ │ │ ├── __init__.py │ │ │ └── elevation.py │ │ ├── profile.py │ │ └── profiledb.py │ ├── osm │ │ ├── __init__.py │ │ ├── graph.py │ │ ├── load_osm.py │ │ ├── osm.py │ │ ├── osmdb.py │ │ ├── osmfilters.py │ │ ├── profiledb.py │ │ ├── simplify_osm.py │ │ └── visitors.py │ └── routeserver │ │ ├── __init__.py │ │ ├── events.py │ │ ├── fcgi.py │ │ ├── geocoders.py │ │ ├── handlers.yaml │ │ └── routeserver.py ├── graphdb.py ├── gsdll.py ├── util.py ├── vector.py └── vincenty.py ├── setup.py └── test ├── README ├── __init__.py ├── stress_test ├── stress_test.py └── stress_utils.py └── unit_test ├── __init__.py ├── test_ch.py ├── test_combination.py ├── test_crossing.py ├── test_edge.py ├── test_egress.py ├── test_elapsetime.py ├── test_graph.py ├── test_graph_database.py ├── test_headway.py ├── test_headwayalight.py ├── test_headwayboard.py ├── test_link.py ├── test_listnode.py ├── test_path.py ├── test_pypayload.py ├── test_servicecalendar.py ├── test_serviceperiod.py ├── test_spt.py ├── test_sptvertex.py ├── test_state.py ├── test_street.py ├── test_timezone.py ├── test_timezoneperiod.py ├── test_tripalight.py ├── test_tripboard.py ├── test_util.py ├── test_vector.py ├── test_vertex.py ├── test_wait.py └── test_walkoptions.py /.gitignore: -------------------------------------------------------------------------------- 1 | *.pyc 2 | *.d 3 | *.o 4 | *.so 5 | pygs/build/* 6 | 7 | .metadata 8 | apps/heatmap/*.surface 9 | apps/heatmap/*.png 10 | apps/sptdrawing/*.png 11 | apps/transitshed/backend/data 12 | apps/transitshed/*.surface 13 | core/.cproject 14 | core/.project 15 | core/Debug 16 | core/test/build 17 | jags/.classpath 18 | jags/.project 19 | jags/.settings 20 | jags/bin 21 | jags/target 22 | misc/sptviz2/.svn 23 | misc/sptviz2/code/.svn 24 | misc/sptviz2/data 25 | pygs/.project 26 | pygs/.pydevproject 27 | pygs/dist 28 | pygs/graphserver.egg-info 29 | test/.cproject 30 | test/.project 31 | test/Debug 32 | test/gmon.out 33 | test/northseattle.csv 34 | test/wallingford.csv 35 | 36 | pygs/test/unit_testunit_test.db 37 | *.swp 38 | pygs/test/integration_test/map.osm 39 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Unless otherwise noted, code included with Graphserver is covered under the BSD license 2 | 3 | Copyright (c) 2007, 2008, 2009, 2010, Graphserver contributors 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions 7 | are met: 8 | 9 | * Redistributions of source code must retain the above copyright 10 | notice, this list of conditions and the following disclaimer. 11 | 12 | * Redistributions in binary form must reproduce the above copyright 13 | notice, this list of conditions and the following disclaimer in the 14 | documentation and/or other materials provided with the distribution. 15 | 16 | * Neither the name of the original author; nor the names of any contributors 17 | may be used to endorse or promote products derived from this software 18 | without specific prior written permission. 19 | 20 | 21 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 22 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 23 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 24 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 25 | CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 26 | EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 27 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 28 | PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 29 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 30 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 31 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 | -------------------------------------------------------------------------------- /README.markdown: -------------------------------------------------------------------------------- 1 | # GRAPHSERVER 2 | 3 | ## OVERVIEW 4 | 5 | Graphserver is a multi-modal trip planner. Graphserver supports transit modes 6 | through GTFS, and street-based modes through OSM. 7 | 8 | The core graphserver library has Python bindings which provide easy construction, 9 | storage, and analysis of graph objects. 10 | 11 | Learn more about Graphserver at [http://graphserver.github.com/graphserver/](http://graphserver.github.com/graphserver/) 12 | 13 | ## INSTALLATION 14 | 15 | ### Prerequisites 16 | Python 2.6+ (or 2.5+ for only graphserver.core) 17 | 18 | ### Build 19 | 20 | $ cd pygs 21 | $ sudo python2.6 setup.py install 22 | 23 | setup.py installs several executables. On debian these go into /usr/local/bin/*. 24 | On Mac OS X, these go into 25 | /Library/Frameworks/Python.framework/Versions/2.6/bin/* 26 | 27 | ### Test a successful installation: 28 | $ python2.6 -c "import graphserver.core; graphserver.core.Graph(); print 'Graphserver can be imported'" 29 | 30 | ### Run the test harness (in verbose mode): 31 | $ python2.6 setup.py nosetests -v 32 | 33 | ## TOOLS 34 | 35 | #### gs_gtfsdb_compile 36 | Create a GTFSDatabase (sqlite3 db) from a GTFS zip file 37 | $ gs_gtfsdb_compile google_transit.zip google_transit.gtfsdb 38 | 39 | #### gs_osmdb_compile 40 | Create a OSM database (sqlite3 db) from an OSM xml file 41 | $ gs_osmdb_compile map.osm map.osmdb 42 | 43 | #### gs_new 44 | Create a new graph file 45 | $ gs_new foobar.gdb 46 | 47 | #### gs_import_osm 48 | Import an OSM database to a graph file 49 | $ gs_import_osm foobar.gdb map.osmdb 50 | 51 | #### gs_import_gtfs 52 | Import a GTFS database to a graph file 53 | $ gs_import_gtfs foobar.gdb google_transit.gtfsdb 54 | 55 | #### gs_link_osm_gtfs 56 | Link OSM vertices to GTFS vertices to enable multimodal trip planning 57 | $ gs_link_osm_gtfs foobar.gdb map.osmdb google_transit.gtfsdb 58 | 59 | #### gs_osmfilter: run one of the filter classes from graphserver.ext.osm.osmfilters on an OSMDB instance 60 | $ gs_osmfilter [ ...] 61 | 62 | ## Building just the C .dll/.so 63 | 64 | Provides the core DLL for routing. It is not necessary to manually build this if 65 | using the Python bindings. 66 | 67 | Build: 68 | $ cd core 69 | $ make 70 | 71 | Install: 72 | $ cd core 73 | $ sudo make install 74 | 75 | -------------------------------------------------------------------------------- /STYLE: -------------------------------------------------------------------------------- 1 | # Graphserver Styleguide. 2 | 3 | ## A note 4 | 5 | These principles are broken by older code. Over time, the entire codebase should conform. 6 | 7 | ## Principles 8 | 9 | Classes are camel-cased. Instance variable are lower-cased, with underscores between words. 10 | 11 | Longform variables "longform_variable" are good, but don't go overboard. Shortform variables "x1" are okay when conforming to well established convention. 12 | 13 | Items in a vector of items of homogenous type are named (object1, object2, object3) et cetera. 14 | 15 | Name like object_property not object_propertytype. For example, "arrival_time" not "arrival_secs". 16 | 17 | ## Preferred Terms 18 | 19 | arrival_time 20 | departure_time 21 | -------------------------------------------------------------------------------- /core/Makefile: -------------------------------------------------------------------------------- 1 | all: libgraphserver.so 2 | 3 | # to override base installation directory run 4 | # PREFIX=... make install 5 | PREFIX=/usr 6 | 7 | OBJECTS= fibheap/dirfibheap.o \ 8 | fibheap/fibheap.o \ 9 | graph.o \ 10 | hashtable/hashtable.o \ 11 | hashtable/hashtable_gs.o \ 12 | hashtable/hashtable_itr.o \ 13 | hashtable/hashtable_utility.o \ 14 | state.o \ 15 | walkoptions.o \ 16 | edgetypes/elapsehelpers.o \ 17 | edgetypes/link.o \ 18 | edgetypes/street.o \ 19 | edgetypes/egress.o \ 20 | edgetypes/wait.o \ 21 | edgetypes/elapsetime.o \ 22 | edgetypes/headway.o \ 23 | edgetypes/tripboard.o \ 24 | edgetypes/headwayboard.o \ 25 | edgetypes/headwayalight.o \ 26 | edgetypes/crossing.o \ 27 | edgetypes/tripalight.o \ 28 | edgetypes/custompayload.o \ 29 | edgetypes/combination.o \ 30 | edgepayload.o \ 31 | list.o \ 32 | servicecalendar.o \ 33 | timezone.o \ 34 | path.o \ 35 | vector.o \ 36 | contraction.o \ 37 | heap.o 38 | 39 | # You know what? Honestly? I don't know what most of these switches do. 40 | CFLAGS=-g -fno-strict-aliasing -O2 -fPIC -Wall 41 | LDFLAGS= -L. -Bsymbolic-functions -Wall -ldl -lm -lc 42 | 43 | OS := $(shell uname) 44 | 45 | ifeq ($(OS),Darwin) 46 | LDFLAGS += -dynamiclib 47 | else 48 | LDFLAGS += -shared 49 | endif 50 | 51 | # This complicated-looking rule will autogenerate the appropriate dependancies 52 | # for each source file, ensuring that they are recompiled when the headers 53 | # they include change 54 | # see: http://www.cs.berkeley.edu/~smcpeak/autodepend/autodepend.html 55 | %.o: %.c 56 | cc $*.c -c -o $@ $(CFLAGS) 57 | cc $*.c -MM $(CFLAGS) > $*.d 58 | @mv -f $*.d $*.d.tmp 59 | @sed -e 's|.*:|$*.o:|' < $*.d.tmp > $*.d 60 | @sed -e 's/.*://' -e 's/\\$$//' < $*.d.tmp | fmt -1 | \ 61 | sed -e 's/^ *//' -e 's/$$/:/' >> $*.d 62 | @rm -f $*.d.tmp 63 | -include $(OBJECTS:.o=.d) 64 | 65 | 66 | libgraphserver.so: $(OBJECTS) 67 | cc -shared -o $@ $(OBJECTS) $(LDFLAGS) 68 | 69 | install: 70 | cp libgraphserver.so $(PREFIX)/lib 71 | mkdir -p $(PREFIX)/include/graphserver 72 | cp fibheap/fibheap.h $(PREFIX)/include/graphserver 73 | cp fibheap/dirfibheap.h $(PREFIX)/include/graphserver 74 | cp graph.h $(PREFIX)/include/graphserver 75 | cp hashtable/hashtable_gs.h $(PREFIX)/include/graphserver 76 | cp hashtable/hashtable_itr.h $(PREFIX)/include/graphserver 77 | cp hashtable/hashtable.h $(PREFIX)/include/graphserver 78 | cp hashtable/hashtable_utility.h $(PREFIX)/include/graphserver 79 | cp hashtable/hashtable_private.h $(PREFIX)/include/graphserver 80 | 81 | clean: 82 | rm -f *.{o,so,~,d} */*.{o,so,~,d} 83 | -------------------------------------------------------------------------------- /core/contraction.h: -------------------------------------------------------------------------------- 1 | 2 | struct CHPath { 3 | int n; 4 | EdgePayload** payloads; 5 | long length; 6 | Vertex* fromv; 7 | Vertex* tov; 8 | } ; 9 | 10 | struct CH { 11 | Graph* up; 12 | Graph* down; 13 | } ; 14 | 15 | CHPath* chpNew( int n, long length ) ; 16 | 17 | int chpLength( CHPath* this ) ; 18 | 19 | CHPath* chpCombine( CHPath* a, CHPath* b ) ; 20 | 21 | void chpDestroy( CHPath* this ) ; 22 | 23 | CHPath* dist( Graph *gg, char* from_v_label, char* to_v_label, WalkOptions *wo, int weightlimit, int return_full_path ) ; 24 | 25 | CHPath** get_shortcuts( Graph *gg, Vertex* vv, WalkOptions* wo, int search_limit, int* n ) ; 26 | 27 | Heap* init_priority_queue( Graph* gg, WalkOptions* wo, int search_limit ); 28 | 29 | void pqPush( Heap *pq, Vertex* item, long priority ); 30 | 31 | Vertex* pqPop( Heap *pq, long *priority ) ; 32 | 33 | CH* get_contraction_hierarchies(Graph* gg, WalkOptions* wo, int search_limit) ; 34 | 35 | CH* chNew(void); 36 | 37 | Graph* chUpGraph( CH* this ) ; 38 | 39 | Graph* chDownGraph( CH* this ) ; 40 | -------------------------------------------------------------------------------- /core/edgepayload.c: -------------------------------------------------------------------------------- 1 | #include "graphserver.h" 2 | 3 | //--------------------EDGEPAYLOAD FUNCTIONS------------------- 4 | 5 | EdgePayload* 6 | epNew( edgepayload_t type, void* payload ) { 7 | EdgePayload* ret = (EdgePayload*)malloc(sizeof(EdgePayload)); 8 | ret->external_id = 0; 9 | ret->type = PL_NONE; 10 | return ret; 11 | } 12 | 13 | EdgePayload* 14 | epDup( EdgePayload* this ) { 15 | EdgePayload* ret = (EdgePayload*)malloc( sizeof(EdgePayload) ); 16 | memcpy( ret, this, sizeof( EdgePayload ) ); 17 | return ret; 18 | } 19 | 20 | void 21 | epDestroy( EdgePayload* this ) { 22 | switch( this->type ) { 23 | case PL_STREET: 24 | streetDestroy( (Street*)this ); 25 | break; 26 | case PL_LINK: 27 | linkDestroy( (Link*)this ); 28 | break; 29 | case PL_EXTERNVALUE: 30 | cpDestroy( (CustomPayload*)this ); 31 | break; 32 | case PL_WAIT: 33 | waitDestroy( (Wait*)this ); 34 | break; 35 | case PL_HEADWAY: 36 | headwayDestroy( (Headway*)this ); 37 | break; 38 | case PL_EGRESS: 39 | egressDestroy( (Egress*)this ); 40 | break; 41 | case PL_TRIPBOARD: 42 | tbDestroy( (TripBoard*)this ); 43 | break; 44 | case PL_ALIGHT: 45 | alDestroy( (TripAlight*)this ); 46 | break; 47 | case PL_CROSSING: 48 | crDestroy( (Crossing*)this ); 49 | break; 50 | default: 51 | free( this ); 52 | } 53 | } 54 | 55 | edgepayload_t 56 | epGetType( EdgePayload* this ) { 57 | return this->type; 58 | } 59 | 60 | long 61 | epGetExternalId( EdgePayload *this ) { 62 | return this->external_id; 63 | } 64 | 65 | void 66 | epSetExternalId( EdgePayload *this, long external_id ) { 67 | this->external_id = external_id; 68 | } 69 | 70 | State* 71 | epWalk( EdgePayload* this, State* state, WalkOptions* options ) { 72 | if( !this ) 73 | return NULL; 74 | 75 | if( this->type == PL_EXTERNVALUE ) { 76 | return cpWalk( (CustomPayload*)this, state, options ); 77 | } 78 | 79 | return this->walk( this, state, options ); 80 | 81 | } 82 | 83 | State* 84 | epWalkBack( EdgePayload* this, State* state, WalkOptions* options ) { 85 | if(!this) 86 | return NULL; 87 | 88 | if( this->type == PL_EXTERNVALUE ){ 89 | return cpWalkBack( (CustomPayload*)this, state, options ); 90 | } 91 | 92 | return this->walkBack( this, state, options ); 93 | } 94 | -------------------------------------------------------------------------------- /core/edgepayload.h: -------------------------------------------------------------------------------- 1 | #ifndef _EDGEPAYLOAD_H_ 2 | #define _EDGEPAYLOAD_H_ 3 | 4 | //---------------DECLARATIONS FOR EDGEPAYLOAD CLASS--------------------- 5 | 6 | struct EdgePayload { 7 | edgepayload_t type; 8 | long external_id; 9 | State* (*walk)(struct EdgePayload*, struct State*, struct WalkOptions*); 10 | State* (*walkBack)(struct EdgePayload*, struct State*, struct WalkOptions*); 11 | } ; 12 | 13 | EdgePayload* 14 | epNew( edgepayload_t type, void* payload ); 15 | 16 | void 17 | epDestroy( EdgePayload* this ); 18 | 19 | edgepayload_t 20 | epGetType( EdgePayload* this ); 21 | 22 | long 23 | epGetExternalId( EdgePayload* this ); 24 | 25 | void 26 | epSetExternalId( EdgePayload *this, long external_id ); 27 | 28 | State* 29 | epWalk( EdgePayload* this, State* param, WalkOptions* options ); 30 | 31 | State* 32 | epWalkBack( EdgePayload* this, State* param, WalkOptions* options ); 33 | 34 | #endif 35 | -------------------------------------------------------------------------------- /core/edgetypes/combination.c: -------------------------------------------------------------------------------- 1 | #include "../graphserver.h" 2 | 3 | //=========COMBINATION FUNCTIONS============== 4 | 5 | Combination* 6 | comboNew(int cap) { 7 | Combination* ret = (Combination*)malloc(sizeof(Combination)); 8 | ret->external_id = 0; 9 | ret->type = PL_COMBINATION; 10 | ret->cap = cap; 11 | ret->n = 0; 12 | ret->payloads = (EdgePayload**)malloc(cap*sizeof(EdgePayload*)); 13 | 14 | ret->cache_state_forward = NULL; 15 | ret->cache_state_reverse = NULL; 16 | 17 | ret->walk = &comboWalk; 18 | ret->walkBack = &comboWalkBack; 19 | 20 | return ret; 21 | } 22 | 23 | void 24 | comboAdd(Combination *this, EdgePayload *ep) { 25 | if( this->n < this->cap ) { 26 | this->payloads[this->n] = ep; 27 | this->n++; 28 | } 29 | } 30 | 31 | void 32 | comboDestroy(Combination* this) { 33 | if( this->cache_state_forward ) 34 | stateDestroy( this->cache_state_forward ); 35 | if( this->cache_state_reverse ) 36 | stateDestroy( this->cache_state_reverse ); 37 | 38 | free( this->payloads ); 39 | free( this ); 40 | } 41 | 42 | inline State* 43 | comboWalk(EdgePayload* superthis, State* param, WalkOptions* options) { 44 | Combination* this = (Combination*)superthis; 45 | 46 | if( this->cache_state_forward ) { 47 | State* ret = stateDup( this->cache_state_forward ); 48 | ret->weight = param->weight+this->cache_deltaw_forward; 49 | ret->time = param->time+this->cache_deltat_forward; 50 | return ret; 51 | } 52 | 53 | if( this->n == 0 ) return NULL; 54 | 55 | State* ret = epWalk( this->payloads[0], param, options ); 56 | 57 | int i; 58 | for(i=1; in; i++) { 59 | State* intermediate = ret; 60 | ret = epWalk( this->payloads[i], intermediate, options ); 61 | stateDestroy( intermediate ); 62 | } 63 | 64 | this->cache_state_forward = stateDup( ret ); 65 | this->cache_deltaw_forward = ret->weight - param->weight; 66 | this->cache_deltat_forward = ret->time - param->time; 67 | 68 | return ret; 69 | } 70 | 71 | inline State* 72 | comboWalkBack(EdgePayload* superthis, State* param, WalkOptions* options) { 73 | Combination* this = (Combination*)superthis; 74 | 75 | if( this->cache_state_reverse ) { 76 | State* ret = stateDup( this->cache_state_reverse ); 77 | ret->weight = param->weight+this->cache_deltaw_reverse; 78 | ret->time = param->time+this->cache_deltat_reverse; 79 | return ret; 80 | } 81 | 82 | if( this->n == 0 ) return NULL; 83 | 84 | State* ret = epWalkBack( this->payloads[this->n-1], param, options ); 85 | 86 | int i; 87 | for(i=this->n-2; i>=0; i--) { 88 | State* intermediate = ret; 89 | ret = epWalkBack( this->payloads[i], intermediate, options ); 90 | stateDestroy( intermediate ); 91 | } 92 | 93 | this->cache_state_reverse = stateDup( ret ); 94 | this->cache_deltaw_reverse = ret->weight - param->weight; 95 | this->cache_deltat_reverse = ret->time - param->time; 96 | 97 | return ret; 98 | } 99 | 100 | EdgePayload* 101 | comboGet(Combination *this, int i) { 102 | if( i < this->n && i >= 0 ) { 103 | return this->payloads[i]; 104 | } else { 105 | return NULL; 106 | } 107 | } 108 | 109 | int 110 | comboN(Combination *this) { 111 | return this->n; 112 | } 113 | 114 | -------------------------------------------------------------------------------- /core/edgetypes/combination.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef _COMBINATION_H_ 3 | #define _COMBINATION_H_ 4 | 5 | //---------------DECLARATIONS FOR COMBINATION CLASS--------------------- 6 | 7 | struct Combination { 8 | edgepayload_t type; 9 | long external_id; 10 | State* (*walk)(struct EdgePayload*, struct State*, struct WalkOptions*); 11 | State* (*walkBack)(struct EdgePayload*, struct State*, struct WalkOptions*); 12 | 13 | int cap; 14 | int n; 15 | EdgePayload** payloads; 16 | 17 | long cache_deltaw_forward; 18 | long cache_deltat_forward; 19 | State *cache_state_forward; 20 | long cache_deltaw_reverse; 21 | long cache_deltat_reverse; 22 | State *cache_state_reverse; 23 | 24 | } ; 25 | 26 | Combination* 27 | comboNew(int cap) ; 28 | 29 | void 30 | comboAdd(Combination *this, EdgePayload *ep) ; 31 | 32 | void 33 | comboDestroy(Combination* this) ; 34 | 35 | inline State* 36 | comboWalk(EdgePayload* superthis, State* param, WalkOptions* options) ; 37 | 38 | inline State* 39 | comboWalkBack(EdgePayload* superthis, State* param, WalkOptions* options) ; 40 | 41 | EdgePayload* 42 | comboGet(Combination *this, int i) ; 43 | 44 | int 45 | comboN(Combination *this) ; 46 | 47 | #endif 48 | -------------------------------------------------------------------------------- /core/edgetypes/crossing.h: -------------------------------------------------------------------------------- 1 | #ifndef _CROSSING_H_ 2 | #define _CROSSING_H_ 3 | 4 | //---------------DECLARATIONS FOR CROSSING CLASS------------------------------------------- 5 | 6 | struct Crossing { 7 | edgepayload_t type; 8 | long external_id; 9 | State* (*walk)(struct EdgePayload*, struct State*, struct WalkOptions*); 10 | State* (*walkBack)(struct EdgePayload*, struct State*, struct WalkOptions*); 11 | 12 | int* crossing_times; 13 | char** crossing_time_trip_ids; 14 | int n; 15 | } ; 16 | 17 | Crossing* 18 | crNew(void); 19 | 20 | void 21 | crDestroy(Crossing* this); 22 | 23 | void 24 | crAddCrossingTime(Crossing* this, char* trip_id, int crossing_time); 25 | 26 | int 27 | crGetCrossingTime(Crossing* this, char* trip_id); 28 | 29 | char* 30 | crGetCrossingTimeTripIdByIndex(Crossing* this, int i); 31 | 32 | int 33 | crGetCrossingTimeByIndex(Crossing* this, int i); 34 | 35 | int 36 | crGetSize(Crossing* this); 37 | 38 | inline State* 39 | crWalk( EdgePayload* superthis, State* state, WalkOptions* options ); 40 | 41 | inline State* 42 | crWalkBack( EdgePayload* superthis, State* state, WalkOptions* options ); 43 | 44 | #endif 45 | -------------------------------------------------------------------------------- /core/edgetypes/custompayload.c: -------------------------------------------------------------------------------- 1 | #include "../graphserver.h" 2 | 3 | // CUSTOM Payload Functions 4 | 5 | PayloadMethods* 6 | defineCustomPayloadType(void (*destroy)(void*), 7 | State* (*walk)(void*,State*,WalkOptions*), 8 | State* (*walkback)(void*,State*,WalkOptions*)) { 9 | PayloadMethods* this = (PayloadMethods*)malloc(sizeof(PayloadMethods)); 10 | this->destroy = destroy; 11 | this->walk = walk; 12 | this->walkBack = walkback; 13 | return this; 14 | } 15 | 16 | void 17 | undefineCustomPayloadType( PayloadMethods* this ) { 18 | free(this); 19 | } 20 | 21 | CustomPayload* 22 | cpNew( void* soul, PayloadMethods* methods ) { 23 | CustomPayload* this = (CustomPayload*)malloc(sizeof(CustomPayload)); 24 | this->type = PL_EXTERNVALUE; 25 | this->soul = soul; 26 | this->methods = methods; 27 | return this; 28 | } 29 | 30 | void 31 | cpDestroy( CustomPayload* this ) { 32 | this->methods->destroy(this->soul); 33 | free( this ); 34 | } 35 | 36 | void* 37 | cpSoul( CustomPayload* this ) { 38 | return this->soul; 39 | } 40 | 41 | PayloadMethods* 42 | cpMethods( CustomPayload* this ) { 43 | return this->methods; 44 | } 45 | 46 | State* 47 | cpWalk(CustomPayload* this, State* state, WalkOptions* walkoptions) { 48 | State* s = this->methods->walk(this->soul, state, walkoptions); 49 | s->prev_edge = (EdgePayload*)this; 50 | return s; 51 | } 52 | State* 53 | cpWalkBack(CustomPayload* this, State* state, WalkOptions* walkoptions) { 54 | State* s = this->methods->walkBack(this->soul, state, walkoptions); 55 | s->prev_edge = (EdgePayload*)this; 56 | return s; 57 | } 58 | -------------------------------------------------------------------------------- /core/edgetypes/custompayload.h: -------------------------------------------------------------------------------- 1 | #ifndef _CUSTOMPAYLOAD_H_ 2 | #define _CUSTOMPAYLOAD_H_ 3 | 4 | struct PayloadMethods { 5 | void (*destroy)(void*); 6 | State* (*walk)(void*,State*,WalkOptions*); 7 | State* (*walkBack)(void*,State*,WalkOptions*); 8 | //char* (*to_str)(void*); 9 | }; 10 | 11 | struct CustomPayload { 12 | edgepayload_t type; 13 | void* soul; 14 | PayloadMethods* methods; 15 | }; 16 | 17 | PayloadMethods* 18 | defineCustomPayloadType(void (*destroy)(void*), 19 | State* (*walk)(void*,State*,WalkOptions*), 20 | State* (*walkback)(void*,State*,WalkOptions*)); 21 | 22 | 23 | void 24 | undefineCustomPayloadType( PayloadMethods* this ); 25 | 26 | CustomPayload* 27 | cpNew( void* soul, PayloadMethods* methods ); 28 | 29 | void 30 | cpDestroy( CustomPayload* this ); 31 | 32 | void* 33 | cpSoul( CustomPayload* this ); 34 | 35 | PayloadMethods* 36 | cpMethods( CustomPayload* this ); 37 | 38 | State* 39 | cpWalk(CustomPayload* this, State* state, WalkOptions* walkoptions); 40 | 41 | State* 42 | cpWalkBack(CustomPayload* this, State* state, WalkOptions* walkoptions); 43 | 44 | #endif 45 | -------------------------------------------------------------------------------- /core/edgetypes/egress.c: -------------------------------------------------------------------------------- 1 | 2 | #include "../graphserver.h" 3 | 4 | //EGRESS FUNCTIONS 5 | Egress* 6 | egressNew(const char *name, double length) { 7 | Egress* ret = (Egress*)malloc(sizeof(Egress)); 8 | ret->external_id = 0; 9 | ret->type = PL_EGRESS; 10 | ret->name = (char*)malloc((strlen(name)+1)*sizeof(char)); 11 | strcpy(ret->name, name); 12 | ret->length = length; 13 | 14 | //bind functions to methods 15 | ret->walk = &egressWalk; 16 | ret->walkBack = &egressWalkBack; 17 | 18 | return ret; 19 | } 20 | 21 | void 22 | egressDestroy(Egress* tokill) { 23 | free(tokill->name); 24 | free(tokill); 25 | } 26 | 27 | char* 28 | egressGetName(Egress* this) { 29 | return this->name; 30 | } 31 | 32 | double 33 | egressGetLength(Egress* this) { 34 | return this->length; 35 | } 36 | 37 | 38 | inline State* 39 | egressWalkGeneral(EdgePayload* superthis, State* state, WalkOptions* options, int forward) { 40 | Egress* this = (Egress*)superthis; 41 | State* ret = stateDup( state ); 42 | 43 | double end_dist = state->dist_walked + this->length; 44 | // no matter what the options say (e.g. you're on a bike), 45 | // the walking speed should be 1.1 mps, because you can't ride in 46 | // a station 47 | long delta_t = (long)(this->length/1.1); 48 | long delta_w = delta_t*options->walking_reluctance; 49 | if(end_dist > options->max_walk) 50 | delta_w += (end_dist - options->max_walk)*options->walking_overage*delta_t; 51 | 52 | if( forward ) { 53 | elapse_time_and_service_period_forward(ret, state, delta_t); 54 | } else { 55 | elapse_time_and_service_period_backward(ret, state, delta_t); 56 | } 57 | 58 | ret->weight += delta_w; 59 | ret->dist_walked = end_dist; 60 | ret->prev_edge = superthis; 61 | 62 | return ret; 63 | } 64 | 65 | inline State* 66 | egressWalk(EdgePayload* superthis, State* state, WalkOptions* options) { 67 | return egressWalkGeneral( superthis, state, options, TRUE ); 68 | } 69 | 70 | inline State* 71 | egressWalkBack(EdgePayload* superthis, State* state, WalkOptions* options) { 72 | return egressWalkGeneral( superthis, state, options, FALSE ); 73 | } 74 | -------------------------------------------------------------------------------- /core/edgetypes/egress.h: -------------------------------------------------------------------------------- 1 | #ifndef _EGRESS_H_ 2 | #define _EGRESS_H_ 3 | 4 | //---------------DECLARATIONS FOR EGRESS CLASS--------------------- 5 | 6 | struct Egress { 7 | edgepayload_t type; 8 | long external_id; 9 | State* (*walk)(struct EdgePayload*, struct State*, struct WalkOptions*); 10 | State* (*walkBack)(struct EdgePayload*, struct State*, struct WalkOptions*); 11 | 12 | char* name; 13 | double length; 14 | } ; 15 | 16 | Egress* 17 | egressNew(const char *name, double length); 18 | 19 | void 20 | egressDestroy(Egress* tokill); 21 | 22 | inline State* 23 | egressWalk(EdgePayload* superthis, State* state, WalkOptions* options); 24 | 25 | inline State* 26 | egressWalkBack(EdgePayload* superthis, State* state, WalkOptions* options); 27 | 28 | char* 29 | egressGetName(Egress* this); 30 | 31 | double 32 | egressGetLength(Egress* this); 33 | 34 | #endif 35 | -------------------------------------------------------------------------------- /core/edgetypes/elapsehelpers.c: -------------------------------------------------------------------------------- 1 | #include "../graphserver.h" 2 | 3 | void elapse_time_and_service_period_forward(State *ret, State *state, long delta_t) { 4 | int i; 5 | ret->time += delta_t; 6 | for(i=0; in_agencies; i++) { 7 | ServicePeriod* sp = state->service_periods[i]; 8 | if(sp && ret->time >= sp->end_time) { 9 | ret->service_periods[i] = sp->next_period; 10 | } 11 | } 12 | } 13 | 14 | void elapse_time_and_service_period_backward(State *ret, State *state, long delta_t) { 15 | int i; 16 | ret->time -= delta_t; 17 | for(i=0; in_agencies; i++) { 18 | ServicePeriod* sp = state->service_periods[i]; 19 | if(sp && ret->time < sp->begin_time) { 20 | ret->service_periods[i] = sp->prev_period; 21 | } 22 | } 23 | } -------------------------------------------------------------------------------- /core/edgetypes/elapsehelpers.h: -------------------------------------------------------------------------------- 1 | 2 | void elapse_time_and_service_period_forward(State *ret, State *state, long delta_t) ; 3 | 4 | void elapse_time_and_service_period_backward(State *ret, State *state, long delta_t) ; -------------------------------------------------------------------------------- /core/edgetypes/elapsetime.c: -------------------------------------------------------------------------------- 1 | #include "../graphserver.h" 2 | 3 | //ElapseTime FUNCTIONS 4 | ElapseTime* 5 | elapseTimeNew(long seconds) { 6 | ElapseTime* ret = (ElapseTime*)malloc(sizeof(ElapseTime)); 7 | ret->external_id = 0; 8 | ret->type = PL_ELAPSE_TIME; 9 | ret->seconds = seconds; 10 | 11 | ret->walk = elapseTimeWalk; 12 | ret->walkBack = elapseTimeWalkBack; 13 | 14 | return ret; 15 | } 16 | 17 | void 18 | elapseTimeDestroy(ElapseTime* tokill) { 19 | free(tokill); 20 | } 21 | 22 | long 23 | elapseTimeGetSeconds(ElapseTime* this) { 24 | return this->seconds; 25 | } 26 | 27 | inline State* 28 | elapseTimeWalkGeneral(EdgePayload* this, State* state, WalkOptions* options, int forward) { 29 | 30 | State* ret = stateDup( state ); 31 | 32 | int delta_t = ((ElapseTime*)this)->seconds; 33 | 34 | if( forward ) { 35 | elapse_time_and_service_period_forward(ret, state, delta_t); 36 | } else { 37 | elapse_time_and_service_period_backward(ret, state, delta_t); 38 | } 39 | 40 | // this could have a multiplier via WalkOptions, but this is currently not necessary 41 | ret->weight += delta_t; 42 | ret->prev_edge = this; 43 | 44 | return ret; 45 | } 46 | 47 | inline State* 48 | elapseTimeWalk(EdgePayload* this, State* state, WalkOptions* options) { 49 | return elapseTimeWalkGeneral( this, state, options, TRUE ); 50 | } 51 | 52 | inline State* 53 | elapseTimeWalkBack(EdgePayload* this, State* state, WalkOptions* options) { 54 | return elapseTimeWalkGeneral( this, state, options, FALSE ); 55 | } 56 | -------------------------------------------------------------------------------- /core/edgetypes/elapsetime.h: -------------------------------------------------------------------------------- 1 | #ifndef _ELAPSETIME_H_ 2 | #define _ELAPSETIME_H_ 3 | 4 | //---------------DECLARATIONS FOR ELAPSE TIME CLASS------------------------ 5 | 6 | struct ElapseTime { 7 | edgepayload_t type; 8 | long external_id; 9 | State* (*walk)(struct EdgePayload*, struct State*, struct WalkOptions*); 10 | State* (*walkBack)(struct EdgePayload*, struct State*, struct WalkOptions*); 11 | 12 | long seconds; 13 | } ; 14 | 15 | ElapseTime* 16 | elapseTimeNew(long seconds); 17 | 18 | void 19 | elapseTimeDestroy(ElapseTime* tokill); 20 | 21 | inline State* 22 | elapseTimeWalk(EdgePayload* superthis, State* param, WalkOptions* options); 23 | 24 | inline State* 25 | elapseTimeWalkBack(EdgePayload* superthis, State* param, WalkOptions* options); 26 | 27 | long 28 | elapseTimeGetSeconds(ElapseTime* this); 29 | 30 | #endif 31 | -------------------------------------------------------------------------------- /core/edgetypes/headway.h: -------------------------------------------------------------------------------- 1 | #ifndef _HEADWAY_H_ 2 | #define _HEADWAY_H_ 3 | 4 | //---------------DECLARATIONS FOR HEADWAY CLASS--------------------- 5 | 6 | struct Headway { 7 | edgepayload_t type; 8 | long external_id; 9 | State* (*walk)(struct EdgePayload*, struct State*, struct WalkOptions*); 10 | State* (*walkBack)(struct EdgePayload*, struct State*, struct WalkOptions*); 11 | 12 | int begin_time; 13 | int end_time; 14 | int wait_period; 15 | int transit; 16 | char* trip_id; 17 | ServiceCalendar* calendar; 18 | Timezone* timezone; 19 | int agency; 20 | ServiceId service_id; 21 | } ; 22 | 23 | Headway* 24 | headwayNew(int begin_time, int end_time, int wait_period, int transit, char* trip_id, ServiceCalendar* calendar, Timezone* timezone, int agency, ServiceId service_id); 25 | 26 | void 27 | headwayDestroy(Headway* tokill); 28 | 29 | inline State* 30 | headwayWalk(EdgePayload* this, State* param, WalkOptions* options); 31 | 32 | inline State* 33 | headwayWalkBack(EdgePayload* this, State* param, WalkOptions* options); 34 | 35 | int 36 | headwayBeginTime(Headway* this); 37 | 38 | int 39 | headwayEndTime(Headway* this); 40 | 41 | int 42 | headwayWaitPeriod(Headway* this); 43 | 44 | int 45 | headwayTransit(Headway* this); 46 | 47 | char* 48 | headwayTripId(Headway* this); 49 | 50 | ServiceCalendar* 51 | headwayCalendar(Headway* this); 52 | 53 | Timezone* 54 | headwayTimezone(Headway* this); 55 | 56 | int 57 | headwayAgency(Headway* this); 58 | 59 | ServiceId 60 | headwayServiceId(Headway* this); 61 | 62 | #endif 63 | -------------------------------------------------------------------------------- /core/edgetypes/headwayalight.h: -------------------------------------------------------------------------------- 1 | #ifndef _HEADWAYALIGHT_H_ 2 | #define _HEADWAYALIGHT_H_ 3 | 4 | //---------------DECLARATIONS FOR HEADWAYALIGHT CLASS--------------------------------------- 5 | 6 | struct HeadwayAlight { 7 | edgepayload_t type; 8 | long external_id; 9 | State* (*walk)(struct EdgePayload*, struct State*, struct WalkOptions*); 10 | State* (*walkBack)(struct EdgePayload*, struct State*, struct WalkOptions*); 11 | 12 | ServiceId service_id; 13 | char* trip_id; 14 | int start_time; 15 | int end_time; 16 | int headway_secs; 17 | 18 | ServiceCalendar* calendar; 19 | Timezone* timezone; 20 | int agency; 21 | }; 22 | 23 | HeadwayAlight* 24 | haNew( ServiceId service_id, ServiceCalendar* calendar, Timezone* timezone, int agency, char* trip_id, int start_time, int end_time, int headway_secs ); 25 | 26 | void 27 | haDestroy(HeadwayAlight* this); 28 | 29 | ServiceCalendar* 30 | haGetCalendar( HeadwayAlight* this ); 31 | 32 | Timezone* 33 | haGetTimezone( HeadwayAlight* this ); 34 | 35 | int 36 | haGetAgency( HeadwayAlight* this ); 37 | 38 | ServiceId 39 | haGetServiceId( HeadwayAlight* this ); 40 | 41 | char* 42 | haGetTripId( HeadwayAlight* this ); 43 | 44 | int 45 | haGetStartTime( HeadwayAlight* this ); 46 | 47 | int 48 | haGetEndTime( HeadwayAlight* this ); 49 | 50 | int 51 | haGetHeadwaySecs( HeadwayAlight* this ); 52 | 53 | inline State* 54 | haWalk( EdgePayload* superthis, State* state, WalkOptions* options ); 55 | 56 | inline State* 57 | haWalkBack( EdgePayload* superthis, State* state, WalkOptions* options ); 58 | 59 | #endif 60 | -------------------------------------------------------------------------------- /core/edgetypes/headwayboard.h: -------------------------------------------------------------------------------- 1 | #ifndef _HEADWAYBOARD_H_ 2 | #define _HEADWAYBOARD_H_ 3 | 4 | //---------------DECLARATIONS FOR HEADWAYBOARD CLASS--------------------------------------- 5 | 6 | struct HeadwayBoard { 7 | edgepayload_t type; 8 | long external_id; 9 | State* (*walk)(struct EdgePayload*, struct State*, struct WalkOptions*); 10 | State* (*walkBack)(struct EdgePayload*, struct State*, struct WalkOptions*); 11 | 12 | ServiceId service_id; 13 | char* trip_id; 14 | int start_time; 15 | int end_time; 16 | int headway_secs; 17 | 18 | ServiceCalendar* calendar; 19 | Timezone* timezone; 20 | int agency; 21 | } ; 22 | 23 | HeadwayBoard* 24 | hbNew( ServiceId service_id, ServiceCalendar* calendar, Timezone* timezone, int agency, char* trip_id, int start_time, int end_time, int headway_secs ); 25 | 26 | void 27 | hbDestroy(HeadwayBoard* this); 28 | 29 | ServiceCalendar* 30 | hbGetCalendar( HeadwayBoard* this ); 31 | 32 | Timezone* 33 | hbGetTimezone( HeadwayBoard* this ); 34 | 35 | int 36 | hbGetAgency( HeadwayBoard* this ); 37 | 38 | ServiceId 39 | hbGetServiceId( HeadwayBoard* this ); 40 | 41 | char* 42 | hbGetTripId( HeadwayBoard* this ); 43 | 44 | int 45 | hbGetStartTime( HeadwayBoard* this ); 46 | 47 | int 48 | hbGetEndTime( HeadwayBoard* this ); 49 | 50 | int 51 | hbGetHeadwaySecs( HeadwayBoard* this ); 52 | 53 | inline State* 54 | hbWalk( EdgePayload* superthis, State* state, WalkOptions* options ); 55 | 56 | inline State* 57 | hbWalkBack( EdgePayload* superthis, State* state, WalkOptions* options ); 58 | 59 | #endif 60 | -------------------------------------------------------------------------------- /core/edgetypes/link.c: -------------------------------------------------------------------------------- 1 | 2 | #include "../graphserver.h" 3 | 4 | //LINK FUNCTIONS 5 | Link* 6 | linkNew() { 7 | Link* ret = (Link*)malloc(sizeof(Link)); 8 | ret->external_id = 0; 9 | ret->type = PL_LINK; 10 | ret->name = (char*)malloc(5*sizeof(char)); 11 | strcpy(ret->name, "LINK"); 12 | 13 | //bind functions to methods 14 | ret->walk = &linkWalk; 15 | ret->walkBack = &linkWalkBack; 16 | 17 | return ret; 18 | } 19 | 20 | void 21 | linkDestroy(Link* tokill) { 22 | free( tokill->name ); 23 | free( tokill ); 24 | } 25 | 26 | char* 27 | linkGetName(Link* this) { 28 | return this->name; 29 | } 30 | 31 | int 32 | linkReturnOne(Link* this) { 33 | return 1; 34 | } 35 | 36 | inline State* 37 | linkWalkBackGeneral(EdgePayload* this, State* state, WalkOptions* options) { 38 | 39 | State* ret = stateDup( state ); 40 | 41 | ret->prev_edge = this; 42 | 43 | return ret; 44 | } 45 | 46 | inline State* 47 | linkWalkBack(EdgePayload* this, State* state, WalkOptions* options) { 48 | return linkWalkBackGeneral(this, state, options); 49 | } 50 | 51 | inline State* 52 | linkWalk(EdgePayload* this, State* state, WalkOptions* options) { 53 | return linkWalkBackGeneral(this, state, options); 54 | } 55 | -------------------------------------------------------------------------------- /core/edgetypes/link.h: -------------------------------------------------------------------------------- 1 | #ifndef _LINK_H_ 2 | #define _LINK_H_ 3 | 4 | //---------------DECLARATIONS FOR LINK CLASS--------------------- 5 | 6 | struct Link { 7 | edgepayload_t type; 8 | long external_id; 9 | State* (*walk)(struct EdgePayload*, struct State*, struct WalkOptions*); 10 | State* (*walkBack)(struct EdgePayload*, struct State*, struct WalkOptions*); 11 | 12 | char* name; 13 | }; 14 | 15 | Link* 16 | linkNew(void); 17 | 18 | void 19 | linkDestroy(Link* tokill); 20 | 21 | inline State* 22 | linkWalk(EdgePayload* this, State* param, WalkOptions* options); 23 | 24 | inline State* 25 | linkWalkBack(EdgePayload* this, State* param, WalkOptions* options); 26 | 27 | char* 28 | linkGetName(Link* this); 29 | 30 | #endif 31 | -------------------------------------------------------------------------------- /core/edgetypes/street.c: -------------------------------------------------------------------------------- 1 | #include "../graphserver.h" 2 | 3 | //STREET FUNCTIONS 4 | Street* 5 | streetNew(const char *name, double length, int reverse_of_source) { 6 | Street* ret = (Street*)malloc(sizeof(Street)); 7 | ret->external_id = 0; 8 | ret->type = PL_STREET; 9 | ret->name = (char*)malloc((strlen(name)+1)*sizeof(char)); 10 | strcpy(ret->name, name); 11 | ret->length = length; 12 | ret->rise = 0; 13 | ret->fall = 0; 14 | ret->slog = 1; 15 | ret->way = 0; 16 | ret->reverse_of_source = reverse_of_source; 17 | 18 | //bind functions to methods 19 | ret->walk = &streetWalk; 20 | ret->walkBack = &streetWalkBack; 21 | 22 | return ret; 23 | } 24 | 25 | Street* 26 | streetNewElev(const char *name, double length, float rise, float fall, int reverse_of_source) { 27 | Street* ret = streetNew( name, length, reverse_of_source ); 28 | ret->rise = rise; 29 | ret->fall = fall; 30 | return ret; 31 | } 32 | 33 | void 34 | streetDestroy(Street* tokill) { 35 | free(tokill->name); 36 | free(tokill); 37 | } 38 | 39 | char* 40 | streetGetName(Street* this) { 41 | return this->name; 42 | } 43 | 44 | double 45 | streetGetLength(Street* this) { 46 | return this->length; 47 | } 48 | 49 | float 50 | streetGetRise(Street* this) { 51 | return this->rise; 52 | } 53 | 54 | void 55 | streetSetRise(Street* this, float rise) { 56 | this->rise = rise; 57 | } 58 | 59 | float 60 | streetGetFall(Street* this) { 61 | return this->fall; 62 | } 63 | 64 | void 65 | streetSetFall(Street* this, float fall) { 66 | this->fall = fall; 67 | } 68 | 69 | float 70 | streetGetSlog(Street* this) { 71 | return this->slog; 72 | } 73 | 74 | void 75 | streetSetSlog(Street* this, float slog) { 76 | this->slog = slog; 77 | } 78 | 79 | long 80 | streetGetWay(Street* this) { 81 | return this->way; 82 | } 83 | 84 | void 85 | streetSetWay(Street* this, long way) { 86 | this->way = way; 87 | } 88 | 89 | int 90 | streetGetReverseOfSource( Street *this ) { 91 | return this->reverse_of_source; 92 | } 93 | 94 | #ifndef EDGEWEIGHTS_FIRSTTHROUGH 95 | #define EDGEWEIGHTS_FIRSTTHROUGH 1 96 | float speed_from_grade(WalkOptions* options, float grade) { 97 | if( grade <= 0 ) { 98 | return options->downhill_fastness*grade + options->walking_speed; 99 | } else if( grade <= options->phase_change_grade ) { 100 | return options->phase_change_velocity_factor*grade*grade + options->downhill_fastness*grade + options->walking_speed; 101 | } else { 102 | return (options->uphill_slowness*options->walking_speed)/(options->uphill_slowness+grade); 103 | } 104 | } 105 | #endif 106 | 107 | inline State* 108 | streetWalkGeneral(EdgePayload* superthis, State* state, WalkOptions* options, int forward) { 109 | Street* this = (Street*)superthis; 110 | State* ret = stateDup( state ); 111 | 112 | float average_grade = 0; 113 | if (this->length > 0) { 114 | average_grade = (this->rise-this->fall)/this->length; 115 | } 116 | float average_speed = speed_from_grade(options, average_grade); 117 | 118 | long delta_t = this->length / average_speed; 119 | 120 | long delta_w = delta_t*options->walking_reluctance + this->rise*options->hill_reluctance; 121 | if( delta_w < 0 ) { 122 | delta_w = 0; 123 | } 124 | 125 | // max_walk overage considerations 126 | double end_dist = state->dist_walked + this->length; 127 | if(end_dist > options->max_walk) 128 | delta_w += (end_dist - options->max_walk)*options->walking_overage*delta_t; 129 | 130 | // turning considerations 131 | if( state->prev_edge && 132 | state->prev_edge->type == PL_STREET && 133 | ((Street*)state->prev_edge)->way != this->way ) { 134 | delta_w += options->turn_penalty; 135 | } 136 | 137 | if( forward ) { 138 | elapse_time_and_service_period_forward(ret, state, delta_t); 139 | } else { 140 | elapse_time_and_service_period_backward(ret, state, delta_t); 141 | } 142 | 143 | if (end_dist > ABSOLUTE_MAX_WALK) //TODO profile this to see if it's worth it 144 | ret->weight = MAX_LONG; 145 | else 146 | ret->weight += this->slog*delta_w; 147 | ret->dist_walked = end_dist; 148 | ret->prev_edge = superthis; 149 | 150 | return ret; 151 | } 152 | 153 | inline State* 154 | streetWalk(EdgePayload* superthis, State* state, WalkOptions* options) { 155 | return streetWalkGeneral(superthis, state, options, TRUE); 156 | } 157 | 158 | inline State* 159 | streetWalkBack(EdgePayload* superthis, State* state, WalkOptions* options) { 160 | return streetWalkGeneral(superthis, state, options, FALSE); 161 | } 162 | -------------------------------------------------------------------------------- /core/edgetypes/street.h: -------------------------------------------------------------------------------- 1 | #ifndef _STREET_H_ 2 | #define _STREET_H_ 3 | 4 | //---------------DECLARATIONS FOR STREET CLASS--------------------- 5 | 6 | struct Street { 7 | edgepayload_t type; 8 | long external_id; 9 | State* (*walk)(struct EdgePayload*, struct State*, struct WalkOptions*); 10 | State* (*walkBack)(struct EdgePayload*, struct State*, struct WalkOptions*); 11 | 12 | char* name; 13 | double length; 14 | float rise; 15 | float fall; 16 | float slog; 17 | long way; 18 | 19 | int reverse_of_source; 20 | }; 21 | 22 | Street* 23 | streetNew(const char *name, double length, int reverse_of_source); 24 | 25 | Street* 26 | streetNewElev(const char *name, double length, float rise, float fall, int reverse_of_source); 27 | 28 | void 29 | streetDestroy(Street* tokill); 30 | 31 | inline State* 32 | streetWalk(EdgePayload* superthis, State* state, WalkOptions* options); 33 | 34 | inline State* 35 | streetWalkBack(EdgePayload* superthis, State* state, WalkOptions* options); 36 | 37 | char* 38 | streetGetName(Street* this); 39 | 40 | double 41 | streetGetLength(Street* this); 42 | 43 | float 44 | streetGetRise(Street* this); 45 | 46 | float 47 | streetGetFall(Street* this); 48 | 49 | void 50 | streetSetRise(Street* this, float rise) ; 51 | 52 | void 53 | streetSetFall(Street* this, float fall) ; 54 | long 55 | streetGetWay(Street* this); 56 | 57 | void 58 | streetSetWay(Street* this, long way); 59 | 60 | int 61 | streetGetReverseOfSource(Street* this) ; 62 | 63 | #endif 64 | -------------------------------------------------------------------------------- /core/edgetypes/tripalight.h: -------------------------------------------------------------------------------- 1 | #ifndef _ALIGHT_H_ 2 | #define _ALIGHT_H_ 3 | 4 | //---------------DECLARATIONS FOR ALIGHT CLASS--------------------------------------------- 5 | 6 | struct TripAlight { 7 | edgepayload_t type; 8 | long external_id; 9 | State* (*walk)(struct EdgePayload*, struct State*, struct WalkOptions*); 10 | State* (*walkBack)(struct EdgePayload*, struct State*, struct WalkOptions*); 11 | 12 | int n; 13 | int* arrivals; 14 | char** trip_ids; 15 | int* stop_sequences; 16 | 17 | ServiceCalendar* calendar; 18 | Timezone* timezone; 19 | int agency; 20 | ServiceId service_id; 21 | 22 | int overage; //number of seconds schedules past midnight of the last departure. If it's at 12:00:00, the overage is 0. 23 | } ; 24 | 25 | TripAlight* 26 | alNew( ServiceId service_id, ServiceCalendar* calendar, Timezone* timezone, int agency ); 27 | 28 | void 29 | alDestroy(TripAlight* this); 30 | 31 | ServiceCalendar* 32 | alGetCalendar( TripAlight* this ); 33 | 34 | Timezone* 35 | alGetTimezone( TripAlight* this ); 36 | 37 | int 38 | alGetAgency( TripAlight* this ); 39 | 40 | ServiceId 41 | alGetServiceId( TripAlight* this ); 42 | 43 | int 44 | alGetNumAlightings(TripAlight* this); 45 | 46 | void 47 | alAddAlighting(TripAlight* this, char* trip_id, int arrival, int stop_sequence); 48 | 49 | char* 50 | alGetAlightingTripId(TripAlight* this, int i); 51 | 52 | int 53 | alGetAlightingArrival(TripAlight* this, int i); 54 | 55 | int 56 | alGetAlightingStopSequence(TripAlight* this, int i); 57 | 58 | int 59 | alSearchAlightingsList(TripAlight* this, int time); 60 | 61 | int 62 | alGetLastAlightingIndex(TripAlight* this, int time); 63 | 64 | int 65 | alGetOverage(TripAlight* this); 66 | 67 | int 68 | alGetAlightingIndexByTripId(TripAlight* this, char* trip_id); 69 | 70 | inline State* 71 | alWalk(EdgePayload* this, State* state, WalkOptions* options); 72 | 73 | inline State* 74 | alWalkBack(EdgePayload* this, State* state, WalkOptions* options); 75 | 76 | #endif 77 | -------------------------------------------------------------------------------- /core/edgetypes/tripboard.h: -------------------------------------------------------------------------------- 1 | #ifndef _TRIPBOARD_H_ 2 | #define _TRIPBOARD_H_ 3 | 4 | #define NO_OVERAGE_VALUE -1 5 | 6 | //---------------DECLARATIONS FOR TRIPBOARD CLASS------------------------------------------ 7 | 8 | struct TripBoard { 9 | edgepayload_t type; 10 | long external_id; 11 | State* (*walk)(struct EdgePayload*, struct State*, struct WalkOptions*); 12 | State* (*walkBack)(struct EdgePayload*, struct State*, struct WalkOptions*); 13 | 14 | int n; 15 | int* departs; 16 | char** trip_ids; 17 | int* stop_sequences; 18 | 19 | ServiceCalendar* calendar; 20 | Timezone* timezone; 21 | int agency; 22 | ServiceId service_id; 23 | 24 | int overage; //number of seconds schedules past midnight of the last departure. If it's at 12:00:00, the overage is 0. 25 | } ; 26 | 27 | TripBoard* 28 | tbNew( ServiceId service_id, ServiceCalendar* calendar, Timezone* timezone, int agency ); 29 | 30 | void 31 | tbDestroy(TripBoard* this); 32 | 33 | ServiceCalendar* 34 | tbGetCalendar( TripBoard* this ); 35 | 36 | Timezone* 37 | tbGetTimezone( TripBoard* this ); 38 | 39 | int 40 | tbGetAgency( TripBoard* this ); 41 | 42 | ServiceId 43 | tbGetServiceId( TripBoard* this ); 44 | 45 | int 46 | tbGetNumBoardings(TripBoard* this); 47 | 48 | void 49 | tbAddBoarding(TripBoard* this, char* trip_id, int depart, int stop_sequence); 50 | 51 | char* 52 | tbGetBoardingTripId(TripBoard* this, int i); 53 | 54 | int 55 | tbGetBoardingDepart(TripBoard* this, int i); 56 | 57 | int 58 | tbGetBoardingStopSequence(TripBoard* this, int i); 59 | 60 | int 61 | tbSearchBoardingsList(TripBoard* this, int time); 62 | 63 | int 64 | tbGetNextBoardingIndex(TripBoard* this, int time); 65 | 66 | int 67 | tbGetOverage(TripBoard* this); 68 | 69 | inline State* 70 | tbWalk( EdgePayload* superthis, State* state, WalkOptions* options ); 71 | 72 | inline State* 73 | tbWalkBack( EdgePayload* superthis, State* state, WalkOptions* options ); 74 | 75 | int 76 | tbGetBoardingIndexByTripId(TripBoard* this, char* trip_id); 77 | 78 | #endif 79 | -------------------------------------------------------------------------------- /core/edgetypes/wait.c: -------------------------------------------------------------------------------- 1 | 2 | #include "../graphserver.h" 3 | 4 | //WAIT FUNCTIONS 5 | Wait* 6 | waitNew(long end, Timezone* timezone) { 7 | Wait* ret = (Wait*)malloc(sizeof(Wait)); 8 | ret->external_id = 0; 9 | ret->type = PL_WAIT; 10 | ret->end = end; 11 | ret->timezone = timezone; 12 | 13 | ret->walk = waitWalk; 14 | ret->walkBack = waitWalkBack; 15 | 16 | return ret; 17 | } 18 | 19 | void 20 | waitDestroy(Wait* tokill) { 21 | free(tokill); 22 | } 23 | 24 | long 25 | waitGetEnd(Wait* this) { 26 | return this->end; 27 | } 28 | 29 | Timezone* 30 | waitGetTimezone(Wait* this) { 31 | return this->timezone; 32 | } 33 | 34 | 35 | inline State* 36 | waitWalk(EdgePayload* superthis, State* state, WalkOptions* options) { 37 | Wait* this = (Wait*)superthis; 38 | 39 | State* ret = stateDup( state ); 40 | 41 | ret->prev_edge = superthis; 42 | 43 | long secs_since_local_midnight = (state->time+tzUtcOffset(this->timezone, state->time))%SECS_IN_DAY; 44 | long wait_time = this->end - secs_since_local_midnight; 45 | if(wait_time<0) { 46 | wait_time += SECS_IN_DAY; 47 | } 48 | 49 | ret->time += wait_time; 50 | ret->weight += wait_time; 51 | 52 | return ret; 53 | } 54 | 55 | inline State* 56 | waitWalkBack(EdgePayload* superthis, State* state, WalkOptions* options) { 57 | Wait* this = (Wait*)superthis; 58 | 59 | State* ret = stateDup( state ); 60 | 61 | ret->prev_edge = superthis; 62 | 63 | long secs_since_local_midnight = (state->time+tzUtcOffset(this->timezone, state->time))%SECS_IN_DAY; 64 | long wait_time = secs_since_local_midnight - this->end; 65 | if(wait_time<0) { 66 | wait_time += SECS_IN_DAY; 67 | } 68 | 69 | ret->time -= wait_time; 70 | ret->weight += wait_time; 71 | 72 | return ret; 73 | } 74 | -------------------------------------------------------------------------------- /core/edgetypes/wait.h: -------------------------------------------------------------------------------- 1 | 2 | //---------------DECLARATIONS FOR WAIT CLASS------------------------ 3 | 4 | struct Wait { 5 | edgepayload_t type; 6 | long external_id; 7 | State* (*walk)(struct EdgePayload*, struct State*, struct WalkOptions*); 8 | State* (*walkBack)(struct EdgePayload*, struct State*, struct WalkOptions*); 9 | 10 | long end; 11 | Timezone* timezone; 12 | } ; 13 | 14 | Wait* 15 | waitNew(long end, Timezone* timezone); 16 | 17 | void 18 | waitDestroy(Wait* tokill); 19 | 20 | inline State* 21 | waitWalk(EdgePayload* superthis, State* param, WalkOptions* options); 22 | 23 | inline State* 24 | waitWalkBack(EdgePayload* superthis, State* param, WalkOptions* options); 25 | 26 | long 27 | waitGetEnd(Wait* this); 28 | 29 | Timezone* 30 | waitGetTimezone(Wait* this); 31 | -------------------------------------------------------------------------------- /core/fibheap/dirfibheap.c: -------------------------------------------------------------------------------- 1 | 2 | #include "../graphserver.h" 3 | #include "fibheap.h" 4 | #include "../graph.h" 5 | #include "dirfibheap.h" 6 | #include 7 | #include "../hashtable/hashtable_gs.h" 8 | #include "../hashtable/hashtable.h" 9 | 10 | dirfibheap_t 11 | dirfibheap_new(long initSize) 12 | { 13 | dirfibheap_t ret = (dirfibheap_t)malloc( sizeof(struct dirfibheap) ); 14 | ret->heap = fibheap_new(); 15 | ret->dir = create_hashtable_string(initSize); 16 | return ret; 17 | } 18 | 19 | fibnode_t 20 | dirfibheap_insert_or_dec_key( dirfibheap_t self, Vertex* vtx, fibheapkey_t priority ) 21 | { 22 | char* key = vtx->label; 23 | 24 | fibnode_t fibnode = hashtable_search( self->dir, key ); 25 | 26 | if( fibnode ) { 27 | fibheap_replace_key( self->heap, fibnode, priority ); 28 | } else { 29 | fibnode = fibheap_insert( self->heap, priority, (void*)vtx ); 30 | hashtable_insert_string(self->dir, key, fibnode); 31 | 32 | } 33 | return fibnode; 34 | } 35 | 36 | Vertex* 37 | dirfibheap_extract_min( dirfibheap_t self ) 38 | { 39 | Vertex* best = (Vertex*)fibheap_extract_min( self->heap ); 40 | if(best) 41 | hashtable_remove(self->dir, best->label); 42 | return best; 43 | } 44 | 45 | fibnode_t 46 | dirfibheap_get_fibnode( dirfibheap_t self, char* key ) { 47 | return hashtable_search( self->dir, key ); 48 | } 49 | 50 | int 51 | dirfibheap_empty( dirfibheap_t self ) { 52 | return fibheap_empty( self->heap ); 53 | } 54 | 55 | void 56 | dirfibheap_delete( dirfibheap_t self ) 57 | { 58 | hashtable_destroy( self->dir, 0 ); //do not delete values in queue 59 | fibheap_delete( self->heap ); 60 | free( self ); 61 | } 62 | -------------------------------------------------------------------------------- /core/fibheap/dirfibheap.h: -------------------------------------------------------------------------------- 1 | #ifndef DIRFIBHEAP_H 2 | #define DIRFIBHEAP_H 3 | 4 | struct dirfibheap { 5 | struct hashtable *dir; 6 | struct fibheap *heap; 7 | }; 8 | 9 | typedef struct dirfibheap* dirfibheap_t; 10 | 11 | extern dirfibheap_t dirfibheap_new(long initSize); 12 | extern fibnode_t dirfibheap_insert_or_dec_key ( dirfibheap_t , Vertex* , fibheapkey_t ); 13 | extern Vertex* dirfibheap_extract_min ( dirfibheap_t ); 14 | extern fibnode_t dirfibheap_get_fibnode( dirfibheap_t self, char* key ); 15 | extern int dirfibheap_empty( dirfibheap_t ); 16 | extern void dirfibheap_delete ( dirfibheap_t ); 17 | 18 | #endif 19 | -------------------------------------------------------------------------------- /core/fibheap/fibheap.h: -------------------------------------------------------------------------------- 1 | /* A Fibonacci heap datatype. 2 | Copyright 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc. 3 | Contributed by Daniel Berlin (dan@cgsoftware.com). 4 | 5 | This file is part of GCC. 6 | 7 | GCC is free software; you can redistribute it and/or modify it 8 | under the terms of the GNU General Public License as published by 9 | the Free Software Foundation; either version 2, or (at your option) 10 | any later version. 11 | 12 | GCC is distributed in the hope that it will be useful, but 13 | WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | General Public License for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with GCC; see the file COPYING. If not, write to 19 | the Free Software Foundation, 51 Franklin Street - Fifth Floor, 20 | Boston, MA 02110-1301, USA. */ 21 | 22 | /* Fibonacci heaps are somewhat complex, but, there's an article in 23 | DDJ that explains them pretty well: 24 | 25 | http://www.ddj.com/articles/1997/9701/9701o/9701o.htm?topic=algoritms 26 | 27 | Introduction to algorithms by Corman and Rivest also goes over them. 28 | 29 | The original paper that introduced them is "Fibonacci heaps and their 30 | uses in improved network optimization algorithms" by Tarjan and 31 | Fredman (JACM 34(3), July 1987). 32 | 33 | Amortized and real worst case time for operations: 34 | 35 | ExtractMin: O(lg n) amortized. O(n) worst case. 36 | DecreaseKey: O(1) amortized. O(lg n) worst case. 37 | Insert: O(2) amortized. O(1) actual. 38 | Union: O(1) amortized. O(1) actual. */ 39 | 40 | #ifndef _FIBHEAP_H_ 41 | #define _FIBHEAP_H_ 42 | 43 | #include "stdio.h" 44 | 45 | typedef long fibheapkey_t; 46 | //typedef double fibheapkey_t; 47 | 48 | typedef struct fibheap 49 | { 50 | size_t nodes; 51 | struct fibnode *min; 52 | struct fibnode *root; 53 | } *fibheap_t; 54 | 55 | typedef struct fibnode 56 | { 57 | struct fibnode *parent; 58 | struct fibnode *child; 59 | struct fibnode *left; 60 | struct fibnode *right; 61 | fibheapkey_t key; 62 | void *data; 63 | #if defined (__GNUC__) && (!defined (SIZEOF_INT) || SIZEOF_INT < 4) 64 | __extension__ unsigned long int degree : 31; 65 | __extension__ unsigned long int mark : 1; 66 | #else 67 | unsigned int degree : 31; 68 | unsigned int mark : 1; 69 | #endif 70 | } *fibnode_t; 71 | 72 | extern fibheap_t fibheap_new (void); 73 | extern fibnode_t fibheap_insert (fibheap_t, fibheapkey_t, void *); 74 | extern int fibheap_empty (fibheap_t); 75 | extern fibheapkey_t fibheap_min_key (fibheap_t); 76 | extern fibheapkey_t fibheap_replace_key (fibheap_t, fibnode_t, 77 | fibheapkey_t); 78 | extern void *fibheap_replace_key_data (fibheap_t, fibnode_t, 79 | fibheapkey_t, void *); 80 | extern void *fibheap_extract_min (fibheap_t); 81 | extern void *fibheap_min (fibheap_t); 82 | extern void *fibheap_replace_data (fibheap_t, fibnode_t, void *); 83 | extern void *fibheap_delete_node (fibheap_t, fibnode_t); 84 | extern void fibheap_delete (fibheap_t); 85 | extern fibheap_t fibheap_union (fibheap_t, fibheap_t); 86 | 87 | #endif /* _FIBHEAP_H_ */ 88 | -------------------------------------------------------------------------------- /core/graphserver.h: -------------------------------------------------------------------------------- 1 | #ifndef _GRAPHSERVER_H_ 2 | #define _GRAPHSERVER_H_ 3 | 4 | #define ABSOLUTE_MAX_WALK 1000000 //meters. 100 km. prevents overflow 5 | #define MAX_LONG 2147483647 6 | #define INFINITY MAX_LONG 7 | #define SECS_IN_DAY 86400 8 | #define TRUE 1 9 | #define FALSE 0 10 | 11 | typedef int ServiceId; 12 | 13 | // generally useful classes 14 | typedef struct EdgePayload EdgePayload; 15 | typedef struct State State; 16 | typedef struct WalkOptions WalkOptions; 17 | typedef struct Vertex Vertex; 18 | typedef struct Edge Edge; 19 | typedef struct ListNode ListNode; 20 | typedef struct Graph Graph; 21 | typedef struct Path Path; 22 | typedef struct Vector Vector; 23 | typedef struct SPTVertex SPTVertex; 24 | typedef struct ShortestPathTree ShortestPathTree; 25 | 26 | // classes that support edgetypes 27 | typedef struct ServicePeriod ServicePeriod; 28 | typedef struct ServiceCalendar ServiceCalendar; 29 | typedef struct Timezone Timezone; 30 | typedef struct TimezonePeriod TimezonePeriod; 31 | 32 | // edgetypes 33 | typedef struct Link Link; 34 | typedef struct Street Street; 35 | typedef struct Egress Egress; 36 | typedef struct Wait Wait; 37 | typedef struct ElapseTime ElapseTime; 38 | typedef struct Headway Headway; 39 | typedef struct TripBoard TripBoard; 40 | typedef struct HeadwayBoard HeadwayBoard; 41 | typedef struct HeadwayAlight HeadwayAlight; 42 | typedef struct Crossing Crossing; 43 | typedef struct TripAlight TripAlight; 44 | typedef struct Combination Combination; 45 | typedef struct CHPath CHPath; 46 | typedef struct CH CH; 47 | typedef struct Heap Heap; 48 | typedef struct HeapNode HeapNode; 49 | 50 | typedef struct PayloadMethods PayloadMethods; 51 | typedef struct CustomPayload CustomPayload; 52 | 53 | typedef enum { 54 | PL_STREET, 55 | PL_TRIPHOPSCHED_DEPRIC, 56 | PL_TRIPHOP_DEPRIC, 57 | PL_LINK, 58 | PL_EXTERNVALUE, 59 | PL_NONE, // 5 60 | PL_WAIT, 61 | PL_HEADWAY, 62 | PL_TRIPBOARD, 63 | PL_CROSSING, 64 | PL_ALIGHT, // 10 65 | PL_HEADWAYBOARD, 66 | PL_EGRESS, 67 | PL_HEADWAYALIGHT, 68 | PL_ELAPSE_TIME, 69 | PL_COMBINATION 70 | } edgepayload_t; 71 | 72 | #include "state.h" 73 | #include "walkoptions.h" 74 | #include "edgetypes/elapsehelpers.h" 75 | 76 | #include "edgetypes/link.h" 77 | #include "edgetypes/street.h" 78 | #include "edgetypes/egress.h" 79 | #include "edgetypes/wait.h" 80 | #include "edgetypes/elapsetime.h" 81 | #include "edgetypes/headway.h" 82 | #include "edgetypes/tripboard.h" 83 | #include "edgetypes/headwayboard.h" 84 | #include "edgetypes/headwayalight.h" 85 | #include "edgetypes/crossing.h" 86 | #include "edgetypes/tripalight.h" 87 | #include "edgetypes/custompayload.h" 88 | #include "edgetypes/combination.h" 89 | #include "edgepayload.h" 90 | #include "list.h" 91 | #include "servicecalendar.h" 92 | #include "timezone.h" 93 | #include "path.h" 94 | #include "vector.h" 95 | #include "heap.h" 96 | 97 | // things that everyone needs 98 | #include 99 | #include 100 | 101 | #endif 102 | -------------------------------------------------------------------------------- /core/hashtable/hashtable_gs.c: -------------------------------------------------------------------------------- 1 | #include "hashtable_gs.h" 2 | #include 3 | #include 4 | #include 5 | #include "hashtable.h" 6 | #include "hashtable_utility.h" 7 | 8 | static unsigned int 9 | quickhash(void *str) 10 | { 11 | unsigned long hash = 5381; 12 | int c; 13 | 14 | while ((c = *(char*)str++)) 15 | hash = ((hash << 5) + hash) + c; /* hash * 33 + c */ 16 | 17 | return hash; 18 | } 19 | 20 | static int str_eql(void* str1, void* str2) { 21 | if( strcmp(str1, str2) == 0 ) 22 | return 1; 23 | else 24 | return 0; 25 | } 26 | 27 | struct hashtable * 28 | create_hashtable_string(unsigned int minsize) { 29 | struct hashtable *ret = create_hashtable(minsize, quickhash, str_eql); 30 | return ret; 31 | } 32 | 33 | int hashtable_insert_string(struct hashtable *h, const char *key, void *v) { 34 | size_t length = strlen(key)+1; 35 | 36 | char* permakey = (char*)malloc(length*sizeof(char)); 37 | memcpy( permakey, key, length ); 38 | 39 | return hashtable_insert(h, permakey, v); 40 | } 41 | 42 | int hashtable_insert_str_long(struct hashtable *h, const char *key, long v) { 43 | long* permaval = (long*)malloc(sizeof(long)); 44 | *permaval = v; 45 | 46 | return hashtable_insert_string(h, key, permaval); 47 | } 48 | 49 | int hashtable_change_str_long(struct hashtable *h, char *key, long v) { 50 | long *permaval = (long*)malloc(sizeof(long)); 51 | *permaval = v; 52 | 53 | return hashtable_change(h, key, permaval, 1); 54 | } 55 | -------------------------------------------------------------------------------- /core/hashtable/hashtable_gs.h: -------------------------------------------------------------------------------- 1 | #ifndef HASHTABLE_GS_H 2 | #define HASHTABLE_GS_H 3 | 4 | struct hashtable * 5 | create_hashtable_string(unsigned int minsize); 6 | 7 | int hashtable_insert_string(struct hashtable *h, const char *key, void *v); 8 | 9 | int hashtable_insert_str_long(struct hashtable *h, const char *key, long v); 10 | 11 | int hashtable_change_str_long(struct hashtable *h, char *key, long v); 12 | 13 | #endif 14 | -------------------------------------------------------------------------------- /core/hashtable/hashtable_itr.h: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2002, 2004 Christopher Clark */ 2 | 3 | #ifndef __HASHTABLE_ITR_CWC22__ 4 | #define __HASHTABLE_ITR_CWC22__ 5 | #include "hashtable.h" 6 | #include "hashtable_private.h" /* needed to enable inlining */ 7 | 8 | /*****************************************************************************/ 9 | /* This struct is only concrete here to allow the inlining of two of the 10 | * accessor functions. */ 11 | struct hashtable_itr 12 | { 13 | struct hashtable *h; 14 | struct entry *e; 15 | struct entry *parent; 16 | unsigned int index; 17 | }; 18 | 19 | 20 | /*****************************************************************************/ 21 | /* hashtable_iterator 22 | */ 23 | 24 | struct hashtable_itr * 25 | hashtable_iterator(struct hashtable *h); 26 | 27 | /*****************************************************************************/ 28 | /* hashtable_iterator_key 29 | * - return the value of the (key,value) pair at the current position */ 30 | 31 | extern inline void * 32 | hashtable_iterator_key(struct hashtable_itr *i) 33 | { 34 | return i->e->k; 35 | } 36 | 37 | /*****************************************************************************/ 38 | /* value - return the value of the (key,value) pair at the current position */ 39 | 40 | extern inline void * 41 | hashtable_iterator_value(struct hashtable_itr *i) 42 | { 43 | return i->e->v; 44 | } 45 | 46 | /*****************************************************************************/ 47 | /* advance - advance the iterator to the next element 48 | * returns zero if advanced to end of table */ 49 | 50 | int 51 | hashtable_iterator_advance(struct hashtable_itr *itr); 52 | 53 | /*****************************************************************************/ 54 | /* remove - remove current element and advance the iterator to the next element 55 | * NB: if you need the value to free it, read it before 56 | * removing. ie: beware memory leaks! 57 | * returns zero if advanced to end of table */ 58 | 59 | int 60 | hashtable_iterator_remove(struct hashtable_itr *itr); 61 | 62 | /*****************************************************************************/ 63 | /* search - overwrite the supplied iterator, to point to the entry 64 | * matching the supplied key. 65 | h points to the hashtable to be searched. 66 | * returns zero if not found. */ 67 | int 68 | hashtable_iterator_search(struct hashtable_itr *itr, 69 | struct hashtable *h, void *k); 70 | 71 | #define DEFINE_HASHTABLE_ITERATOR_SEARCH(fnname, keytype) \ 72 | int fnname (struct hashtable_itr *i, struct hashtable *h, keytype *k) \ 73 | { \ 74 | return (hashtable_iterator_search(i,h,k)); \ 75 | } 76 | 77 | 78 | 79 | #endif /* __HASHTABLE_ITR_CWC22__*/ 80 | 81 | /* 82 | * Copyright (c) 2002, 2004, Christopher Clark 83 | * All rights reserved. 84 | * 85 | * Redistribution and use in source and binary forms, with or without 86 | * modification, are permitted provided that the following conditions 87 | * are met: 88 | * 89 | * * Redistributions of source code must retain the above copyright 90 | * notice, this list of conditions and the following disclaimer. 91 | * 92 | * * Redistributions in binary form must reproduce the above copyright 93 | * notice, this list of conditions and the following disclaimer in the 94 | * documentation and/or other materials provided with the distribution. 95 | * 96 | * * Neither the name of the original author; nor the names of any contributors 97 | * may be used to endorse or promote products derived from this software 98 | * without specific prior written permission. 99 | * 100 | * 101 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 102 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 103 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 104 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 105 | * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 106 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 107 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 108 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 109 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 110 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 111 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 112 | */ 113 | 114 | -------------------------------------------------------------------------------- /core/hashtable/hashtable_private.h: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2002, 2004 Christopher Clark */ 2 | 3 | #ifndef __HASHTABLE_PRIVATE_CWC22_H__ 4 | #define __HASHTABLE_PRIVATE_CWC22_H__ 5 | 6 | #include "hashtable.h" 7 | 8 | /*****************************************************************************/ 9 | struct entry 10 | { 11 | void *k, *v; 12 | unsigned int h; 13 | struct entry *next; 14 | }; 15 | 16 | struct hashtable { 17 | unsigned int tablelength; 18 | struct entry **table; 19 | unsigned int entrycount; 20 | unsigned int loadlimit; 21 | unsigned int primeindex; 22 | unsigned int (*hashfn) (void *k); 23 | int (*eqfn) (void *k1, void *k2); 24 | }; 25 | 26 | /*****************************************************************************/ 27 | unsigned int 28 | hash(struct hashtable *h, void *k); 29 | 30 | /*****************************************************************************/ 31 | /* indexFor */ 32 | static inline unsigned int 33 | indexFor(unsigned int tablelength, unsigned int hashvalue) { 34 | return (hashvalue % tablelength); 35 | }; 36 | 37 | /* Only works if tablelength == 2^N */ 38 | /*static inline unsigned int 39 | indexFor(unsigned int tablelength, unsigned int hashvalue) 40 | { 41 | return (hashvalue & (tablelength - 1u)); 42 | } 43 | */ 44 | 45 | /*****************************************************************************/ 46 | #define freekey(X) free(X) 47 | /*define freekey(X) ; */ 48 | 49 | 50 | /*****************************************************************************/ 51 | 52 | #endif /* __HASHTABLE_PRIVATE_CWC22_H__*/ 53 | 54 | /* 55 | * Copyright (c) 2002, Christopher Clark 56 | * All rights reserved. 57 | * 58 | * Redistribution and use in source and binary forms, with or without 59 | * modification, are permitted provided that the following conditions 60 | * are met: 61 | * 62 | * * Redistributions of source code must retain the above copyright 63 | * notice, this list of conditions and the following disclaimer. 64 | * 65 | * * Redistributions in binary form must reproduce the above copyright 66 | * notice, this list of conditions and the following disclaimer in the 67 | * documentation and/or other materials provided with the distribution. 68 | * 69 | * * Neither the name of the original author; nor the names of any contributors 70 | * may be used to endorse or promote products derived from this software 71 | * without specific prior written permission. 72 | * 73 | * 74 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 75 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 76 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 77 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 78 | * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 79 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 80 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 81 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 82 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 83 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 84 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 85 | */ 86 | 87 | -------------------------------------------------------------------------------- /core/hashtable/hashtable_utility.c: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2002 Christopher Clark */ 2 | 3 | #include "hashtable.h" 4 | #include "hashtable_private.h" 5 | #include "hashtable_utility.h" 6 | #include 7 | #include 8 | #include 9 | 10 | /*****************************************************************************/ 11 | /* hashtable_change 12 | * 13 | * function to change the value associated with a key, where there already 14 | * exists a value bound to the key in the hashtable. 15 | * Source due to Holger Schemel. 16 | * 17 | * */ 18 | int 19 | hashtable_change(struct hashtable *h, void *k, void *v, int destructive) 20 | { 21 | struct entry *e; 22 | unsigned int hashvalue, index; 23 | hashvalue = hash(h,k); 24 | index = indexFor(h->tablelength,hashvalue); 25 | e = h->table[index]; 26 | while (NULL != e) 27 | { 28 | /* Check hash value to short circuit heavier comparison */ 29 | if ((hashvalue == e->h) && (h->eqfn(k, e->k))) 30 | { 31 | if( destructive ) 32 | free(e->v); 33 | e->v = v; 34 | return -1; 35 | } 36 | e = e->next; 37 | } 38 | return 0; 39 | } 40 | 41 | /* 42 | * Copyright (c) 2002, Christopher Clark 43 | * All rights reserved. 44 | * 45 | * Redistribution and use in source and binary forms, with or without 46 | * modification, are permitted provided that the following conditions 47 | * are met: 48 | * 49 | * * Redistributions of source code must retain the above copyright 50 | * notice, this list of conditions and the following disclaimer. 51 | * 52 | * * Redistributions in binary form must reproduce the above copyright 53 | * notice, this list of conditions and the following disclaimer in the 54 | * documentation and/or other materials provided with the distribution. 55 | * 56 | * * Neither the name of the original author; nor the names of any contributors 57 | * may be used to endorse or promote products derived from this software 58 | * without specific prior written permission. 59 | * 60 | * 61 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 62 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 63 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 64 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 65 | * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 66 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 67 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 68 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 69 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 70 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 71 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 72 | */ 73 | 74 | -------------------------------------------------------------------------------- /core/hashtable/hashtable_utility.h: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2002 Christopher Clark */ 2 | 3 | #ifndef __HASHTABLE_CWC22_UTILITY_H__ 4 | #define __HASHTABLE_CWC22_UTILITY_H__ 5 | 6 | /***************************************************************************** 7 | * hashtable_change 8 | * 9 | * function to change the value associated with a key, where there already 10 | * exists a value bound to the key in the hashtable. 11 | * Source due to Holger Schemel. 12 | * 13 | * @name hashtable_change 14 | * @param h the hashtable 15 | * @param key 16 | * @param value 17 | * 18 | */ 19 | 20 | /* Un-comment to enable behavior whereby the hashtable takes free() liberties 21 | * with inserted values 22 | */ 23 | //#define DESTRUCTIVE 24 | 25 | int 26 | hashtable_change(struct hashtable *h, void *k, void *v, int destructive); 27 | 28 | #endif /* __HASHTABLE_CWC22_H__ */ 29 | 30 | /* 31 | * Copyright (c) 2002, Christopher Clark 32 | * All rights reserved. 33 | * 34 | * Redistribution and use in source and binary forms, with or without 35 | * modification, are permitted provided that the following conditions 36 | * are met: 37 | * 38 | * * Redistributions of source code must retain the above copyright 39 | * notice, this list of conditions and the following disclaimer. 40 | * 41 | * * Redistributions in binary form must reproduce the above copyright 42 | * notice, this list of conditions and the following disclaimer in the 43 | * documentation and/or other materials provided with the distribution. 44 | * 45 | * * Neither the name of the original author; nor the names of any contributors 46 | * may be used to endorse or promote products derived from this software 47 | * without specific prior written permission. 48 | * 49 | * 50 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 51 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 52 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 53 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 54 | * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 55 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 56 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 57 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 58 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 59 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 60 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 61 | */ 62 | 63 | -------------------------------------------------------------------------------- /core/heap.c: -------------------------------------------------------------------------------- 1 | //#include 2 | //#include 3 | //#include "heap.h" 4 | #include "graphserver.h" 5 | 6 | Heap* heapNew( int init_capacity ) { 7 | Heap* this = (Heap*)malloc(sizeof(Heap)); 8 | this->nodes = (HeapNode*)malloc( (init_capacity+1)*sizeof(HeapNode) ); 9 | this->capacity = init_capacity; 10 | this->size = 0; 11 | return this; 12 | } 13 | 14 | void heapDestroy( Heap* this ) { 15 | free( this->nodes ); 16 | free( this ); 17 | } 18 | 19 | void heapDouble( Heap *this ) { 20 | this->capacity = this->capacity * 2; 21 | this->nodes = (HeapNode*)realloc( this->nodes, (this->capacity+1)*sizeof(HeapNode) ); 22 | } 23 | 24 | void heapInsert( Heap* this, void* payload, long priority ) { 25 | if( this->size == this->capacity ) { 26 | heapDouble( this ); 27 | } 28 | 29 | this->size++; 30 | int hole = this->size; 31 | 32 | this->nodes[ 0 ].payload = payload; 33 | this->nodes[ 0 ].priority = priority; 34 | 35 | // so long as the inserted priority is lower than the current priority, keep moving up the tree 36 | while( priority < this->nodes[ hole / 2 ].priority ) { 37 | this->nodes[ hole ] = this->nodes[ hole / 2 ]; 38 | hole /= 2; 39 | } 40 | 41 | this->nodes[ hole ].payload = payload; 42 | this->nodes[ hole ].priority = priority; 43 | } 44 | 45 | int heapEmpty( Heap* this ) { 46 | return this->size == 0; 47 | } 48 | 49 | void* heapMin( Heap* this, long* priority ) { 50 | if( this->size == 0 ) { 51 | return NULL; 52 | } else { 53 | *priority = this->nodes[1].priority; 54 | return this->nodes[1].payload; 55 | } 56 | } 57 | 58 | void heapPercolateDown( Heap* this, int hole ) { 59 | int child; 60 | HeapNode tmp = this->nodes[ hole ]; 61 | 62 | while( hole * 2 <= this->size ) { 63 | 64 | child = hole * 2; 65 | if( child != this->size && this->nodes[ child + 1 ].priority < this->nodes[ child ].priority ) { 66 | child++; 67 | } 68 | 69 | if( this->nodes[ child ].priority < tmp.priority ) { 70 | this->nodes[ hole ] = this->nodes[ child ]; 71 | } else { 72 | break; 73 | } 74 | 75 | hole = child; 76 | } 77 | 78 | this->nodes[ hole ] = tmp; 79 | } 80 | 81 | void* heapPop( Heap* this, long* priority ) { 82 | void* ret = heapMin( this, priority ); 83 | 84 | this->nodes[1] = this->nodes[ this->size ]; 85 | this->size--; 86 | heapPercolateDown( this, 1 ); 87 | 88 | return ret; 89 | } 90 | -------------------------------------------------------------------------------- /core/heap.h: -------------------------------------------------------------------------------- 1 | #ifndef _HEAP_H_ 2 | #define _HEAP_H_ 3 | 4 | struct HeapNode { 5 | long priority; 6 | void *payload; 7 | } ; 8 | 9 | struct Heap { 10 | struct HeapNode* nodes; 11 | int capacity; 12 | int size; 13 | } ; 14 | 15 | Heap* heapNew( int init_capacity ) ; 16 | 17 | void heapDestroy( Heap* this ) ; 18 | 19 | void heapInsert( Heap* this, void* payload, long priority ) ; 20 | 21 | int heapEmpty( Heap* this ) ; 22 | 23 | void* heapMin( Heap* this, long* priority ) ; 24 | 25 | void* heapPop( Heap* this, long* priority ) ; 26 | 27 | #endif 28 | -------------------------------------------------------------------------------- /core/list.c: -------------------------------------------------------------------------------- 1 | #include "graphserver.h" 2 | 3 | // LIST FUNCTIONS 4 | 5 | ListNode* 6 | liNew(Edge *data) { 7 | ListNode *ret = (ListNode*)malloc(sizeof(ListNode)); 8 | ret->data = data; 9 | ret->next = NULL; 10 | return ret; 11 | } 12 | 13 | void 14 | liInsertAfter( ListNode *this, ListNode* add ) { 15 | add->next = this->next; 16 | this->next = add; 17 | } 18 | 19 | void 20 | liRemoveAfter( ListNode *this ) { 21 | if( this->next ) { 22 | ListNode* condemned = this->next; 23 | this->next = this->next->next; 24 | free( condemned ); 25 | } 26 | } 27 | 28 | void 29 | liRemoveRef( ListNode *dummyhead, Edge *data ) { 30 | ListNode* prev = dummyhead; 31 | ListNode* curr = dummyhead->next; 32 | 33 | while(curr) { 34 | if(curr->data == data) { 35 | liRemoveAfter( prev ); 36 | break; 37 | } 38 | prev = curr; 39 | curr = prev->next; 40 | } 41 | } 42 | 43 | Edge* 44 | liGetData( ListNode *this ) { 45 | return this->data; 46 | } 47 | 48 | ListNode* 49 | liGetNext( ListNode *this ) { 50 | return this->next; 51 | } 52 | -------------------------------------------------------------------------------- /core/list.h: -------------------------------------------------------------------------------- 1 | #ifndef _LIST_H_ 2 | #define _LIST_H_ 3 | 4 | struct ListNode { 5 | Edge* data; 6 | ListNode* next; 7 | } ; 8 | 9 | //LIST FUNCTIONS 10 | 11 | /* 12 | * create a new list 13 | */ 14 | ListNode* 15 | liNew(Edge *data); 16 | 17 | /* 18 | * append an existing list node after the given list node 19 | */ 20 | void 21 | liInsertAfter( ListNode *this, ListNode *add) ; 22 | 23 | void 24 | liRemoveAfter( ListNode *this ) ; 25 | 26 | void 27 | liRemoveRef( ListNode *dummyhead, Edge* data ); 28 | 29 | Edge* 30 | liGetData( ListNode *this ); 31 | 32 | ListNode* 33 | liGetNext( ListNode *this ); 34 | 35 | #endif -------------------------------------------------------------------------------- /core/path.c: -------------------------------------------------------------------------------- 1 | #include "graphserver.h" 2 | #include 3 | 4 | // PATH FUNCTIONS 5 | 6 | Path * 7 | pathNew( Vertex* origin, int init_size, int expand_delta ) { 8 | Path *this = (Path*)malloc(sizeof(Path)); 9 | 10 | this->vertices = vecNew( init_size, expand_delta ); 11 | this->edges = vecNew( init_size, expand_delta ); 12 | 13 | /* 14 | * A path is an alternating series of (vertex, edge, vertex, edge, vertex) 15 | * elements. As such a complete path always has one more vertices than 16 | * edges. One way to deal with this inconveniently dangling Vertex is to 17 | * specify it at path initialization. 18 | */ 19 | vecAdd( this->vertices, origin ); 20 | 21 | return this; 22 | } 23 | 24 | void 25 | pathDestroy(Path *this) { 26 | vecDestroy( this->vertices ); 27 | vecDestroy( this->edges ); 28 | free(this); 29 | } 30 | 31 | Vertex * 32 | pathGetVertex( Path *this, int i ) { 33 | return (Vertex*)vecGet( this->vertices, i ); 34 | } 35 | 36 | Edge * 37 | pathGetEdge( Path *this, int i ) { 38 | return (Edge*)vecGet( this->edges, i ); 39 | } 40 | 41 | void 42 | pathAddSegment( Path *this, Vertex *vertex, Edge *edge ) { 43 | vecAdd( this->vertices, vertex ); 44 | vecAdd( this->edges, edge ); 45 | } 46 | 47 | void* 48 | pathGetVertexPointer( Path *this ) { 49 | return this->vertices; 50 | } 51 | 52 | void* 53 | pathGetEdgePointer( Path *this ) { 54 | return this->edges; 55 | } -------------------------------------------------------------------------------- /core/path.h: -------------------------------------------------------------------------------- 1 | struct Path { 2 | Vector *vertices; 3 | Vector *edges; 4 | } ; 5 | 6 | // PATH FUNCTIONS 7 | 8 | Path * 9 | pathNew( Vertex* origin, int init_size, int expand_delta ); 10 | 11 | void 12 | pathDestroy(Path *this); 13 | 14 | Vertex * 15 | pathGetVertex( Path *this, int i ); 16 | 17 | Edge * 18 | pathGetEdge( Path *this, int i ); 19 | 20 | void 21 | pathAddSegment( Path *this, Vertex *vertex, Edge *edge ); -------------------------------------------------------------------------------- /core/router.c: -------------------------------------------------------------------------------- 1 | ShortestPathTree* 2 | #ifndef RETRO 3 | gShortestPathTree( Graph* this, char *from, char *to, State* init_state, WalkOptions* options, long maxtime, int hoplimit, long weightlimit ) { 4 | #else 5 | gShortestPathTreeRetro( Graph* this, char *from, char *to, State* init_state, WalkOptions* options, long mintime, int hoplimit, long weightlimit ) { 6 | #endif 7 | 8 | /* 9 | * VARIABLE SETUP 10 | */ 11 | //Iteration Variables 12 | Vertex *u, *v; 13 | SPTVertex *spt_u, *spt_v; 14 | State *du, *dv; 15 | int count = 1; 16 | 17 | //Goal Variables 18 | #ifndef RETRO 19 | char* origin = from; 20 | char* target = to; 21 | #else 22 | char* origin = to; 23 | char* target = from; 24 | #endif 25 | 26 | //Get origin vertex to make sure it exists 27 | Vertex* origin_v = gGetVertex( this, origin ); 28 | if( origin_v == NULL ) { 29 | return NULL; 30 | } 31 | 32 | //Return Tree 33 | ShortestPathTree* spt = sptNew(); 34 | sptAddVertex( spt, origin_v, 0 )->state = init_state; 35 | //Priority Queue 36 | dirfibheap_t q = dirfibheap_new( 1 ); 37 | dirfibheap_insert_or_dec_key( q, gGetVertex( this, origin ), 0 ); 38 | 39 | /* 40 | * CENTRAL ITERATION 41 | * 42 | */ 43 | 44 | while( !dirfibheap_empty( q ) ) { //Until the priority queue is empty: 45 | u = dirfibheap_extract_min( q ); //get the lowest-weight Vertex 'u', 46 | 47 | if( !strcmp( u->label, target ) ) //(end search if reached destination vertex) 48 | break; 49 | 50 | spt_u = sptGetVertex( spt, u->label ); //get corresponding SPT Vertex, 51 | 52 | if( spt_u->hop >= hoplimit ) { 53 | break; 54 | } 55 | 56 | if( spt_u->state->weight > weightlimit ) { 57 | break; 58 | } 59 | 60 | du = (State*)spt_u->state; //and get State of u 'du'. 61 | 62 | #ifndef RETRO 63 | if( du->time > maxtime ) 64 | break; 65 | #else 66 | if( du->time < mintime ) 67 | break; 68 | #endif 69 | 70 | #ifndef RETRO 71 | ListNode* edges = vGetOutgoingEdgeList( u ); 72 | #else 73 | ListNode* edges = vGetIncomingEdgeList( u ); 74 | #endif 75 | while( edges ) { //For each Edge 'edge' connecting u 76 | Edge* edge = edges->data; 77 | #ifndef RETRO 78 | v = edge->to; //to Vertex v: 79 | #else 80 | v = edge->from; 81 | #endif 82 | 83 | long old_w; 84 | if( (spt_v = sptGetVertex( spt, v->label )) ) { //get the SPT Vertex corresponding to 'v' 85 | dv = (State*)spt_v->state; //and its State 'dv' 86 | old_w = dv->weight; 87 | } else { 88 | dv = NULL; //which may not exist yet 89 | old_w = INFINITY; 90 | } 91 | 92 | #ifndef RETRO 93 | State *new_dv = eWalk( edge, du, options ); 94 | #else 95 | State *new_dv = eWalkBack( edge, du, options ); 96 | #endif 97 | 98 | // When an edge leads nowhere (as indicated by returning NULL), the iteration is over. 99 | if(!new_dv) { 100 | edges = edges->next; 101 | continue; 102 | } 103 | 104 | // States cannot have weights lower than their parent State. 105 | if(new_dv->weight < du->weight) { 106 | fprintf(stderr, "Negative weight (%s(%ld) -> %s(%ld))\n",edge->from->label, du->weight, edge->to->label, new_dv->weight); 107 | edges = edges->next; 108 | stateDestroy( new_dv ); 109 | continue; 110 | } 111 | 112 | long new_w = new_dv->weight; 113 | // If the new way of getting there is better, 114 | if( new_w < old_w ) { 115 | dirfibheap_insert_or_dec_key( q, v, new_w ); // rekey v in the priority queue 116 | 117 | // If this is the first time v has been reached 118 | if( !spt_v ) { 119 | spt_v = sptAddVertex( spt, v, spt_u->hop+1 ); //Copy v over to the SPT 120 | count++; 121 | } 122 | 123 | //if((count%10000) == 0) 124 | // fprintf(stdout, "Shortest path tree size: %d\n",count); 125 | 126 | if(spt_v->state) 127 | stateDestroy(spt_v->state); 128 | spt_v->state = new_dv; //Set the State of v in the SPT to the current winner 129 | 130 | sptvSetParent( spt_v, spt_u, edge->payload ); //Make u the parent of v in the SPT 131 | } else { 132 | stateDestroy(new_dv); //new_dv will never be used; merge it with the infinite. 133 | } 134 | edges = edges->next; 135 | } 136 | } 137 | 138 | dirfibheap_delete( q ); 139 | 140 | //fprintf(stdout, "Final shortest path tree size: %d\n",count); 141 | return spt; 142 | } 143 | -------------------------------------------------------------------------------- /core/servicecalendar.h: -------------------------------------------------------------------------------- 1 | #ifndef _SERVICECALENDAR_H_ 2 | #define _SERVICECALENDAR_H_ 3 | 4 | struct ServiceCalendar { 5 | /* TripHops have service types, and the ServiceCalendar provides the correspondance between points in time and lists of service_ids. 6 | * For example, A triphop that has a service_id attribute with the value "WKDY" will only run during service periods 7 | * associated with the service_id "WKDY", which the service calendar will show corresponds roughly with weekdays. (Or, more literally, 8 | * the daytime periods of every day except two days on a seven day cycle.) As an optimization, triphop structs do not have a string attribute 9 | * service_id, but an integer which corresponds to the service_id. Because most transit agencies use short strings for their service_ids, 10 | * and talking about the service_id "weekday" is way easier than service_id 5, the service calendar has a lookup and reverse lookup table for string 11 | * service_ids to integer service_ids. 12 | */ 13 | 14 | ServicePeriod* head; 15 | 16 | int num_sids; 17 | struct hashtable* sid_str_to_int; 18 | char** sid_int_to_str; 19 | } ; 20 | 21 | struct ServicePeriod { 22 | long begin_time; //the first second since the epoch on which the service period is in effect 23 | long end_time; //first moment after the period; exclusive. 24 | int n_service_ids; 25 | ServiceId* service_ids; 26 | ServicePeriod* prev_period; 27 | ServicePeriod* next_period; 28 | } ; 29 | 30 | ServiceCalendar* 31 | scNew(void); 32 | 33 | int 34 | scAddServiceId( ServiceCalendar* this, char* service_id ); 35 | 36 | char* 37 | scGetServiceIdString( ServiceCalendar* this, int service_id ); 38 | 39 | int 40 | scGetServiceIdInt( ServiceCalendar* this, char* service_id ); 41 | 42 | // TODO 43 | //int 44 | //scGetOrAddServiceIdInt( ServiceCalendar* this, char* service_id ); 45 | 46 | void 47 | scAddPeriod( ServiceCalendar* this, ServicePeriod* period ); 48 | 49 | ServicePeriod* 50 | scPeriodOfOrAfter( ServiceCalendar* this, long time ); 51 | 52 | ServicePeriod* 53 | scPeriodOfOrBefore( ServiceCalendar* this, long time ); 54 | 55 | ServicePeriod* 56 | scHead( ServiceCalendar* this ); 57 | 58 | void 59 | scDestroy( ServiceCalendar* this ); 60 | 61 | ServicePeriod* 62 | spNew( long begin_time, long end_time, int n_service_ids, ServiceId* service_ids ); 63 | 64 | void 65 | spDestroyPeriod( ServicePeriod* this ); 66 | 67 | int 68 | spPeriodHasServiceId( ServicePeriod* this, ServiceId service_id); 69 | 70 | ServicePeriod* 71 | spRewind( ServicePeriod* this ); 72 | 73 | ServicePeriod* 74 | spFastForward( ServicePeriod* this ); 75 | 76 | void 77 | spPrint( ServicePeriod* this ) ; 78 | 79 | void 80 | spPrintPeriod( ServicePeriod* this ) ; 81 | 82 | inline long 83 | spNormalizeTime( ServicePeriod* this, int timezone_offset, long time ) ; 84 | 85 | #endif 86 | -------------------------------------------------------------------------------- /core/state.c: -------------------------------------------------------------------------------- 1 | 2 | #include "graphserver.h" 3 | 4 | //STATE FUNCTIONS 5 | State* 6 | stateNew(int n_agencies, long time) { 7 | State* ret = (State*)malloc( sizeof(State) ); 8 | ret->time = time; 9 | ret->weight = 0; 10 | ret->dist_walked = 0; 11 | ret->num_transfers = 0; 12 | ret->trip_id = NULL; 13 | ret->stop_sequence = -1; 14 | ret->prev_edge = NULL; 15 | ret->n_agencies = n_agencies; 16 | ret->service_periods = (ServicePeriod**)malloc(n_agencies*sizeof(ServicePeriod*)); //hash of strings->calendardays 17 | 18 | int i; 19 | for(i=0; iservice_periods[i] = NULL; 21 | } 22 | 23 | return ret; 24 | } 25 | 26 | State* 27 | stateDup( State* this ) { 28 | State* ret = (State*)malloc( sizeof(State) ); 29 | memcpy( ret, this, sizeof( State ) ); 30 | 31 | ret->service_periods = (ServicePeriod**)malloc(this->n_agencies*sizeof(ServicePeriod*)); //hash of strings->calendardays 32 | memcpy( ret->service_periods, this->service_periods, this->n_agencies*sizeof(ServicePeriod*)); 33 | 34 | return ret; 35 | } 36 | 37 | //the State object does not own State#calendar 38 | void 39 | stateDestroy(State* this) { 40 | free( this->service_periods ); 41 | free( this ); 42 | } 43 | 44 | long 45 | stateGetTime( State* this ) { return this->time; } 46 | 47 | long 48 | stateGetWeight( State* this) { return this->weight; } 49 | 50 | double 51 | stateGetDistWalked( State* this ) { return this->dist_walked; } 52 | 53 | int 54 | stateGetNumTransfers( State* this ) { return this->num_transfers; } 55 | 56 | EdgePayload* 57 | stateGetPrevEdge( State* this ) { return this->prev_edge; } 58 | 59 | char* 60 | stateGetTripId( State* this ) { return this->trip_id; } 61 | 62 | int 63 | stateGetStopSequence( State* this ) { return this->stop_sequence; } 64 | 65 | int 66 | stateGetNumAgencies( State* this ) { return this->n_agencies; } 67 | 68 | ServicePeriod* 69 | stateServicePeriod( State* this, int agency ) { return this->service_periods[agency]; } 70 | 71 | void 72 | stateSetTime( State* this, long time ) { this->time = time; } 73 | 74 | void 75 | stateSetWeight( State* this, long weight ) { this->weight = weight; } 76 | 77 | void 78 | stateSetDistWalked( State* this, double dist ) { this->dist_walked = dist; } 79 | 80 | void 81 | stateSetNumTransfers( State* this, int n) { this->num_transfers = n; } 82 | 83 | void 84 | stateSetServicePeriod( State* this, int agency, ServicePeriod* cal ) { this->service_periods[agency] = cal; } 85 | 86 | // the state does not keep ownership of the trip_id, so the state 87 | // may not live longer than whatever object set its trip_id 88 | void 89 | stateDangerousSetTripId( State* this, char* trip_id ) { this->trip_id = trip_id; } 90 | 91 | void 92 | stateSetPrevEdge( State* this, EdgePayload* edge ) { this->prev_edge = edge; } 93 | -------------------------------------------------------------------------------- /core/state.h: -------------------------------------------------------------------------------- 1 | #ifndef _STATE_H_ 2 | #define _STATE_H_ 3 | 4 | //---------------DECLARATIONS FOR STATE CLASS--------------------- 5 | 6 | struct State { 7 | long time; //seconds since the epoch 8 | long weight; 9 | double dist_walked; //meters 10 | int num_transfers; 11 | EdgePayload* prev_edge; 12 | char* trip_id; 13 | int stop_sequence; 14 | int n_agencies; 15 | ServicePeriod** service_periods; 16 | } ; 17 | 18 | State* 19 | stateNew(int numcalendars, long time); 20 | 21 | void 22 | stateDestroy( State* this); 23 | 24 | State* 25 | stateDup( State* this ); 26 | 27 | long 28 | stateGetTime( State* this ); 29 | 30 | long 31 | stateGetWeight( State* this); 32 | 33 | double 34 | stateGetDistWalked( State* this ); 35 | 36 | int 37 | stateGetNumTransfers( State* this ); 38 | 39 | EdgePayload* 40 | stateGetPrevEdge( State* this ); 41 | 42 | char* 43 | stateGetTripId( State* this ); 44 | 45 | int 46 | stateGetStopSequence( State* this ); 47 | 48 | int 49 | stateGetNumAgencies( State* this ); 50 | 51 | ServicePeriod* 52 | stateServicePeriod( State* this, int agency ); 53 | 54 | void 55 | stateSetServicePeriod( State* this, int agency, ServicePeriod* cal ); 56 | 57 | void 58 | stateSetTime( State* this, long time ); 59 | 60 | void 61 | stateSetWeight( State* this, long weight ); 62 | 63 | void 64 | stateSetDistWalked( State* this, double dist ); 65 | 66 | void 67 | stateSetNumTransfers( State* this, int n); 68 | 69 | // the state does not keep ownership of the trip_id, so the state 70 | // may not live longer than whatever object set its trip_id 71 | void 72 | stateDangerousSetTripId( State* this, char* trip_id ); 73 | 74 | void 75 | stateSetPrevEdge( State* this, EdgePayload* edge ); 76 | 77 | #endif 78 | -------------------------------------------------------------------------------- /core/test/README: -------------------------------------------------------------------------------- 1 | Here's a set of simple unit tests in C. Run them with the 'valgrind' memory profiler to check for memory leaks and invalid reads. 2 | 3 | $ make 4 | $ valgrind --leak_check=yes ./streetprofile -------------------------------------------------------------------------------- /core/test/deadend.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "../graphserver.h" 5 | #include "../graph.h" 6 | #include 7 | 8 | int main() { 9 | Graph* gg = gNew(); 10 | gAddVertex( gg, "A" ); 11 | gAddVertex( gg, "B" ); 12 | 13 | //construct and add TripHop edge 14 | Timezone* tz = tzNew(); 15 | TimezonePeriod* tzp = tzpNew( 0, 100000, 0 ); 16 | tzAddPeriod( tz, tzp ); 17 | ServiceCalendar* cal = scNew(); 18 | ServiceId* sids = malloc( 1*sizeof(ServiceId) ); 19 | sids[0] = 1; 20 | ServicePeriod* sp = spNew( 0, 1*3600*24, 1, sids ); 21 | scAddPeriod( cal, sp ); 22 | 23 | ServiceId sid = 0; 24 | int agency = 0; 25 | TripBoard *tb = tbNew( sid, cal, tz, agency ); 26 | tbAddBoarding( tb, "A1", 10, 0 ); 27 | 28 | gAddEdge( gg, "A", "B", (EdgePayload*)tb); 29 | 30 | State* initstate = stateNew(1, 20); 31 | WalkOptions* wo = woNew(); 32 | ShortestPathTree* spt = gShortestPathTree( gg, "A", "B", initstate, wo, 1000000, 1000000, 1000000 ); 33 | 34 | sptDestroy(spt); 35 | woDestroy( wo ); 36 | gDestroy(gg); 37 | tzDestroy( tz ); 38 | scDestroy( cal ); 39 | free( sids ); 40 | //nothing should be left 41 | 42 | return 1; 43 | } 44 | -------------------------------------------------------------------------------- /core/test/hops.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "../graphserver.h" 5 | #include "../graph.h" 6 | #include 7 | 8 | int main() { 9 | 10 | Graph* gg = gNew(); 11 | ServiceCalendar* sc = scNew(); 12 | ServiceId sid = 0; 13 | ServicePeriod* sp = spNew( 0, 1000000, 1, &sid ); 14 | scAddPeriod( sc, sp ); 15 | TimezonePeriod *tzp = tzpNew( 0, 1000000, 0 ); 16 | Timezone *tz = tzNew(); 17 | tzAddPeriod( tz, tzp ); 18 | 19 | FILE* fp = fopen( "hopslines", "r" ); 20 | char* fromv = (char*)malloc(255*sizeof(char)); 21 | char* frompsv = (char*)malloc(255*sizeof(char)); 22 | char* topsv = (char*)malloc(255*sizeof(char)); 23 | char* tov = (char*)malloc(255*sizeof(char)); 24 | char* tripid = (char*)malloc(255*sizeof(char)); 25 | int depart; 26 | int crossing; 27 | int arrive; 28 | int i = 0; 29 | while(!feof(fp)) { 30 | fscanf( fp, "%s %s %s %s %s %d %d %d", fromv, frompsv, topsv, tov, tripid, &depart, &crossing, &arrive ); 31 | printf( "%s %s %s %s %s %d %d %d\n",fromv, frompsv, topsv, tov, tripid, depart, crossing, arrive); 32 | 33 | gAddVertex( gg, fromv ); 34 | gAddVertex( gg, tov ); 35 | gAddVertex( gg, frompsv ); 36 | gAddVertex( gg, topsv ); 37 | 38 | TripBoard* tb = tbNew( 0, sc, tz, 0 ); 39 | tbAddBoarding(tb, tripid, depart, 0); 40 | gAddEdge( gg, fromv, frompsv, (EdgePayload*)tb ); 41 | 42 | Crossing* cr = crNew( ); 43 | gAddEdge( gg, frompsv, topsv, (EdgePayload*)cr ); 44 | 45 | TripAlight* al = alNew( 0, sc, tz, 0 ); 46 | alAddAlighting( al, tripid, arrive, 0 ); 47 | gAddEdge( gg, topsv, tov, (EdgePayload*)al ); 48 | 49 | } 50 | 51 | 52 | //clean up 53 | free(fromv); 54 | free(frompsv); 55 | free(tov); 56 | free(topsv); 57 | free(tripid); 58 | 59 | tzDestroy(tz); 60 | scDestroy(sc); 61 | fclose( fp ); 62 | gDestroy( gg ); 63 | return 1; 64 | } 65 | -------------------------------------------------------------------------------- /core/test/init_prio_queue.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "../graphserver.h" 5 | #include "../graph.h" 6 | #include "../heap.h" 7 | #include 8 | #include "../contraction.h" 9 | #include "../fibheap/fibheap.h" 10 | 11 | int main() { 12 | 13 | int MAX_IMPORT = 100; 14 | 15 | Graph* gg = gNew(); 16 | 17 | //Load up edges 18 | FILE* fp = fopen("map.csv", "r"); 19 | char via[20]; 20 | char from[20]; 21 | char to[20]; 22 | double length; 23 | int i=0; 24 | while( !feof( fp ) && i < MAX_IMPORT ){ 25 | i++; 26 | 27 | fscanf(fp, "%[^,],%[^,],%[^,],%lf\n", &via, &from, &to, &length); 28 | 29 | gAddVertex( gg, from ); 30 | gAddVertex( gg, to ); 31 | 32 | Street* s1 = streetNew( via, length, 0 ); 33 | gAddEdge(gg, from, to, (EdgePayload*)s1); 34 | Street* s2 = streetNew( via, length, 0 ); 35 | gAddEdge(gg, to, from, (EdgePayload*)s2); 36 | } 37 | fclose( fp ); 38 | 39 | WalkOptions* wo = woNew(); 40 | Heap* pq = init_priority_queue( gg, wo, 1 ); 41 | 42 | while( !heapEmpty(pq) ) { 43 | long prio; 44 | Vertex* next = pqPop( pq, &prio ); 45 | printf( "next vertex: %p has prio: %d\n", next, prio ); 46 | } 47 | 48 | heapDestroy( pq ); 49 | woDestroy( wo ); 50 | gDestroy(gg); 51 | 52 | return 1; 53 | } 54 | -------------------------------------------------------------------------------- /core/test/makefile: -------------------------------------------------------------------------------- 1 | 2 | SRCS = testsetparent.c deadend.c hops.c streetprofile.c testdestroystates.c test_crossing.c init_prio_queue.c testheap.c test_ch.c 3 | TESTS = $(SRCS:.c=) 4 | BUILDDIR = build 5 | 6 | all: buildbuild $(TESTS) 7 | 8 | clean: 9 | rm $(TESTS) 10 | 11 | buildbuild: 12 | mkdir -p $(BUILDDIR) 13 | 14 | %: %.c ../libgraphserver.so 15 | cc -g $< ../libgraphserver.so -o $(BUILDDIR)/$@ -lm 16 | -------------------------------------------------------------------------------- /core/test/streetprofile.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "../graphserver.h" 5 | #include "../graph.h" 6 | #include 7 | 8 | //This should leak memory 9 | int main() { 10 | 11 | Graph* gg = gNew(); 12 | 13 | //Load up vertices 14 | FILE* fp = fopen("nodes.csv", "r"); 15 | char vertexid[40]; 16 | while( !feof( fp ) ) { 17 | fscanf(fp, "%s\n", &vertexid); 18 | 19 | gAddVertex(gg, vertexid); 20 | 21 | Vertex* vv = gGetVertex(gg, vertexid); 22 | } 23 | fclose( fp ); 24 | 25 | //Load up edges 26 | fp = fopen("map.csv", "r"); 27 | char via[20]; 28 | char from[20]; 29 | char to[20]; 30 | double length; 31 | while( !feof( fp ) ){ 32 | fscanf(fp, "%[^,],%[^,],%[^,],%lf\n", &via, &from, &to, &length); 33 | 34 | Street* ss = streetNew( via, length, 0 ); 35 | gAddEdge(gg, from, to, (EdgePayload*)ss); 36 | } 37 | fclose( fp ); 38 | 39 | WalkOptions *wo = woNew(); 40 | 41 | //Find a shortest-path tree 42 | 43 | int i=0; 44 | for(i=0; i<1; i++) { 45 | ShortestPathTree* spt; 46 | spt = gShortestPathTree(gg, "53204010", "bogus", stateNew(1,0), wo, 1000000, 100000, 100000); 47 | sptDestroy(spt); 48 | spt = gShortestPathTree(gg, "53116165", "bogus", stateNew(1,0), wo, 10000001, 100000, 100000); 49 | sptDestroy(spt); 50 | spt = gShortestPathTree(gg, "53157403", "bogus", stateNew(1,0), wo, 10000001, 100000, 100000); 51 | sptDestroy(spt); 52 | spt = gShortestPathTree(gg, "30279744", "bogus", stateNew(1,0), wo, 10000001, 100000, 100000); 53 | sptDestroy(spt); 54 | spt = gShortestPathTree(gg, "67539645", "bogus", stateNew(1,0), wo, 10000001, 100000, 100000); 55 | sptDestroy(spt); 56 | spt = gShortestPathTree(gg, "53217469", "bogus", stateNew(1,0), wo, 10000001, 100000, 100000); 57 | sptDestroy(spt); 58 | spt = gShortestPathTree(gg, "152264675", "bogus", stateNew(1,0), wo, 10000001, 100000, 100000); 59 | sptDestroy(spt); 60 | spt = gShortestPathTree(gg, "53062837", "bogus", stateNew(1,0), wo, 10000001, 100000, 100000); 61 | sptDestroy(spt); 62 | spt = gShortestPathTree(gg, "53190677", "bogus", stateNew(1,0), wo, 10000001, 100000, 100000); 63 | sptDestroy(spt); 64 | spt = gShortestPathTree(gg, "53108368", "bogus", stateNew(1,0), wo, 10000001, 100000, 100000); 65 | sptDestroy(spt); 66 | spt = gShortestPathTree(gg, "91264868", "bogus", stateNew(1,0), wo, 10000001, 100000, 100000); 67 | sptDestroy(spt); 68 | spt = gShortestPathTree(gg, "53145350", "bogus", stateNew(1,0), wo, 10000001, 100000, 100000); 69 | sptDestroy(spt); 70 | spt = gShortestPathTree(gg, "53156103", "bogus", stateNew(1,0), wo, 10000001, 100000, 100000); 71 | sptDestroy(spt); 72 | spt = gShortestPathTree(gg, "53139148", "bogus", stateNew(1,0), wo, 10000001, 100000, 100000); 73 | sptDestroy(spt); 74 | spt = gShortestPathTree(gg, "108423294", "bogus", stateNew(1,0), wo, 10000001, 100000, 100000); 75 | sptDestroy(spt); 76 | spt = gShortestPathTree(gg, "53114499", "bogus", stateNew(1,0), wo, 10000001, 100000, 100000); 77 | sptDestroy(spt); 78 | spt = gShortestPathTree(gg, "53110306", "bogus", stateNew(1,0), wo, 10000001, 100000, 100000); 79 | sptDestroy(spt); 80 | spt = gShortestPathTree(gg, "53132736", "bogus", stateNew(1,0), wo, 10000001, 100000, 100000); 81 | sptDestroy(spt); 82 | spt = gShortestPathTree(gg, "53103049", "bogus", stateNew(1,0), wo, 10000001, 100000, 100000); 83 | sptDestroy(spt); 84 | spt = gShortestPathTree(gg, "53178033", "bogus", stateNew(1,0), wo, 10000001, 100000, 100000); 85 | sptDestroy(spt); 86 | } 87 | 88 | gDestroy(gg); 89 | woDestroy( wo ); 90 | 91 | return 1; 92 | } 93 | -------------------------------------------------------------------------------- /core/test/test_ch.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "../graphserver.h" 4 | #include "../graph.h" 5 | #include "../heap.h" 6 | #include "../contraction.h" 7 | #include 8 | 9 | void test_empty_graph() { 10 | 11 | Graph *gg = gNew(); 12 | WalkOptions *wo = woNew(); 13 | 14 | CH *ch = get_contraction_hierarchies( gg, wo, 1 ); 15 | 16 | assert( gSize( ch->up ) == 0 ); 17 | assert( gSize( ch->down ) == 0 ); 18 | 19 | woDestroy( wo ); 20 | chDestroy( ch ); 21 | gDestroy( gg ); 22 | 23 | } 24 | 25 | void test_simple_graph() { 26 | 27 | // create a simple graph with two vertices and one edge 28 | Graph *gg = gNew(); 29 | gAddVertex( gg, "A" ); 30 | gAddVertex( gg, "B" ); 31 | gAddEdge( gg, "A", "B", (EdgePayload*)streetNew( "AtoB", 10, 0 ) ); 32 | 33 | // create a contraction hierarchy of the graph 34 | WalkOptions *wo = woNew(); 35 | CH *ch = get_contraction_hierarchies( gg, wo, 1 ); 36 | 37 | // asserts 38 | assert( gSize( ch->up ) == 2 ); 39 | assert( gSize( ch->down ) == 2 ); 40 | 41 | // clean up 42 | woDestroy( wo ); 43 | chDestroy( ch ); 44 | gDestroy( gg ); 45 | } 46 | 47 | int main() { 48 | test_empty_graph(); 49 | test_simple_graph(); 50 | 51 | return 1; 52 | } 53 | -------------------------------------------------------------------------------- /core/test/testdestroystates.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "../graphserver.h" 5 | #include "../graph.h" 6 | #include 7 | 8 | int main() { 9 | Graph* gg = gNew(); 10 | gAddVertex( gg, "A" ); 11 | gAddVertex( gg, "B" ); 12 | gAddEdge( gg, "A", "B", (EdgePayload*)linkNew()); 13 | 14 | WalkOptions *wo = woNew(); 15 | 16 | State* initstate = stateNew(1, 0); 17 | ShortestPathTree* spt = gShortestPathTree( gg, "A", "B", initstate, wo, 1000001, 100000, 100000 ); 18 | 19 | woDestroy(wo); 20 | sptDestroy(spt); 21 | gDestroy(gg); 22 | //nothing should be left 23 | 24 | return 1; 25 | } 26 | -------------------------------------------------------------------------------- /core/test/testheap.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "../graphserver.h" 5 | #include "../graph.h" 6 | #include 7 | #include "../heap.h" 8 | 9 | #define TRUE 1 10 | #define FALSE 0 11 | 12 | int main() { 13 | 14 | Heap* hh = heapNew( 1 ); 15 | 16 | heapInsert( hh, "first", 1 ); 17 | 18 | long pp; 19 | char* itemout = heapPop( hh, &pp ); 20 | 21 | printf( "%s\n", itemout ); 22 | printf( "size:%d\n", hh->size ); 23 | 24 | heapInsert( hh, "one", 1 ); 25 | heapInsert( hh, "ten", 10 ); 26 | 27 | while( !heapEmpty( hh ) ) { 28 | itemout = heapPop( hh, &pp ); 29 | printf( "%s\n", itemout ); 30 | printf( "size:%d\n", hh->size ); 31 | } 32 | 33 | heapInsert( hh, "ten", 10 ); 34 | heapInsert( hh, "one", 1 ); 35 | 36 | while( !heapEmpty( hh ) ) { 37 | itemout = heapPop( hh, &pp ); 38 | printf( "%s\n", itemout ); 39 | printf( "size:%d\n", hh->size ); 40 | } 41 | 42 | heapInsert( hh, "384", 384 ); 43 | heapInsert( hh, "887", 887 ); 44 | heapInsert( hh, "778", 778 ); 45 | 46 | while( !heapEmpty( hh ) ) { 47 | itemout = heapPop( hh, &pp ); 48 | printf( "%s\n", itemout ); 49 | printf( "size:%d\n", hh->size ); 50 | } 51 | 52 | int i; 53 | for(i=0; i<1000; i++) { 54 | char* payload = (char*)malloc(200*sizeof(char)); 55 | long priority = rand()%1000+1; 56 | sprintf(payload, "%ld", priority); 57 | 58 | printf( "inserting '%s' with priority %ld\n", payload, priority ); 59 | 60 | heapInsert( hh, payload, priority ); 61 | } 62 | 63 | while( !heapEmpty( hh ) ) { 64 | itemout = heapPop( hh, &pp ); 65 | printf( "%s\n", itemout ); 66 | printf( "size:%d\n", hh->size ); 67 | free(itemout); 68 | } 69 | 70 | heapDestroy( hh ); 71 | 72 | return 1; 73 | } 74 | -------------------------------------------------------------------------------- /core/test/testsetparent.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "../graphserver.h" 5 | #include "../graph.h" 6 | #include 7 | 8 | int main() { 9 | Vertex* v1 = vNew("A"); 10 | Vertex* v2 = vNew("B"); 11 | 12 | Link* origlink = linkNew(); 13 | vLink(v1, v2, (EdgePayload*)origlink); 14 | vSetParent(v2, v1, (EdgePayload*)linkNew()); //results in invalid write 15 | 16 | vDestroy(v1, 1); 17 | vDestroy(v2, 1); 18 | linkDestroy(origlink); 19 | 20 | return 1; 21 | } 22 | -------------------------------------------------------------------------------- /core/timezone.c: -------------------------------------------------------------------------------- 1 | 2 | #include "graphserver.h" 3 | 4 | Timezone* 5 | tzNew( ) { 6 | Timezone* ret = (Timezone*)malloc(sizeof(Timezone)); 7 | ret->head = NULL; 8 | 9 | return ret; 10 | } 11 | 12 | void 13 | tzAddPeriod( Timezone* this, TimezonePeriod* period ) { 14 | if(!this->head) { 15 | this->head = period; 16 | } else { 17 | TimezonePeriod* prev = NULL; 18 | TimezonePeriod* curs = this->head; 19 | 20 | while(curs && period->begin_time > curs->end_time ) { 21 | prev = curs; 22 | curs = curs->next_period; 23 | } 24 | 25 | //link last and period; replace the head if necessary 26 | if(prev) { 27 | prev->next_period = period; 28 | } else { 29 | this->head = period; 30 | } 31 | 32 | //link period and curs 33 | period->next_period = curs; 34 | 35 | } 36 | } 37 | 38 | TimezonePeriod* 39 | tzPeriodOf( Timezone* this, long time) { 40 | TimezonePeriod* period = this->head; 41 | 42 | while( period && period->end_time < time ) { 43 | period = period->next_period; 44 | } 45 | 46 | if( period && time < period->begin_time ) { 47 | return NULL; 48 | } 49 | 50 | return period; 51 | } 52 | 53 | int 54 | tzUtcOffset( Timezone* this, long time) { 55 | //Returns seconds offset UTC for this timezone, at the given time 56 | 57 | TimezonePeriod* now = tzPeriodOf( this, time ); 58 | 59 | if( !now ) { 60 | return -100*3600; //utc offset larger than any conceivable offset, as an error signal 61 | } 62 | 63 | return tzpUtcOffset( now ); 64 | } 65 | 66 | int 67 | tzTimeSinceMidnight( Timezone* this, long time ) { 68 | TimezonePeriod* now = tzPeriodOf( this, time ); 69 | 70 | if( !now ) { 71 | return -1; 72 | } 73 | 74 | return (time+now->utc_offset)%SECS_IN_DAY; 75 | } 76 | 77 | TimezonePeriod* 78 | tzHead( Timezone* this ) { 79 | return this->head; 80 | } 81 | 82 | void 83 | tzDestroy( Timezone* this ) { 84 | TimezonePeriod* curs = this->head; 85 | TimezonePeriod* next; 86 | 87 | while(curs) { 88 | next = curs->next_period; 89 | tzpDestroy(curs); 90 | curs = next; 91 | } 92 | 93 | free(this); 94 | } 95 | 96 | TimezonePeriod* 97 | tzpNew( long begin_time, long end_time, int utc_offset ) { 98 | TimezonePeriod* ret = (TimezonePeriod*)malloc(sizeof(TimezonePeriod)); 99 | ret->begin_time = begin_time; 100 | ret->end_time = end_time; 101 | ret->utc_offset = utc_offset; 102 | ret->next_period = NULL; 103 | 104 | return ret; 105 | } 106 | 107 | void 108 | tzpDestroy( TimezonePeriod* this ) { 109 | free( this ); 110 | } 111 | 112 | int 113 | tzpUtcOffset( TimezonePeriod* this ) { 114 | return this->utc_offset; 115 | } 116 | 117 | int 118 | tzpTimeSinceMidnight( TimezonePeriod* this, long time ) { 119 | return (time+this->utc_offset)%SECS_IN_DAY; 120 | } 121 | 122 | long 123 | tzpBeginTime( TimezonePeriod* this ) { 124 | return this->begin_time; 125 | } 126 | 127 | long 128 | tzpEndTime( TimezonePeriod* this ) { 129 | return this->end_time; 130 | } 131 | 132 | TimezonePeriod* 133 | tzpNextPeriod(TimezonePeriod* this) { 134 | return this->next_period; 135 | } -------------------------------------------------------------------------------- /core/timezone.h: -------------------------------------------------------------------------------- 1 | #ifndef _TIMEZONE_H_ 2 | #define _TIMEZONE_H_ 3 | 4 | struct TimezonePeriod { 5 | long begin_time; //the first second on which the service_period is valid 6 | long end_time; //the last second on which the service_period is valid 7 | int utc_offset; 8 | TimezonePeriod* next_period; 9 | } ; 10 | 11 | struct Timezone { 12 | TimezonePeriod* head; 13 | } ; 14 | 15 | Timezone* 16 | tzNew(void); 17 | 18 | void 19 | tzAddPeriod( Timezone* this, TimezonePeriod* period ); 20 | 21 | TimezonePeriod* 22 | tzPeriodOf( Timezone* this, long time); 23 | 24 | int 25 | tzUtcOffset( Timezone* this, long time); 26 | 27 | int 28 | tzTimeSinceMidnight( Timezone* this, long time ); 29 | 30 | TimezonePeriod* 31 | tzHead( Timezone* this ); 32 | 33 | void 34 | tzDestroy( Timezone* this ); 35 | 36 | TimezonePeriod* 37 | tzpNew( long begin_time, long end_time, int utc_offset ); 38 | 39 | void 40 | tzpDestroy( TimezonePeriod* this ); 41 | 42 | int 43 | tzpUtcOffset( TimezonePeriod* this ); 44 | 45 | int 46 | tzpTimeSinceMidnight( TimezonePeriod* this, long time ); 47 | 48 | long 49 | tzpBeginTime( TimezonePeriod* this ); 50 | 51 | long 52 | tzpEndTime( TimezonePeriod* this ); 53 | 54 | TimezonePeriod* 55 | tzpNextPeriod(TimezonePeriod* this); 56 | 57 | #endif 58 | -------------------------------------------------------------------------------- /core/vector.c: -------------------------------------------------------------------------------- 1 | #include "graphserver.h" 2 | 3 | Vector * 4 | vecNew( int init_size, int expand_delta ) { 5 | Vector *this = (Vector*)malloc(sizeof(Vector)); 6 | 7 | this->num_elements = 0; 8 | this->num_alloc = init_size; 9 | this->expand_delta = expand_delta; 10 | 11 | this->elements = (void**)malloc((this->num_alloc)*sizeof(void*)); 12 | 13 | return this; 14 | } 15 | 16 | void 17 | vecDestroy(Vector *this) { 18 | free(this->elements); 19 | free(this); 20 | } 21 | 22 | void 23 | vecAdd(Vector *this, void *element) { 24 | if (this->num_elements == this->num_alloc) { 25 | vecExpand( this, this->expand_delta ); 26 | } 27 | 28 | this->elements[this->num_elements] = element; 29 | this->num_elements += 1; 30 | } 31 | 32 | void * 33 | vecGet(Vector *this, int index) { 34 | if( index < 0 || index >= this->num_elements ) { 35 | return NULL; 36 | } 37 | 38 | return this->elements[index]; 39 | } 40 | 41 | void 42 | vecExpand(Vector *this, int amount){ 43 | this->num_alloc += amount; 44 | this->elements = (void**)realloc( this->elements, this->num_alloc*sizeof(void*) ); 45 | } -------------------------------------------------------------------------------- /core/vector.h: -------------------------------------------------------------------------------- 1 | struct Vector { 2 | int num_elements; 3 | int num_alloc; 4 | int expand_delta; 5 | 6 | void **elements; 7 | } ; 8 | 9 | // VECTOR FUNCTIONS 10 | 11 | Vector * 12 | vecNew( int init_size, int expand_delta ); 13 | 14 | void 15 | vecDestroy(Vector *this); 16 | 17 | void 18 | vecAdd(Vector *this, void *element); 19 | 20 | void * 21 | vecGet(Vector *this, int index); 22 | 23 | void 24 | vecExpand(Vector *this, int amount); -------------------------------------------------------------------------------- /core/walkoptions.c: -------------------------------------------------------------------------------- 1 | 2 | #include "graphserver.h" 3 | 4 | //---------------DEFINITIONS FOR WALKOPTIONS CLASS--------------- 5 | 6 | WalkOptions* 7 | woNew() { 8 | WalkOptions* ret = (WalkOptions*)malloc( sizeof(WalkOptions) ); 9 | ret->transfer_penalty = 0; 10 | ret->turn_penalty = 0; 11 | ret->walking_speed = 6.07; //meters per second 12 | ret->walking_reluctance = 1; 13 | ret->uphill_slowness = 0.05; //Factor by which someone's speed is slowed going uphill. 14 | ret->downhill_fastness = -12.1; // meters per second per grade percentage 15 | ret->phase_change_grade = 0.045; // Grade. An interesting thing happens at a particular grade, when they settle in for a long slog. 16 | ret->hill_reluctance = 0; //Factor by which an uphill stretch is penalized, in addition to whatever time is lost by simply gaining. 17 | ret->max_walk = 10000; //meters 18 | ret->walking_overage = 0.1; 19 | 20 | // velocity between 0 grade and the phase change grade is Ax^2+Bx+C, where A is the phase_change_velocity_factor, B is the downhill fastness, and C is the average speed 21 | float phase_change_speed = (ret->uphill_slowness*ret->walking_speed)/(ret->uphill_slowness+ret->phase_change_grade); 22 | ret->phase_change_velocity_factor = (phase_change_speed - ret->downhill_fastness*ret->phase_change_grade - ret->walking_speed)/(ret->phase_change_grade*ret->phase_change_grade); 23 | 24 | return ret; 25 | } 26 | 27 | void 28 | woDestroy( WalkOptions* this ) { 29 | free(this); 30 | } 31 | 32 | int 33 | woGetTransferPenalty( WalkOptions* this ) { 34 | return this->transfer_penalty; 35 | } 36 | 37 | void 38 | woSetTransferPenalty( WalkOptions* this, int transfer_penalty ) { 39 | this->transfer_penalty = transfer_penalty; 40 | } 41 | 42 | float 43 | woGetWalkingSpeed( WalkOptions* this ) { 44 | return this->walking_speed; 45 | } 46 | 47 | void 48 | woSetWalkingSpeed( WalkOptions* this, float walking_speed ) { 49 | this->walking_speed = walking_speed; 50 | } 51 | 52 | float 53 | woGetWalkingReluctance( WalkOptions* this ) { 54 | return this->walking_reluctance; 55 | } 56 | 57 | void 58 | woSetWalkingReluctance( WalkOptions* this, float walking_reluctance ) { 59 | this->walking_reluctance = walking_reluctance; 60 | } 61 | 62 | float 63 | woGetUphillSlowness( WalkOptions* this ) { 64 | return this->uphill_slowness; 65 | } 66 | 67 | void 68 | woSetUphillSlowness( WalkOptions* this, float uphill_slowness ) { 69 | this->uphill_slowness = uphill_slowness; 70 | } 71 | 72 | float 73 | woGetDownhillFastness( WalkOptions* this ) { 74 | return this->downhill_fastness; 75 | } 76 | 77 | void 78 | woSetDownhillFastness( WalkOptions* this, float downhill_fastness ) { 79 | this->downhill_fastness = downhill_fastness; 80 | } 81 | 82 | float 83 | woGetHillReluctance( WalkOptions* this ) { 84 | return this->hill_reluctance; 85 | } 86 | 87 | void 88 | woSetHillReluctance( WalkOptions* this, float hill_reluctance ) { 89 | this->hill_reluctance = hill_reluctance; 90 | } 91 | 92 | int 93 | woGetMaxWalk( WalkOptions* this ) { 94 | return this->max_walk; 95 | } 96 | 97 | void 98 | woSetMaxWalk( WalkOptions* this, int max_walk ) { 99 | this->max_walk = max_walk; 100 | } 101 | 102 | float 103 | woGetWalkingOverage( WalkOptions* this ) { 104 | return this->walking_overage; 105 | } 106 | 107 | void 108 | woSetWalkingOverage( WalkOptions* this, float walking_overage ) { 109 | this->walking_overage = walking_overage; 110 | } 111 | 112 | int 113 | woGetTurnPenalty( WalkOptions* this ) { 114 | return this->turn_penalty; 115 | } 116 | 117 | void 118 | woSetTurnPenalty( WalkOptions* this, int turn_penalty ) { 119 | this->turn_penalty = turn_penalty; 120 | } -------------------------------------------------------------------------------- /core/walkoptions.h: -------------------------------------------------------------------------------- 1 | #ifndef _WALKOPTIONS_H_ 2 | #define _WALKOPTIONS_H_ 3 | 4 | //---------------DECLARATIONS FOR WALKOPTIONS CLASS--------------- 5 | 6 | struct WalkOptions { 7 | int transfer_penalty; 8 | float walking_speed; 9 | float walking_reluctance; 10 | float uphill_slowness; 11 | float downhill_fastness; 12 | float phase_change_grade; 13 | float hill_reluctance; 14 | int max_walk; 15 | float walking_overage; 16 | int turn_penalty; 17 | 18 | float phase_change_velocity_factor; 19 | } ; 20 | 21 | WalkOptions* 22 | woNew(void); 23 | 24 | void 25 | woDestroy( WalkOptions* this ); 26 | 27 | int 28 | woGetTransferPenalty( WalkOptions* this ); 29 | 30 | void 31 | woSetTransferPenalty( WalkOptions* this, int transfer_penalty ); 32 | 33 | float 34 | woGetWalkingSpeed( WalkOptions* this ); 35 | 36 | void 37 | woSetWalkingSpeed( WalkOptions* this, float walking_speed ); 38 | 39 | float 40 | woGetWalkingReluctance( WalkOptions* this ); 41 | 42 | void 43 | woSetWalkingReluctance( WalkOptions* this, float walking_reluctance ); 44 | 45 | int 46 | woGetMaxWalk( WalkOptions* this ); 47 | 48 | void 49 | woSetMaxWalk( WalkOptions* this, int max_walk ); 50 | 51 | float 52 | woGetWalkingOverage( WalkOptions* this ); 53 | 54 | void 55 | woSetWalkingOverage( WalkOptions* this, float walking_overage ); 56 | 57 | int 58 | woGetTurnPenalty( WalkOptions* this ); 59 | 60 | void 61 | woSetTurnPenalty( WalkOptions* this, int turn_penalty ); 62 | 63 | #endif 64 | -------------------------------------------------------------------------------- /pygs/README: -------------------------------------------------------------------------------- 1 | To install, simply run setup.py like so: 2 | 3 | $ sudo python setup.py install -------------------------------------------------------------------------------- /pygs/graphserver/__init__.py: -------------------------------------------------------------------------------- 1 | __version__='0.9.0' 2 | -------------------------------------------------------------------------------- /pygs/graphserver/compiler/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bmander/graphserver/1a9564d9d0777f0fc7a8c86e933e8402ea37229a/pygs/graphserver/compiler/__init__.py -------------------------------------------------------------------------------- /pygs/graphserver/compiler/dedupe.py: -------------------------------------------------------------------------------- 1 | # eliminate duplicate service periods from a GTFS database 2 | 3 | from graphserver.ext.gtfs.gtfsdb import GTFSDatabase 4 | 5 | import sys 6 | from optparse import OptionParser 7 | 8 | def main(): 9 | usage = """usage: python dedupe.py """ 10 | parser = OptionParser(usage=usage) 11 | 12 | (options, args) = parser.parse_args() 13 | 14 | if len(args) != 1: 15 | parser.print_help() 16 | exit(-1) 17 | 18 | graphdb_filename = args[0] 19 | 20 | gtfsdb = GTFSDatabase( graphdb_filename ) 21 | 22 | query = """ 23 | SELECT count(*), monday, tuesday, wednesday, thursday, friday, saturday, sunday, start_date, end_date 24 | FROM calendar 25 | GROUP BY monday, tuesday, wednesday, thursday, friday, saturday, sunday, start_date, end_date""" 26 | 27 | duped_periods = gtfsdb.execute( query ) 28 | 29 | equivilants = [] 30 | 31 | for count, m,t,w,th,f,s,su,start_date,end_date in duped_periods: 32 | # no need to check for dupes if there's only one 33 | if count==1: 34 | continue 35 | 36 | #print count, m, t, w, th, f, s, su, start_date, end_date 37 | 38 | # get service_ids for this dow/start_date/end_date combination 39 | service_ids = [x[0] for x in list( gtfsdb.execute( "SELECT service_id FROM calendar where monday=? and tuesday=? and wednesday=? and thursday=? and friday=? and saturday=? and sunday=? and start_date=? and end_date=?", (m,t,w,th,f,s,su,start_date,end_date) ) ) ] 40 | 41 | # group by service periods with the same set of exceptions 42 | exception_set_grouper = {} 43 | for service_id in service_ids: 44 | exception_set = list(gtfsdb.execute( "SELECT date, exception_type FROM calendar_dates WHERE service_id=?", (service_id,) ) ) 45 | exception_set.sort() 46 | exception_set = tuple(exception_set) 47 | 48 | exception_set_grouper[exception_set] = exception_set_grouper.get(exception_set,[]) 49 | exception_set_grouper[exception_set].append( service_id ) 50 | 51 | # extend list of equivilants 52 | for i, exception_set_group in enumerate( exception_set_grouper.values() ): 53 | equivilants.append( ("%d%d%d%d%d%d%d-%s-%s-%d"%(m,t,w,th,f,s,su,start_date,end_date,i), exception_set_group) ) 54 | 55 | for new_name, old_names in equivilants: 56 | for old_name in old_names: 57 | print old_name, new_name 58 | 59 | c = gtfsdb.conn.cursor() 60 | 61 | c.execute( "UPDATE calendar SET service_id=? WHERE service_id=?", (new_name, old_name) ) 62 | c.execute( "UPDATE calendar_dates SET service_id=? WHERE service_id=?", (new_name, old_name) ) 63 | c.execute( "UPDATE trips SET service_id=? WHERE service_id=?", (new_name, old_name) ) 64 | 65 | gtfsdb.conn.commit() 66 | 67 | c.close() 68 | 69 | if __name__=='__main__': 70 | main() 71 | 72 | -------------------------------------------------------------------------------- /pygs/graphserver/compiler/gdb_import_ned.py: -------------------------------------------------------------------------------- 1 | from graphserver.graphdb import GraphDatabase 2 | from graphserver.ext.osm.profiledb import ProfileDB 3 | from graphserver.core import Street 4 | 5 | def cons(ary): 6 | for i in range(len(ary)-1): 7 | yield (ary[i], ary[i+1]) 8 | 9 | def get_rise_and_fall( profile ): 10 | rise=0 11 | fall=0 12 | 13 | if profile is not None: 14 | for (d1, e1), (d2, e2) in cons(profile): 15 | diff = e2-e1 16 | if diff>0: 17 | rise += diff 18 | elif diff<0: 19 | fall -= diff 20 | 21 | return rise, fall 22 | 23 | from sys import argv 24 | 25 | def main(): 26 | if len(argv) < 2: 27 | print "usage: python import_ned.py graphdb_filename profiledb_filename" 28 | return 29 | 30 | graphdb_filename = argv[1] 31 | profiledb_filename = argv[2] 32 | 33 | gdb = GraphDatabase( graphdb_filename ) 34 | profiledb = ProfileDB( profiledb_filename ) 35 | 36 | n = gdb.num_edges() 37 | 38 | for i, (oid, vertex1, vertex2, edge) in enumerate( list(gdb.all_edges(include_oid=True)) ): 39 | if i%500==0: print "%s/%s"%(i,n) 40 | 41 | if isinstance( edge, Street ): 42 | rise, fall = get_rise_and_fall( profiledb.get( edge.name ) ) 43 | edge.rise = rise 44 | edge.fall = fall 45 | 46 | gdb.remove_edge( oid ) 47 | gdb.add_edge( vertex1, vertex2, edge ) 48 | 49 | if __name__=='__main__': 50 | main() 51 | 52 | 53 | -------------------------------------------------------------------------------- /pygs/graphserver/compiler/gdb_import_osm.py: -------------------------------------------------------------------------------- 1 | from optparse import OptionParser 2 | from graphserver.graphdb import GraphDatabase 3 | import os 4 | from graphserver.core import Street 5 | from graphserver.ext.osm.osmdb import OSMDB 6 | import sys 7 | from graphserver.ext.osm.profiledb import ProfileDB 8 | from gdb_import_ned import get_rise_and_fall 9 | 10 | def edges_from_osmdb(osmdb, vertex_namespace, slogs, profiledb=None): 11 | """generates (vertex1_label, vertex2_label, edgepayload) from osmdb""" 12 | 13 | street_id_counter = 0 14 | street_names = {} 15 | 16 | # for each edge in the osmdb 17 | for i, (id, parent_id, node1, node2, distance, geom, tags) in enumerate( osmdb.edges() ): 18 | 19 | # Find rise/fall of edge, if profiledb is given 20 | rise=0 21 | fall=0 22 | if profiledb: 23 | profile = profiledb.get( id ) 24 | if profile: 25 | rise, fall = get_rise_and_fall( profile ) 26 | 27 | # insert end vertices of edge to graph 28 | vertex1_label = "%s-%s"%(vertex_namespace,node1) 29 | vertex2_label = "%s-%s"%(vertex_namespace,node2) 30 | 31 | # create ID for the way's street 32 | street_name = tags.get("name") 33 | if street_name is None: 34 | street_id_counter += 1 35 | street_id = street_id_counter 36 | else: 37 | if street_name not in street_names: 38 | street_id_counter += 1 39 | street_names[street_name] = street_id_counter 40 | street_id = street_names[street_name] 41 | 42 | # Create edges to be inserted into graph 43 | s1 = Street( id, distance, rise, fall ) 44 | s2 = Street( id, distance, fall, rise, reverse_of_source=True ) 45 | s1.way = street_id 46 | s2.way = street_id 47 | 48 | # See if the way's highway tag is penalized with a 'slog' value; if so, set it in the edges 49 | slog = slogs.get( tags.get("highway") ) 50 | if slog: 51 | s1.slog = s2.slog = slog 52 | 53 | # Add the forward edge and the return edge if the edge is not oneway 54 | yield vertex1_label, vertex2_label, s1 55 | 56 | oneway = tags.get("oneway") 57 | if oneway != "true" and oneway != "yes": 58 | yield vertex2_label, vertex1_label, s2 59 | 60 | def gdb_import_osm(gdb, osmdb, vertex_namespace, slogs, profiledb=None): 61 | cursor = gdb.get_cursor() 62 | 63 | n_edges = osmdb.count_edges()*2 # two edges for each bidirectional edge 64 | 65 | # for each edge in the osmdb 66 | for i, (vertex1_label, vertex2_label, edge ) in enumerate( edges_from_osmdb( osmdb, vertex_namespace, slogs, profiledb ) ): 67 | 68 | if i%(n_edges//100+1)==0: sys.stdout.write( "%d/~%d edges loaded\r\n"%(i, n_edges)) 69 | 70 | gdb.add_vertex( vertex1_label, cursor ) 71 | gdb.add_vertex( vertex2_label, cursor ) 72 | 73 | gdb.add_edge( vertex1_label, vertex2_label, edge, cursor ) 74 | 75 | gdb.commit() 76 | 77 | print "indexing vertices..." 78 | gdb.index() 79 | 80 | def main(): 81 | usage = """usage: python gdb_import_osm.py """ 82 | parser = OptionParser(usage=usage) 83 | parser.add_option("-n", "--namespace", dest="namespace", default="osm", 84 | help="prefix all imported vertices with namespace string") 85 | parser.add_option("-s", "--slog", 86 | action="append", dest="slog_strings", default=[], 87 | help="specify slog for highway type, in highway_type:slog form. For example, 'motorway:10.5'") 88 | parser.add_option("-p", "--profiledb", dest="profiledb_filename", default=None, 89 | help="specify profiledb to annotate streets with rise/fall data") 90 | 91 | (options, args) = parser.parse_args() 92 | 93 | if len(args) != 2: 94 | parser.print_help() 95 | exit(-1) 96 | 97 | slogs = {} 98 | for slog_string in options.slog_strings: 99 | highway_type,slog_penalty = slog_string.split(":") 100 | slogs[highway_type] = float(slog_penalty) 101 | print "slog values: %s"%slogs 102 | 103 | graphdb_filename = args[0] 104 | osmdb_filename = args[1] 105 | 106 | print "importing osmdb '%s' into graphdb '%s'"%(osmdb_filename, graphdb_filename) 107 | 108 | profiledb = ProfileDB( options.profiledb_filename ) if options.profiledb_filename else None 109 | osmdb = OSMDB( osmdb_filename ) 110 | gdb = GraphDatabase( graphdb_filename, overwrite=False ) 111 | 112 | gdb_import_osm(gdb, osmdb, options.namespace, slogs, profiledb); 113 | 114 | print "done" 115 | 116 | if __name__ == '__main__': 117 | main() 118 | 119 | 120 | -------------------------------------------------------------------------------- /pygs/graphserver/compiler/gdb_link_gtfs_gtfs.py: -------------------------------------------------------------------------------- 1 | from graphserver.ext.gtfs.gtfsdb import GTFSDatabase 2 | from graphserver.ext.osm.osmdb import OSMDB 3 | from graphserver.graphdb import GraphDatabase 4 | from graphserver.core import Link, Street 5 | from graphserver.vincenty import vincenty 6 | 7 | import sys 8 | from optparse import OptionParser 9 | 10 | def main(): 11 | usage = """usage: python gdb_link_gtfs_gtfs.py """ 12 | parser = OptionParser(usage=usage) 13 | 14 | (options, args) = parser.parse_args() 15 | 16 | if len(args) != 3: 17 | parser.print_help() 18 | exit(-1) 19 | 20 | graphdb_filename = args[0] 21 | gtfsdb_filename = args[1] 22 | range = float(args[2]) 23 | 24 | gtfsdb = GTFSDatabase( gtfsdb_filename ) 25 | gdb = GraphDatabase( graphdb_filename ) 26 | 27 | n_stops = gtfsdb.count_stops() 28 | 29 | for i, (stop_id, stop_name, stop_lat, stop_lon) in enumerate( gtfsdb.stops() ): 30 | print "%d/%d %s"%(i,n_stops,stop_id), 31 | 32 | station_vertex_id = "sta-%s"%stop_id 33 | 34 | for link_stop_id, link_stop_name, link_stop_lat, link_stop_lon in gtfsdb.nearby_stops( stop_lat, stop_lon, range ): 35 | if link_stop_id == stop_id: 36 | continue 37 | 38 | print ".", 39 | 40 | link_length = vincenty( stop_lat, stop_lon, link_stop_lat, link_stop_lon) 41 | link_station_vertex_id = "sta-%s"%link_stop_id 42 | gdb.add_edge( station_vertex_id, link_station_vertex_id, Street("link", link_length) ) 43 | 44 | print "" 45 | 46 | if __name__=='__main__': 47 | main() 48 | -------------------------------------------------------------------------------- /pygs/graphserver/compiler/gdb_link_osm_gtfs.py: -------------------------------------------------------------------------------- 1 | from graphserver.ext.gtfs.gtfsdb import GTFSDatabase 2 | from graphserver.ext.osm.osmdb import OSMDB 3 | from graphserver.graphdb import GraphDatabase 4 | from graphserver.core import Link 5 | 6 | import sys 7 | from optparse import OptionParser 8 | 9 | def main(): 10 | usage = """usage: python gdb_link_osm_gtfs.py """ 11 | parser = OptionParser(usage=usage) 12 | 13 | (options, args) = parser.parse_args() 14 | 15 | if len(args) != 3: 16 | parser.print_help() 17 | exit(-1) 18 | 19 | graphdb_filename = args[0] 20 | osmdb_filename = args[1] 21 | gtfsdb_filename = args[2] 22 | 23 | gtfsdb = GTFSDatabase( gtfsdb_filename ) 24 | osmdb = OSMDB( osmdb_filename ) 25 | gdb = GraphDatabase( graphdb_filename ) 26 | 27 | n_stops = gtfsdb.count_stops() 28 | 29 | c = gdb.get_cursor() 30 | for i, (stop_id, stop_name, stop_lat, stop_lon) in enumerate( gtfsdb.stops() ): 31 | print "%d/%d"%(i,n_stops) 32 | 33 | nd_id, nd_lat, nd_lon, nd_dist = osmdb.nearest_node( stop_lat, stop_lon ) 34 | station_vertex_id = "sta-%s"%stop_id 35 | osm_vertex_id = "osm-%s"%nd_id 36 | 37 | print station_vertex_id, osm_vertex_id 38 | 39 | gdb.add_edge( station_vertex_id, osm_vertex_id, Link(), c ) 40 | gdb.add_edge( osm_vertex_id, station_vertex_id, Link(), c ) 41 | 42 | gdb.commit() 43 | 44 | if __name__=='__main__': 45 | main() -------------------------------------------------------------------------------- /pygs/graphserver/compiler/gdb_new.py: -------------------------------------------------------------------------------- 1 | from optparse import OptionParser 2 | from graphserver.graphdb import GraphDatabase 3 | import os 4 | 5 | def main(): 6 | usage = """usage: python new_gdb.py [options] """ 7 | parser = OptionParser(usage=usage) 8 | parser.add_option("-o", "--overwrite", 9 | action="store_true", dest="overwrite", default=False, 10 | help="overwrite any existing database") 11 | 12 | (options, args) = parser.parse_args() 13 | 14 | if len(args) != 1: 15 | parser.print_help() 16 | exit(-1) 17 | 18 | graphdb_filename = args[0] 19 | 20 | if not os.path.exists(graphdb_filename) or options.overwrite: 21 | print "Creating graph database '%s'"%graphdb_filename 22 | 23 | graphdb = GraphDatabase( graphdb_filename, overwrite=options.overwrite ) 24 | else: 25 | print "Graph database '%s' already exists. Use -o to overwrite"%graphdb_filename 26 | 27 | if __name__=='__main__': 28 | main() -------------------------------------------------------------------------------- /pygs/graphserver/compiler/tools.py: -------------------------------------------------------------------------------- 1 | from graphserver.core import ServiceCalendar 2 | import pytz 3 | from datetime import timedelta, datetime, time 4 | from graphserver.util import TimeHelpers 5 | 6 | def iter_dates(startdate, enddate): 7 | currdate = startdate 8 | while currdate <= enddate: 9 | yield currdate 10 | currdate += timedelta(1) 11 | 12 | def service_calendar_from_timezone(gtfsdb, timezone_name): 13 | 14 | MAX_CALENDAR_SIZE = 1024 15 | sc_count = list(gtfsdb.execute( "SELECT DISTINCT count(*) FROM (SELECT service_id FROM calendar_dates UNION SELECT service_id FROM calendar )" ))[0][0] 16 | if sc_count > MAX_CALENDAR_SIZE: 17 | raise Exception( "Service period count %d is greater than the maximum of %d"%(sc_count, MAX_CALENDAR_SIZE) ) 18 | 19 | timezone = pytz.timezone( timezone_name ) 20 | 21 | # grab date, day service bounds 22 | start_date, end_date = gtfsdb.date_range() 23 | 24 | # init empty calendar 25 | cal = ServiceCalendar() 26 | 27 | # for each day in service range, inclusive 28 | for currdate in iter_dates(start_date, end_date): 29 | 30 | # get and encode in utf-8 the service_ids of all service periods running thos date 31 | service_ids = [x.encode('utf8') for x in gtfsdb.service_periods( currdate )] 32 | 33 | # figure datetime.datetime bounds of this service day 34 | currdate_start = datetime.combine(currdate, time(0)) 35 | currdate_local_start = timezone.localize(currdate_start) 36 | service_period_begins = timezone.normalize( currdate_local_start ) 37 | service_period_ends = timezone.normalize( currdate_local_start + timedelta(hours=24) ) 38 | 39 | # enter as entry in service calendar 40 | cal.add_period( TimeHelpers.datetime_to_unix(service_period_begins), TimeHelpers.datetime_to_unix(service_period_ends), service_ids ) 41 | 42 | return cal 43 | 44 | -------------------------------------------------------------------------------- /pygs/graphserver/ext/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bmander/graphserver/1a9564d9d0777f0fc7a8c86e933e8402ea37229a/pygs/graphserver/ext/__init__.py -------------------------------------------------------------------------------- /pygs/graphserver/ext/gtfs/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bmander/graphserver/1a9564d9d0777f0fc7a8c86e933e8402ea37229a/pygs/graphserver/ext/gtfs/__init__.py -------------------------------------------------------------------------------- /pygs/graphserver/ext/gtfs/gtfsdb_stats.py: -------------------------------------------------------------------------------- 1 | from gtfsdb import GTFSDatabase 2 | import sys 3 | 4 | if __name__=='__main__': 5 | if len(sys.argv) < 2: 6 | print "usage: python gtfsdb_stats.py gtfsdb_filename" 7 | exit() 8 | 9 | db = GTFSDatabase( sys.argv[1] ) 10 | print "extent: %s"%(db.extent(),) 11 | print "stop count: %d"%db.count_stops() 12 | 13 | print "date range: %s"%(db.date_range(),) -------------------------------------------------------------------------------- /pygs/graphserver/ext/gtfs/process_gtfs.py: -------------------------------------------------------------------------------- 1 | from gtfsdb import main_compile_gtfsdb 2 | import sys 3 | 4 | if __name__=='__main__': main_compile_gtfsdb() 5 | -------------------------------------------------------------------------------- /pygs/graphserver/ext/ned/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bmander/graphserver/1a9564d9d0777f0fc7a8c86e933e8402ea37229a/pygs/graphserver/ext/ned/__init__.py -------------------------------------------------------------------------------- /pygs/graphserver/ext/ned/elevation/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bmander/graphserver/1a9564d9d0777f0fc7a8c86e933e8402ea37229a/pygs/graphserver/ext/ned/elevation/__init__.py -------------------------------------------------------------------------------- /pygs/graphserver/ext/ned/profile.py: -------------------------------------------------------------------------------- 1 | from graphserver.ext.osm.osmdb import OSMDB 2 | from elevation.elevation import ElevationPile, GridFloat, BIL 3 | from graphserver.ext.osm.profiledb import ProfileDB 4 | 5 | OSMDB_NAME = "./data/osm/map2.osmdb" 6 | ELEV_BASENAME = "./data/83892907/83892907" 7 | PROFILEDB_NAME = "profile.db" 8 | 9 | def compress(ary, ratio): 10 | yield ary[0] 11 | for i in range(1, len(ary)-1, ratio): 12 | yield ary[i] 13 | yield ary[-1] 14 | 15 | def cons(ary): 16 | for i in range(len(ary)-1): 17 | yield (ary[i], ary[i+1]) 18 | 19 | class Profile(object): 20 | def __init__(self): 21 | self.segs = [] 22 | 23 | def add(self, seg): 24 | self.segs.append( seg ) 25 | 26 | def concat(self, npoints=None): 27 | ret = [] 28 | s = 0 29 | 30 | for seg in self.segs: 31 | if len(seg)<2: 32 | continue 33 | 34 | s0, e0 = seg[0] 35 | ret.append( (s, e0) ) 36 | for (s0, e0), (s1, e1) in cons(seg): 37 | s += abs(s1-s0) 38 | ret.append( (s, e1) ) 39 | 40 | if npoints is not None: 41 | compression = int(len(ret)/float(npoints)) 42 | if compression <= 1: 43 | return ret 44 | 45 | return list(compress(ret,compression)) 46 | 47 | return ret 48 | 49 | def populate_profile_db( osmdb_name, profiledb_name, dem_basenames, resolution ): 50 | 51 | ddb = OSMDB( osmdb_name ) 52 | elevs = ElevationPile() 53 | for dem_basename in dem_basenames: 54 | elevs.add( dem_basename ) 55 | pdb = ProfileDB( profiledb_name, overwrite=True ) 56 | 57 | n = ddb.count_edges() 58 | print "Profiling %d way segments"%n 59 | 60 | for i, (id, parent_id, node1, node2, dist, geom, tags) in enumerate( ddb.edges() ): 61 | if i%1000==0: print "%d/%d"%(i,n) 62 | 63 | raw_profile = elevs.profile( geom, resolution ) 64 | profile = [] 65 | 66 | tunnel = tags.get('tunnel') 67 | bridge = tags.get('bridge') 68 | if tunnel == 'yes' or tunnel == 'true' or bridge == 'yes' or bridge == 'true': 69 | if len(raw_profile) > 0: 70 | ss, ee = raw_profile[0] 71 | if ee is not None: profile.append( (ss,ee) ) 72 | if len(raw_profile) > 1: 73 | ss, ee = raw_profile[-1] 74 | if ee is not None: profile.append( (ss,ee) ) 75 | else: 76 | for ss, ee in raw_profile: 77 | if ee is not None: profile.append( (ss,ee) ) 78 | 79 | pdb.store( id, profile ) 80 | 81 | pdb.conn.commit() 82 | 83 | from sys import argv 84 | def main(): 85 | usage = "python profile.py osmdb_name profiledb_name resolution dem_basename " 86 | if len(argv) < 5: 87 | print usage 88 | exit() 89 | 90 | osmdb_name = argv[1] 91 | profiledb_name = argv[2] 92 | resolution = int(argv[3]) 93 | dem_basenames = argv[4:] 94 | 95 | print "osmdb name:", osmdb_name 96 | print "profiledb name:", profiledb_name 97 | print "resolution:", resolution 98 | print "dem_basenames:", dem_basenames 99 | 100 | populate_profile_db(osmdb_name, profiledb_name, dem_basenames, resolution) 101 | 102 | if __name__ == '__main__': 103 | main() 104 | -------------------------------------------------------------------------------- /pygs/graphserver/ext/ned/profiledb.py: -------------------------------------------------------------------------------- 1 | from graphserver.ext.osm.profiledb import main 2 | 3 | if __name__=='__main__': 4 | main() -------------------------------------------------------------------------------- /pygs/graphserver/ext/osm/__init__.py: -------------------------------------------------------------------------------- 1 | from osm import Way, Node, OSM 2 | from graph import OSMGraph 3 | from load_osm import OSMLoadable 4 | -------------------------------------------------------------------------------- /pygs/graphserver/ext/osm/graph.py: -------------------------------------------------------------------------------- 1 | import time 2 | from osm import OSM, dist 3 | import sys 4 | 5 | sys.path.append('../../..') 6 | from graphserver.core import Graph, Street, State 7 | 8 | 9 | class OSMGraph(Graph): 10 | 11 | def __init__(self, filename_osmobject_or_stream, projection): 12 | """ Builds an OSM graph based on a filename or filehandle. Projection is used for calculating lengths. 13 | Subclasses can override the is_valid_way and create_edgepayload methods to filter path types and 14 | create alternative payloads.""" 15 | 16 | super(OSMGraph, self).__init__() 17 | self.projection = projection 18 | 19 | t0 = time.time() 20 | if filename_osmobject_or_stream.__class__ == OSM: 21 | self.osm = filename_osmobject_or_stream 22 | osm = self.osm 23 | else: 24 | print "parsing OSM file" 25 | osm = OSM(filename_osmobject_or_stream) 26 | self.osm = osm 27 | t1 = time.time() 28 | print "parsing took: %f"%(t1-t0) 29 | t0 = t1 30 | 31 | print "load vertices into memory" 32 | for nodeid in osm.nodes.keys(): 33 | self.add_vertex( str(nodeid) ) 34 | 35 | print "load edges into memory" 36 | for way in osm.ways.values(): 37 | if self.is_valid_way(way): 38 | # need two copies of the payload 39 | self.add_edge( str(way.fromv), str(way.tov), self.create_edgepayload(way) ) 40 | self.add_edge( str(way.tov), str(way.fromv), self.create_edgepayload(way) ) 41 | t1 = time.time() 42 | print "populating graph took: %f"%(t1-t0) 43 | 44 | def is_valid_way(self, way): 45 | return 'highway' in way.tags 46 | 47 | def create_edgepayload(self, way): 48 | len = way.length() 49 | return Street( way.id, len ) 50 | 51 | def shortest_path_tree(self, from_v, to_v, state): 52 | t0 = time.time() 53 | spt = super(OSMGraph, self).shortest_path_tree( from_v, to_v, state) 54 | t1 = time.time() 55 | print "shortest_path_tree took: %f"%(t1-t0) 56 | return spt 57 | 58 | def write_graph(self, fp, format="%(from)s:%(to)s:%(points)s\n", reproject=True, point_delim=","): 59 | for edge in self.edges: 60 | osmway = self.osm.ways[ edge.payload.name ] 61 | if reproject: 62 | points = osmway.get_projected_points(self.projection) 63 | else: 64 | points = osmway.get_projected_points() 65 | fp.write( format % {'from':edge.from_v.label, 66 | 'to':edge.to_v.label, 67 | 'name':osmway.tags.get('name',''), 68 | 'length':edge.payload.length, 69 | 'points':point_delim.join( [" ".join([str(c) for c in p]) for p in points] )}) 70 | 71 | 72 | def write_spt(self, fp, spt, format="%(from)s:%(to)s:%(length)f:%(weight)d:%(points)s\n", 73 | reproject=True, point_delim=","): 74 | """ Writes out a shortest path tree. """ 75 | for edge in spt.edges: 76 | osmway = self.osm.ways[ edge.payload.name ] 77 | state = edge.to_v.payload 78 | if reproject: 79 | points = osmway.get_projected_points(self.projection) 80 | else: 81 | points = osmway.get_projected_points() 82 | length = edge.payload.length #osmway.length(osm.nodes) 83 | elapsed = state.time 84 | num_transfers = state.num_transfers 85 | 86 | fp.write( format % {'from':edge.from_v.label, 87 | 'to':edge.to_v.label, 88 | 'length':length, 89 | 'weight':state.weight, 90 | 'state':state, 91 | 'time':state.time, 92 | 'dist_walked':state.dist_walked, 93 | 'num_transfers':state.num_transfers, 94 | 'points':point_delim.join( [" ".join([str(c) for c in p]) for p in points] )} ) 95 | 96 | def find_nearest_vertex(self, lng, lat): 97 | return self.osm.find_nearest_node(lng, lat).id 98 | -------------------------------------------------------------------------------- /pygs/graphserver/ext/osm/load_osm.py: -------------------------------------------------------------------------------- 1 | from osm import OSM,Node,Way 2 | import sys 3 | sys.path.append('../../..') 4 | from graphserver.core import Graph, Street 5 | 6 | class OSMLoadable: 7 | def load_osm(self, osm_filename_or_object, projection, multipliers=[], prefix="osm"): 8 | """multipliers is a dict of highway types to edge weight multipliers (highwaytype,multiplier) which effect the 9 | preferential weighting of a kind of edge. For example, {'cycleway':0.333} makes cycleways three 10 | times easier to traverse""" 11 | 12 | if type(osm_filename_or_object) == str: 13 | osm = OSM(osm_filename_or_object) 14 | else: 15 | osm = osm_filename_or_object 16 | 17 | for way in osm.ways.values(): 18 | # Nodes will be added to the vertex twice. That's not a problem: the second time, nothing happens. 19 | # Do this instead of adding each osm.nodes.keys(), because not all nodes are connected to other nodes 20 | self.add_vertex( prefix+str(way.fromv) ) 21 | self.add_vertex( prefix+str(way.tov) ) 22 | 23 | for wayid, way in osm.ways.iteritems(): 24 | if 'highway' in way.tags: 25 | #len = way.length(projection) 26 | # distance is not dependant on projection since osm nodes always use the same srs 27 | len = way.length_haversine() 28 | 29 | if way.tags['highway'] in multipliers: 30 | len = len*multipliers[way.tags['highway']] 31 | 32 | self.add_edge( prefix+str(way.fromv), prefix+str(way.tov), Street( wayid, len ) ) 33 | self.add_edge( prefix+str(way.tov), prefix+str(way.fromv), Street( wayid, len ) ) 34 | -------------------------------------------------------------------------------- /pygs/graphserver/ext/osm/profiledb.py: -------------------------------------------------------------------------------- 1 | #A little encapsulated databse for storing elevation profiles of OSM ways 2 | 3 | import os 4 | import sqlite3 5 | try: 6 | import json 7 | except ImportError: 8 | import simplejson as json 9 | import binascii 10 | from struct import pack, unpack 11 | 12 | def pack_coords(coords): 13 | return binascii.b2a_base64( "".join([pack( "ff", *coord ) for coord in coords]) ) 14 | 15 | def unpack_coords(str): 16 | bin = binascii.a2b_base64( str ) 17 | return [unpack( "ff", bin[i:i+8] ) for i in range(0, len(bin), 8)] 18 | 19 | class ProfileDB: 20 | def __init__(self, dbname,overwrite=False): 21 | self.dbname = dbname 22 | 23 | if overwrite: 24 | try: 25 | os.remove( dbname ) 26 | except OSError: 27 | pass 28 | 29 | self.conn = sqlite3.connect(dbname) 30 | 31 | if overwrite: 32 | self.setup() 33 | 34 | def get_cursor(self): 35 | # Attempts to get a cursor using the current connection to the db. If we've found ourselves in a different thread 36 | # than that which the connection was made in, re-make the connection. 37 | 38 | try: 39 | ret = self.conn.cursor() 40 | except sqlite3.ProgrammingError: 41 | self.conn = sqlite3.connect(self.dbname) 42 | ret = self.conn.cursor() 43 | 44 | return ret 45 | 46 | def setup(self): 47 | c = self.get_cursor() 48 | c.execute( "CREATE TABLE profiles (id TEXT, profile TEXT)" ) 49 | c.execute( "CREATE INDEX profile_id ON profiles (id)" ) 50 | self.conn.commit() 51 | c.close() 52 | 53 | def store(self, id, profile): 54 | c = self.get_cursor() 55 | 56 | c.execute( "INSERT INTO profiles VALUES (?, ?)", (id, pack_coords( profile )) ) 57 | 58 | c.close() 59 | 60 | def get(self, id): 61 | c = self.get_cursor() 62 | c.execute( "SELECT profile FROM profiles WHERE id = ?", (id,) ) 63 | 64 | try: 65 | (profile,) = c.next() 66 | except StopIteration: 67 | return None 68 | finally: 69 | c.close() 70 | 71 | return unpack_coords( profile ) 72 | 73 | def execute(self,sql,args=None): 74 | c = self.get_cursor() 75 | if args: 76 | for row in c.execute(sql,args): 77 | yield row 78 | else: 79 | for row in c.execute(sql): 80 | yield row 81 | c.close() 82 | 83 | from sys import argv 84 | def main(): 85 | if len(argv) > 1: 86 | pdb = ProfileDB( argv[1] ) 87 | 88 | if len(argv) > 2: 89 | print pdb.get( argv[2] ) 90 | else: 91 | for (id,) in list( pdb.execute( "SELECT id from profiles" ) ): 92 | print id 93 | else: 94 | print "python profiledb.py profiledb_filename [profile_id]" 95 | 96 | if __name__ == '__main__': 97 | main() 98 | 99 | 100 | -------------------------------------------------------------------------------- /pygs/graphserver/ext/osm/simplify_osm.py: -------------------------------------------------------------------------------- 1 | from osm import OSM, Node, Way 2 | 3 | osm = OSM( "map.osm" ) 4 | 5 | fp = open("nodes.csv", "w") 6 | for nodeid in osm.nodes.keys(): 7 | fp.write( "%s\n"%nodeid ) 8 | fp.close() 9 | 10 | fp = open("map.csv", "w") 11 | 12 | for wayid, way in osm.ways.iteritems(): 13 | if 'highway' in way.tags: 14 | fp.write("%s,%s,%s,%f\n"%(wayid, way.fromv, way.tov, way.length(osm.nodes))) 15 | 16 | fp.close() -------------------------------------------------------------------------------- /pygs/graphserver/ext/osm/visitors.py: -------------------------------------------------------------------------------- 1 | 2 | from osmdb import OSMDB 3 | try: 4 | import json 5 | except ImportError: 6 | import simplejson as json 7 | 8 | 9 | class Visitor(object): 10 | """ Basic interface for an OSM visitor.""" 11 | def visit(self, db, *args): 12 | pass 13 | 14 | class UniqueTagNames(object): 15 | def visit(self, db, feature_type): 16 | tag_names = {} 17 | if feature_type == 'nodes': 18 | query = "SELECT tags FROM nodes" 19 | else: 20 | query = "SELECT tags FROM ways" 21 | 22 | for row in db.execute(query): 23 | t = json.loads(row[0]) 24 | for k in t.keys(): 25 | if k not in tag_names: 26 | tag_names[k] = 1 27 | 28 | for k in tag_names.keys(): 29 | print "KEY: %s" % k 30 | 31 | class UniqueTagValues(object): 32 | def visit(self, db, feature_type, tag_name): 33 | tag_values = {} 34 | if feature_type == 'nodes': 35 | query = "SELECT tags FROM nodes" 36 | else: 37 | query = "SELECT tags FROM ways" 38 | 39 | for row in db.execute(query): 40 | t = json.loads(row[0]) 41 | if tag_name in t: 42 | tag_values[t[tag_name]] = 1 43 | 44 | for k in tag_values.keys(): 45 | print "TAG VALUE: %s" % k 46 | 47 | def main(): 48 | from sys import argv 49 | visitor_cls, osmdb_file = argv[1:3] 50 | try: 51 | visitor = globals()[visitor_cls]() 52 | except KeyError, e: 53 | raise Exception("Visitor not found.") 54 | 55 | db = OSMDB(osmdb_file) 56 | 57 | if len(argv) > 3: 58 | extra = argv[3:] 59 | else: 60 | extra = [] 61 | #print extra 62 | visitor.visit(db, *extra) 63 | 64 | if __name__ == '__main__': 65 | main() 66 | 67 | -------------------------------------------------------------------------------- /pygs/graphserver/ext/routeserver/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bmander/graphserver/1a9564d9d0777f0fc7a8c86e933e8402ea37229a/pygs/graphserver/ext/routeserver/__init__.py -------------------------------------------------------------------------------- /pygs/graphserver/ext/routeserver/geocoders.py: -------------------------------------------------------------------------------- 1 | from graphserver.ext.osm.osmdb import OSMDB 2 | 3 | class OSMReverseGeocoder: 4 | def __init__(self, osmdb_filename): 5 | self.osmdb = OSMDB( osmdb_filename ) 6 | 7 | def __call__(self, lat, lon): 8 | nearby_vertex = list(self.osmdb.nearest_node(lat, lon)) 9 | return "osm-%s"%(nearby_vertex[0]) 10 | 11 | def bounds(self): 12 | """return tuple representing bounding box of reverse geocoder with form (left, bottom, right, top)""" 13 | 14 | return self.osmdb.bounds() -------------------------------------------------------------------------------- /pygs/graphserver/ext/routeserver/handlers.yaml: -------------------------------------------------------------------------------- 1 | edge_handlers: 2 | # - name: graphserver.ext.routeserver.events.AllEdgeEvent 3 | - name: graphserver.ext.routeserver.events.BoardEvent 4 | args: 5 | gtfsdb_filename: CHANGEME.gtfsdb 6 | timezone_name: America/Los_Angeles 7 | - name: graphserver.ext.routeserver.events.DescribeCrossingAtAlightEvent 8 | args: 9 | gtfsdb_filename: CHANGEME.gtfsdb 10 | timezone_name: America/Los_Angeles 11 | - name: graphserver.ext.routeserver.events.AlightEvent 12 | args: 13 | gtfsdb_filename: CHANGEME.gtfsdb 14 | timezone_name: America/Los_Angeles 15 | - name: graphserver.ext.routeserver.events.StreetEvent 16 | args: 17 | osmdb_filename: CHANGEME.osmdb 18 | timezone_name: America/Los_Angeles 19 | - name: graphserver.ext.routeserver.events.HeadwayBoardEvent 20 | args: 21 | gtfsdb_filename: CHANGEME.gtfsdb 22 | timezone_name: America/Los_Angeles 23 | - name: graphserver.ext.routeserver.events.HeadwayAlightEvent 24 | args: 25 | gtfsdb_filename: CHANGEME.gtfsdb 26 | timezone_name: America/Los_Angeles 27 | 28 | vertex_handlers: 29 | # - name: graphserver.ext.routeserver.events.AllVertexEvent 30 | - name: graphserver.ext.routeserver.events.StreetTurnEvent 31 | args: 32 | osmdb_filename: CHANGEME.osmdb 33 | timezone_name: America/Los_Angeles 34 | - name: graphserver.ext.routeserver.events.StreetStartEvent 35 | args: 36 | osmdb_filename: CHANGEME.osmdb 37 | timezone_name: America/Los_Angeles 38 | - name: graphserver.ext.routeserver.events.StreetEndEvent 39 | args: 40 | osmdb_filename: CHANGEME.osmdb 41 | timezone_name: America/Los_Angeles 42 | 43 | vertex_reverse_geocoders: 44 | - name: graphserver.ext.routeserver.geocoders.OSMReverseGeocoder 45 | args: 46 | osmdb_filename: CHANGEME.osmdb -------------------------------------------------------------------------------- /pygs/graphserver/util.py: -------------------------------------------------------------------------------- 1 | import pytz 2 | from datetime import datetime 3 | import time 4 | import sys 5 | 6 | import calendar 7 | 8 | SECS_IN_MINUTE = 60 9 | SECS_IN_HOURS = 60*SECS_IN_MINUTE 10 | SECS_IN_DAYS = 24*SECS_IN_HOURS 11 | 12 | class TimeHelpers: 13 | 14 | @classmethod 15 | def unix_time(cls,year,month,day,hour,minute,second,offset=0): 16 | """When it is midnight in London, it is 4PM in Seattle: The offset is eight hours. In order 17 | to find the unix time of a local time in Seattle, take the unix time for the time in London. 18 | Then, increase the unix time by eight hours. At this time, it is 4PM in Seattle. Because 19 | Seattle is "behind" London, you will need to subtract the negative number in order to obtain 20 | the unix time of the local number. Thus: 21 | 22 | unix_time(local_time,offset) = london_unix_time(hours(local_time))-offset""" 23 | return calendar.timegm( (year,month,day,hour,minute,second) ) - offset 24 | 25 | @classmethod 26 | def localtime_to_unix(cls,year,month,day,hour,minute,second,timezone): 27 | dt = pytz.timezone(timezone).localize(datetime(year,month,day,hour,minute,second)).astimezone(pytz.utc) 28 | return calendar.timegm( (dt.year, dt.month, dt.day, dt.hour, dt.minute, dt.second) ) 29 | 30 | @classmethod 31 | def datetime_to_unix(cls, dt): 32 | dt = dt.astimezone(pytz.utc) 33 | return calendar.timegm( (dt.year, dt.month, dt.day, dt.hour, dt.minute, dt.second) ) 34 | 35 | @classmethod 36 | def create_localtime(cls,year,month,day,hour,minute,second,timezone): 37 | return pytz.timezone(timezone).localize(datetime(year,month,day,hour,minute,second)) 38 | 39 | @classmethod 40 | def unix_to_localtime(cls,unixtime, timezone): 41 | tt = time.gmtime( unixtime ) 42 | dt = pytz.utc.localize(datetime(tt[0],tt[1],tt[2],tt[3],tt[4],tt[5])) 43 | return dt.astimezone( pytz.timezone(timezone) ) 44 | 45 | @classmethod 46 | def timedelta_to_seconds(cls,td): 47 | return td.days*SECS_IN_DAYS+td.seconds+td.microseconds/1000000.0 48 | 49 | @classmethod 50 | def unixtime_to_daytimes(cls,unixtime,timezone): 51 | dt = cls.unix_to_localtime(unixtime,timezone) 52 | ret = dt.hour*3600+dt.minute*60+dt.second 53 | return ret, ret+24*3600, ret+2*24*3600 54 | 55 | def withProgress(seq, modValue=100): 56 | c = -1 57 | 58 | for c, v in enumerate(seq): 59 | if (c+1) % modValue == 0: 60 | sys.stdout.write("%s\r" % (c+1)) 61 | sys.stdout.flush() 62 | yield v 63 | 64 | print("\nCompleted %s" % (c+1)) 65 | -------------------------------------------------------------------------------- /pygs/graphserver/vector.py: -------------------------------------------------------------------------------- 1 | from gsdll import CShadow, lgs 2 | 3 | from ctypes import Structure, c_int, c_void_p, pointer, addressof, byref 4 | 5 | class Vector(Structure): 6 | _fields_ = [("num_elements", c_int), 7 | ("num_alloc", c_int), 8 | ("expand_delta", c_int), 9 | ("elements", c_void_p)] 10 | 11 | def __new__(cls, init_size=50, expand_delta=50): 12 | # initiate the Path Struct with a C constructor 13 | soul = lgs.vecNew( init_size, expand_delta ) 14 | 15 | # wrap an instance of this class around that pointer 16 | return cls.from_address( soul ) 17 | 18 | def __init__(self, init_size=50, expand_delta=50): 19 | # this gets called with the same arguments as __new__ right after 20 | # __new__ is called, but we've already constructed the struct, so 21 | # do nothing 22 | 23 | pass 24 | 25 | def expand(self, amount): 26 | lgs.vecExpand( addressof(self), amount ) 27 | 28 | def add(self, element): 29 | lgs.vecAdd( addressof(self), element ) 30 | 31 | def get(self, index): 32 | return lgs.vecGet( addressof(self), index ) 33 | 34 | def __repr__(self): 35 | return ""%(hex(addressof(self)),self.num_elements, self.num_alloc) 36 | 37 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /pygs/graphserver/vincenty.py: -------------------------------------------------------------------------------- 1 | """ 2 | 822 OpenLayers.Util.distVincenty=function(p1, p2) { 3 | 823 var a = 6378137, b = 6356752.3142, f = 1/298.257223563; 4 | 824 var L = OpenLayers.Util.rad(p2.lon - p1.lon); 5 | 825 var U1 = Math.atan((1-f) * Math.tan(OpenLayers.Util.rad(p1.lat))); 6 | 826 var U2 = Math.atan((1-f) * Math.tan(OpenLayers.Util.rad(p2.lat))); 7 | 827 var sinU1 = Math.sin(U1), cosU1 = Math.cos(U1); 8 | 828 var sinU2 = Math.sin(U2), cosU2 = Math.cos(U2); 9 | 829 var lambda = L, lambdaP = 2*Math.PI; 10 | 830 var iterLimit = 20; 11 | 831 while (Math.abs(lambda-lambdaP) > 1e-12 && --iterLimit>0) { 12 | 832 var sinLambda = Math.sin(lambda), cosLambda = Math.cos(lambda); 13 | 833 var sinSigma = Math.sqrt((cosU2*sinLambda) * (cosU2*sinLambda) + 14 | 834 (cosU1*sinU2-sinU1*cosU2*cosLambda) * (cosU1*sinU2-sinU1*cosU2*cosLambda)); 15 | 835 if (sinSigma==0) { 16 | 836 return 0; // co-incident points 17 | 837 } 18 | 838 var cosSigma = sinU1*sinU2 + cosU1*cosU2*cosLambda; 19 | 839 var sigma = Math.atan2(sinSigma, cosSigma); 20 | 840 var alpha = Math.asin(cosU1 * cosU2 * sinLambda / sinSigma); 21 | 841 var cosSqAlpha = Math.cos(alpha) * Math.cos(alpha); 22 | 842 var cos2SigmaM = cosSigma - 2*sinU1*sinU2/cosSqAlpha; 23 | 843 var C = f/16*cosSqAlpha*(4+f*(4-3*cosSqAlpha)); 24 | 844 lambdaP = lambda; 25 | 845 lambda = L + (1-C) * f * Math.sin(alpha) * 26 | 846 (sigma + C*sinSigma*(cos2SigmaM+C*cosSigma*(-1+2*cos2SigmaM*cos2SigmaM))); 27 | 847 } 28 | 848 if (iterLimit==0) { 29 | 849 return NaN; // formula failed to converge 30 | 850 } 31 | 851 var uSq = cosSqAlpha * (a*a - b*b) / (b*b); 32 | 852 var A = 1 + uSq/16384*(4096+uSq*(-768+uSq*(320-175*uSq))); 33 | 853 var B = uSq/1024 * (256+uSq*(-128+uSq*(74-47*uSq))); 34 | 854 var deltaSigma = B*sinSigma*(cos2SigmaM+B/4*(cosSigma*(-1+2*cos2SigmaM*cos2SigmaM)- 35 | 855 B/6*cos2SigmaM*(-3+4*sinSigma*sinSigma)*(-3+4*cos2SigmaM*cos2SigmaM))); 36 | 856 var s = b*A*(sigma-deltaSigma); 37 | 857 var d = s.toFixed(3)/1000; // round to 1mm precision 38 | 858 return d; 39 | 859 }; 40 | """ 41 | 42 | from math import sin, cos, tan, atan, radians, pi, sqrt, atan2, asin 43 | 44 | def vincenty(lat1,lon1, lat2, lon2): 45 | """returns distance in meters between any points earth""" 46 | 47 | a = 6378137 48 | b = 6356752.3142 49 | f = 1/298.257223563 50 | 51 | L = radians( lon2-lon1 ) 52 | U1 = atan( (1-f) * tan( radians(lat1) ) ) 53 | U2 = atan( (1-f) * tan( radians(lat2) ) ) 54 | sinU1 = sin(U1); cosU1 = cos(U1) 55 | sinU2 = sin(U2); cosU2 = cos(U2) 56 | lmbda = L; lmbdaP = 2*pi 57 | 58 | iterLimit = 20 59 | 60 | while( iterLimit > 0 ): 61 | if abs(lmbda-lmbdaP) < 1E-12: 62 | break 63 | 64 | sinLambda = sin(lmbda); cosLambda = cos(lmbda) 65 | sinSigma = sqrt((cosU2*sinLambda) * (cosU2*sinLambda) + \ 66 | (cosU1*sinU2-sinU1*cosU2*cosLambda) * (cosU1*sinU2-sinU1*cosU2*cosLambda)) 67 | if sinSigma==0: 68 | return 0 # co-incident points 69 | 70 | cosSigma = sinU1*sinU2 + cosU1*cosU2*cosLambda 71 | sigma = atan2(sinSigma, cosSigma) 72 | alpha = asin(cosU1 * cosU2 * sinLambda / sinSigma) 73 | cosSqAlpha = cos(alpha) * cos(alpha) 74 | cos2SigmaM = cosSigma - 2*sinU1*sinU2/cosSqAlpha 75 | C = f/16*cosSqAlpha*(4+f*(4-3*cosSqAlpha)) 76 | lmbdaP = lmbda; 77 | lmbda = L + (1-C) * f * sin(alpha) * \ 78 | (sigma + C*sinSigma*(cos2SigmaM+C*cosSigma*(-1+2*cos2SigmaM*cos2SigmaM))) 79 | 80 | iterLimit -= 1 81 | 82 | if iterLimit==0: 83 | return None # formula failed to converge 84 | 85 | uSq = cosSqAlpha * (a*a - b*b) / (b*b); 86 | A = 1 + uSq/16384*(4096+uSq*(-768+uSq*(320-175*uSq))) 87 | B = uSq/1024 * (256+uSq*(-128+uSq*(74-47*uSq))) 88 | deltaSigma = B*sinSigma*(cos2SigmaM+B/4*(cosSigma*(-1+2*cos2SigmaM*cos2SigmaM)- 89 | B/6*cos2SigmaM*(-3+4*sinSigma*sinSigma)*(-3+4*cos2SigmaM*cos2SigmaM))) 90 | s = b*A*(sigma-deltaSigma) 91 | 92 | return s 93 | 94 | 95 | if __name__=='__main__': 96 | import time 97 | t0 = time.time() 98 | for i in range(10000): 99 | d = vincenty(47.68382,-122.376709, 47.683155,-122.376666) 100 | t1 = time.time() 101 | print( t1-t0 ) 102 | print vincenty(47.68382,-122.376709, 47.68408,-122.375722) -------------------------------------------------------------------------------- /pygs/setup.py: -------------------------------------------------------------------------------- 1 | from setuptools import setup, find_packages 2 | import os.path, sys, subprocess 3 | 4 | LIBSO = os.path.join('..','core','libgraphserver.so') 5 | 6 | # build and copy libgraphserver.so 7 | subprocess.call(["make","-s", "-C","../core"]) 8 | subprocess.call(["cp",LIBSO,"graphserver/"]) 9 | 10 | setup( name='graphserver', 11 | version='1.0.0', 12 | packages = find_packages(exclude=['examples.*','examples','test','test.*']), 13 | install_requires=['pytz>=2008b','servable>=2009b','nose>=0.10.4'], 14 | zip_safe=False, 15 | extras_require = { 16 | # 'transitfeed': ["transitfeed>=1.1.6"], 17 | }, 18 | 19 | test_suite='nose.collector', 20 | 21 | # metadata for upload to PyPI 22 | author = "Brandon Martin-Anderson", 23 | author_email = "badhill@gmail.com", 24 | description = "Graphserver routing engine.", 25 | license = "BSD", 26 | keywords = "OSM OpenStreetMap GTFS routing transit", 27 | url = "http://github.com/bmander/graphserver/tree/master", 28 | 29 | # put libgraphserver.so next to gsdll.py 30 | package_data = {'graphserver':['libgraphserver.so']} , 31 | 32 | entry_points = { 33 | 'console_scripts': [ 34 | 'gs_osmfilter = graphserver.ext.osm.osmfilters:main', 35 | 'gs_osmdb_compile = graphserver.ext.osm.osmdb:main', 36 | 'gs_gtfsdb_compile = graphserver.ext.gtfs.gtfsdb:main_compile_gtfsdb', 37 | 'gs_gtfsdb_inspect = graphserver.ext.gtfs.gtfsdb:main_inspect_gtfsdb', 38 | 'gs_crawl = graphserver.ext.graphcrawler:main', 39 | 'gs_new = graphserver.compiler.gdb_new:main', 40 | 'gs_import_osm = graphserver.compiler.gdb_import_osm:main', 41 | 'gs_import_gtfs = graphserver.compiler.gdb_import_gtfs:main', 42 | 'gs_import_ned = graphserver.compiler.gdb_import_ned:main', 43 | 'gs_link_osm_gtfs = graphserver.compiler.gdb_link_osm_gtfs:main', 44 | 'gs_link_gtfs_gtfs = graphserver.compiler.gdb_link_gtfs_gtfs:main', 45 | 'gs_gdb_inspect = graphserver.graphdb:main', 46 | 'gs_routeserver = graphserver.ext.routeserver.routeserver:main', 47 | 'gs_profile = graphserver.ext.ned.profile:main', 48 | 'gs_profiledb = graphserver.ext.osm.profiledb:main', 49 | ], 50 | #'setuptools.installation': ['eggsecutable = umigis.server.setup:main'] 51 | } 52 | 53 | ) 54 | -------------------------------------------------------------------------------- /pygs/test/README: -------------------------------------------------------------------------------- 1 | To run all tests, use 'nosetests' 2 | 3 | $ nosetests -v 4 | 5 | To run a specific test file: 6 | 7 | $ nosetests -v unit_test.py 8 | 9 | -------------------------------------------------------------------------------- /pygs/test/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bmander/graphserver/1a9564d9d0777f0fc7a8c86e933e8402ea37229a/pygs/test/__init__.py -------------------------------------------------------------------------------- /pygs/test/stress_test/stress_utils.py: -------------------------------------------------------------------------------- 1 | import os 2 | import sys 3 | 4 | def get_mem_usage(): 5 | """returns percentage and vsz mem usage of this script""" 6 | pid = os.getpid() 7 | psout = os.popen( "ps u -p %s"%pid ).read() 8 | 9 | parsed_psout = psout.split("\n")[1].split() 10 | 11 | return float(parsed_psout[3]), int( parsed_psout[4] ) -------------------------------------------------------------------------------- /pygs/test/unit_test/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bmander/graphserver/1a9564d9d0777f0fc7a8c86e933e8402ea37229a/pygs/test/unit_test/__init__.py -------------------------------------------------------------------------------- /pygs/test/unit_test/test_ch.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | from graphserver.core import * 3 | 4 | class TestCH( unittest.TestCase ): 5 | def test_basic(self): 6 | ch = ContractionHierarchy() 7 | assert ch.soul 8 | 9 | assert ch.upgraph.soul 10 | assert ch.downgraph.soul 11 | 12 | if __name__ == '__main__': 13 | tl = unittest.TestLoader() 14 | 15 | suite = tl.loadTestsFromTestCase(TestCH) 16 | unittest.TextTestRunner(verbosity=2).run(suite) 17 | -------------------------------------------------------------------------------- /pygs/test/unit_test/test_combination.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | from graphserver.core import * 3 | 4 | class TestCombination(unittest.TestCase): 5 | def test_basic(self): 6 | s1 = Street( "A", 1 ) 7 | c0 = Combination( 1 ) 8 | c0.add( s1 ) 9 | 10 | assert c0.__class__ == Combination 11 | assert c0.get( -1 ) == None 12 | assert c0.get( 0 ).__class__ == Street 13 | assert c0.get( 1 ) == None 14 | 15 | assert c0.walk( State(0,0), WalkOptions() ).weight == 0 16 | 17 | s2 = Street( "B", 2 ) 18 | c1 = Combination( 2 ) 19 | c1.add( s1 ) 20 | c1.add( s2 ) 21 | 22 | assert c1.__class__ == Combination 23 | assert c1.get( -1 ) == None 24 | assert c1.get( 0 ).__class__ == Street 25 | assert c1.get( 0 ).name == "A" 26 | assert c1.get( 1 ).__class__ == Street 27 | assert c1.get( 1 ).name == "B" 28 | assert c1.get( 2 ) == None 29 | 30 | assert c1.walk( State(0,0), WalkOptions() ).weight == 0 31 | assert c1.walk_back( State(0, 100), WalkOptions() ).weight == 0 32 | 33 | s3 = Street( "C", 3 ) 34 | 35 | c2 = Combination( 3 ) 36 | c2.add( s1 ) 37 | c2.add( s2 ) 38 | c2.add( s3 ) 39 | 40 | assert c2.walk( State(0,0), WalkOptions() ).weight == 0 41 | assert c2.walk_back( State(0,100), WalkOptions() ).weight == 0 42 | 43 | c3 = Combination( 2 ) 44 | c3.add( c1 ) 45 | c3.add( s3 ) 46 | 47 | assert c3.walk( State(0,0), WalkOptions() ).weight == 0 48 | assert c3.walk_back( State(0,100), WalkOptions() ).weight == 0 49 | 50 | s1.destroy() 51 | s2.destroy() 52 | s3.destroy() 53 | c1.destroy() 54 | c2.destroy() 55 | 56 | 57 | if __name__ == '__main__': 58 | tl = unittest.TestLoader() 59 | 60 | suite = tl.loadTestsFromTestCase(TestCombination) 61 | unittest.TextTestRunner(verbosity=2).run(suite) 62 | -------------------------------------------------------------------------------- /pygs/test/unit_test/test_crossing.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | from graphserver.core import * 3 | 4 | class TestCrossing(unittest.TestCase): 5 | 6 | def test_basic(self): 7 | 8 | cr = Crossing() 9 | 10 | assert cr 11 | assert cr.soul 12 | assert cr.size == 0 13 | assert cr.get_crossing_time( "1" ) == None 14 | assert cr.get_crossing( 0 ) == None 15 | 16 | def test_add_crossing(self): 17 | cr = Crossing() 18 | 19 | cr.add_crossing_time( "1", 10 ) 20 | 21 | assert cr.size == 1 22 | assert cr.get_crossing_time( "1" ) == 10 23 | assert cr.get_crossing( 0 ) == ("1", 10) 24 | 25 | cr.add_crossing_time( "2", 20 ) 26 | cr.add_crossing_time( "3", 30 ) 27 | 28 | assert cr.size == 3 29 | assert cr.get_crossing_time( "1" ) == 10 30 | assert cr.get_crossing_time( "2" ) == 20 31 | 32 | assert cr.get_crossing( 0 ) == ('1', 10) 33 | assert cr.get_crossing( 1 ) == ('2', 20) 34 | assert cr.get_crossing( 2 ) == ('3', 30) 35 | 36 | def test_pickle_and_reconstitute(self): 37 | cr = Crossing() 38 | 39 | cr.add_crossing_time( "1", 10 ) 40 | cr.add_crossing_time( "2", 20 ) 41 | cr.add_crossing_time( "3", 30 ) 42 | 43 | state = cr.__getstate__() 44 | 45 | cr2 = Crossing.reconstitute(state, None) 46 | 47 | assert cr2.size==3 48 | assert cr.get_crossing( 0 ) == ('1', 10) 49 | assert cr.get_crossing( 1 ) == ('2', 20) 50 | assert cr.get_crossing( 2 ) == ('3', 30) 51 | 52 | def test_walk(self): 53 | 54 | cr = Crossing() 55 | cr.add_crossing_time("1", 10) 56 | 57 | s = State(1, 0) 58 | ret = cr.walk(s,WalkOptions()) 59 | 60 | # state has no trip_id, shouldn't evaluate at all 61 | assert ret == None 62 | 63 | s.dangerous_set_trip_id( "1" ) 64 | s1 = cr.walk(s,WalkOptions()) 65 | assert s1.time == 10 66 | assert s1.weight == 10 67 | 68 | def test_walk_back(self): 69 | 70 | cr = Crossing() 71 | cr.add_crossing_time("1", 10) 72 | 73 | s = State(1, 10) 74 | ret = cr.walk_back(s, WalkOptions()) 75 | assert ret == None 76 | 77 | s.dangerous_set_trip_id( "1" ) 78 | s1 = cr.walk_back(s, WalkOptions()) 79 | assert s1.time == 0 80 | assert s1.weight == 10 81 | 82 | if __name__ == '__main__': 83 | tl = unittest.TestLoader() 84 | 85 | suite = tl.loadTestsFromTestCase(TestCrossing) 86 | unittest.TextTestRunner(verbosity=2).run(suite) -------------------------------------------------------------------------------- /pygs/test/unit_test/test_edge.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | from graphserver.core import * 3 | 4 | class TestEdge(unittest.TestCase): 5 | def test_basic(self): 6 | v1 = Vertex( "A" ) 7 | v2 = Vertex( "B" ) 8 | e1 = Edge( v1, v2, Street( "atob", 10.0 ) ) 9 | 10 | assert e1.enabled == True 11 | 12 | e1.enabled = False 13 | assert e1.enabled == False 14 | 15 | def test_walk(self): 16 | v1 = Vertex( "A" ) 17 | v2 = Vertex( "B" ) 18 | e1 = Edge( v1, v2, Street( "atob", 10.0 ) ) 19 | 20 | wo = WalkOptions() 21 | wo.walking_speed = 1 22 | 23 | assert e1.walk( State(0,0), wo ) is not None 24 | assert e1.walk( State(0,0), wo ).weight == 10 25 | 26 | def test_disable(self): 27 | v1 = Vertex( "A" ) 28 | v2 = Vertex( "B" ) 29 | e1 = Edge( v1, v2, Street( "atob", 10.0 ) ) 30 | 31 | wo = WalkOptions() 32 | wo.walking_speed = 1 33 | 34 | assert e1.walk( State(0,0), wo ) is not None 35 | assert e1.walk( State(0,0), wo ).weight == 10 36 | 37 | e1.enabled = False 38 | 39 | assert e1.walk( State(0,0), WalkOptions() ) == None 40 | 41 | gg = Graph() 42 | gg.add_vertex( "A" ) 43 | gg.add_vertex( "B" ) 44 | heavy = Street( "Heavy", 100 ) 45 | light = Street( "Light", 1 ) 46 | gg.add_edge( "A", "B", heavy ) 47 | gg.add_edge( "A", "B", light ) 48 | 49 | assert gg.shortest_path_tree( "A", "B", State(0,0), WalkOptions() ).path("B")[1][0].payload.name == "Light" 50 | 51 | lightedge = gg.get_vertex("A").outgoing[0] 52 | lightedge.enabled = False 53 | 54 | assert gg.shortest_path_tree( "A", "B", State(0,0), WalkOptions() ).path("B")[1][0].payload.name == "Heavy" 55 | 56 | def test_disable_vertex(self): 57 | gg = Graph() 58 | gg.add_vertex( "A" ) 59 | gg.add_vertex( "B" ) 60 | gg.add_vertex( "C" ) 61 | gg.add_vertex( "D" ) 62 | gg.add_edge( "A", "B", Street( "atob", 1 ) ) 63 | gg.add_edge( "B", "D", Street( "btod", 1 ) ) 64 | gg.add_edge( "A", "C", Street( "atoc", 1 ) ) 65 | gg.add_edge( "C", "D", Street( "ctod", 1 ) ) 66 | 67 | for edge in gg.get_vertex("B").outgoing: 68 | assert edge.enabled == True 69 | for edge in gg.get_vertex("B").incoming: 70 | assert edge.enabled == True 71 | 72 | gg.set_vertex_enabled( "B", False ) 73 | 74 | for edge in gg.get_vertex("B").outgoing: 75 | assert edge.enabled == False 76 | for edge in gg.get_vertex("B").incoming: 77 | assert edge.enabled == False 78 | 79 | for edge in gg.get_vertex("C").outgoing: 80 | assert edge.enabled == True 81 | for edge in gg.get_vertex("C").incoming: 82 | assert edge.enabled == True 83 | 84 | gg.set_vertex_enabled( "B", True ) 85 | 86 | for edge in gg.get_vertex("B").outgoing: 87 | assert edge.enabled == True 88 | for edge in gg.get_vertex("B").incoming: 89 | assert edge.enabled == True 90 | 91 | if __name__ == '__main__': 92 | tl = unittest.TestLoader() 93 | 94 | suite = tl.loadTestsFromTestCase(TestEdge) 95 | unittest.TextTestRunner(verbosity=2).run(suite) 96 | -------------------------------------------------------------------------------- /pygs/test/unit_test/test_egress.py: -------------------------------------------------------------------------------- 1 | from graphserver.core import * 2 | import unittest 3 | 4 | class TestEgress(unittest.TestCase): 5 | def test_street(self): 6 | s = Egress("mystreet", 1.1) 7 | assert s.name == "mystreet" 8 | assert s.length == 1.1 9 | assert s.to_xml() == "" 10 | 11 | def test_destroy(self): 12 | s = Egress("mystreet", 1.1) 13 | s.destroy() 14 | 15 | assert s.soul==None 16 | 17 | def test_street_big_length(self): 18 | s = Egress("longstreet", 240000) 19 | assert s.name == "longstreet" 20 | assert s.length == 240000 21 | 22 | assert s.to_xml() == "" 23 | 24 | def test_walk(self): 25 | s = Egress("longstreet", 10) 26 | wo = WalkOptions() 27 | wo.walking_reluctance = 1 28 | after = s.walk(State(0,0),wo) 29 | wo.destroy() 30 | self.assertEqual( after.time , 9 ) 31 | self.assertEqual( after.weight , 9 ) 32 | self.assertEqual( after.dist_walked , 10 ) 33 | self.assertEqual( after.prev_edge.__class__ , Egress ) 34 | self.assertEqual( after.prev_edge.name , "longstreet" ) 35 | self.assertEqual( after.num_agencies , 0 ) 36 | 37 | def test_walk_back(self): 38 | s = Egress("longstreet", 10) 39 | 40 | before = s.walk_back(State(0,100),WalkOptions()) 41 | self.assertEqual( before.time , 100 - (9) ) 42 | self.assertEqual( before.weight , 9 ) 43 | self.assertEqual( before.dist_walked , 10.0 ) 44 | self.assertEqual( before.prev_edge.type , 12 ) 45 | self.assertEqual( before.prev_edge.name , "longstreet" ) 46 | self.assertEqual( before.num_agencies , 0 ) 47 | 48 | def test_getstate(self): 49 | s = Egress("longstreet", 2) 50 | 51 | assert s.__getstate__() == ('longstreet', 2) 52 | 53 | def test_graph(self): 54 | g = Graph() 55 | g.add_vertex("E") 56 | g.add_vertex("S") 57 | g.add_edge("E", "S", Egress("E2S",10)) 58 | 59 | spt = g.shortest_path_tree("E", "S", State(0,0), WalkOptions()) 60 | assert spt 61 | assert spt.__class__ == ShortestPathTree 62 | assert spt.get_vertex("S").state.dist_walked==10 63 | 64 | spt.destroy() 65 | g.destroy() 66 | 67 | if __name__ == '__main__': 68 | tl = unittest.TestLoader() 69 | 70 | suite = tl.loadTestsFromTestCase(TestEgress) 71 | unittest.TextTestRunner(verbosity=2).run(suite) 72 | -------------------------------------------------------------------------------- /pygs/test/unit_test/test_elapsetime.py: -------------------------------------------------------------------------------- 1 | from graphserver.core import * 2 | import unittest 3 | 4 | class TestElapseTime(unittest.TestCase): 5 | def test_new(self): 6 | s = ElapseTime(120) 7 | assert s.seconds == 120 8 | assert s.to_xml() == "" 9 | 10 | def test_destroy(self): 11 | s = ElapseTime(1) 12 | s.destroy() 13 | 14 | assert s.soul==None 15 | 16 | def test_big_seconds(self): 17 | s = ElapseTime(240000) 18 | assert s.seconds == 240000 19 | 20 | assert s.to_xml() == "" 21 | 22 | def test_walk(self): 23 | s = ElapseTime(2) 24 | 25 | after = s.walk(State(0,0),WalkOptions()) 26 | assert after.time == 2 27 | assert after.weight == 2 28 | assert after.dist_walked == 0 29 | assert after.prev_edge.type == 14 30 | assert after.num_agencies == 0 31 | 32 | def test_walk_back(self): 33 | s = ElapseTime(2) 34 | 35 | before = s.walk_back(State(0,100),WalkOptions()) 36 | 37 | assert before.time == 98 38 | assert before.weight == 2 39 | assert before.dist_walked == 0 40 | assert before.prev_edge.type == 14 41 | assert before.num_agencies == 0 42 | 43 | def test_getstate(self): 44 | s = ElapseTime(2) 45 | 46 | assert s.__getstate__() == 2 47 | 48 | if __name__ == '__main__': 49 | tl = unittest.TestLoader() 50 | 51 | suite = tl.loadTestsFromTestCase(TestElapseTime) 52 | unittest.TextTestRunner(verbosity=2).run(suite) -------------------------------------------------------------------------------- /pygs/test/unit_test/test_graph_database.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | from graphserver.core import Graph, Link, Street, WalkOptions, Combination 3 | from graphserver.graphdb import GraphDatabase 4 | import os 5 | 6 | def glen(gen): 7 | return len(list(gen)) 8 | 9 | class TestGraphDatabase(unittest.TestCase): 10 | def test_basic(self): 11 | g = Graph() 12 | g.add_vertex("A") 13 | g.add_vertex("B") 14 | g.add_edge("A", "B", Link()) 15 | g.add_edge("A", "B", Street("foo", 20.0)) 16 | gdb_file = os.path.dirname(__file__) + "unit_test.db" 17 | if os.path.exists(gdb_file): 18 | os.remove(gdb_file) 19 | gdb = GraphDatabase(gdb_file) 20 | gdb.populate(g) 21 | 22 | list(gdb.execute("select * from resources")) 23 | assert "A" in list(gdb.all_vertex_labels()) 24 | assert "B" in list(gdb.all_vertex_labels()) 25 | assert glen(gdb.all_edges()) == 2 26 | assert glen(gdb.all_outgoing("A")) == 2 27 | assert glen(gdb.all_outgoing("B")) == 0 28 | assert glen(gdb.all_incoming("A")) == 0 29 | assert glen(gdb.all_incoming("B")) == 2 30 | assert glen(gdb.resources()) == 0 31 | assert gdb.num_vertices() == 2 32 | assert gdb.num_edges() == 2 33 | 34 | g.destroy() 35 | g = gdb.incarnate() 36 | 37 | list(gdb.execute("select * from resources")) 38 | assert "A" in list(gdb.all_vertex_labels()) 39 | assert "B" in list(gdb.all_vertex_labels()) 40 | assert glen(gdb.all_edges()) == 2 41 | assert glen(gdb.all_outgoing("A")) == 2 42 | assert glen(gdb.all_outgoing("B")) == 0 43 | assert glen(gdb.all_incoming("A")) == 0 44 | assert glen(gdb.all_incoming("B")) == 2 45 | assert glen(gdb.resources()) == 0 46 | assert gdb.num_vertices() == 2 47 | assert gdb.num_edges() == 2 48 | 49 | os.remove( gdb_file ) 50 | 51 | def test_ch(self): 52 | g = Graph() 53 | 54 | g.add_vertex( "A" ) 55 | g.add_vertex( "B" ) 56 | g.add_vertex( "C" ) 57 | g.add_edge( "A", "B", Street( "foo", 10 ) ) 58 | g.add_edge( "B", "C", Street( "bar", 10 ) ) 59 | g.add_edge( "C", "A", Street( "baz", 10 ) ) 60 | 61 | wo = WalkOptions() 62 | ch = g.get_contraction_hierarchies(wo) 63 | 64 | gdb_file = os.path.dirname(__file__) + "unit_test.db" 65 | gdb = GraphDatabase( gdb_file ) 66 | gdb.populate( ch.upgraph ) 67 | 68 | laz = gdb.incarnate() 69 | 70 | combo = laz.edges[1] 71 | self.assertEqual( combo.payload.get(0).name, "baz" ) 72 | self.assertEqual( combo.payload.get(1).name, "foo" ) 73 | 74 | os.remove( gdb_file ) 75 | 76 | if __name__ == '__main__': 77 | tl = unittest.TestLoader() 78 | 79 | suite = tl.loadTestsFromTestCase(TestGraphDatabase) 80 | unittest.TextTestRunner(verbosity=2).run(suite) 81 | -------------------------------------------------------------------------------- /pygs/test/unit_test/test_headway.py: -------------------------------------------------------------------------------- 1 | from graphserver.core import * 2 | import unittest 3 | 4 | class TestHeadway(unittest.TestCase): 5 | def test_basic(self): 6 | sc = ServiceCalendar() 7 | sc.add_period( 0, 1*3600*24, ['WKDY','SAT'] ) 8 | tz = Timezone() 9 | tz.add_period( TimezonePeriod(0, 1*3600*24, 0) ) 10 | 11 | headway = Headway( 0, 1*3600*24, 60, 120, "HEADWAY", sc, tz, 0, "WKDY" ) 12 | 13 | assert headway.begin_time == 0 14 | assert headway.end_time == 1*3600*24 15 | assert headway.wait_period == 60 16 | assert headway.transit == 120 17 | assert headway.trip_id == "HEADWAY" 18 | assert headway.calendar.soul == sc.soul 19 | assert headway.timezone.soul == tz.soul 20 | assert headway.agency == 0 21 | assert headway.int_service_id == 0 22 | assert headway.service_id == "WKDY" 23 | 24 | def test_walk(self): 25 | sc = ServiceCalendar() 26 | sc.add_period( 0, 1*3600*24-1, ['WKDY'] ) 27 | sc.add_period( 1*3600*25, 2*3600*25-1, ['SAT'] ) 28 | tz = Timezone() 29 | tz.add_period( TimezonePeriod(0, 1*3600*24, 0) ) 30 | 31 | headway = Headway( 3600, 2*3600, 60, 120, "HEADWAY", sc, tz, 0, "WKDY" ) 32 | 33 | #wrong day 34 | s = State(1, 1*3600*24) 35 | ret = headway.walk( s,WalkOptions() ) 36 | assert ret == None 37 | 38 | #before headway 39 | s = State(1, 0) 40 | ret = headway.walk( s,WalkOptions() ) 41 | assert ret.time == 3720 42 | assert ret.weight == 3720 43 | assert ret.num_transfers == 1 44 | assert ret.prev_edge.type == 7 45 | 46 | #right at beginning of headway 47 | s = State(1, 3600) 48 | ret = headway.walk( s,WalkOptions() ) 49 | assert ret.time == 3720 50 | assert ret.weight == 120 51 | assert ret.num_transfers == 1 52 | assert ret.prev_edge.type == 7 53 | 54 | #in the middle of the headway 55 | s = State(1, 4000) 56 | ret = headway.walk( s,WalkOptions() ) 57 | assert ret.time == 4000+60+120 58 | assert ret.weight == 60+120 59 | assert ret.num_transfers == 1 60 | assert ret.prev_edge.type == 7 61 | 62 | #the last second of the headway 63 | s = State(1, 2*3600) 64 | ret = headway.walk( s,WalkOptions() ) 65 | assert ret.time == 2*3600+60+120 66 | assert ret.weight == 60+120 67 | assert ret.num_transfers == 1 68 | assert ret.prev_edge.type == 7 69 | 70 | #no-transfer 71 | s = State(1, 4000) 72 | s.prev_edge = headway = Headway( 3600, 2*3600, 60, 120, "HEADWAY", sc, tz, 0, "WKDY" ) 73 | ret = headway.walk( s,WalkOptions() ) 74 | assert ret.time == 4000+120 75 | assert ret.weight == 120 76 | assert ret.num_transfers == 0 77 | assert ret.prev_edge.type == 7 78 | assert ret.prev_edge.trip_id == "HEADWAY" 79 | 80 | def test_getstate(self): 81 | sc = ServiceCalendar() 82 | sc.add_period( 0, 1*3600*24, ['WKDY','SAT'] ) 83 | tz = Timezone() 84 | tz.add_period( TimezonePeriod(0, 1*3600*24, 0) ) 85 | 86 | headway = Headway( 0, 1*3600*24, 60, 120, "HEADWAY", sc, tz, 0, "WKDY" ) 87 | 88 | assert headway.__getstate__() == (0, 1*3600*24, 60, 120, "HEADWAY", sc.soul, tz.soul, 0, "WKDY") 89 | 90 | if __name__ == '__main__': 91 | tl = unittest.TestLoader() 92 | 93 | suite = tl.loadTestsFromTestCase(TestHeadway) 94 | unittest.TextTestRunner(verbosity=2).run(suite) 95 | -------------------------------------------------------------------------------- /pygs/test/unit_test/test_headwayalight.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | from graphserver.core import * 3 | 4 | class TestHeadwayAlight(unittest.TestCase): 5 | def test_basic(self): 6 | sc = ServiceCalendar() 7 | sc.add_period( 0, 1*3600*24, ['WKDY','SAT'] ) 8 | tz = Timezone() 9 | tz.add_period( TimezonePeriod(0, 1*3600*24, 0) ) 10 | 11 | ha = HeadwayAlight("WKDY", sc, tz, 0, "hwtrip1", 0, 1000, 100) 12 | 13 | assert ha.calendar.soul == sc.soul 14 | assert ha.timezone.soul == tz.soul 15 | 16 | assert ha.agency == 0 17 | assert ha.int_service_id == 0 18 | 19 | assert ha.trip_id == "hwtrip1" 20 | 21 | assert ha.start_time == 0 22 | assert ha.end_time == 1000 23 | assert ha.headway_secs == 100 24 | 25 | ha.destroy() 26 | 27 | def test_walk_back(self): 28 | sc = ServiceCalendar() 29 | sc.add_period( 0, 1*3600*24, ['WKDY'] ) 30 | tz = Timezone() 31 | tz.add_period( TimezonePeriod(0, 1*3600*24, 0) ) 32 | 33 | ha = HeadwayAlight("WKDY", sc, tz, 0, "tr1", 200, 1000, 50) 34 | 35 | # 200 after end of headway 36 | s0 = State(1,1200) 37 | s1 = ha.walk_back(s0,WalkOptions()) 38 | assert s1.time == 1000 39 | assert s1.weight == 201 40 | 41 | # at very end of the headway 42 | s0 = State(1,1000) 43 | s1 = ha.walk_back(s0,WalkOptions()) 44 | assert s1.time == 1000 45 | assert s1.weight == 1 46 | 47 | # in the middle of headway period 48 | s0 = State(1, 500) 49 | s1 = ha.walk_back(s0,WalkOptions()) 50 | assert s1.time == 500 51 | assert s1.weight == 1 52 | 53 | # at the very beginning of the headway period 54 | s0 = State(1, 200) 55 | s1 = ha.walk_back(s0,WalkOptions()) 56 | assert s1.time == 200 57 | assert s1.weight == 1 58 | 59 | # before beginning of headway period 60 | s0 = State(1, 199) 61 | s1 = ha.walk_back(s0,WalkOptions()) 62 | assert s1 == None 63 | 64 | def test_walk(self): 65 | sc = ServiceCalendar() 66 | sc.add_period( 0, 1*3600*24, ['WKDY'] ) 67 | tz = Timezone() 68 | tz.add_period( TimezonePeriod(0, 1*3600*24, 0) ) 69 | 70 | ha = HeadwayAlight("WKDY", sc, tz, 0, "tr1", 200, 1000, 50) 71 | 72 | s0 = State(1,0) 73 | s1 = ha.walk(s0, WalkOptions()) 74 | assert s1.trip_id == None 75 | 76 | def test_headwayalight_over_midnight(self): 77 | 78 | sc = ServiceCalendar() 79 | sc.add_period(0, 1*3600*24, ['WKDY']) 80 | sc.add_period(1*3600*24,2*3600*24, ['SAT']) 81 | tz = Timezone() 82 | tz.add_period( TimezonePeriod(0,2*3600*24,0) ) 83 | 84 | ha = HeadwayAlight( "WKDY", sc, tz, 0, "owl", 23*3600, 26*3600, 100 ) 85 | 86 | # just past the end 87 | s0 = State(1, 26*3600+100) 88 | s1 = ha.walk_back(s0,WalkOptions()) 89 | assert s1.weight == 101 90 | assert s1.service_period(0).service_ids == [1] 91 | 92 | # right at the end 93 | s0 = State(1, 26*3600 ) 94 | s1 = ha.walk_back(s0,WalkOptions()) 95 | assert s1.weight == 1 96 | assert s1.service_period(0).service_ids == [1] 97 | 98 | # in the middle, over midnight 99 | s0 = State(1, 25*3600 ) 100 | s1 = ha.walk_back(s0,WalkOptions()) 101 | assert s1.time == 25*3600 102 | assert s1.weight == 1 103 | assert s1.service_period(0).service_ids == [1] 104 | 105 | # in the middle, at midnight 106 | s0 = State(1, 24*3600 ) 107 | s1 = ha.walk_back(s0,WalkOptions()) 108 | assert s1.weight == 1 109 | assert s1.service_period(0).service_ids == [1] 110 | 111 | #before midnight, at the beginning 112 | s0 = State(1, 23*3600 ) 113 | s1 = ha.walk_back(s0,WalkOptions()) 114 | assert s1.time == 23*3600 115 | assert s1.weight == 1 116 | assert s1.service_period(0).service_ids == [0] 117 | 118 | s0 = State(1, 23*3600-1) 119 | s1 = ha.walk_back(s0,WalkOptions()) 120 | assert s1 == None 121 | 122 | if __name__ == '__main__': 123 | tl = unittest.TestLoader() 124 | 125 | suite = tl.loadTestsFromTestCase(TestHeadwayAlight) 126 | unittest.TextTestRunner(verbosity=2).run(suite) -------------------------------------------------------------------------------- /pygs/test/unit_test/test_headwayboard.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | from graphserver.core import * 3 | 4 | class TestHeadwayBoard(unittest.TestCase): 5 | def test_basic(self): 6 | sc = ServiceCalendar() 7 | sc.add_period( 0, 1*3600*24, ['WKDY','SAT'] ) 8 | tz = Timezone() 9 | tz.add_period( TimezonePeriod(0, 1*3600*24, 0) ) 10 | 11 | hb = HeadwayBoard("WKDY", sc, tz, 0, "hwtrip1", 0, 1000, 100) 12 | 13 | assert hb.calendar.soul == sc.soul 14 | assert hb.timezone.soul == tz.soul 15 | 16 | assert hb.agency == 0 17 | assert hb.int_service_id == 0 18 | 19 | assert hb.trip_id == "hwtrip1" 20 | 21 | assert hb.start_time == 0 22 | assert hb.end_time == 1000 23 | assert hb.headway_secs == 100 24 | 25 | hb.destroy() 26 | 27 | def test_walk(self): 28 | sc = ServiceCalendar() 29 | sc.add_period( 0, 1*3600*24, ['WKDY'] ) 30 | tz = Timezone() 31 | tz.add_period( TimezonePeriod(0, 1*3600*24, 0) ) 32 | 33 | hb = HeadwayBoard("WKDY", sc, tz, 0, "tr1", 200, 1000, 50) 34 | 35 | s0 = State(1,0) 36 | s1 = hb.walk(s0,WalkOptions()) 37 | assert s1.time == 250 38 | assert s1.weight == 251 39 | 40 | s0 = State(1,200) 41 | s1 = hb.walk(s0,WalkOptions()) 42 | assert s1.time == 250 43 | assert s1.weight == 51 44 | 45 | s0 = State(1, 500) 46 | s1 = hb.walk(s0,WalkOptions()) 47 | assert s1.time == 550 48 | assert s1.weight == 51 49 | 50 | s0 = State(1, 1000) 51 | s1 = hb.walk(s0,WalkOptions()) 52 | assert s1.time == 1050 53 | assert s1.weight == 51 54 | 55 | s0 = State(1, 1001) 56 | s1 = hb.walk(s0,WalkOptions()) 57 | assert s1 == None 58 | 59 | def test_walk_back(self): 60 | sc = ServiceCalendar() 61 | sc.add_period( 0, 1*3600*24, ['WKDY'] ) 62 | tz = Timezone() 63 | tz.add_period( TimezonePeriod(0, 1*3600*24, 0) ) 64 | 65 | hb = HeadwayBoard("WKDY", sc, tz, 0, "tr1", 200, 1000, 50) 66 | 67 | s0 = State(1,0) 68 | s1 = hb.walk(s0, WalkOptions()) 69 | s2 = hb.walk_back(s1, WalkOptions()) 70 | assert s2.trip_id == None 71 | 72 | def test_tripboard_over_midnight(self): 73 | 74 | sc = ServiceCalendar() 75 | sc.add_period(0, 1*3600*24, ['WKDY']) 76 | sc.add_period(1*3600*24,2*3600*24, ['SAT']) 77 | tz = Timezone() 78 | tz.add_period( TimezonePeriod(0,2*3600*24,0) ) 79 | 80 | hb = HeadwayBoard( "WKDY", sc, tz, 0, "owl", 23*3600, 26*3600, 100 ) 81 | 82 | s0 = State(1, 0) 83 | s1 = hb.walk(s0,WalkOptions()) 84 | assert s1.weight == 82901 85 | assert s1.service_period(0).service_ids == [0] 86 | 87 | s0 = State(1, 23*3600 ) 88 | s1 = hb.walk(s0,WalkOptions()) 89 | assert s1.weight == 101 90 | assert s1.service_period(0).service_ids == [0] 91 | 92 | s0 = State(1, 24*3600 ) 93 | s1 = hb.walk(s0,WalkOptions()) 94 | assert s1.weight == 101 95 | assert s1.service_period(0).service_ids == [1] 96 | 97 | s0 = State(1, 25*3600 ) 98 | s1 = hb.walk(s0,WalkOptions()) 99 | assert s1.time == 25*3600+100 100 | assert s1.weight == 101 101 | assert s1.service_period(0).service_ids == [1] 102 | 103 | s0 = State(1, 26*3600 ) 104 | s1 = hb.walk(s0,WalkOptions()) 105 | assert s1.time == 26*3600+100 106 | assert s1.weight == 101 107 | assert s1.service_period(0).service_ids == [1] 108 | 109 | s0 = State(1, 26*3600+1) 110 | s1 = hb.walk(s0,WalkOptions()) 111 | assert s1 == None 112 | 113 | if __name__ == '__main__': 114 | tl = unittest.TestLoader() 115 | 116 | suite = tl.loadTestsFromTestCase(TestHeadwayBoard) 117 | unittest.TextTestRunner(verbosity=2).run(suite) -------------------------------------------------------------------------------- /pygs/test/unit_test/test_link.py: -------------------------------------------------------------------------------- 1 | from graphserver.core import Link, State, WalkOptions 2 | import unittest 3 | 4 | class TestLink(unittest.TestCase): 5 | def link_test(self): 6 | l = Link() 7 | assert l 8 | assert str(l)=="" 9 | 10 | def test_destroy(self): 11 | l = Link() 12 | l.destroy() 13 | 14 | assert l.soul==None 15 | 16 | def test_name(self): 17 | l = Link() 18 | assert l.name == "LINK" 19 | 20 | def test_walk(self): 21 | l = Link() 22 | 23 | after = l.walk(State(1,0), WalkOptions()) 24 | 25 | assert after.time==0 26 | assert after.weight==0 27 | assert after.dist_walked==0 28 | assert after.prev_edge.type == 3 29 | assert after.prev_edge.name == "LINK" 30 | assert after.num_agencies == 1 31 | 32 | def test_walk_back(self): 33 | l = Link() 34 | 35 | before = l.walk_back(State(1,0), WalkOptions()) 36 | 37 | assert before.time == 0 38 | assert before.weight == 0 39 | assert before.dist_walked == 0.0 40 | assert before.prev_edge.type == 3 41 | assert before.prev_edge.name == "LINK" 42 | assert before.num_agencies == 1 43 | 44 | def test_getstate(self): 45 | l = Link() 46 | assert l.__getstate__() == tuple([]) 47 | 48 | if __name__ == '__main__': 49 | tl = unittest.TestLoader() 50 | 51 | suite = tl.loadTestsFromTestCase(TestLink) 52 | unittest.TextTestRunner(verbosity=2).run(suite) -------------------------------------------------------------------------------- /pygs/test/unit_test/test_listnode.py: -------------------------------------------------------------------------------- 1 | from graphserver.core import * 2 | import unittest 3 | 4 | class TestListNode(unittest.TestCase): 5 | def test_list_node(self): 6 | l = ListNode() 7 | 8 | assert l 9 | 10 | if __name__ == '__main__': 11 | tl = unittest.TestLoader() 12 | 13 | suite = tl.loadTestsFromTestCase(TestListNode) 14 | unittest.TextTestRunner(verbosity=2).run(suite) -------------------------------------------------------------------------------- /pygs/test/unit_test/test_pypayload.py: -------------------------------------------------------------------------------- 1 | from graphserver.core import * 2 | import unittest 3 | import StringIO 4 | import sys 5 | 6 | class TestPyPayload(unittest.TestCase): 7 | def _minimal_graph(self): 8 | g = Graph() 9 | 10 | g.add_vertex( "Seattle" ) 11 | g.add_vertex( "Portland" ) 12 | return g 13 | 14 | def test_basic(self): 15 | p = NoOpPyPayload(1.1) 16 | 17 | def test_cast(self): 18 | g = self._minimal_graph() 19 | e = NoOpPyPayload(1.2) 20 | 21 | ed = g.add_edge( "Seattle", "Portland", e ) 22 | assert e == ed.payload 23 | ep = ed.payload # uses EdgePayload.from_pointer internally. 24 | assert e == ep 25 | assert ep.num == 1.2 26 | 27 | 28 | 29 | def test_walk(self): 30 | class IncTimePayload(GenericPyPayload): 31 | def walk_impl(self, state, walkopts): 32 | state.time = state.time + 10 33 | state.weight = 5 34 | return state 35 | 36 | def walk_back_impl(self, state, walkopts): 37 | state.time = state.time - 10 38 | state.weight = 0 39 | return state 40 | 41 | g = self._minimal_graph() 42 | ed = g.add_edge( "Seattle", "Portland", IncTimePayload()) 43 | assert(isinstance(ed.payload,IncTimePayload)) 44 | s = State(1,1) 45 | assert s.time == 1 46 | s1 = ed.walk(s, WalkOptions()) 47 | assert s1 48 | assert s.time == 1 49 | assert s1.soul != s.soul 50 | assert s1.time == 11 51 | assert s1.weight == 5 52 | s2 = ed.walk_back(s1, WalkOptions()) 53 | assert s2 54 | assert s2.time == 1 55 | assert s2.weight == 0 56 | g.destroy() 57 | 58 | def test_failures(self): 59 | class ExceptionRaiser(GenericPyPayload): 60 | def walk_bad_stuff(self, state, walkopts): 61 | raise Exception("I am designed to fail.") 62 | walk_impl = walk_bad_stuff 63 | walk_back_impl = walk_bad_stuff 64 | 65 | g = self._minimal_graph() 66 | ed = g.add_edge( "Seattle", "Portland", ExceptionRaiser()) 67 | 68 | # save stdout so we can set it back the way we found it 69 | stderrsave = sys.stderr 70 | 71 | # get a string-file to catch things placed into stdout 72 | stderr_catcher = StringIO.StringIO() 73 | 74 | sys.stderr = stderr_catcher 75 | 76 | # this will barf into stdout 77 | ed.walk(State(1,0), WalkOptions()) 78 | 79 | # the last line of the exception traceback just blurted out should be ... 80 | stderr_catcher.seek(0) 81 | self.assertEqual( stderr_catcher.read().split("\n")[-2] , "Exception: I am designed to fail." ) 82 | 83 | # set up a new buffer to catch a traceback 84 | stderr_catcher = StringIO.StringIO() 85 | sys.stderr = stderr_catcher 86 | 87 | # blurt into it 88 | ed.walk_back(State(1,0), WalkOptions()) 89 | 90 | # check that the last line of the traceback looks like we expect 91 | stderr_catcher.seek(0) 92 | self.assertEqual( stderr_catcher.read().split("\n")[-2] , "Exception: I am designed to fail." ) 93 | 94 | g.destroy() 95 | 96 | sys.stderr = stderrsave 97 | 98 | def test_basic_graph(self): 99 | class MovingWalkway(GenericPyPayload): 100 | def walk_impl(self, state, walkopts): 101 | state.time = state.time + 10 102 | state.weight = 5 103 | return state 104 | 105 | def walk_back_impl(self, state, walkopts): 106 | state.time = state.time - 10 107 | state.weight = 0 108 | return state 109 | 110 | g = self._minimal_graph() 111 | g.add_edge( "Seattle", "Portland", MovingWalkway()) 112 | spt = g.shortest_path_tree("Seattle", "Portland", State(0,0), WalkOptions()) 113 | assert spt 114 | assert spt.__class__ == ShortestPathTree 115 | assert spt.get_vertex("Portland").state.weight==5 116 | assert spt.get_vertex("Portland").state.time==10 117 | 118 | spt.destroy() 119 | g.destroy() 120 | 121 | if __name__ == '__main__': 122 | tl = unittest.TestLoader() 123 | 124 | suite = tl.loadTestsFromTestCase(TestPyPayload) 125 | unittest.TextTestRunner(verbosity=2).run(suite) 126 | -------------------------------------------------------------------------------- /pygs/test/unit_test/test_serviceperiod.py: -------------------------------------------------------------------------------- 1 | from graphserver.core import * 2 | import unittest 3 | import pickle 4 | 5 | class TestServicePeriod(unittest.TestCase): 6 | def test_service_period(self): 7 | c = ServicePeriod(0, 1*3600*24, [1,2]) 8 | assert(c.begin_time == 0) 9 | assert(c.end_time == 1*3600*24) 10 | assert(len(c.service_ids) == 2) 11 | assert(c.service_ids == [1,2]) 12 | 13 | def test_fast_forward_rewind(self): 14 | cc = ServiceCalendar() 15 | cc.add_period( 0, 100, ["A","B"] ) 16 | cc.add_period( 101, 200, ["C","D"] ) 17 | cc.add_period( 201, 300, ["E","F"] ) 18 | 19 | hh = cc.head 20 | ff = hh.fast_forward() 21 | assert ff.begin_time==201 22 | pp = ff.rewind() 23 | assert pp.begin_time==0 24 | 25 | def test_midnight_datum(self): 26 | c = ServicePeriod( 0, 1*3600*24, [1]) 27 | 28 | assert c.datum_midnight(timezone_offset=0) == 0 29 | 30 | c = ServicePeriod( 500, 1000, [1]) 31 | 32 | assert c.datum_midnight(timezone_offset=0) == 0 33 | 34 | c = ServicePeriod( 1*3600*24, 2*3600*24, [1]) 35 | 36 | assert c.datum_midnight(timezone_offset=0) == 86400 37 | assert c.datum_midnight(timezone_offset=-3600) == 3600 38 | assert c.datum_midnight(timezone_offset=3600) == 82800 39 | 40 | c = ServicePeriod( 1*3600*24+50, 1*3600*24+60, [1]) 41 | 42 | assert c.datum_midnight(timezone_offset=0) == 86400 43 | assert c.datum_midnight(timezone_offset=-3600) == 3600 44 | 45 | def test_normalize_time(self): 46 | c = ServicePeriod(0, 1*3600*24, [1,2]) 47 | 48 | assert c.normalize_time( 0, 0 ) == 0 49 | assert c.normalize_time( 0, 100 ) == 100 50 | 51 | def test_pickle(self): 52 | cc = ServicePeriod(0, 100, [1,2,3,4,5]) 53 | 54 | ss = pickle.dumps( cc ) 55 | laz = pickle.loads( ss ) 56 | 57 | assert laz.__getstate__() == cc.__getstate__() 58 | 59 | if __name__ == '__main__': 60 | tl = unittest.TestLoader() 61 | 62 | suite = tl.loadTestsFromTestCase(TestServicePeriod) 63 | unittest.TextTestRunner(verbosity=2).run(suite) -------------------------------------------------------------------------------- /pygs/test/unit_test/test_sptvertex.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | from graphserver.core import * 3 | 4 | class TestSPTVertex(unittest.TestCase): 5 | def test_basic(self): 6 | vv = Vertex("home") 7 | v=SPTVertex( vv ) 8 | 9 | assert v.mirror.soul == vv.soul 10 | assert v 11 | 12 | def test_init_hop(self): 13 | v = SPTVertex( Vertex("A") ) 14 | assert v.hop == 0 15 | 16 | v = SPTVertex( Vertex("B"), 1 ) 17 | assert v.hop == 1 18 | 19 | def test_destroy(self): #mostly just check that it doesn't segfault. the stress test will check if it works or not. 20 | v=SPTVertex( Vertex("home") ) 21 | v.destroy() 22 | 23 | try: 24 | v.label 25 | assert False #pop exception by now 26 | except: 27 | pass 28 | 29 | def test_label(self): 30 | v=SPTVertex( Vertex("home") ) 31 | print v.label 32 | assert v.label == "home" 33 | 34 | def test_incoming(self): 35 | v=SPTVertex( Vertex("home") ) 36 | assert v.incoming == [] 37 | assert v.degree_in == 0 38 | 39 | def test_outgoing(self): 40 | v=SPTVertex( Vertex("home") ) 41 | assert v.outgoing == [] 42 | assert v.degree_out == 0 43 | 44 | def test_prettyprint(self): 45 | v = SPTVertex( Vertex("home") ) 46 | assert v.to_xml() == "" 47 | 48 | 49 | if __name__ == '__main__': 50 | tl = unittest.TestLoader() 51 | 52 | suite = tl.loadTestsFromTestCase(TestSPTVertex) 53 | unittest.TextTestRunner(verbosity=2).run(suite) 54 | -------------------------------------------------------------------------------- /pygs/test/unit_test/test_state.py: -------------------------------------------------------------------------------- 1 | from graphserver.core import * 2 | import unittest 3 | 4 | class TestState(unittest.TestCase): 5 | def test_basic(self): 6 | s = State(1,0) 7 | assert s.time == 0 8 | assert s.weight == 0 9 | assert s.dist_walked == 0 10 | assert s.num_transfers == 0 11 | assert s.prev_edge == None 12 | assert s.num_agencies == 1 13 | assert s.service_period(0) == None 14 | assert s.trip_id == None 15 | assert s.stop_sequence == -1 16 | 17 | def test_basic_multiple_calendars(self): 18 | s = State(2,0) 19 | assert s.time == 0 20 | assert s.weight == 0 21 | assert s.dist_walked == 0 22 | assert s.num_transfers == 0 23 | assert s.prev_edge == None 24 | assert s.num_agencies == 2 25 | assert s.service_period(0) == None 26 | assert s.service_period(1) == None 27 | assert s.stop_sequence == -1 28 | 29 | def test_set_cal(self): 30 | s = State(1,0) 31 | sp = ServicePeriod(0, 1*3600*24, [1,2]) 32 | 33 | try: 34 | s.set_calendar_day(1, cal) 35 | assert False #should have failed by now 36 | except: 37 | pass 38 | 39 | s.set_service_period(0, sp) 40 | 41 | spout = s.service_period(0) 42 | 43 | assert spout.begin_time == 0 44 | assert spout.end_time == 86400 45 | assert spout.service_ids == [1,2] 46 | 47 | def test_destroy(self): 48 | s = State(1) 49 | 50 | s.destroy() #did we segfault? 51 | 52 | try: 53 | print s.time 54 | assert False #should have popped exception by now 55 | except: 56 | pass 57 | 58 | try: 59 | s.destroy() 60 | assert False 61 | except: 62 | pass 63 | 64 | def test_clone(self): 65 | 66 | s = State(1,0) 67 | sp = ServicePeriod(0, 1*3600*24, [1,2]) 68 | s.set_service_period(0,sp) 69 | 70 | s2 = s.clone() 71 | 72 | s.clone() 73 | 74 | assert s2.time == 0 75 | assert s2.weight == 0 76 | assert s2.dist_walked == 0 77 | assert s2.num_transfers == 0 78 | assert s2.prev_edge == None 79 | assert s2.num_agencies == 1 80 | assert s2.service_period(0).to_xml() == "" 81 | assert s2.stop_sequence == -1 82 | 83 | if __name__ == '__main__': 84 | tl = unittest.TestLoader() 85 | 86 | suite = tl.loadTestsFromTestCase(TestState) 87 | unittest.TextTestRunner(verbosity=2).run(suite) -------------------------------------------------------------------------------- /pygs/test/unit_test/test_street.py: -------------------------------------------------------------------------------- 1 | from graphserver.core import * 2 | import unittest 3 | 4 | class TestStreet(unittest.TestCase): 5 | def test_street(self): 6 | s = Street("mystreet", 1.1) 7 | assert s.name == "mystreet" 8 | assert s.length == 1.1 9 | assert s.rise == 0 10 | assert s.fall == 0 11 | assert s.slog == 1 12 | assert s.way == 0 13 | assert s.external_id == 0 14 | assert s.to_xml() == "" 15 | 16 | s.external_id = 15 17 | assert Street.from_pointer( s.soul ).external_id == 15 18 | 19 | s.slog = 2500 20 | s.way = 232323 21 | assert s.slog == 2500 22 | assert s.way == 232323 23 | 24 | def test_street_elev(self): 25 | s = Street("mystreet", 1.1, 24.5, 31.2) 26 | assert s.name == "mystreet" 27 | assert s.length == 1.1 28 | assert round(s.rise,3) == 24.5 29 | assert round(s.fall,3) == 31.2 30 | assert s.to_xml() == "" 31 | 32 | def test_destroy(self): 33 | s = Street("mystreet", 1.1) 34 | s.destroy() 35 | 36 | assert s.soul==None 37 | 38 | def test_street_big_length(self): 39 | s = Street("longstreet", 240000) 40 | assert s.name == "longstreet" 41 | assert s.length == 240000 42 | 43 | assert s.to_xml() == "" 44 | 45 | def test_walk(self): 46 | s = Street("longstreet", 2) 47 | 48 | wo = WalkOptions() 49 | wo.walking_speed = 1 50 | 51 | after = s.walk(State(0,0),wo) 52 | assert after.time == 2 53 | assert after.weight == 2 54 | assert after.dist_walked == 2 55 | assert after.prev_edge.type == 0 56 | assert after.prev_edge.name == "longstreet" 57 | assert after.num_agencies == 0 58 | 59 | def test_walk_slog(self): 60 | s = Street("longstreet", 2) 61 | s.slog = 10 62 | 63 | wo = WalkOptions() 64 | wo.walking_speed = 1 65 | 66 | after = s.walk(State(0,0),wo) 67 | assert after.time == 2 68 | assert after.weight == 20 69 | assert after.dist_walked == 2 70 | assert after.prev_edge.type == 0 71 | assert after.prev_edge.name == "longstreet" 72 | assert after.num_agencies == 0 73 | 74 | def test_walk_back(self): 75 | s = Street("longstreet", 2) 76 | 77 | wo = WalkOptions() 78 | wo.walking_speed = 1 79 | 80 | before = s.walk_back(State(0,100),wo) 81 | 82 | assert before.time == 98 83 | assert before.weight == 2 84 | assert before.dist_walked == 2.0 85 | assert before.prev_edge.type == 0 86 | assert before.prev_edge.name == "longstreet" 87 | assert before.num_agencies == 0 88 | 89 | def test_street_turn(self): 90 | wo = WalkOptions() 91 | wo.turn_penalty = 20 92 | wo.walking_speed = 1 93 | 94 | e0 = Street("a1", 10) 95 | e0.way = 42 96 | e1 = Street("a2", 10) 97 | e1.way = 43 98 | s0 = State(0,0) 99 | s0.prev_edge = e0 100 | 101 | s1 = e1.walk(s0, wo) 102 | assert s1.weight == 30 103 | 104 | 105 | def test_getstate(self): 106 | s = Street("longstreet", 2) 107 | 108 | assert s.__getstate__() == ('longstreet', 2.0, 0.0, 0.0, 1.0,0,False) 109 | 110 | if __name__ == '__main__': 111 | tl = unittest.TestLoader() 112 | 113 | suite = tl.loadTestsFromTestCase(TestStreet) 114 | unittest.TextTestRunner(verbosity=2).run(suite) 115 | -------------------------------------------------------------------------------- /pygs/test/unit_test/test_timezoneperiod.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | from graphserver.core import * 3 | from graphserver import util 4 | import pickle 5 | 6 | class TestTimezonePeriod(unittest.TestCase): 7 | def test_basic(self): 8 | tzp = TimezonePeriod(0, 100, -10) 9 | 10 | assert tzp 11 | assert tzp.begin_time == 0 12 | assert tzp.end_time == 100 13 | assert tzp.utc_offset == -10 14 | 15 | def test_dict(self): 16 | tzp = TimezonePeriod(3, 7, -11) 17 | 18 | assert tzp.__getstate__() == (3, 7, -11) 19 | 20 | ss = pickle.dumps( tzp ) 21 | laz = pickle.loads( ss ) 22 | assert laz.begin_time == 3 23 | assert laz.end_time == 7 24 | assert laz.utc_offset == -11 25 | 26 | def test_time_since_midnight(self): 27 | tzp = TimezonePeriod(0, 24*3600*256, -8*3600) 28 | 29 | assert tzp.time_since_midnight( 8*3600 ) == 0 30 | 31 | summer_tzp = TimezonePeriod( util.TimeHelpers.localtime_to_unix( 2008,6,1,0,0,0, "America/Los_Angeles" ), 32 | util.TimeHelpers.localtime_to_unix( 2008,9,1,0,0,0, "America/Los_Angeles" ), 33 | -7*3600 ) 34 | 35 | assert summer_tzp.time_since_midnight( util.TimeHelpers.localtime_to_unix( 2008, 7,1,0,0,0,"America/Los_Angeles" ) ) == 0 36 | assert summer_tzp.time_since_midnight( util.TimeHelpers.localtime_to_unix( 2008, 7, 2, 2, 0, 0, "America/Los_Angeles" ) ) == 3600*2 37 | 38 | winter_tzp = TimezonePeriod( util.TimeHelpers.localtime_to_unix( 2008,1,1,0,0,0, "America/Los_Angeles" ), 39 | util.TimeHelpers.localtime_to_unix( 2008,4,1,0,0,0, "America/Los_Angeles" ), 40 | -8*3600 ) 41 | 42 | assert winter_tzp.time_since_midnight( util.TimeHelpers.localtime_to_unix( 2008, 2,1,0,0,0,"America/Los_Angeles" ) ) == 0 43 | assert winter_tzp.time_since_midnight( util.TimeHelpers.localtime_to_unix( 2008, 2, 2, 2, 0, 0, "America/Los_Angeles" ) ) == 3600*2 44 | 45 | if __name__ == '__main__': 46 | tl = unittest.TestLoader() 47 | 48 | suite = tl.loadTestsFromTestCase(TestTimezonePeriod) 49 | unittest.TextTestRunner(verbosity=2).run(suite) -------------------------------------------------------------------------------- /pygs/test/unit_test/test_util.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | from graphserver.util import TimeHelpers 3 | 4 | class TestUtil(unittest.TestCase): 5 | 6 | def test_basic(self): 7 | assert TimeHelpers.localtime_to_unix(2008,10,12,6,0,0,"Europe/Paris") == 1223784000 8 | assert str(TimeHelpers.unix_to_localtime(1199181360, "America/New_York")) == "2008-01-01 04:56:00-05:00" 9 | assert TimeHelpers.unixtime_to_daytimes(1219834260, "America/Los_Angeles") == (13860, 100260, 186660) 10 | assert str(TimeHelpers.unix_to_localtime(1221459000, "America/Chicago")) == "2008-09-15 01:10:00-05:00" 11 | assert TimeHelpers.unixtime_to_daytimes(1230354000, "America/Chicago") == (82800, 169200, 255600) 12 | assert TimeHelpers.unix_time(2008,8,27,12,0,0,-7*3600) == 1219863600 13 | assert TimeHelpers.localtime_to_unix(2008,8,27,12,0,0,"America/Los_Angeles") == 1219863600 14 | assert str(TimeHelpers.unix_to_localtime(1219863600, "America/Los_Angeles")) == "2008-08-27 12:00:00-07:00" 15 | 16 | if __name__ == '__main__': 17 | tl = unittest.TestLoader() 18 | 19 | suite = tl.loadTestsFromTestCase(TestUtil) 20 | unittest.TextTestRunner(verbosity=2).run(suite) 21 | -------------------------------------------------------------------------------- /pygs/test/unit_test/test_vector.py: -------------------------------------------------------------------------------- 1 | from graphserver.vector import Vector 2 | import unittest 3 | 4 | class TestVector(unittest.TestCase): 5 | def test_basic(self): 6 | # basic test 7 | vec = Vector(expand_delta=40) 8 | 9 | assert vec.num_elements == 0 10 | assert vec.num_alloc == 50 11 | assert vec.expand_delta == 40 12 | 13 | vec.expand( 50 ) 14 | 15 | assert vec.num_alloc == 100 16 | 17 | vec.add( 11 ) 18 | assert vec.get( 0 ) == 11 19 | vec.add( 15 ) 20 | assert vec.get( 0 ) == 11 21 | assert vec.get( 1 ) == 15 22 | 23 | del(vec) 24 | 25 | def test_expand(self): 26 | # expand test 27 | 28 | vec = Vector(init_size=1, expand_delta=10) 29 | assert vec.num_alloc == 1 30 | assert vec.num_elements == 0 31 | 32 | vec.add( 3 ) 33 | assert vec.num_alloc == 1 34 | assert vec.num_elements == 1 35 | assert vec.get(0) == 3 36 | 37 | vec.add( 5 ) 38 | assert vec.num_alloc == 11 39 | assert vec.num_elements == 2 40 | assert vec.get(0) == 3 41 | assert vec.get(1) == 5 42 | 43 | if __name__ == '__main__': 44 | 45 | unittest.main() -------------------------------------------------------------------------------- /pygs/test/unit_test/test_vertex.py: -------------------------------------------------------------------------------- 1 | from graphserver.core import * 2 | import unittest 3 | 4 | class TestVertex(unittest.TestCase): 5 | def test_basic(self): 6 | """create a vertex""" 7 | v=Vertex("home") 8 | assert v 9 | 10 | def test_destroy(self): #mostly just check that it doesn't segfault. the stress test will check if it works or not. 11 | """destroy a vertex""" 12 | v=Vertex("home") 13 | v.destroy() 14 | 15 | try: 16 | v.label 17 | assert False #pop exception by now 18 | except: 19 | pass 20 | 21 | def test_label(self): 22 | """set the vertex label""" 23 | v=Vertex("home") 24 | assert v.label == "home" 25 | 26 | def test_incoming(self): 27 | """new vertex has no incoming edges""" 28 | v=Vertex("home") 29 | assert v.incoming == [] 30 | assert v.degree_in == 0 31 | 32 | def test_outgoing(self): 33 | """new vertex has no outgoing edges""" 34 | v=Vertex("home") 35 | assert v.outgoing == [] 36 | assert v.degree_out == 0 37 | 38 | def test_prettyprint(self): 39 | """vertex can output itself to xml""" 40 | v = Vertex("home") 41 | assert v.to_xml() == "" 42 | 43 | if __name__ == '__main__': 44 | tl = unittest.TestLoader() 45 | 46 | suite = tl.loadTestsFromTestCase(TestVertex) 47 | unittest.TextTestRunner(verbosity=2).run(suite) 48 | -------------------------------------------------------------------------------- /pygs/test/unit_test/test_wait.py: -------------------------------------------------------------------------------- 1 | from graphserver.core import Wait, Timezone, TimezonePeriod, State, WalkOptions 2 | import unittest 3 | 4 | class TestWait(unittest.TestCase): 5 | def test_wait(self): 6 | waitend = 100 7 | tz = Timezone() 8 | tz.add_period(TimezonePeriod(0,100000,0)) 9 | w = Wait(waitend, tz) 10 | assert w.end == waitend 11 | assert w.timezone.soul == tz.soul 12 | assert w.to_xml() == "" 13 | 14 | s = State(1,0) 15 | sprime = w.walk(s, WalkOptions()) 16 | assert sprime.time == 100 17 | assert sprime.weight == 100 18 | 19 | s = State(1, 150) 20 | sprime = w.walk_back(s, WalkOptions()) 21 | assert sprime.time == 100 22 | assert sprime.weight == 50 23 | 24 | s = State(1, 86400) 25 | sprime = w.walk(s, WalkOptions()) 26 | assert sprime.time == 86500 27 | assert sprime.weight == 100 28 | 29 | w.destroy() 30 | 31 | tz = Timezone() 32 | tz.add_period(TimezonePeriod(0,100000,-20)) 33 | w = Wait(100, tz) 34 | assert w.end == 100 35 | assert w.timezone.soul == tz.soul 36 | s = State(1, 86400) 37 | sprime = w.walk(s, WalkOptions()) 38 | assert sprime.weight == 120 39 | 40 | def test_august(self): 41 | # noon, -7 hours off UTC, as America/Los_Angeles in summer 42 | tz = Timezone.generate("America/Los_Angeles") 43 | w = Wait(43200, tz) 44 | 45 | # one calendar, noon august 27, America/Los_Angeles 46 | s = State(1, 1219863600) 47 | 48 | assert w.walk(s, WalkOptions()).time == 1219863600 49 | 50 | # one calendar, 11:55 AM August 27 2008, America/Los_Angeles 51 | s = State(1, 1219863300) 52 | assert w.walk(s, WalkOptions()).time == 1219863600 53 | assert w.walk(s, WalkOptions()).weight == 300 54 | 55 | def test_getstate(self): 56 | # noon, -7 hours off UTC, as America/Los_Angeles in summer 57 | tz = Timezone.generate("America/Los_Angeles") 58 | w = Wait(43200, tz) 59 | 60 | assert w.__getstate__() == (43200, tz.soul) 61 | 62 | if __name__ == '__main__': 63 | tl = unittest.TestLoader() 64 | 65 | suite = tl.loadTestsFromTestCase(TestWait) 66 | unittest.TextTestRunner(verbosity=2).run(suite) 67 | -------------------------------------------------------------------------------- /pygs/test/unit_test/test_walkoptions.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | from graphserver.core import * 3 | 4 | class TestWalkOptions(unittest.TestCase): 5 | def test_basic(self): 6 | wo = WalkOptions() 7 | 8 | assert wo 9 | 10 | assert wo.transfer_penalty == 0 11 | assert wo.turn_penalty == 0 12 | assert wo.walking_speed*100//1 == 607.0 13 | assert wo.walking_reluctance == 1.0 14 | assert wo.max_walk == 10000 15 | assert round(wo.walking_overage,3) == 0.1 16 | 17 | wo.transfer_penalty = 50 18 | assert wo.transfer_penalty == 50 19 | 20 | wo.turn_penalty = 3 21 | assert wo.turn_penalty == 3 22 | 23 | wo.walking_speed = 1.05 24 | assert round(wo.walking_speed*100) == 105.0 25 | 26 | wo.walking_reluctance = 2.0 27 | assert wo.walking_reluctance == 2.0 28 | 29 | wo.max_walk = 100 30 | assert wo.max_walk == 100 31 | 32 | wo.walking_overage = 1.0 33 | assert wo.walking_overage == 1.0 34 | 35 | wo.uphill_slowness = 1.5 36 | assert wo.uphill_slowness == 1.5 37 | 38 | wo.downhill_fastness = 3.4 39 | assert round(wo.downhill_fastness,3) == 3.4 40 | 41 | wo.hill_reluctance = 1.4 42 | assert round(wo.hill_reluctance,3) == 1.4 43 | 44 | wo.destroy() 45 | assert wo.soul == None 46 | 47 | def test_from_ptr(self): 48 | wo = WalkOptions() 49 | wo.transfer_penalty = 10 50 | wo1 = WalkOptions.from_pointer(wo.soul) 51 | assert wo.transfer_penalty == wo1.transfer_penalty 52 | assert wo1.soul == wo.soul 53 | wo.destroy() 54 | 55 | if __name__ == '__main__': 56 | tl = unittest.TestLoader() 57 | 58 | suite = tl.loadTestsFromTestCase(TestWalkOptions) 59 | unittest.TextTestRunner(verbosity=2).run(suite) --------------------------------------------------------------------------------