Skip to content

Instantly share code, notes, and snippets.

@toanalien
Last active October 2, 2015 12:46
Show Gist options
  • Save toanalien/1e6ac4a3690c9cd2fcf2 to your computer and use it in GitHub Desktop.
Save toanalien/1e6ac4a3690c9cd2fcf2 to your computer and use it in GitHub Desktop.
get panorama google streetview
var getTileData = require('./modules/get-panorama-tiles');
var panorama = require('./modules/get-panorama-by-location');
var getPanoURL = require('./modules/get-pano-url');
var Canvas = require('canvas');
var request = require('request');
var Image = require('canvas').Image;
var express = require('express');
var app = express();
var fs = require('fs');
function getPanoTileImages(id, zoom) {
if (!id) {
throw new Error('must specify panorama ID');
}
zoom = (typeof zoom === 'number' ? zoom : 1) | 0; // integer value
if (zoom < 0 || zoom > 5) {
throw new Error('zoom is out of range, must be between 0 - 5 (inclusive)');
}
var data = getTileData(zoom);
var images = [];
for (var y = 0; y < data.rows; y++) {
for (var x = 0; x < data.columns; x++) {
images.push({
url: getPanoURL(id, {
x: x,
y: y,
zoom: zoom
}),
position: [x * data.tileWidth, y * data.tileHeight]
});
}
}
data.images = images;
return data;
}
function getImageFromURL(url) {
var img = new Image();
var abc;
request.get({
url: url,
encoding: null
}, function(err, res, body) {
img.src = body;
return body;
});
}
app.get('/json', function(req, res) {
if (!req.query.lat || !req.query.lng) {
res.end('lat & lng required !');
}
var location = [req.query.lat, req.query.lng];
var zoom = parseInt(req.query.zoom);
panorama(location, function(err, result) {
if (err) throw err;
var data = getPanoTileImages(result.id, zoom);
var canvas = new Canvas(data.width, data.height);
var ctx = canvas.getContext('2d');
data.images.forEach(function(images) {
request({
url: images.url,
encoding: null
}, function(err, res, body) {
if (err) throw err;
var img = new Image();
img.src = new Buffer(body, 'binary');
ctx.drawImage(img, images.position[0], images.position[1], data.tileWidth, data.tileHeight);
});
});
console.log(canvas.toDataURL());
});
});
var server = app.listen(3000);
module.exports = streetViewUrl;
function streetViewUrl (panoId, opt) {
opt = opt || {};
var x = opt.x || 0;
var y = opt.y || 0;
var zoom = opt.zoom || 0;
// alternative:
// return 'https://cbks2.google.com/cbk?cb_client=maps_sv.tactile&authuser=0&hl=en&panoid=' + id + '&output=tile&zoom=' + zoom + '&x=' + x + '&y=' + y + '&' + Date.now()
return 'https://geo0.ggpht.com/cbk?cb_client=maps_sv.tactile&authuser=0&hl=en&panoid=' + panoId + '&output=tile&x=' + x + '&y=' + y + '&zoom=' + zoom + '&nbt&fover=2';
}
var nets = require('nets');
var defined = require('defined');
module.exports = function panoramaByLocation(location, opt, cb) {
if (!location || !Array.isArray(location)) {
throw new TypeError('must provide location [ lat, lng ]');
}
if (typeof opt === 'function') {
cb = opt;
opt = {};
}
opt = opt || {};
var radius = defined(opt.radius, 50);
var url = 'https://cbks0.google.com/cbk?cb_client=apiv3&authuser=0&hl=en&output=polygon&it=1%3A1&rank=closest&ll=' + location[0] + ',' + location[1] + '&radius=' + radius;
nets({
url: url,
json: true
}, function(err, res, body) {
if (err) {
return cb(bail(location));
}
if (!/^2/.test(res.statusCode)) {
return cb(new Error('http status code: ' + res.statusCode));
}
if (!body || !body.result || !body.result.length) {
return cb(bail(location));
}
cb(null, body.result[0]);
});
};
function bail(location) {
return new Error('could not find street view at: [ ' + location.join(', ') + ' ]');
}
// Much inspired by:
// https://github.com/spite/PanomNom.js
var widths = [416, 832, 1664, 3328, 6656, 13312];
var heights = [416, 416, 832, 1664, 3328, 6656];
var levelsW = [1, 2, 4, 7, 13, 26];
var levelsH = [1, 1, 2, 4, 7, 13];
module.exports = equirect;
function equirect(zoom, data) {
if (typeof zoom !== 'number') {
throw new Error('must provide zoom');
}
var width, height, cols, rows, squareW, squareH;
if (data) {
// if meta info is specified, we will compute the exact tile sizes
// works with StreetView and PhotoSphere
var ratio = data.worldSize.width / data.tileSize.width;
var nearestZoom = Math.floor(Math.log(ratio) / Math.log(2));
width = Math.floor(data.worldSize.width * Math.pow(2, zoom - 1) / Math.pow(2, nearestZoom));
height = Math.floor(data.worldSize.height * Math.pow(2, zoom - 1) / Math.pow(2, nearestZoom));
cols = Math.max(1, Math.ceil(width / data.tileSize.width));
rows = Math.max(1, Math.ceil(height / data.tileSize.height));
squareW = data.tileSize.width;
squareH = data.tileSize.height;
} else {
// otherwise, we approximate them assuming the result is
// a regular StreetView panorama
width = widths[zoom];
height = heights[zoom];
cols = levelsW[zoom];
rows = levelsH[zoom];
squareW = 512;
squareH = 512;
}
return {
columns: cols,
rows: rows,
tileWidth: squareW,
tileHeight: squareH,
width: width,
height: height
};
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment