0% found this document useful (0 votes)
32 views63 pages

THESIS Paper

The thesis titled 'Web Development of Bike Route Generator' by Javier David H. Bolong aims to create a web application that addresses the safety and navigational needs of cyclists in Quezon City, Philippines. It focuses on back-end development using data mining techniques to filter and analyze external databases for generating safe cycling routes. The study highlights the importance of promoting cycling as a sustainable transportation method while acknowledging the limitations of existing navigation apps that do not prioritize cyclist safety.

Uploaded by

Javier Bolong
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
32 views63 pages

THESIS Paper

The thesis titled 'Web Development of Bike Route Generator' by Javier David H. Bolong aims to create a web application that addresses the safety and navigational needs of cyclists in Quezon City, Philippines. It focuses on back-end development using data mining techniques to filter and analyze external databases for generating safe cycling routes. The study highlights the importance of promoting cycling as a sustainable transportation method while acknowledging the limitations of existing navigation apps that do not prioritize cyclist safety.

Uploaded by

Javier Bolong
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
You are on page 1/ 63

Web Development of

Bike Route Generator

An Undergraduate thesis by:

Javier David H. Bolong

Submitted to the

Department of Electronics, Computer, and Communications Engineering

School of Science and Engineering

Ateneo De Manila University

In partial fulfillment of the Requirements for for the Degree of

Bachelor of Science in Computer Engineering

May 2025
This is to certify that this undergraduate thesis, entitled Web Development of Bike Route

Generator was prepared and submitted by Javier David H. Bolong

King Harold A. Recto, PhD

Panel Member

Carlos M. Oppus M.S.

Panel Member

Luisito L. Agustin, PhD

Panel Member

Maria Leonora C. Guico, M.S.

Thesis Adviser

Jan Kevin A. Galicia, M.A

Co-Thesis Adviser

Erees Queen B. Macabebe,PhD

Chair, Dept. of ECCE

Final Grade for the Thesis


ABSTRACT

The Philippines has over 11.2 million cyclists, with the government building helpful

infrastructure to accommodate them. However, they don’t pursue cycling due to concerns

of safety, backed by the 2397 recorded accidents faced by cyclists. This project aims to

develop a web-app that helps meet the navigational and safety needs of cyclists. Due to

time and resource constraints, this thesis focused on the Back-end development of the

route generator with the testing area limited to Quezon City. Data Filtering and Data

mining techniques are performed on external databases like Google, Strava, and Cyclosm.

Models are built from this data, and used as a filter overlay for the map of Quezon City to

highlight safe routes for the algorithm to analyze. Using this filtered map, and the

specifications for the trip inputted by the user, a route is generated.


ACKNOWLEDGEMENTS

First and foremost, I would like to express my deepest gratitude to my research

advisers, Engr. Jan Kevin Galicia, and Engr. . Maria Leonora Guico for their invaluable

guidance, and endless patience throughout this research. Their wise mentorship has been

instrumental towards the quality and direction of my thesis.

I also extend my sincerest gratitude to my panelists - Dr. Luisito Agustin, Engr.

Carlos Oppus and Dr. King Harold Recto - for their constructive feedback and undeniable

support. Their recommendations have helped me to identify any flaws in my research as

well enhance the clarity of my work.

To my friends, who have provided not only intellectual support but a reason to

smile even in the most stressful and exhausting times. Their honest personalities and

unwavering love has carried me through many sleepless nights.

Last but not least, I am profoundly grateful to my family. Though they may have

many expectations of me, their encouragement has pushed me to achieve what I thought I

could not. They are the foundation of my life, and I hope to make them proud with this

paper.

Thus, this research paper is not only the product of my effort but the culmination

of all the support and inspiration I have received from these wonderful people.
ABOUT THE AUTHOR

Javier David H. Bolong is a Computer

engineering student at Ateneo De Manila

University. Although born to a family of

doctors, his love for computers could not

be contained. Throughout his life, he would

spend time tinkering with machines and

programs, ranging from simple changes

with computer settings, tinkering with

source code inside games, to ideating

personal coding projects to show to his

friends. That is why when the time came to

apply for a course at the prestigious

university of Ateneo De Manila, he would

pick computer engineering as his course, to

not only further his knowledge on this branch of technology but also in search of

opportunities to grow as a tinkerer of computers and most especially as a programmer.

This thesis reflects this desire. As a collaborative effort with his friend’s startup-company

Kabike, an app that would provide safe routes for bikers was ideated, to which Mr.

Bolong would provide the technical assistance. This research hopes to contribute

whatever it can towards incentivizing a more sustainable lifestyle accessible to any

Filipino.

Email Address: javierbolong@ gmail.com


TABLE OF CONTENTS

ABSTRACT.......................................................................................................................iii

ACKNOWLEDGEMENTS..............................................................................................iv

ABOUT THE AUTHOR....................................................................................................v

TABLE OF CONTENTS..................................................................................................vi

LIST OF TABLES..........................................................................................................viii

LIST OF FIGURES..........................................................................................................ix

CHAPTERS

1. INTRODUCTION..........................................................................................................1

1.1 Statement of the Problem...........................................................................................1

1.2 Research Objectives...................................................................................................2

1.3 Significance of the Study............................................................................................2

1.4 Scope and limitations.................................................................................................3

2. REVIEW OF RELATED LITERATURE...................................................................4

2.1 Data Mining and Filtering..........................................................................................4

2.2 Deep learning for Multiple POI route planning.........................................................5

2.3 Unique Routes using K-means Clustering Approach.................................................6

2.4 Deaggregation of Data................................................................................................6

2.5 Assessing Bike safety in a given area.........................................................................7

3. METHODOLOGY.........................................................................................................8

3.1 Build a collection of Data...........................................................................................8

3.2 Development of Web page.........................................................................................9


3.3 Coding the Algorithm...............................................................................................10

3.4 Testing......................................................................................................................11

4. RESULTS AND DISCUSSION..................................................................................17

4.1 Data Collection for a filtered dataset........................................................................17

4.2 Web page..................................................................................................................17

4.3 Algorithm and Code.................................................................................................20

4.4 Testing......................................................................................................................36

5. CONCLUSION.............................................................................................................42

REFERENCES.................................................................................................................43

APPENDIX.......................................................................................................................45

AUTHOR IN ACTION....................................................................................................56

LIST OF TABLES
Table 1. list of routes for testing.....................................................................................12

Table 2. Imports and Dependencies...............................................................................27

Table 3. Explanation of code for urls.py (under the app folder).................................28

Table 4. Explanation of code for views.py.....................................................................29

Table 5. Explanation of the code for Home.html..........................................................31

Table 6. Explanation of Config.yml................................................................................33

Table 7. Explanation of code in Bike_safe.json file.......................................................34

Table 8. Execution time Comparison.............................................................................37

Table 9. Slope Averages across routes............................................................................39

Table 10. Percentage of Hard and Smooth surface roads taken................................40

Table 11. Percentage of Bike Friendly Road Categories.............................................41

List of Figures
Fig 1. Flow of Development (Left to Right)................................................................................................
Fig 2. Summary of algorithm functionality...............................................................................................

Fig 3. Data collection flow (slope)................................................................................................................

Fig 4. Data collection flow (road category)................................................................................................

Fig 5. Data collection flow (surface)............................................................................................................

Fig 6. UI interface..........................................................................................................................................

Fig 7. Dropdown menu, and search bar......................................................................................................

Fig 8. Sample of Route Details.....................................................................................................................

Fig 9. Basic A-star traversal. .......................................................................................................................

Fig 10. A-Star traversal with Slope Weighted map...................................................................................

Fig 11. A-Star traversal with Road Category Weighted map. .................................................................

Fig 12. A-Star traversal with Road Surface Weighted Map.....................................................................

Fig 13. A-Star traversal with all weighted maps combined......................................................................


CHAPTER I

INTRODUCTION

1.1 Statement of the Problem

The Philippines is rated 9th out of 81 other countries for having the worst traffic situation

in ASEAN. It scored a time index of 44.64 minutes for a one-way commute, and attained

an inefficiency index of 248.96 due to overuse of private motor vehicular transportation

[1]. To alleviate these problems, the government has sought to improve existing

infrastructure, implement more public commuting, and build cycling infrastructure. They

have invested over Php 700M for expanding bike lanes spanning 564 km within the

Metro Manila region. [2].

Such a move allows over 11.2 million active cycling users in the Philippines to

utilize these new roads for commuting over private vehicles [3], 4 times more than

recorded active car owners [4]. Despite the improved infrastructure, road safety and

navigation concerns remain an issue for cyclists. In a report by the MMDA, over 2,397

cyclists were found in road crash accidents, with 33 being lethal [4].

Of the available solutions, bikers would opt for navigational apps to travel,

notably Google Maps, or Waze. Limitations occur when these applications only consider

the fastest paths to travel. Routes generated with this in mind don’t consider the potential

risk posed by the roads taken, especially for cyclists. Factors such as traffic density,

presence of bike lanes, and road quality are some of those which cyclists consider when

taking a certain road on their journey [5].

With these considerations in mind, a Bike Route Generator was proposed that

factors in the quality and the safety of the cycling journey. This is in conjunction with the
wider project of a commercial web-app “Kabike”. For the sake of clarity during

discussion, the route generator and algorithm are the same.

1.2 Research Objectives

Specifically this project aims to:

1. Build filtered dataset the structure and state of the road by accessing external

databases in the internet

2. Construct the web page that coordinates the requests from the user, and sends

back the relevant output

3. Use an algorithm that calculates biker routes in terms of destinations within

Quezon City, using collected data as to model optimal bike routes (mild slope,

hard and smooth roads, non-congested roads)

4. Conduct tests to determine the performance and accuracy of the route generator

1.3 Significance of the Study

Biking is a sustainable and affordable solution towards the traffic problems the

nation is facing. There is a significant portion of the population that are willing to use

bikes as their primary form of transportation but lack the assurance of a safe and quality

journey due to problems with infrastructure and vehicles sharing the same routes. The

web-app will serve to meet the needs of the user by making routes that pose minimal risk,

and arrive at their destination within a reasonable time. This connects the user to relevant

data that can help in determining a good route, without the time-consuming process of

analyzing them. These features aim to contribute to the objective of Kabike, incentivizing

a more sustainable means of transportation through cycling.


1.4 Scope and limitations

This thesis focused on the development of the Back-end code of the route

generator, one aspect of the wider Web-App of Kabike. Features such as web security,

Front-end design, and monetization is not part of the discussion. The web-server will

be constructed in this thesis. However, the extent of its development will only go as far

as its relevance towards the base operation of the route generator.

Kabike was intended to be a product that can operate all throughout the Philippine

nation, but the scope of the thesis’ functionality will only be Quezon City.

Although similar in function to Google Maps, this route generator focuses on the

biker demographic. It does not focus on providing the shortest path, but instead

focuses on the quality of the bike trip by providing routes that are safer (less traffic

dense, paved roads, a mild incline or decline), and contain bike-related architecture

(dedicated bike lanes, footways, etc),


CHAPTER II

REVIEW OF RELATED LITERATURE

2.1 Data Mining and Filtering

Data is generated every second that passes, circulated and stored throughout

various databases in the web. A system was devised to take advantage of this, for the

context of tourism . It used both data mining and filtering techniques to sift through

databases for relevant data to be used, analyzed and reconfigured for the purpose for the

user. In this study, the created recommendation system data-mines databases filled with

browser histories, and data on search traffic on the internet to gather information on user

demand [6]. Using collaborative filtering techniques, it creates a sub-set from the data-

mined data that matches the top-rated/on demand destination with the preferences of the

user. This was made by going through the settings/preferences (distance, time,

destination) inputted by the user, and his/her travel profile, gathered through knowledge

based transfer learning [6]. A travel log will then be generated, filtered through

collaborative filtering to provide only a final set of recommended destinations, its reviews

and summarised relevant context of the place. It did achieve a good performance, proving

to have a high accuracy of around 85% within the shortest time when compared to other

algorithms like SMTM, ATRS, and CAFOB [6].

Through leveraging data mining & filtering, information from user activity, data

subsets of their proposed taste via user digital activities can be created. Allowing for a

point of comparison in aligning distance, time and destination data towards the

characteristics of destinations; creating an almost perfect fit of where they want to go.

Such methods however must consider accuracy and quantity of information to create a

confident data subset of user preferences.


2.2 Deep learning for Multiple POI route planning

Being able to identify POIs within a user's current region, provide multiple routes

with least detrimental detours, and schedule an order of places to visit all bound within

the time budget of the user were shown to be difficult in implementing at the same time

[8]. In addressing this, the Multi-task Deep Travel Route Planning (MDTRP) framework

was developed.

MDTRP leverages heterogeneous network embedding to seamlessly integrate user

preferences and POI attributes into a comprehensive database. It employs a deep attention

model to learn the probabilities of the next POIs based on input patterns from diverse

users. Additionally, the framework utilizes a beam search algorithm to explore multiple

feasible routes for each of the three planning tasks, optimizing the itinerary [8]. The

effectiveness of such has been rigorously evaluated using six public datasets, and it has

demonstrated superior performance compared to its competitors, establishing itself as a

robust solution for multi-objective route planning in the tourism context [8].

Through leveraging handpicked datasets to fit user needs, MDTRP excels in

tailoring travel experiences to the preferences and constraints of individual tourists. The

integration of user preferences, such as preferred POIs and time constraints, enables it to

provide personalized and highly efficient route planning. By accommodating user-

specific preferences, it not only optimizes routes but also enhances the overall satisfaction

of travelers, ensuring they visit the places of their choice while adhering to their time

limitations.
2.3 Unique Routes using K-means Clustering Approach

Given the complexity of identifying route preferences, knowing what exact data

sets are needed in aligning to suggested routes is necessary. Aside from creating

specific data sets manually, an alternative approach is through K-means clustering

which identifies common characteristics of data and builds data sets through it. This

process reduces redundancies for more efficient analysis and creates better

preferences, as insights are brought directly from its pool of data. As shown when a

survey was done to test that algorithm generated unique routes and whether the system

helped in understanding the differences between them, with a result of 75%

satisfaction [9]. Towards its importance in route design, such a model allows for

refined analysis of GPS data by highlighting significant data that bikers tend to do.

2.4 Deaggregation of Data

When engaging with Bike related information for research and development,

disaggregated data allows for detailed breakdown and straightforward approach when

it comes to analyzing or creating data sets. Limitations occur when open source

information such as Strava provides aggregate data that makes analysis difficult due to

the generalization of information in light of data privacy. In the study, data is layered

on three levels ``Definition and Generation of a Zonal Network", "Matching GPS

tracks to zones", and "Computation of way strings" discussing how to collate [10],

match and synthesize such information for analysis. Results showcase the potential of

aggregate data to be synthesized, and account for other route considerations that

normal methods may overlook.


2.5 Assessing Bike safety in a given area

Particular methods need to be taken to turn the subjective experience of safety into

measurable parameters that can be passed to a program. A software system was made,

under the context of the Swiss city of Zurich, that leveraged the present data on bike-

related accidents and passed it into a risk-assessment model to visualize how accident

prone a given area is [11]. This is calculated alongside a discomfort model that rates a

street by the quality of the road, the incline, and the distance of one point to the other.

Then with both of these models, a certain rating is granted towards an area. With all of

those ratings layered on top of the map of the city, the software recommends routes that

takes into account these variables, outputting a route that has a minimized risk and

discomfort overall rating [11]. Though this data is more accessible in bike-centered

countries like Switzerland (an aspect that the Philippines lack in), the process in which it

assesses the safety of certain streets could help guide in gathering data and finalizing the

methodology.
CHAPTER III

METHODOLOGY

Fig 1. Flow of Development (Left to Right)

3.1 Build a collection of Data

Data will be collected from two main sources: GeoFabrik, TomTom

Geofabrik is a company that specializes in providing digital geographic data of

continents, countries and regions. It offers a regularly updated dataset that describes the

layouts of the environments, such as road networks, land use, and administrative

boundaries. For the case of this research, data pertaining to road architecture, road class,

and road conditions are used. This aids the algorithm as to which roads to prioritize over

others, as some paths are much safer and easier to ride with a bike than others. One

example being, inclusion of bike networks/lanes on the roads which is important in bike

safety [5].
Tomtom is a global mapping technology company that provides an API of its own

name sake. With this, the geocoding services will be used in order to obtain addresses,

place names, and coordinates of these Points of Interests (POIs). The data present will be

used to allow the user to search for locations in the web-app instead of manually

configuring the coordinates of their starting and ending destinations. TomTom will be the

one to provide those coordinates and input it into the routing algorithm.

The data from these databases are imported into the django project. However, due

to the scope of this project, the coded algorithm will only call in locations within Quezon

City. These will serve to help build an objective statistic on desirable paths for a cyclist

that the algorithm can use in its route generation. Then using the Django API, an interface

will be provided to access the data to search for the starting and ending destination

(TomTom). Meanwhile Graphhopper will use the data obtained from Geofabrik, to

initialize priorities in certain segments of the map, to which the algorithm will navigate

through. The libraries from graphhopper will also be used by the algorithm for route

calculations.

3.2 Development of Web page

Using Django, the base architecture of the web-app was developed. Here a web

page to house the web-app was made. At this stage of development, the main classes of

the web-app were developed for its base operation including features such as user request

retrieval, request parsing, data accessing, output packaging, and data visualization.

External tools for data management from Django and Graphhopper were also integrated.

Django provides the interface that allows the user to input their desired starting and

ending destinations. The Backend of Django, calls for the database contained in TomTom
to fetch names of POIs. Once the starting and ending destinations have been set, the

coordinates are fetched from TomTom which are then inputted to the routing algorithm.

3.3 Coding the Algorithm

The Algorithm is a system of functions that does the actual calculation to make the

route, factoring in inputs of the user and the data showing the situation of the roads. The

inputs are simply the starting and the ending destination.

Before any calculations are done, the map is initialized using Graphhopper. This is

made through segments that connect at certain intersections until it makes a geographical

representation of Metro Manila. In these segments the routing algorithm provides certain

weights to certain segments given certain conditions that pertain to a safer and higher

quality bike route. If it impedes the bike route, they are given a lower weight. If it assists

the bike route they are given a higher weight. This final weighted map will be the

reference where the routes are determined.

A-Star is a common navigation technique used to provide the shortest path for general

navigation. Graphhopper uses an optimized version for navigating a map that can be

accessed through its associated API. However, since the custom weighted map changes

the server routing logic in the API, the company only documents that only allows these

custom weighted maps to be used in self-hosted maps. Using these custom maps were

stated to pose security issues (such as code injection or misconfiguration) if hosted in

their public servers. Alongside this, self-hosting allows the use of OSM data from

geofabrik and TomTom to be used in generating the map itself instead of pre-fabricated

ones in graphHopper. If there was any missing data on the cloud-end of graphHopper it
cannot be uploaded with more data to fill in the gaps, allowing for better data

management. Finally this version of the API allows for unlimited queries into the

weighted map, which allows for testing without restrictions. Thus the API is called from a

server that is hosted by the researcher’s own device. It is through this navigation

technique that it will navigate the map. It will output the fastest route given the weighted

paths present. The paths with the higher weight are prioritized over ones with lower

weight. This will be displayed through Leaflet, an API that allows maps to be displayed.

Fig 2. Summary of algorithm functionality

3.4 Testing

Raw Performance/ Speed of execution will be judged by the response time when

given a certain cost of the inputs given. The cost is calculated by the amount of memory

used, the amount of data needed to calculate the route, and the wait time it takes to

calculate it [6]. Graphhopper contains a version of the A* star algorithm [11], that has a

time and space complexity of O(b^d). Wherein:

b = average number of edges from each node

d = number of nodes in resulting path


Although this is an approximation and the cost can vary with the heuristic

function/ implementation of the algorithm, this will serve as a reference to test for

performance. As a general metric, google maps will be used as a frame of reference for

typical speeds of a routing algorithm. A timer will be set every time a route is initialized

with the inputs and ends once the route has been outputted. If the time increase from

google maps to the research’s routing algorithm is less than 50%, then the test is

considered to be a success. In order to maintain a controlled environment when testing, a

randomly generated list of routes with starting and ending destinations was made with

ChatGPT, which will be inputted into each algorithm. This will be further used in the

research to test safety.

Table 1. list of routes for testing.

# Start POI End POI

1 Ateneo De Manila University Congress building

(14.6623, 121.0525) (14.6468, 121.0500)

2 Gateway Mall Eastwood City (Libis)

(14.6219, 121.0530) (14.6097, 121.0801)

3 UP Town Center La Mesa Eco Park

(14.6510, 121.0750) (14.7119, 121.0743)

4 SM city North Edsa Maginhawa street

(14.6570, 121.0304) (14.6470, 121.0500)

5 Q.C City Hall St. Luke’s Medical Center

(14.6468, 121.0500) (14.6227, 121.0233)

6 Trinoma Chowking East Avenue

(14.6531, 121.0334) (14.6360, 121.0460)


7 ABS CBN broad casting center UP Diliman

(14.6406, 121.0367) (14.6532, 121.0633)

8 Kamuning MRT station Project 4

(14.6351, 121.0434) (14.6220, 121.0650)

9 Celebrity Sports club Araneta coliseum

(14.6480, 121.0700) (14.6219, 121.0530)

10 Ninoy Aquino Parks and Wildlife Center Q.C sports club

(14.6530, 121.0450) (14.6470, 121.0500)

Though the amount of routes used is relatively small due to time constraints, the

routes used covered the topographical and urban variation present in Quezon City. Routes

1 and 6 are near important institutions and main roads, while routes 2 and 3 are near

green less congested spaces. . Routes 4 and 5 are near residential and local streets. Route

8 is within a relatively flat plane while Route 10 is in a more hilly area.

The “Safety” of a route will be judged by the overall grade. As mentioned earlier

a weighted map was used in conjunction with the given data that push the routes to be

more safe. To determine the sufficiency in creating a “safe” route, 3 main categories were

taken into consideration. Here the list of routes from Table 1 are used.
- Slope

- Dictates how steep a road is. Steeper the elevation gain or loss, harder is

to pedal upwards or downwards. Measured in terms of percentage gain

wherein:

(e/d) * 100

where: e = elevation gain or loss (calculated by the difference of elevation at point

A to point B)

d = horizontal distance

- The equation is expressed in percentage to show how steep of an incline

the slope is. Positive value means uphill, and negative value means

downhill

- Based on the documentation for graphhopper [13], a more than 10% result

represents a steep climb, a 5 - 9% result means a climbable hill, while

anything less than 5% means a relatively flat plane.

- If the 10 routes from table 1. fall below an average total slope of 5% then

the test is considered a success.

Fig 3. Data collection flow (slope)

- Road category
- This category dictates what type of road this is typically used for. Certain

roads are far more congested than others, thus more accessible for bikes.

Here the list of routes from table 1 are used. This is split into 3 categories:

- Bike-friendly (roads designed for bikes or uncongested streets):

dedicated bike streets, streets with bike lanes, residential areas

- Moderately Bike Friendly (Some caution for bikers, but can be

used if there is no alternative): city roads, footway

- Bike Unfriendly (traffic-filled streets that need to be avoided):

highways, major car roads

- If at least 60% of the streets used in the road are categorized as “bike

friendly”, then this test is considered successful. This will be tested with

the routes in table 1.

Fig 4. Data collection flow (road category)

- Road surface

- As the name suggests, it dictates what surface the biker will ride on in the

route. There are various categories within road_surface however, some are

more preferable than others. Here the list of routes from table 1 are used.

This is split into 3 categories:

- hard and smooth surfaces (Paved Concrete, Asphalt): They require

less effort to ride through and is stable to ride through


- bumpy and hard surfaces (Gravel, Wood): bumps requires more

effort to ride through, and may cause skidding

- bumpy and soft surfaces (Sand, Grass, Unpaved): Is hard to pedal

through, and may cause the tires to get stuck

- If at least 60% of the routes are on “hard and smooth” then this test is

considered a success

- This will be tested with the routes in table 1.

Fig 5. Data collection flow (surface)


CHAPTER IV

RESULTS AND DISCUSSION

4.1 Data Collection for a filtered dataset

Data was gathered from two separate sources geofabrik and TomTom. Geofabrik

was used to setup the map for A* algorithm. This includes road networks, footpaths, road

surface types, road categories, elevation data and many more. This was stored in a file

named “philippines-latest.osm” which was then processed by graphHopper. TomTom

meanwhile contains the addresses of the POIs in a country’s map alongside its associated

coordinates. This is called through a request by the backend of the Django Framework.

Whenever the algorithm is called by the code, the dataset was filtered to contain only

points within Quezon City to help decrease performance cost and maintain within the

scope of the research.

4.2 Web page

A basic UI interface as shown in Fig. 3 was made using the Django framework. It

contains two search bars, wherein the user can search for 2 destinations, one for the

starting destination and the other for the ending destination. A map is provided at the

center, which is powered by Leaflet which defaults to the coordinates of Metro Manila.

When letters are typed in, TomTom will search for any relevant POIs the user will be

looking for, with a dropdown menu providing a list of at most 10 suggestions. It is only a

valid destination once the user clicks and then sets the destination contained in the

dropdown menu. A button was also developed to provide the current location of the user,

which can act as the starting destination as shown in fig 4. However, if the location is not
within the TomTom dataset a route will not be generated, and and error message is

presented by Django

Fig 6. UI interface

Fig 7. Dropdown menu, and search bar


Fig 8. Sample of Route Details. Once a valid route has been procured from the

code, it will zoom in on the specified route and highlight a blue path along the

map. Alongside this, route details will be provided which direct the user where to

turn, and notify how long and how far the destination will be.
4.3 Algorithm and Code

Fig 9. Basic A-star traversal. The algorithm was built using an A-Star algorithm built-in

to graphhopper. In a basic map, it traverses the map to get from point A to point B to gain

the fastest ETA possible, sticking to direct paths whenever possible. However, to output a

bike-safe route, a weighted map was made, using the categories of slope, road category,

and road surface. To analyze the logic of the algorithm 4 separate routes were made with

the same starting and ending destinations. The basic A-star traversal where the shortest

route from starting to ending destination is shown in fig 10. Figs 11- 14 show how the

weighted maps affect the A-star traversal.


Fig 10. A-Star traversal with Slope Weighted map For the slope-weighted A-star

traversal as shown in Fig. 10, little has changed since it was observed that the majority of

the path was within 0-5% in terms of slopage. However early on in the route, it picked

general mac-arthur avenue over continuing down 9th avenue since the total segment

would contain around a 5-6% slopage down the entire path. Thus the algorithm detoured

to general mac-arthur avenue then turned right to 13th avenue to decrease the total

slopage to 3-4% percent. The difference between a 3% and around 5% slopage is the

difference between a slight incline to a little hill.


Fig 11. A-Star traversal with Road Category Weighted map. Among the other

weighted maps, Road categories were observed to garner the most amount of changes

from the base A-star Traversal as shown in Fig. 11. This version prioritizes categories of

roads that see little to no congestion in terms of traffic density. Categories such as

highways, and primary roads that see the majority of vehicles used to travel are avoided.

Thus roads such as 20th, and 15th avenue (highlighted in black) are given little weight.

The A-star algorithm instead travels through residential areas that are marked in the map

in white, as much as possible. However, as shown in its turn around colonel benny

avenue, if the path taken is still the most direct path towards the objective and there are no

alternative routes, a “primary” road will be used by the algorithm.


Fig 12. A-Star traversal with Road Surface Weighted Map. For the Road surface

weighted map as shown in Fig. 8, no discernable difference was observed. From the data,

it was observed that the route was primarily done on concrete or asphalt roads, which in

terms of safety would be categorized as “bike-safe” since it's a hard and smooth type of

road. However the change is more observable when the weighted map is used in

conjunction with the other weighted maps.


Fig 13. A-Star traversal with all weighted maps combined. It shows the combined

weighted map. The changes from the slope and road category maps were observed,

wherein it avoided steep roads (highlighted in orange) and congested primary avenues

(highlighted in black).

Code Creation and explanation

● Overview

● This coding project is divided into 2 main parts: the django project and the locally

hosted GraphHopper API.

● How to setup the project

○ Django Project

■ Virtual environment was created through the terminal to ensure

stable testing and installation. This was done through the command

“py -m venv myenv”. Then it is activated by “.\myenv\scripts\

activate” This is activated everytime the code is being tested


■ Django was installed through the command “pip install django”

(python and pip must be installed beforehand for command to

work)

■ The Django project was made through command “django-admin

startproject [insert name of project]”. A folder full of files will be

made, the most relevant of which will be settings.py and urls.py.

Which will be discussed under the code breakdown

■ Django App was made through the command “python manage.py

startapp [insert appname]”. This constructs the main infrastructure

that holds the app. Most of the code run for the web-app is found

here

■ Folder was made within the django project directory with the name

“templates”. Here the file “home.html” is made where the main

frontend will be made

■ To activate the web-app the command “py manage.py runserver”.

A link will be provided in the form: http://127.0.0.1:8000/

○ Graphhopper

■ 3 files were obtained: “graphhopper-web-10.0.jar”, “config-

example.yml”, and “philippines-latest.osm.pbf” through the

following links:

● Jar-file:

https://repo1.maven.org/maven2/com/graphhopper/graphho

pper-web/10.0/graphhopper-web-10.0.jar
● Config-file:

https://raw.githubusercontent.com/graphhopper/graphhoppe

r/10.x/config-example.yml

● osm-file-Philippines:

https://download.geofabrik.de/asia/philippines.html

■ The config file will be the most modified to create a weighted map

for the algorithm to use

■ In order to activate the server this command is used: “java -

D"dw.graphhopper.datareader.file=philippines-latest.osm.pbf" -jar

graphhopper-web-10.0.jar server config.yml”. Notice the

datareader file uses philippines.osm file, the jar file uses

graphhopper-web-10.0.jar file and config-example.yml. While the

server is running the algorithm can be used with the Django Project
● Code Breakdown

○ Imports and Dependencies

Table 2. Imports and Dependencies

Dependency Purpose Installation

Django Web framework pip install django

Requests HTTP requests Pip install requests

Leaflet.js Interactive maps <script


src="https://unpkg.com/leaf
let/dist/leaflet.js"></script>

Axios HTTP requests in <script


Javascripts src="https://cdn.jsdelivr.net
/npm/axios/dist/axios.min.j
s"></script>

Graphopper API Routing and route details Requires a running


GraphHopper server and
API key

TomTom API Location Suggestions Requires an API key from


TomTom Developer Portal

Bootstrap Styling Frontend <link rel="stylesheet"


href="https://cdn.jsdelivr.n
et/npm/bootstrap@5.3.0/dis
t/css/bootstrap.min.css">
○ Functionality and logic: Although there are various amounts of files inside

the project (as generated by the django framework) the files that will be

relevant for the research are:

Table 3. Explanation of code for urls.py (under the app folder) url

patterns represent end points the code will access to request certain functions from

views.py.

Code Code Section Purpose/Explanation


Line(s)

1 from django.urls import path Imports the path function


to define URL patterns.

2 from. import views Imports the views


module where view
functions (home,
get_route,
search_location)

3 Urlpatterns = [...] Starts list of URL


patterns

4 path('', views.home, name='home'), Routes the root url to the


home page

5 path('get_route/', views.get_route, Routes /get_route/ to the


name='get_route') get_route view for
fetching bike routes.

6 path('search_location/', Routes /search_location/


views.search_location, to the search_location
name='search_location') view for searching
locations.
Table 4. Explanation of code for views.py. It is the file that contains the

logic for handling requests from the frontend and makes requests from APIs and outputs

them to relevant parts of the code.

Code Code Section Purpose / Explanation


Line(s)

1 from django.shortcuts import Imports the render function to display


render HTML templates.

2 from django.http import Imports JsonResponse for sending JSON


JsonResponse data back to the client (browser).

3 import requests Imports the requests library to make HTTP


requests to external APIs (GraphHopper
and TomTom).

5 GRAPHHOPPER_API_URL Sets the base URL for the local


= ... GraphHopper instance (used to request
route data).

8 TOMTOM_API_KEY = ... Stores the TomTom API key for


authenticating requests to the TomTom
search service.

12–13 def home(request): ... View function that renders the home.html
page when a user visits the site’s
homepage.

15–34 def get_route(request): ... View function that receives start and end
coordinates, sends them to GraphHopper,
and returns the route data.

16 start = request.GET.get('start', '') Gets the starting location from the user’s
request (URL parameter).

17 end = request.GET.get('end', '') Gets the ending location from the user’s
request (URL parameter).

18 if start and end: Checks if both start and end locations were
provided.

20–26 params = {...} Prepares parameters for the GraphHopper


API call, including points, profile, and
requested route details (road class).

27 response = requests.get(...) Sends a GET request to the GraphHopper


API with the provided parameters.

28–30 if response.status_code == Checks if the GraphHopper request


200: ... succeeded; returns the route data as JSON.

31 return If no start or end was provided, it returns


JsonResponse({'error': ...} an error JSON response.

33–53 def search_location(request): ... View function that handles location


searches by sending user queries to the
TomTom API.

34 query = Gets the search query (location text input)


request.GET.get('query', '') from the user.

35–37 country_set, lat, lon Gets or defaults the search location’s


country and coordinates (defaults to Metro
Manila).

39 if query: Checks if the user provided a query string.

41 url = ... Constructs the base URL for the TomTom


search API.

42–46 params = {...} Prepares parameters for the TomTom API


call (query, country, coordinates, and API
key).

48 response = requests.get(...) Sends the GET request to the TomTom


API.

49–51 if response.status_code == If successful, prints the response and


200: ... returns the location data as JSON.

52–53 else ... If the TomTom request failed, logs the


error and sends an error JSON response.

54 return JsonResponse({'error': If no search query was given, returns an


'No query provided'}, ...) error response.

Table 5. Explanation of the code for Home.html. It is the main front-end

template for the web-application. It handles the inputs from the users and outputs the

things retrieved from the requests made in views.py.

Code Code Section Purpose / Explanation


Line(s)

1–2 <!DOCTYPE html> ... <html Declares the HTML document type and
lang="en"> sets language.
3–9 <head> <script src="axios"> imports dependencies (Leaflet for the
map and Axios for HTTP requests).

10–49 <style> ... </style> Internal CSS styles for the user
interface

53 <h1>Search Locations</h1> Page title header.

54–65 <form id="location-form"> ... Creates inputs for start and end
</form> destinations

67 <div id="map"></div> Placeholder where the Leaflet map will


be rendered.

69-73 <div id="route-details"> ... Container for displaying route


</div> instructions and ETA once a route is
fetched.

75 <script> Starts the JavaScript section that


powers the interactive behavior.

77 const map = ... Initializes a Leaflet map centered on


Metro Manila.

79–81 L.tileLayer ... Loads the OpenStreetMap base tiles


into the Leaflet map.

84–120 function fetchSuggestions(...) Defines a function that sends user input


to the TomTom API, and responds with
possible POIs from the input

122-123 fetchSuggestions(...) Attaches the suggestion fetching


fetchSuggestions(...) function to both start and end location
input fields.

125-147 document.getElementById('use Gets the user's current geolocation and


-current-location')... fills the start location input box
automatically.

150-258 document.getElementById('loca When user clicks get route, intializes


tion-form')... routing process

154-157 const startLat = Gets coordinates from POI for starting


document.getElementById('star and end destination
t').dataset.lat;
(...)

169–253 axios.get('/get_route?...') ... Sends the start and end coordinates to


the Django backend (get_route view)
and processes the returned route.

175-179 map.eachLayer(...) Clears existing routes and markers from


the map.

182 L.polyline(...) Draws the new route as a polyline on


the map.
186 - 189 L.marker(...) Adds start and end location markers to
the map.

192 - 199 Const instructions = Lists turn-by-turn navigation instructions


route.instrucitons; on the page.
(...)

201 - 205 Total Distance & Time Displays the total route distance and
estimated time to go through route

194–216 (optional sections - slope, Adds details about surface, slope, and
surface, road class) road class if needed. In this code, only
road class is active.

218–223 Calculate ETA Calculates and displays the estimated


time of arrival based on the current time
and route duration.

225–226 </script> and </body> Ends the script and body sections.

227 </html> Ends the HTML document.

Table 6. Config.yml is the configuration file that helps setup the GraphHopper

routing engine and setup its logic. This calls in the bike_safe.json file to make the

weighted map that the A* algorithm will traverse.

Code Code Section Purpose / Explanation


Line(s)

1 graphhopper: Starts the GraphHopper configuration


block.

2 datareader.file: philippines- Specifies the OpenStreetMap (OSM) file


latest.osm.pbf used to build the weighted graph/map

3 graph.location: graph-cache Directory where GraphHopper will store


its processed map/graph

4 import.osm.ignored_highways: Excludes motorways and trunk roads from


motorway,trunk the routing graph (usually not bike-
friendly).

5 graph.elevation.provider: srtm Enables elevation data using the SRTM


dataset.

6 graph.elevation.cache_dir: Sets the folder where elevation data is


./elevation-cache stored
7 graph.elevation.include_ele_tag Uses elevation tags from the OSM file if
s: true available.

9 vehicle_profiles: Starts the list of vehicle profiles (basic


modes of travel).

10–13 - name: bike ... Defines a vehicle profile called bike that
will be used for routing.

11 profile: bike Uses GraphHopper’s default bike profile


behavior as a base.

12 custom_models.directory: . Directory for storing custom model JSON


files (weighting rules).

15 profiles: Starts the list of routing profiles (rules


about how to prioritize roads).

16–19 - name: bike_safe ... Defines a routing profile named bike_safe.

17 vehicle_profile: bike Links this profile to the earlier bike vehicle


profile.

18 weighting: custom Uses a custom weighting system (instead


of default fastest/shortest).

19 custom_model_files: Specifies the custom model JSON file that


[bike_safe.json] contains routing preferences for safety
(your bike_safe.json).

21 graph.encoded_values: ... Lists extra road data to be read and


stored (road class, surface type, tolls,
average slope, bike speed).

23 server: Starts the server configuration block.

24 application_connectors: Defines how users can connect to the


GraphHopper app.

25–27 - type: http ... Opens the application server at port 8989
on localhost.

28 admin_connectors: Defines how the admin interface can be


accessed.

29–31 - type: http ... Opens the admin server at port 8990 on
localhost.
Table 7. Explanation of code in Bike_safe.json file. It contains the constraints

and weightings that will be made to the map that will be traversed. Characteristics such as

road_class, road_surface and slope are contained here.

Code Code Section Purpose / Explanation


Line(s)

2–19 "priority": [ ... ] Defines how different road properties affect priority
(favorability) of a road segment.

3 if: road_class == Favors cycleways heavily by multiplying priority by


CYCLEWAY 2.0.

4 else_if: road_class == Slightly favors living streets (low-speed residential) —


LIVING_STREET multiply by 1.7.

5 else_if: road_class == Favors residential streets — multiply by 1.6.


RESIDENTIAL

6 else_if: road_class == Slightly favors footways (may be usable paths) —


FOOTWAY multiply by 1.2.

7 else_if: road_class == Penalizes primary roads — multiply by 0.4.


PRIMARY

8 else_if: road_class == Penalizes secondary roads — multiply by 0.5.


SECONDARY

9 else_if: road_class == Strongly penalizes steps (not suitable for bikes) —


STEPS multiply by 0.1.

10 else_if: MOTORWAY or Strongly penalizes major highways — multiply by 0.1.


TRUNK

12 surface == PAVED / Rewards good surfaces by increasing priority by 1.2.


CONCRETE / ASPHALT

13 surface == GRAVEL / Slight penalty for gravel/wood — multiply by 0.8.


WOOD

14 surface == SAND / Strong penalty for unpaved/sandy paths — multiply by


GRASS / UNPAVED 0.5.

17 toll == ALL Strong penalty for tolled roads — multiply by 0.2.

20 average_slope > 0.10 Penalizes steep slopes over 10% — multiply by 0.5.

21 average_slope > 0.05 Slight penalty for moderate slopes (5% to 10%) —
multiply by 0.85.

22 average_slope <= 0.05 Rewards gentle slopes — multiply by 1.2.


25 else Default multiplier for segments that don’t match any
conditions — 1.0.

27–29 "speed": [...] Sets the speed calculation rule.

28 if: true → limit_to Uses the encoded value bike_average_speed to set the
bike_average_speed maximum speed for route calculations.

30 distance_influence: 50.0 Sets how much distance affects route choice — higher
values prefer shorter distances over better priority
weighting.
4.4 Testing

4.4.1 Raw performance

Table 8. Execution time Comparison.

Route # google maps (s) Public use Research Algorithm (s)

GraphHopper (s)

1 1.36 0.95 2.39

2 0.87 0.91 2.20

3 1.14 0.80 3.37

4 1.14 0.86 2.58

5 0.89 0.90 2.72

6 0.67 0.85 2.66

7 1.15 0.90 2.52

8 1.08 1.01 2.78

9 0.95 1.20 2.60

10 1.10 0.96 2.52

average 1.045 0.934 2.634


252% performance cost increase was observed when comparing google maps and the

research algorithm as shown in table 8. When calling a standard A* traversal algorithm

from the server, using their public domain, the performance of graphHopper was around

0.934s on average. The main difference between the A* traversal algorithm used with

standard graphHopper and the research algorithm’s, was the use of the weighted map

which twists its routing logic and the self-hosting the API on a local machine. Thus it can

be concluded that this is the main reason for the performance cost increase. The

difference is still in seconds, which is still relatively low. The routing algorithm is still

usable. However, given the typical rate of routing algorithms like google maps being near

instant, there could be a perceived defect from typical users if it is not as fast as google

maps. Nevertheless the raw performance test is considered a failure, and will be a point

of improvement for future research on the subject.


4.4.2 Safety

Table 9. Slope Averages across routes

Route # Average slope A

1 0.012% s
2 -0.62

3 0.38

4 -0.10

5 0.08

6 0.07

7 0.44

8 -0.17

9 -0.58%

10 0.53%

average 0.0042%

observed in table 9 the average slope of the routes generated were relatively flat. A flat

surface means little deviation in terms of effort exerted towards maneuvering the bike, in

turn allowing better control over the bike. Across the results shown in table 3, it averaged

around 0.0042% which falls under the 5% metric as stated. Given that Quezon City is

relatively hilly in certain areas the slope reduction along the routes taken was significant.

Thus the algorithm was successful in minimizing the slope of the routes generated.
Table 10. Percentage of Hard and Smooth surface roads taken.

Route # Percentage of Hard and smooth road along route T

1 33.49% a

2 71.74% b

3 61.88% l

4 57.33% e
5 71.21%

6 61.84%

7 76.77

8 86.49%

9 57.6%

10 62.3%

average 64.7%

10 shows that 64.7% of the roads used were bike friendly (asphalt, paved and concrete

roads fall under this category). It was noted that 41.74% of the data was missing. For the

sake of testing, they were considered as non-hard and smooth surfaces, so as to account

for the worst-case scenario wherein all of those missing data would be non-bike friendly

surfaces. Nevertheless even in this worst case scenario, the routing algorithm was able to

output routes to which contain a more than average bike-friendly surface along the paths

it took.

Table 11. Percentage of Bike Friendly Road Categories.

Route # % of bike friendly road categories along route

1 48.82%

2 36.67%
3 59.46%

4 54.67%

5 49.23%

6 59.26%

7 58.16%

8 69.12%

9 42.31%

10 62.3%

average 54.0%

It was observed that on average 54% of the paths taken were on roads that were

considered to be bike friendly, whereas they were generally on non-congested and traffic

heavy avenues. The middling results was traced to the amount of categories present in the

dataset, that are considered non-bike friendly such as motorways and highways, roads

designed for cars. Nevertheless this has not affected the algorithm significantly and the

route was still able to push routes that were primarily in non-congested road categories.

CHAPTER V

CONCLUSION

A Web-App was successfully made that contained a functional bike route

generator with a filtered dataset, with data sourced from geofabrik and tomtom, to output

routes that made bikers safer. Django was used to build a UI interface that allowed users

to search for POIs within Quezon City. The inputs were fed into the A-star algorithm self-

hosted by the researcher to traverse a pre-weighted map that prioritizes conditions such as

the slope, road surface and road category of the path taken. Finally, the algorithm itself

was tested for its performance, and the “safety” it provides to the routes by ensuring the
route goes through a relatively flat plane, a hard and smooth road surface and a non-

congested road category.

There were some complications present in the development. Performance

increased dramatically by 252%, due to the computing taken from a personal computer

instead of the servers APIs were typically using. However, since the weighted map was

needed to make bike routes safer, and they were a feature only available if self-hosted, the

research pursued this methodology despite the increase in performance cost. It is

recommended to search for alternatives APIs that allow customly weighted maps while

allowing server-based usage of their A-star traversal services.

Alongside this, more data could be inputted to fill in the gaps presented by the

results such as more complete data on road surfaces for a more accurate route that ensures

a smoother ride for bikers, especially if this should get expanded into a nationwide

application. More data can be collected on bike architecture, the surfaces on current

roads, bike lane networks, are recommended.

REFERENCES

[1] R. Mercurio, “Philippines traffic worst in ASEAN, 9th in world,” Philstar.com,


https://www.philstar.com/headlines/2021/01/11/2069604/philippines-traffic-worst-ase
(accessed Oct. 23, 2023).

[2] J. Cruz, “Dotr to build expanded protected bike lanes in 2023,” Interaksyon,
https://interaksyon.philstar.com/trends-spotlights/2023/03/08/245143/dotr-to-build-
expanded-protected-bike-lanes-in-2023/ (accessed Oct. 23, 2023).

[3] Manila bulletin“Bikers, Bike Lanes, and safe roads: It should not be a test to survive a
journey,” Manila Bulletin,
https://mb.com.ph/2023/5/5/bikers-bike-lanes-and-safe-roads-it-should-not-be-a-test-to-
survive-a-journey

[4] I. Gozum, “More bike owners than car owners in ph – SWS,” RAPPLER,
https://www.rappler.com/nation/bike-car-owners-sws-survey-april-2022/ (accessed Oct.
23, 2023).

[5] M. L. Still, “Expert cyclist route planning: Hazards, preferences, and ... - springer,”
Springerlink, https://link.springer.com/content/pdf/10.1007/978-3-030-59987-4_16.pdf
(accessed Oct. 31, 2023).

[6] X. Nan and X. Wang, “Design and implementation of a personalized tourism


recommendation system based on the data mining and collaborative filtering algorithm,”
Computational Intelligence and Neuroscience, vol. 2022, pp. 1–14, 2022.
doi:10.1155/2022/1424097

[7] Huang, J. Xu, and J. Weng, “Multi-task travel route planning with a flexible deep
learning framework,” IEEE Transactions on Intelligent Transportation Systems, vol. 22,
no. 7, pp. 3907–3918, 2021. doi:10.1109/tits.2020.2987645

[8] T. Wang and S. Yamaguchi, “A travel route recommendation system based on route
clustering algorithm considering spatial similarity of routes,” 2023 11th International
Conference on Information and Education Technology (ICIET), 2023.
doi:10.1109/iciet56899.2023.10111109

[9] S. Huber, “Synthetization of bicycle route data from aggregate GPS-based cycling
data and its utility for Bicycle Route Choice Analysis,” 2021 7th International
Conference on Models and Technologies for Intelligent

[10] D. Castells-Graells, C. Salahub, and E. Pournaras, “On cycling risk and discomfort:
Urban safety mapping and Bike Route Recommendations,” Computing, vol. 102, no. 5,
pp. 1259–1274, 2019. doi:10.1007/s00607-019-00771-y

[11] H. Mehta, P. Kanani, and P. Lande, “Google Maps - Researchgate,” Google Maps,
https://github.com/graphhopper/graphhopper?tab=readme-ov-file

[12] G. Cox, “A* pathfinding algorithm,” A* Pathfinding Algorithm,


https://www.baeldung.com/cs/a-star-algorithm#:~:text=Complexity,nodes%20on%20the
%20resulting%20path. (accessed Dec. 7, 2023).

[13] karusell, peter, et al. “Graphhopper/Graphhopper.” GitHub, 25 Mar. 2021,


github.com/graphhopper/graphhopper.
APPENDIX

A. Source Code for urls.py (under apps folder)

from django.urls import path


from . import views

urlpatterns = [
path('', views.home, name='home'), # Home page
path('get_route/', views.get_route, name='get_route'), # Endpoint for fetching the route
path('search_location/', views.search_location, name='search_location'), # Endpoint for
location search
]

B. Source Code for views.py

from django.shortcuts import render


from django.http import JsonResponse
import requests

# GraphHopper API URL


GRAPHHOPPER_API_URL = 'http://localhost:8989/route'

# TomTom API Key


TOMTOM_API_KEY = 'IZ3GUSzKA5wcHEyDiUUQfY3zRIyAmaT7'

# home view, renders the home page


def home(request):
return render(request, 'home.html')

def get_route(request):
start = request.GET.get('start', '')
end = request.GET.get('end', '')
if start and end:
# Prepares the request to GraphHopper API
params = {
'point': [start, end], # Start and end points
'profile': 'bike_safe', # What custom profile to use
'locale': 'en', # Language for the response
'points_encoded': False, # Ensure coordinates are not encoded for easier parsing
#'details': 'surface'
#'details': 'average_slope'
'details': 'road_class' # Include road class in the response
}
response = requests.get(GRAPHHOPPER_API_URL, params=params)
if response.status_code == 200: # Check if the request was successful
return JsonResponse(response.json())
else:
return JsonResponse({'error': 'Failed to fetch route from GraphHopper'},
status=response.status_code)
return JsonResponse({'error': 'Start or end location missing'}, status=400)

def search_location(request):
query = request.GET.get('query', '')
country_set = request.GET.get('countrySet', 'PH') # Default to the Philippines
lat = request.GET.get('lat', '14.6091') # Default latitude for Metro Manila
lon = request.GET.get('lon', '121.0223') # Default longitude for Metro Manila

if query:
# Call TomTom API to search for locations
url = f'https://api.tomtom.com/search/2/search/{query}.json?
key={TOMTOM_API_KEY}'
params = {
'key': TOMTOM_API_KEY,
'countrySet': country_set,
'lat': lat,
'lon': lon,
}

response = requests.get(url, params=params) # Make the request to TomTom API


if response.status_code == 200: # Check if the request was successful
print('TomTom API Response:', response.json())
return JsonResponse(response.json())
else:
print('TomTom API Error:', response.status_code, response.text)
return JsonResponse({'error': 'Failed to fetch location from TomTom'},
status=response.status_code)
return JsonResponse({'error': 'No query provided'}, status=400)

C. Source Code for home.html

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Search Locations</title>
<link rel="stylesheet" href="https://unpkg.com/leaflet/dist/leaflet.css"> <!--Adds
leaflet map-->
<script src="https://unpkg.com/leaflet/dist/leaflet.js"></script> <!--Installs Leaflet
dependency-->
<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script> <!--Installs
axios dependency-->
<style>

#map { height: 500px; width: 100%; } /* generates map */


.autocomplete-suggestions {
border: 1px solid #ccc;
max-height: 150px;
overflow-y: auto;
position: absolute;
background: white;
z-index: 1000;
width: 300px;
}
.autocomplete-suggestions li {
padding: 5px;
cursor: pointer;
}
.autocomplete-suggestions li:hover {
background: #f0f0f0;
}
#route-details {
margin-top: 20px;
padding: 10px;
border: 1px solid #ccc;
background-color: #f9f9f9;
}

#route-details h2 {
margin-top: 0;
}

#route-instructions {
list-style-type: none;
padding: 0;
}

#route-instructions li {
margin-bottom: 5px;
}
</style>
</head>
<body>
// main page of the web application, where users can search for locations and view
routes on a map.
// sets up basic user interface
<h1>Search Locations</h1>
<form id="location-form">
<label for="start">Start Location:</label>
<input type="text" id="start" name="start" autocomplete="off">
<button type="button" id="use-current-location">Use Current Location</button>
<ul id="start-suggestions" class="autocomplete-suggestions"></ul>

<label for="end">End Location:</label>


<input type="text" id="end" name="end" autocomplete="off">
<ul id="end-suggestions" class="autocomplete-suggestions"></ul>
<button type="submit">Find Route</button>
</form>

<div id="map"></div>

<div id="route-details">
<h2>Route Details</h2>
<ul id="route-instructions"></ul>
<p id="route-eta"></p>
</div>

<script>
// calls the Leaflet library to create a map and display it on the page.
const map = L.map('map').setView([14.6091, 121.0223], 12); // Set initial view to
Metro Manila

L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
maxZoom: 19,
}).addTo(map);

//main function to fetch suggestions from the TomTom API based on user input.
function fetchSuggestions(input, suggestionsList) {
input.addEventListener('input', () => {
const query = input.value;
if (query.length > 2) {
console.log(`Fetching suggestions for: ${query}`); // Debugging

// Add localization parameters: countrySet and lat/lon for Metro Manila


const countrySet = 'PH'; // Restrict to the Philippines
const lat = 14.6091; // Latitude of Metro Manila
const lon = 121.0223; // Longitude of Metro Manila

url = `https://api.tomtom.com/search/2/typeahead/${query}.json`

axios.get(`/search_location?query=${query}&countrySet=$
{countrySet}&lat=${lat}&lon=${lon}`) //axios call to the TomTom API
.then(response => {
console.log('Suggestions response:', response.data); // Debugging
suggestionsList.innerHTML = '';
response.data.results.forEach(result => {
const li = document.createElement('li');
li.textContent = result.poi ? result.poi.name :
result.address.freeformAddress; // Display POI name or freeform address
li.addEventListener('click', () => { // Add click event to select
suggestion
input.value = result.poi ? result.poi.name :
result.address.freeformAddress;
input.dataset.lat = result.position.lat;
input.dataset.lon = result.position.lon;
suggestionsList.innerHTML = '';
});
suggestionsList.appendChild(li);
});
})
.catch(error => {
console.error('Error fetching suggestions:', error);
});
} else {
suggestionsList.innerHTML = ''; // Clear suggestions if input is less than 3
characters
}
});
}

fetchSuggestions(document.getElementById('start'),
document.getElementById('start-suggestions')); //views function "fetchSuggestions" for
start and end locations
fetchSuggestions(document.getElementById('end'), document.getElementById('end-
suggestions'));

document.getElementById('use-current-location').addEventListener('click', () => {
if (navigator.geolocation) { //uses native geolocation to get user's current location
navigator.geolocation.getCurrentPosition(
(position) => {
const { latitude, longitude } = position.coords;

// Set the current location as the starting location


const startInput = document.getElementById('start');
startInput.value = `Current Location (${latitude.toFixed(5)}, $
{longitude.toFixed(5)})`;
startInput.dataset.lat = latitude;
startInput.dataset.lon = longitude;

console.log(`Current location set: ${latitude}, ${longitude}`);


},
(error) => {
console.error('Error fetching location:', error);
alert('Unable to fetch your current location. Please enable location
services.');
}
);
} else {
alert('Geolocation is not supported by your browser.');
}
});

// checks for inputs to fetch route details


document.getElementById('location-form').addEventListener('submit', (e) => {
e.preventDefault();

// Get the start and end locations from the input fields
const startLat = document.getElementById('start').dataset.lat;
const startLon = document.getElementById('start').dataset.lon;
const endLat = document.getElementById('end').dataset.lat;
const endLon = document.getElementById('end').dataset.lon;

//error handling for invalid locations


if (!startLat || !startLon || !endLat || !endLon) {
alert('Please select valid locations from the suggestions.');
return;
}

// Convert to string format for the API request


const start = `${startLat},${startLon}`;
const end = `${endLat},${endLon}`;

axios.get(`/get_route?start=${start}&end=${end}`)
.then(response => {
const route = response.data.paths[0];
const coordinates = route.points.coordinates.map(coord => [coord[1],
coord[0]]); // Reverse [lon, lat] to [lat, lon]

// Clear existing layers (if any)


map.eachLayer(layer => {
if (layer instanceof L.Polyline || layer instanceof L.Marker) {
map.removeLayer(layer);
}
});

// Add the route to the map


const routeLine = L.polyline(coordinates, { color: 'purple' }).addTo(map);
map.fitBounds(routeLine.getBounds());

// Add markers for start and end locations


const startMarker = L.marker([startLat, startLon]).addTo(map)
.bindPopup('Start Location').openPopup();
const endMarker = L.marker([endLat, endLon]).addTo(map)
.bindPopup('End Location').openPopup();

// Display route details


const instructions = route.instructions;
const instructionsList = document.getElementById('route-instructions');
instructionsList.innerHTML = ''; // Clear previous instructions
instructions.forEach(instruction => {
const li = document.createElement('li');
li.textContent = `${instruction.text} (${instruction.distance.toFixed(1)}
meters)`;
instructionsList.appendChild(li);
});

const totalDistance = (route.distance / 1000).toFixed(2); // Convert to


kilometers
const totalTime = (route.time / 60000).toFixed(1); // Convert to minutes
const summary = document.createElement('p');
summary.textContent = `Total Distance: ${totalDistance} km, Total Time: $
{totalTime} minutes`;
instructionsList.parentElement.insertBefore(summary, instructionsList);

//only one of the following 3 sections (surface, slope, category) can be


uncommented at a time ot avoid overcluttering the UI
/*
// Display surface details
const surfaceDetails = route.details.surface; // Surface details from the API
const surfaceList = document.createElement('ul');
surfaceList.id = 'surface-details';
surfaceDetails.forEach(([startIndex, endIndex, surfaceType]) => {
const li = document.createElement('li');
li.textContent = `From point ${startIndex} to ${endIndex}: $
{surfaceType}`;
surfaceList.appendChild(li);
});
instructionsList.parentElement.appendChild(surfaceList);
*/

/*
// Display slope details
const slopeDetails = route.details.average_slope; // Average slope details
from the API
const slopeList = document.createElement('ul');
slopeList.id = 'slope-details';
slopeDetails.forEach(([startIndex, endIndex, slope]) => {
const li = document.createElement('li');
li.textContent = `From point ${startIndex} to ${endIndex}: Average slope
is ${slope.toFixed(2)}%`;
slopeList.appendChild(li);
});
instructionsList.parentElement.appendChild(slopeList);
*/

// Display road class details


const roadClassDetails = route.details.road_class; // Road class details from
the API
const roadClassList = document.createElement('ul');
roadClassList.id = 'road-class-details';
roadClassDetails.forEach(([startIndex, endIndex, roadClass]) => {
const li = document.createElement('li'); //display road class details from
the API one by one
li.textContent = `From point ${startIndex} to ${endIndex}: Road class is $
{roadClass}`;
roadClassList.appendChild(li);
});
instructionsList.parentElement.appendChild(roadClassList);

// Calculate and display ETA


const currentTime = new Date();
const travelTimeInMs = route.time; // Total travel time in milliseconds
const eta = new Date(currentTime.getTime() + travelTimeInMs); // Add
travel time to current time
const etaString = eta.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit'
}); // Format ETA
document.getElementById('route-eta').textContent = `Estimated Time of
Arrival (ETA): ${etaString}`;
})
.catch(error => {
console.error('Error fetching route:', error);
alert('Failed to fetch the route. Please try again.');
});
});
</script>
</body>
</html>

D. Source Code for config.yml

graphhopper:
datareader.file: philippines-latest.osm.pbf
graph.location: graph-cache
import.osm.ignored_highways: motorway,trunk
graph.elevation.provider: srtm
graph.elevation.cache_dir: ./elevation-cache
graph.elevation.include_ele_tags: true

vehicle_profiles:
- name: bike
profile: bike
custom_models.directory: .

profiles:
- name: bike_safe
vehicle_profile: bike
weighting: custom
custom_model_files: [bike_safe.json]

graph.encoded_values: road_class, surface, toll, average_slope, bike_average_speed

server:
application_connectors:
- type: http
port: 8989
bind_host: localhost
admin_connectors:
- type: http
port: 8990
bind_host: localhost

E. Source Code for bike_safe.json

{
"priority": [
{ "if": "road_class == CYCLEWAY", "multiply_by": 2.0 },
{ "else_if": "road_class == LIVING_STREET", "multiply_by": 1.7 },
{ "else_if": "road_class == RESIDENTIAL", "multiply_by": 1.6 },
{ "else_if": "road_class == FOOTWAY", "multiply_by": 1.2 },
{ "else_if": "road_class == PRIMARY", "multiply_by": 0.4 },
{ "else_if": "road_class == SECONDARY", "multiply_by": 0.5 },
{ "else_if": "road_class == STEPS", "multiply_by": 0.1 },
{ "else_if": "road_class == MOTORWAY || road_class == TRUNK", "multiply_by":
0.1 },

{ "if": "surface == PAVED || surface == CONCRETE || surface == ASPHALT",


"multiply_by": 1.2 },
{ "else_if": "surface == GRAVEL || surface == WOOD", "multiply_by": 0.8 },
{ "else_if": "surface == SAND || surface == GRASS || surface == UNPAVED",
"multiply_by": 0.5 },

{ "if": "toll == ALL", "multiply_by": 0.2 },

{ "if": "average_slope > 0.10", "multiply_by": 0.5 },


{ "else_if": "average_slope > 0.05", "multiply_by": 0.85 },
{ "else_if": "average_slope <= 0.05", "multiply_by": 1.2 },

{
"else": "",
"multiply_by": 1.0
}
],
"speed": [
{ "if": "true", "limit_to": "bike_average_speed" }
],
"distance_influence": 50.0
}
AUTHOR IN ACTION

You might also like