June 30, 2012
Maperitive: Alpenglow Effect Using A Custom Shader

The latest release comes with a new Python script called Alpenglow.py which renders a hillshading relief adding some yellowish tint to illuminated high slopes to enhance the 3D effect. It was inspired by the “See the light: How to make illuminated shaded relief in Photoshop 6.0” article on the excellent shadedrelief.com site.

You can run the script by executing

run-python Samples/Python/Alpenglow.py

The script generates the hillshading for a fixed map area in Switzerland, but you can change this quite easily in the script. You can also change other parameters, like shading (and alpenglow) colors, elevation ranges etc.

The script also demonstrates the power of writing a custom shader. A shader transforms a small part of the digital elevation model (DEM) into a pixel color, based on the elevation, aspect and the slope of that part of the DEM. This way you can write your own hillshading effects function and then supply it to the generator. Here’s how it’s done for Alpenglow.py:

# Execute the hillshading
bitmap = ReliefUtils.generate_relief_bitmap(dem, relief_bbox, Srid.WebMercator, 1, alpenglow)

The last parameter of the generate_relief_bitmap function is the shader function, in our case called alpenglow:

# The actual shader function which is called for each pixel of the hillshading bitmap.
# It receives the elevation, the aspect (orientation) of the slope and the steepnes (slope).
def alpenglow(elevation, aspect, slope):
    sin_slope = math.sin (slope)

    nx = math.cos(aspect) * sin_slope
    ny = math.sin(aspect) * sin_slope
    nz = math.cos(slope)

    direction = dotproduct(nx, ny, nz, lx, ly, lz)

    direction = (direction - minDirection) / (1 - minDirection);
    if direction < 0:
        direction = 0

    # This is how we can mix two colors together.
    shade_color = shade_base_color.mix (light_color, direction)

    if direction > 0.0 and elevation > min_alpenglow_elevation:
        elevation_factor = min((elevation - min_alpenglow_elevation) / delta_alpenglow_elevation, 1);

        alpenglow_factor = math.pow(direction, 4)
        return shade_color.mix (alpenglow_color, elevation_factor * alpenglow_factor).argb;

    return shade_color.argb;

May 24, 2012
Mercator’s Egg

UPDATE: my math was buggy, the eggs look a bit different after the correction. Note that the formula fails on very large distances (> 2000 km).

A little Maperitive Python script I was playing with today, showing the line of distance of 3000 km (larger egg) and 2000 km (smaller egg) from my home town of Maribor, drawn on the standard Web Mercator projection map:

Here’s the script:

from maperipy import *
import math

location = Point(15.6530555556, 46.5575)
distance = 3000000

layer = Map.add_custom_layer()

symbol = PolygonSymbol("circle", Srid.Wgs84LonLat)
symbol.style.pen_width = 8
symbol.style.pen_color = Color("blue")
symbol.style.pen_opacity = 0.5
symbol.style.fill_opacity = 0

earth_circumference = 6371000 * math.pi * 2;
points = []
arc = distance / earth_circumference * 360;

for angle in range(0, 360):
    radians = math.radians(angle)
    y = location.y + math.sin(radians) * arc
    lat_factor = math.cos(math.radians(y))
    x = location.x + math.cos(radians) * arc / lat_factor
    points.append(Point(x,y))

circle = Polygon(LinearRing(points))
symbol.add(circle)

layer.add_symbol(symbol)

May 9, 2011
Line Rendering Artifacts

I’m investigating ways of removing nasty little rendering bugs which occur when Maperitive draws something that should be a continuous polyline, but has to be rendered in several separate segments because these segments belong to different layers of painter’s algorithm.

Here’s the bug under the microscope:

I’ve turned the transparency to visualize the actual endings of several line segments. The bug is in the missing pieces of line/curve at the bottom right.

There are some workarounds for it, but of them are perfect. The first one is setting the line-start-cap : round property:

This removes the artifacts between segments, but you end up with an ugly rounded end of lines.

The next one is setting the line-start-cap property to square value:

Now you’ll have nice square end of lines, but you’ll also have new artifacts between line segment joins.

Other possible solutions:

  • Extending each line segment a pixel or two in both directions.
  • Drawing additional joins between unconnected segments once all layers have been drawn. Could be problematic.
  • Some modification of the painter’s algorithm that would allow rendering of polylines as single continuous segments. Now we’re in the SciFi region.

March 30, 2011
Fill Textures In Maperitive

Playing with fill textures in #Maperitive. Just some random forest noise:

Coming up in the next release…

Liked posts on Tumblr: More liked posts »