Sunday, September 13, 2015

Thoughts on the perfect city

What is the most important feature of the property (I mean a flat,  house,  appartment or bungalow)? More important than the amout of rooms or how well it's decorated? It's a location!

Would you like a penthouse in a desert? A small house by the sea is a dream of millions. But our cities are far from being a dream come true. Some people live next to the park or a lake,  but most are not. I was thinking - how should have our cities been built to make everybody happy with their property.

In the past, people took what the nature gave them - a cave, leather drape for a door, a branch as a weapon. With time people started making their own tools and build their homes. But we still build cities randomly - where there's some place not too steep and not too wet and not too dry. I think with time people start making their cities according to the plan larger than just "filling the area with buildings packed as close as possible to each other like in Tetris".

Most poeople like fresh air of the forest. So a city must be a forest. Many like lakes. There should be lakes in the forest. Cities should have good bycicle infrastructure. Bycicle roads in a forest. Cars and roads are still needed. Transporting heavy stuff or lazy people is important. Quickly. So we need highways in a forest.

For a biker a 100 m. detour is more annoying that to a car driver. So we build straight and convenient bycicle roads, without traffic lights! Cars can drive around a bit without much trouble.

Now the houses. Current high building are an efficient use of land but that is not a priority anymore. They are a problem for disabled people, for firefighters, for moms with children, for elderly - effectively for all of us at some stage in life.

So we build a 2-3 storey houses. In which arrangement? Currently every house is isolated from it's neighbors. Often with a fence. Everybody has their own garden,  their own lawnmower, own drill, vacuum clener, Internet connection, phone line, network router, printer, etc. This is very ineffective. It's a share nothing architecture. I suggest to build houses arranged in a circle around a central shared area.

This shared area may have a small playground, a common house used by everybody in a circular block, a common garden. In a house there can be a set of instruments and tools, a large table with chairs for everybody in a block, storage shelves for common and private stuff. People should be encouraged to share things they don't use everyday with their closest neighbors. Why not? Of couse, you can have your private juice maker if you like. I can't convince you. You either support the idea of sharing or you don't.

Parking is underground under the buildings. With space for visitor cars and bikes. Cars can be shared as well, by the way.

So we have circular districts of houses with a common shared house in the center located in a forest with bycicle routes to other circular districts, but in which arrangement?

Current cities are either circular (like Moscow) or square (like New York). Circular are more natural as they evolved around a palace, castle or church. We always have a center or a downtown in every city, where there are more of everything (government institutions, restaurants, entertainment, shops) and the property prices are higher. This leads to traffic into and out of the center,  parking problems, pollution, waste management - all the city problems we heard of so much.

My suggestion is to disperse all that can be usually found in the center equally thoughout the forest-city. There will be a bakery for each X of the circular districts, a kindergarden, school, cinema, hospital and everything else. Yes, this way we need more of these facilities and they will be smaller. Different facilities will have a different dispercity level, of course. But they should not tend to be situated close to each other. Or maybe we can have islands of public service buildings for every X of the living blocks.

Do you imagine a homogenous city consisting of neighborhoods in a forest? Such city can be easily expanded in any direction by just adding living districts with some islands of public service areas. These areas should be reachable in 5-10 minutes by bike.

Would you live in such a city? Let me know in the comments.

About Mapping Services and Other PHP Libraries for using in Mashup application

How I built an http://have-you-been-here.appointment.at/ using third party libraries from http://github.com/

http://have-you-been-here.appointment.at/ is a site where users may submit images of different locations on Earth (provided with geo-coordinates) so that other users may find nice places to visit. When building the site I had used many different PHP and JavaScript libraries. Here I'm sharing the information I leaned about these libs.

Composer

First of all, I use myself and recommend composer. You list the libraries you need to use in your project and then say composer update and all listed libraries get installed into the vendor/ folder. The same command is installing updates to the libs, if available. That's great - no need to check for updates manually. Below is part of my composer.json file. The rest of the post will shortly highlight each of these libraries.

{"name": "have-you-been-here",
    "require": {
        "components/jquery": "*",
        "components/jqueryui": "*",
        "components/bootstrap": "*",
        "hybridauth/hybridauth": "dev-master",
        "blueimp/jquery-file-upload": "dev-master",
        "hpneo/gmaps": "dev-master",
        "pear-pear.php.net/DB": "*",
        "needim/noty": "dev-master",
        "phayes/geoPHP": "dev-master",
        "anthonymartin/geo-location": "dev-master",
        "DanElliottPalmer/GeoJSON-Parser": "dev-master",
        "jrburke/requirejs": "dev-master",
        "flesler/jquery.scrollTo": "dev-master",
        "bradwedell/php-google-map-api": "dev-master",
        "ezyang/htmlpurifier": "dev-master",
        "fg/essence": "dev-master",
        "jakiestfu/Snap.js": "dev-master",
        "components/modernizr": "dev-master"
    }
}

jQuery

jQuery is a must in any project. It changes the way you will write JS. Your code would not look like plain JS anymore, but would become easier to read and shorter to write.
JQueryUI is a collection of widgets like a calendar, slider, ... and a nice CSS for these widgets and error messages.

Bootstrap

Even better CSS framework than jQueryUI. Just like nobody is writing pure JS without any libraries, you shouldn't write your own CSS from the scratch.

Hybridauth

Allows your users to login with Google, Twitter, Facebook and other accounts with OAuth. You can easily add any other OAuth provider which is not pre-configured in Hubridauth.

Jquery-file-upload

The best ever file upload lib with support for drag-n'-drop and unobtrusive degradation to standard HTML uploads. Accepting uploads in PHP is a little awkward (no data in $_FILES) but they provide a PHP class for handling uploads on the server.

Map libraries

I find the original Google Maps API too complicated for simple tasks like showing a map at the specified location and showing a single marker with a tooltip information.

php-google-map-api

Therefore I have gladly used a php-google-map-api. Usage is pretty simple, her3 it shows a map of a specific location and a marker:

include_once("vendor/bradwedell/php-google-map-api/releases/3.0/src/GoogleMap.php");
include_once("vendor/bradwedell/php-google-map-api/releases/3.0/src/JSMin.php");

$map = new GoogleMapAPI();
$map->_minify_js = TRUE;
$map->width = '100%';
$map->addMarkerByCoords($coords[1], $coords[0], $this->model->getName());
$this->index->header[__METHOD__] = $map->getHeaderJS();
$this->index->header[__METHOD__] .= $map->getMapJS();
$content .= $map->getOnLoad();
$content .= '<div class="popin">'.$map->getMap().'</div>';

gmaps.js

This was fine for a static map, but once I needed an interaction with a user in the browser like repositioning the map after geolocation - I had to revert back to JS.
Luckily I've found a gmaps.js a wrapper to Google Maps API with MUCH simplified API than one provided by Google. Making a map is as simple as this:

var map = new GMaps({
  div: '#map',
  lat: -12.043333,
  lng: -77.028333
});

Adding a marker is so simple:

map.addMarker({
  lat: -12.043333,
  lng: -77.028333,
  title: 'Lima',
  click: function(e) {
    alert('You clicked in this marker');
  }
});

Geolocation in one line with four event handlers!

GMaps.geolocate({
  success: function(position) {
    map.setCenter(position.coords.latitude, position.coords.longitude);
  },
  error: function(error) {
    alert('Geolocation failed: '+error.message);
  },
  not_supported: function() {
    alert("Your browser does not support geolocation");
  },
  always: function() {
    alert("Done!");
  }
});

Definitely a way to go if you're new to maps.

GeoPHP and GeoJSON

Once you have a map you most likely need to display more than one marker and download and update markers according to the view area of the map (when user is panning or zooming). Surprisingly, Google doesn't provide any help in this. So everybody is inventing their own JSON/XML format for transferring marker information between server and JS. And,  accordingly, a custom JS to parse and display markers.
There is one standard which kind of goes in the direction of standardizing the geo data transfer - GeoJSON. It allows you to transfer points, polygons, filled areas. I was interested of transferring markers (points in GeoJSON) with additional information (title, tooltip text, click link). Unfortunately point data type is not meant for markers - all additional data are transferred as custom properties and the propery names are not standardized. But there's at least a PHP lib for generating GeoJSON and JS lib for parsing it.
Generation is done without any library like this:

$json = new stdClass();
$json->type = 'FeatureCollection';
$json->features = array();
foreach ($this->data as $row) {
    $feature = new stdClass();
    $feature->type = 'Feature';
    $feature->id = $row['id'];
    $feature->geometry = new stdClass();
    $feature->geometry->type = 'Point';
    $feature->geometry->coordinates = array($row['lon'], $row['lat']);

    $properties = (object)$row;
    unset($properties->exif);
    $feature->properties = $properties;
    $json->features[] = $feature;
}
echo json_encode($json);

AJAX requesting and parsing is done with GeoJSON JS lib:

GeoJSON.loadJSON(jsonURL, function(e) {
    var f = GeoJSON.parse(e);

    for (var a = 0; a < f.length; a++) {
        // add to the map
        var latlng = f[a].getCenter();
        if (!self.contains(latlng)) {
            var marker = new google.maps.Marker({
                position: latlng,
                map: map.map,
                title: f[a].properties.name
            });
            marker.place = f[a];
            self.markers.push(marker);
        }
    }
});

As you can see, generation of the markers and reading marker properties is up to you to program.

Server side map support

I always thought (without having a clue) that one needs complicated queries for searching markers in the database. I've seen PostgreSQL even has a plugin for geo support in the DB.
In fact - it's very simple. Google Maps gives you north-east and south-west coordinates of the currently displayed map. This makes your SQL as simple as

WHERE lat BETWEEN 10 and 20
  AND lon BETWEEN 30 and 40

This, of course, requires that you have lat and lon in the database. If you need to geocode addresses into coordinates you cat use Geocoder-PHP.

GeoLocation.php

There is a. lthough one situation where it gets more complicated. When geolocation has beed done in browser, you get lat/lon of the center of the map, but there is no predefined zoom level and hence - no map boundaries to use in the query above.
I decided to start searching for places in the 1 km area around the location. If there are no or less than three places found - I search in the 2, 4, 8, 16 etc. km area. To be able to search for markers inside the specified radius around the specified location requires converting location/radius into bounding-box coordinates. The math of the process is described nicely here. A GeoLocation.php library has a function for this.

function getBoundingBoxFrom(array $pos, $km) {
    $edison = GeoLocation::fromDegrees($pos['lat'], $pos['lon']);
    $coordinates = $edison->boundingCoordinates($km, 'kilometers');

    $lat1 = $coordinates[0]->getLatitudeInDegrees();
    $lon1 = $coordinates[0]->getLongitudeInDegrees();

    $lat2 = $coordinates[1]->getLatitudeInDegrees();
    $lon2 = $coordinates[1]->getLongitudeInDegrees();

    return array($lat1, $lat2, $lon1, $lon2);
}

SQL will look like this:

list($lat1, $lat2, $lon1, $lon2) = $this->getBoundingBoxFrom($pos, $km);
$pc = new PlaceCollection(NULL, array(
    'lat' => new SQLBetween($lat1, $lat2),
    'lon' => new SQLBetween($lon1, $lon2),
));

Additional map operations

Autofitting map area to the set of found and diaplayed markers.

After retrieving some markers from the above query and transferring them to JS with GeoJSON one needs to zoom the map so all the markers are visible. Probably one could do the calculations in PHP and transfer that somehow in GeoJSON but this operation is easily done with standard Google Maps API.
You collext all markers in an array and get Boundary class do the work.

Reacting on user panning and zooming.

This is easily done qith standard API.

The event 'idle' is triggered after the map is done panning/zooming. Note that this event should be registered AFTER initial displaying of markers as we do boundary fitting, which triggers pan/zoom itself.

Sanitizing user comments

This is very important. Noone wants his site to be vulnerable to XSS or contain viruses. I thought PHP function 'strip_tags' is good enough for this. You are allowed to define unharmful tags which will be kept (like <i>, <b>). But is appears the function is not safe enough. See explanation on the page of ###. It also reviews other solutions and thwir shortcomings. Using ### is as simple as

Embedding content from user submitted links

OEmbwd stansard allows you to embed contend from other sites when all you have is a URL of the content to embed. This ia how you can have YouTube links to be shown as a player and Share? presentations as presentations. ### is the best library for this. Usage:

It comes with a list of oEmbes aites and you can add moee. Other libraries arw listed here, but I disn't like them as much as ###.

Slideable drawer

I believe this cocept is invented by Android or maybe Facebook app. Anyway, I fins it vwry convenient as a way to hide the sidwbar on the narrow screen devices. After reciewing suggested libraries at ###, I have choaen Snap. It requires a very specific HTML layout and uaes absolute CSS positioning so I had some work to embed it into Bootstrap layout, especially as I dont want any drawer functionality on the desktop beowsers. So I have a browser setection after the pagw ia loaded and rhen I manually adjuat Bootstrap layput to fit the requiremwnts of the Snap.

On mobile browser it looks like this.

Modernizr

See how I detect mobile browser in the coee above? Modernizr is testing different browser feautirws and als adds correspinding classes to the tag, allowing you