Skip to content

Commit

Permalink
Add preliminary streetview navigation
Browse files Browse the repository at this point in the history
  • Loading branch information
TheGreatRambler committed Apr 2, 2023
1 parent 23dd1ab commit beaa33b
Show file tree
Hide file tree
Showing 14 changed files with 458 additions and 232 deletions.
3 changes: 0 additions & 3 deletions .gitmodules
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,3 @@
[submodule "third_party/rapidjson"]
path = third_party/rapidjson
url = https://github.com/Tencent/rapidjson
[submodule "third_party/libui"]
path = third_party/libui
url = https://github.com/andlabs/libui
27 changes: 7 additions & 20 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ set(
"${CMAKE_CXX_FLAGS} -Wno-sign-compare -Wno-deprecated-declarations -Wno-unused-parameter -Wno-extern-initializer -Wno-deprecated-enum-enum-conversion"
)

add_definitions(-DRAPIDJSON_HAS_STDSTRING)

if(CMAKE_BUILD_TYPE EQUAL "DEBUG")
add_link_options(-g -O0)
endif()
Expand Down Expand Up @@ -51,32 +53,17 @@ else()
endif()
execute_process(COMMAND ninja WORKING_DIRECTORY ${SKIA_BUILD_DIR})

# LibUI for the renderer
set(LIBUI_DIR ${CMAKE_CURRENT_SOURCE_DIR}/third_party/libui)
set(LIBUI_BUILD_DIR ${CMAKE_CURRENT_BINARY_DIR}/third_party/libui)
file(MAKE_DIRECTORY ${LIBUI_BUILD_DIR})
execute_process(
COMMAND meson setup . ${LIBUI_DIR}
WORKING_DIRECTORY ${LIBUI_BUILD_DIR})
execute_process(
COMMAND meson configure -Ddefault_library=static
WORKING_DIRECTORY ${LIBUI_BUILD_DIR})
execute_process(
COMMAND meson compile
WORKING_DIRECTORY ${LIBUI_BUILD_DIR})
add_library(libui STATIC IMPORTED)
set_property(TARGET libui PROPERTY
IMPORTED_LOCATION ${LIBUI_BUILD_DIR}/meson-out/libui.a)

# For OpenGL
find_package(glfw3 3.3 REQUIRED)

add_executable(streetview_client ${APPLICATION_TYPE}
src/main.cpp
src/parse.cpp
src/extract.cpp
src/renderer.cpp
src/headers.cpp
src/interface.cpp
src/download.cpp
src/preloader.cpp
)

set_target_properties(streetview_client PROPERTIES POSITION_INDEPENDENT_CODE ON)
Expand All @@ -88,5 +75,5 @@ set_target_properties(streetview_client PROPERTIES
CXX_VISIBILITY_PRESET hidden
POSITION_INDEPENDENT_CODE ON)

include_directories(streetview_client include fmt libcurl CLI11 glfw3 ${SKIA_DIR} ${SKIA_DIR}/include ${LIBUI_DIR} ${RAPIDJSON_INCLUDE_DIR})
target_link_libraries(streetview_client PUBLIC fmt libcurl CLI11 skia libui "-framework OpenGl" "-framework CoreFoundation" "-framework CoreGraphics" "-framework CoreText" "-framework CoreServices" "-framework Cocoa" "-framework Metal" "-framework Foundation" "-framework QuartzCore" glfw)
include_directories(streetview_client include fmt libcurl CLI11 glfw3 ${SKIA_DIR} ${SKIA_DIR}/include ${RAPIDJSON_INCLUDE_DIR})
target_link_libraries(streetview_client PUBLIC fmt libcurl CLI11 skia "-framework OpenGl" "-framework CoreFoundation" "-framework CoreGraphics" "-framework CoreText" "-framework CoreServices" "-framework Cocoa" "-framework Metal" "-framework Foundation" "-framework QuartzCore" glfw)
9 changes: 7 additions & 2 deletions src/download.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ rapidjson::Document download_preview_document(

rapidjson::Document download_photometa(
CURL* curl_handle, std::string client_id, std::string panorama_id) {

CURLcode res;
auto photometa_url = fmt::format("https://www.google.com/maps/photometa/"
"v1?authuser=0&hl=en&gl=us&pb=!1m4!1smaps_sv.tactile!11m2!"
Expand All @@ -101,18 +102,21 @@ rapidjson::Document download_photometa(
return photometa_document;
}

sk_sp<SkSurface> download_panorama(CURL* curl_handle, std::string panorama_id, int streetview_zoom,
sk_sp<SkImage> download_panorama(CURL* curl_handle, std::string panorama_id, int streetview_zoom,
rapidjson::Document& photmeta_document) {
auto [tiles_width, tiles_height] = extract_tiles_dimensions(photmeta_document, streetview_zoom);

sk_sp<SkSurface> tile_surface
= SkSurface::MakeRasterN32Premul(tiles_width * 512, tiles_height * 512);

fmt::print("Downloading {} tiles\n", tiles_width * tiles_height);

// Start processing
tile_surface->getCanvas()->clear(SK_ColorWHITE);
for(int y = 0; y < tiles_height; y++) {
for(int x = 0; x < tiles_width; x++) {
// Download the specific tile
// Each tile takes around ~40ms to download
CURLcode res;
auto tile_url = fmt::format("https://streetviewpixels-pa.googleapis.com/v1/"
"tile?cb_client=maps_sv.tactile&panoid={}&x={}&"
Expand All @@ -126,6 +130,7 @@ sk_sp<SkSurface> download_panorama(CURL* curl_handle, std::string panorama_id, i
curl_easy_getinfo(curl_handle, CURLINFO_RESPONSE_CODE, &http_code);
if(http_code == 200) {
// Construct an image from the data
// This is less than 1ms
auto image = SkImage::MakeFromEncoded(
SkData::MakeWithoutCopy(tile_download.data(), tile_download.size()));
tile_surface->getCanvas()->drawImage(image, 512 * x, 512 * y);
Expand All @@ -136,5 +141,5 @@ sk_sp<SkSurface> download_panorama(CURL* curl_handle, std::string panorama_id, i
}
}

return tile_surface;
return tile_surface->makeImageSnapshot();
}
4 changes: 1 addition & 3 deletions src/download.hpp
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
#pragma once

#define RAPIDJSON_HAS_STDSTRING 1

#include <core/SkCanvas.h>
#include <core/SkSurface.h>
#include <curl/curl.h>
Expand All @@ -16,5 +14,5 @@ rapidjson::Document download_preview_document(
CURL* curl_handle, std::string client_id, int num_previews, double lat, double lng, int range);
rapidjson::Document download_photometa(
CURL* curl_handle, std::string client_id, std::string panorama_id);
sk_sp<SkSurface> download_panorama(CURL* curl_handle, std::string panorama_id, int streetview_zoom,
sk_sp<SkImage> download_panorama(CURL* curl_handle, std::string panorama_id, int streetview_zoom,
rapidjson::Document& photmeta_document);
88 changes: 36 additions & 52 deletions src/extract.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,72 +9,56 @@

std::vector<std::string> extract_panorama_ids(rapidjson::Document& preview_document) {
std::vector<std::string> ids;
if(preview_document.IsArray() && preview_document.Size() == 11) {
if(preview_document[0].IsArray() && preview_document[0].Size() > 0) {
// std::cout << preview_document[0].Size() << " previews" << std::endl;
for(auto& preview : preview_document[0].GetArray()) {
if(preview.IsArray() && preview.Size() == 32) {
if(preview[0].IsString()) {
auto panorama_id
= std::string(preview[0].GetString(), preview[0].GetStringLength());
if(panorama_id.size() != 22) {
// Not a street view
continue;
}
ids.push_back(panorama_id);
} else {
std::cout << "Panorama id is not a string" << std::endl;
}
} else {
std::cout << "Panorama is not well formed" << std::endl;
}
}
} else {
std::cout << "No street view panoramas here" << std::endl;
// std::cout << preview_document[0].Size() << " previews" << std::endl;
for(auto& preview : preview_document[0].GetArray()) {
auto panorama_id = std::string(preview[0].GetString(), preview[0].GetStringLength());
if(panorama_id.size() != 22) {
// Not a street view
continue;
}
} else {
std::cout << "Is not well formed array" << std::endl;
ids.push_back(panorama_id);
}
return ids;
}

Panorama extract_info(rapidjson::Document& photometa_document) {
auto& id = photometa_document[1][0][1][1];
auto& lat_long = photometa_document[1][0][5][0][1][0];
return Panorama {
.id = id.GetString(),
.lat = lat_long[2].GetDouble(),
.lng = lat_long[3].GetDouble(),
};
}

Location extract_location(rapidjson::Document& photometa_document) {
Location location;
auto& outer_location = photometa_document[1][0][3];
if(outer_location.IsArray() && outer_location.Size() > 2 && outer_location[2].IsArray()) {
if(outer_location[2].Size() == 1) {
// No address, just city
location.city_and_state = std::string(outer_location[2][0].GetString());
} else if(outer_location[2].Size() == 2) {
// Address and city
location.street = std::string(outer_location[2][0].GetString());
location.city_and_state = std::string(outer_location[2][1].GetString());
}
auto& outer_location = photometa_document[1][0][3][2];
if(outer_location.Size() == 1) {
// No address, just city
location.city_and_state = std::string(outer_location[0].GetString());
} else if(outer_location.Size() == 2) {
// Address and city
location.street = std::string(outer_location[0].GetString());
location.city_and_state = std::string(outer_location[1].GetString());
}

return location;
}

std::vector<Panorama> extract_adjacent_panoramas(rapidjson::Document& photometa_document) {
std::vector<Panorama> panoramas;
auto& outer_adjacent = photometa_document[1][0][5];
if(outer_adjacent.IsArray() && outer_adjacent.Size() == 1 && outer_adjacent[0].IsArray()
&& outer_adjacent[0].Size() == 13 && outer_adjacent[0][3].IsArray()
&& outer_adjacent[0][3].Size() == 1 && outer_adjacent[0][3][0].IsArray()) {
for(auto& adjacent : outer_adjacent[0][3][0].GetArray()) {
if(adjacent.IsArray() && adjacent.Size() == 3 && adjacent[0].IsArray()
&& adjacent[0].Size() == 2) {
Panorama panorama;
auto adjacent_tile = adjacent[0][1].GetString();
panorama.id = std::string(adjacent_tile);
if(adjacent[2].IsArray() && adjacent[2].Size() == 3 && adjacent[2][0].IsArray()
&& adjacent[2][0].Size() == 4) {
panorama.lat = adjacent[2][0][2].GetDouble();
panorama.lng = adjacent[2][0][3].GetDouble();
}
panoramas.push_back(panorama);
}
}
auto current_panorama = extract_info(photometa_document);
auto& adjacent_list = photometa_document[1][0][5][0][3][0];
for(auto& adjacent : adjacent_list.GetArray()) {
Panorama panorama = {
.id = adjacent[0][1].GetString(),
.lat = adjacent[2][0][2].GetDouble(),
.lng = adjacent[2][0][3].GetDouble(),
};
if(panorama.id == current_panorama.id)
continue;
panoramas.push_back(panorama);
}
return panoramas;
}
Expand Down
1 change: 1 addition & 0 deletions src/extract.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ struct Panorama {
};

std::vector<std::string> extract_panorama_ids(rapidjson::Document& preview_document);
Panorama extract_info(rapidjson::Document& photometa_document);
Location extract_location(rapidjson::Document& photometa_document);
std::vector<Panorama> extract_adjacent_panoramas(rapidjson::Document& photometa_document);
std::pair<double, double> extract_tiles_dimensions(
Expand Down
68 changes: 68 additions & 0 deletions src/headers.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
#include "headers.hpp"

curl_slist* get_main_page_headers() {
curl_slist* main_page_headers = NULL;
main_page_headers
= curl_slist_append(main_page_headers, "Accept: "
"text/html,application/xhtml+xml,application/"
"xml;q=0.9,image/avif,image/webp,*/*;q=0.8");
main_page_headers = curl_slist_append(main_page_headers, "Accept-Encoding: en-US,en;q=0.5");
main_page_headers = curl_slist_append(main_page_headers, "Accept-Language: en-US,en;q=0.5");
main_page_headers = curl_slist_append(main_page_headers, "Connection: keep-alive");
main_page_headers = curl_slist_append(main_page_headers, "Host: www.google.com");
main_page_headers = curl_slist_append(main_page_headers, "Sec-Fetch-Dest: document");
main_page_headers = curl_slist_append(main_page_headers, "Sec-Fetch-Mode: navigate");
main_page_headers = curl_slist_append(main_page_headers, "Sec-Fetch-Site: none");
main_page_headers = curl_slist_append(main_page_headers, "Sec-Fetch-User: ?1");
main_page_headers = curl_slist_append(main_page_headers, "TE: trailers");
main_page_headers = curl_slist_append(main_page_headers, "Upgrade-Insecure-Requests: 1");
main_page_headers = curl_slist_append(main_page_headers,
"User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; "
"rv:109.0) Gecko/20100101 Firefox/111.0");
return main_page_headers;
}

curl_slist* get_panorama_headers() {
curl_slist* panorama_headers = NULL;
panorama_headers
= curl_slist_append(panorama_headers, "Accept: "
"text/html,application/xhtml+xml,application/"
"xml;q=0.9,image/avif,image/webp,*/*;q=0.8");
panorama_headers = curl_slist_append(panorama_headers, "Accept-Encoding: en-US,en;q=0.5");
panorama_headers = curl_slist_append(panorama_headers, "Accept-Language: en-US,en;q=0.5");
panorama_headers
= curl_slist_append(panorama_headers, "Alt-Used: streetviewpixels-pa.googleapis.com");
panorama_headers = curl_slist_append(panorama_headers, "Connection: keep-alive");
panorama_headers
= curl_slist_append(panorama_headers, "Host: streetviewpixels-pa.googleapis.com");
panorama_headers = curl_slist_append(panorama_headers, "Sec-Fetch-Dest: document");
panorama_headers = curl_slist_append(panorama_headers, "Sec-Fetch-Mode: navigate");
panorama_headers = curl_slist_append(panorama_headers, "Sec-Fetch-Site: none");
panorama_headers = curl_slist_append(panorama_headers, "Sec-Fetch-User: ?1");
panorama_headers = curl_slist_append(panorama_headers, "TE: trailers");
panorama_headers = curl_slist_append(panorama_headers, "Upgrade-Insecure-Requests: 1");
panorama_headers = curl_slist_append(panorama_headers,
"User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; "
"rv:109.0) Gecko/20100101 Firefox/111.0");
return panorama_headers;
}

curl_slist* get_photometa_headers() {
curl_slist* photometa_headers = NULL;
photometa_headers = curl_slist_append(photometa_headers, "Accept: */*");
photometa_headers = curl_slist_append(photometa_headers, "Accept-Encoding: en-US,en;q=0.5");
photometa_headers = curl_slist_append(photometa_headers, "Accept-Language: en-US,en;q=0.5");
photometa_headers = curl_slist_append(photometa_headers, "Connection: keep-alive");
photometa_headers = curl_slist_append(photometa_headers, "Host: www.google.com");
photometa_headers = curl_slist_append(photometa_headers, "Referer: https://www.google.com/");
// TODO switch to cors
photometa_headers = curl_slist_append(photometa_headers, "Sec-Fetch-Dest: document");
photometa_headers = curl_slist_append(photometa_headers, "Sec-Fetch-Mode: navigate");
photometa_headers = curl_slist_append(photometa_headers, "Sec-Fetch-Site: none");
photometa_headers = curl_slist_append(photometa_headers, "Sec-Fetch-User: ?1");
photometa_headers = curl_slist_append(photometa_headers, "TE: trailers");
photometa_headers = curl_slist_append(photometa_headers,
"User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; "
"rv:109.0) Gecko/20100101 Firefox/111.0");
return photometa_headers;
}
69 changes: 3 additions & 66 deletions src/headers.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,69 +2,6 @@

#include <curl/curl.h>

static curl_slist* get_main_page_headers() {
curl_slist* main_page_headers = NULL;
main_page_headers
= curl_slist_append(main_page_headers, "Accept: "
"text/html,application/xhtml+xml,application/"
"xml;q=0.9,image/avif,image/webp,*/*;q=0.8");
main_page_headers = curl_slist_append(main_page_headers, "Accept-Encoding: en-US,en;q=0.5");
main_page_headers = curl_slist_append(main_page_headers, "Accept-Language: en-US,en;q=0.5");
main_page_headers = curl_slist_append(main_page_headers, "Connection: keep-alive");
main_page_headers = curl_slist_append(main_page_headers, "Host: www.google.com");
main_page_headers = curl_slist_append(main_page_headers, "Sec-Fetch-Dest: document");
main_page_headers = curl_slist_append(main_page_headers, "Sec-Fetch-Mode: navigate");
main_page_headers = curl_slist_append(main_page_headers, "Sec-Fetch-Site: none");
main_page_headers = curl_slist_append(main_page_headers, "Sec-Fetch-User: ?1");
main_page_headers = curl_slist_append(main_page_headers, "TE: trailers");
main_page_headers = curl_slist_append(main_page_headers, "Upgrade-Insecure-Requests: 1");
main_page_headers = curl_slist_append(main_page_headers,
"User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; "
"rv:109.0) Gecko/20100101 Firefox/111.0");
return main_page_headers;
}

static curl_slist* get_panorama_headers() {
curl_slist* panorama_headers = NULL;
panorama_headers
= curl_slist_append(panorama_headers, "Accept: "
"text/html,application/xhtml+xml,application/"
"xml;q=0.9,image/avif,image/webp,*/*;q=0.8");
panorama_headers = curl_slist_append(panorama_headers, "Accept-Encoding: en-US,en;q=0.5");
panorama_headers = curl_slist_append(panorama_headers, "Accept-Language: en-US,en;q=0.5");
panorama_headers
= curl_slist_append(panorama_headers, "Alt-Used: streetviewpixels-pa.googleapis.com");
panorama_headers = curl_slist_append(panorama_headers, "Connection: keep-alive");
panorama_headers
= curl_slist_append(panorama_headers, "Host: streetviewpixels-pa.googleapis.com");
panorama_headers = curl_slist_append(panorama_headers, "Sec-Fetch-Dest: document");
panorama_headers = curl_slist_append(panorama_headers, "Sec-Fetch-Mode: navigate");
panorama_headers = curl_slist_append(panorama_headers, "Sec-Fetch-Site: none");
panorama_headers = curl_slist_append(panorama_headers, "Sec-Fetch-User: ?1");
panorama_headers = curl_slist_append(panorama_headers, "TE: trailers");
panorama_headers = curl_slist_append(panorama_headers, "Upgrade-Insecure-Requests: 1");
panorama_headers = curl_slist_append(panorama_headers,
"User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; "
"rv:109.0) Gecko/20100101 Firefox/111.0");
return panorama_headers;
}

static curl_slist* get_photometa_headers() {
curl_slist* photometa_headers = NULL;
photometa_headers = curl_slist_append(photometa_headers, "Accept: */*");
photometa_headers = curl_slist_append(photometa_headers, "Accept-Encoding: en-US,en;q=0.5");
photometa_headers = curl_slist_append(photometa_headers, "Accept-Language: en-US,en;q=0.5");
photometa_headers = curl_slist_append(photometa_headers, "Connection: keep-alive");
photometa_headers = curl_slist_append(photometa_headers, "Host: www.google.com");
photometa_headers = curl_slist_append(photometa_headers, "Referer: https://www.google.com/");
// TODO switch to cors
photometa_headers = curl_slist_append(photometa_headers, "Sec-Fetch-Dest: document");
photometa_headers = curl_slist_append(photometa_headers, "Sec-Fetch-Mode: navigate");
photometa_headers = curl_slist_append(photometa_headers, "Sec-Fetch-Site: none");
photometa_headers = curl_slist_append(photometa_headers, "Sec-Fetch-User: ?1");
photometa_headers = curl_slist_append(photometa_headers, "TE: trailers");
photometa_headers = curl_slist_append(photometa_headers,
"User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; "
"rv:109.0) Gecko/20100101 Firefox/111.0");
return photometa_headers;
}
curl_slist* get_main_page_headers();
curl_slist* get_panorama_headers();
curl_slist* get_photometa_headers();
Loading

0 comments on commit beaa33b

Please sign in to comment.