Example: Tanaka Contours

Also known as illuminated contours, Tanaka contours give the appearance of three dimensionality to contour lines by brightening lines on a slope facing a presumed light source while darkening lines on a slope facing away from the light source.  Lines are also made wider when perpendicular to the light source.  This topic shows how to create the Tanaka effect in contour lines.





Tech tip:  The technique shown in this topic is highly dependent upon zoom to get the desired visual effect.   To see the effect well on-screen we must zoom in to where averaging effects caused by very many small line segments do not interfere.  For the time being, the Tanaka method works best for illustrating contours when the resulting displays are used within a layout and saved as a PDF.  The illustration above, for example, is a screen shot of a PDF.   Manifold intends to tune rendering of many small line segments so the on-screen effect is as good as what appears in PDF regardless of zoom.


Please begin by reviewing the Example: Contour Areas and Contour Lines topic to learn how to create contour lines.




When we use the Contour Lines transform template we create line objects at the desired contour intervals.  Each contour line is a single line object.    The Tanaka effect depends upon coloring a line differently at different locations on the line, and also drawing the line thicker or thinner at different locations.  However, the Style panel applies color and line width to the entire line object.  How can we vary the color and the line width for a contour line?


We do that by using the Decompose to Segments transform template, which takes each line object and splits it into very many line objects, each of which is one segment of the original line.  We can then color each individual small line object a different color, from light to dark, and we can alter the width of each small line object as well.   Because all of the segments will remain lined up as they were in the original line, the resulting effect gives the illusion of a single line that varies in color and width.


To assign colors and widths, we will create a computed field that calculates the azimuth, that is, the bearing of each line segment.  Based on that bearing we can use Style to thematically format each segment so it has the color and width required for that bearing to create the Tanaka effect.


Creating Tanaka contours by decomposing contour lines into a vastly greater number of tiny line objects and then coloring those very many line objects by their bearings is the traditional way the Tanaka effect is created in various GIS packages.  Although it is a "quick and dirty" way of forcibly creating a very pleasing visual effect, from a purely technical perspective It is basically a highly inefficient hack: converting a single line into very many smaller line objects is very inefficient from a database perspective, and the resulting many objects are not in useful form for data analytics.   However, since the method shows the power of various Manifold capabilities used in combination it provides a useful example.

About Lines

To understand how the Tanaka effect is created we will simplify illustrations to use only a single line.    First, we will take a moment for a quick refresher on lines in Manifold, as discussed in the Drawings topic.




Consider the above line, which forms a closed figure as contour lines normally do:  the line ends at the same location where it starts.  Our example line is a very simple line that consists of only eight straight line segments, so it does not appear like a smooth curve.   Contour lines normally consist of very many more segments so they appear to be smoothly curved.    See the discussion in the Drawings topic for illustrations how using very many segments can make a line appear to be a smooth curve even though in reality it is made up of straight line segments.




If we open the table for our line drawing we see there is only one record, for the single line object in our drawing.   All of the coordinates for the line object are stored in the geom for that single record.




We can see the coordinates which make up that line by Shift-Alt-clicking the line to put it into coordinate editing mode.   That makes each coordinate appear as a small box, with a larger box at the first coordinate.




The Coordinates tab for the Record panel in the Contents pane automatically pops open to show the list of coordinates that make up the line.




Lines in Manifold, as with other GIS packages, always have directionality that is implied by the sequence of coordinates that define them.    When created from closed figures such as areas or as a result of contour creation, the coordinates will define the line in a clockwise sequence.    We will exploit that directionality when coloring line segments, since the directionality implies on which side of a hill a given segment is located.

Decompose Contour Lines into Segments

With the focus on the Line drawing, we use the Transform panel in the Contents pane.




We choose the Decompose to Segments template.  In the Options button we choose a new name for the resulting component that will be created, Line Segments, and we press the Add Component button.




We drag and drop the new Line Segments drawing into the map, turning off the line layer.   To create the illustration above we have individually Shift-Alt-clicked each segment and then moved it, as described in the Editing Drawings topic, so that all of the line objects have been shifted away from each other where we can more clearly see they are all individual line objects.



Opening the Line Segments Table we see that the single line has, indeed been decomposed into eight new line objects.  Each of those line objects is a straight line segment defined by only two coordinates, the start and end coordinate of the segment.

Create an Azimuth Field

We must now add a computed field to the drawing's table that gives the bearing, that is, the azimuth, of each line.   We can then use a thematic format in Style to color each line based on the azimuth of that line.




Each line is a single, straight line segment defined by only two coordinates, (x1, y1) and (x2, y2), so calculating the bearing is easy.  If we do not remember the formula we can look it up online.   Using the SQL Function Atan2, the clockwise bearing for a straight line between two points at (x1, y1) and (x2, y2) is given by:


Atan2(x2-x1, y2-y1)


The clockwise bearing provides compass degree bearings as originally used by Tanaka.   To get counterclockwise bearings (as used by programmers) the formula is Atan2 (y2-y1, x2-x1).   The Atan2 function returns a value in radians, so to get the value in degrees we multiply by 57.2958:


57.2958 * Atan2(x2-x1, x2-y1)


It is easy to extract the X and Y values for a vertex from a geom.    We can use the expressions shown as examples in the Example: Create a Geocoded Table from a Drawing topic.   Copying and pasting we can use the following:


For x2:  VectorValue(GeomCoordXY([Geom], 1),0)


For x1:  VectorValue(GeomCoordXY([Geom], 0),0)


For y2:  VectorValue(GeomCoordXY([Geom], 1),1)


For y1:  VectorValue(GeomCoordXY([Geom], 0),1)


Putting the above all together, the expression which we would write to get the bearing in degrees of any given line segment would be:


57.2958 * Atan2((VectorValue(GeomCoordXY([Geom], 1),0) - VectorValue(GeomCoordXY([Geom], 0),0)), (VectorValue(GeomCoordXY([Geom], 1),1) - VectorValue(GeomCoordXY([Geom], 0),1)))


Clearly, Copy and Paste are our friends!




To add a new, computed field to our table we click on the Line Segments Table and choose Edit - Schema.    In the Schema dialog we click the <new field> command.




We enter azi as the Field name, choose float64 as the Type and then into the Expression box we paste the very long expression which calculates the bearing.  


57.2958 * Atan2((VectorValue(GeomCoordXY([Geom], 1),0) - VectorValue(GeomCoordXY([Geom], 0),0)), (VectorValue(GeomCoordXY([Geom], 1),1) - VectorValue(GeomCoordXY([Geom], 0),1)))



Press the Add button, and then the OK button.




A new computed field called azi appears in our table.   However, this field has negative numbers in it when we would like all of our degree numbers to be in the range from 0 to 360. We can fix that by creating a second computed field that normalizes the values from +/- 0 to 180 to the range 0 to 360.    Once more we choose Edit - Schema.




We add a new field called azimuth that is an int16.   We want our azimuths to be integers for simplicity.     The expression we use to normalize the values is a snippet of SQL that uses the CASE SQL Operator:


CASE WHEN ([azi]< 0) THEN [azi]+360 ELSE [azi] END


Press Add and then OK.




The result is a new, computed field called azimuth is added to the table.  This gives the bearing of each line segment as an integer value in degrees from 0 to 360.  


SQL experts, of course, instead of using two computed fields, the latter of which adjusts the computation of the former, would do this in a single expression for a single computed field.   However, for the purposes of clarity in this example we have used two computed fields.   That also shows how a computed field can, in turn, make computations based on other computed fields.




We can create labels using the azimuth line to add to our map, to show the bearing for each line.


Line Color by Azimuth

Now that we have the bearing for each line we can color each line based on the azimuth.    We click on the Line Segments tab to move the focus to that layer.


We will assume the bearing to the Sun is 315 degrees, the default used in hill shading in Manifold.   To achieve the Tanaka effect that means lines with a bearing of 45 degrees should be white, and lines with a bearing of 225 degrees should be black, with bearings in between interpolated from white to black and then back to white.  





The thematic format shown above will do the trick.  We have manually added intervals with color shades interpolated.  Doing so requires some tinkering at first, but then afterwards we can simply copy the format from the mfd_meta table and re-use it over and over.    Copy and Paste are our friends!   The JSON we would paste into the StyleLineColor property would be:


{ "Field": "azimuth", "Fill": "boundaverage", "Value": 12566463, "Values": { "0": 12566463, "135": 8421504, "180": 4210752, "225": 0, "270": 4210752, "315": 8421504, "360": 12566463, "45": 16777215, "90": 12566463 } }


Pressing Update Style in the above applies the desired grayscale colors from white to black to the line segments based on the value of their azimuth field:




Right away, we can see how the effect occurs.

Line Width by Azimuth

A subtlety of the Tanaka method is to vary the width of contours so that contour line segments which run in the same direction as the Sun azimuth are thinner than those which are perpendicular to the Sun azimuth.    We can vary line widths by azimuths in Style by Ctrl-clicking the line width style button to add width to the intervals.




In the Style panel above, we have used line widths from 1 to 3.


The width values used above are exaggerated widths, larger than we would use in cartography, to provide clearer illustrations in this topic.  To vary widths for actual cartography we would use fractional widths, which can be specified in the JSON string we could paste into the StyleLineSize property  for the drawing in the mfd_meta table.   A typical string might be:


{ "Field": "azimuth", "Fill": "boundaverage", "Value": 2, "Values": { "0": 2, "135": 0, "180": 2, "225": 3, "270": 2, "315": 1, "360": 0, "45": 3, "90": 2 } }


Press Update Style.




The result is that each line's width varies by the azimuth of that line.    To see the Tanaka effect we will move the lines back into position end-to-end.




We have renamed the Line Segments drawing Tanaka, and in the map above we have removed the other, unused layers.   Line segments have been moved back into position by copying and pasting geometry for each line from a backup copy of the original Line Segments drawing, using the same technique as illustrated in the Example: Repair a Wrong Edit using a Backup  topic.   Putting the line segments together shows the Tanaka effect.




To increase the effect, we can color the underlying raster image as shown in the Style: Contouring using Colors topic using a Fill method of closest lower value using palette intervals that are the same intervals as were used to create contour lines.   That will create ranges of flat color within each contour interval that match regions enclosed by contour lines.




When the new Tanaka lines we have created and styled are shown above such matching regions of color, the effect is one of flat, solid contour levels seen slightly in three dimensions.   The opening illustration in this topic uses that effect to overlay Tanaka contours in a layer above a lower raster that has been colored using a Fill method of closest lower value using palette intervals that matched the intervals used to create the contour lines.


The Inventor - Professor Kitiro Tanaka invented the method in 1950, calling it the Relief Contour Method.  In an era before computers it was very tedious to create manually,  although the effect was immediately popular.




Seen above is a map of Japan said to have been created by Professor Tanaka.


A hack?  - Yes, creating Tanaka contours as described in this topic, the same method used in virtually every GIS, is indeed a hack.  An individual contour line can consist of hundreds of thousands, or even millions of segments.   The technique described in this topic could create millions of single-segment lines for each such contour line.  While it is impressive that Manifold has the performance to do that, creating vast numbers of objects to present what in reality is nothing but a more sophisticated drop shadow or highlighting is not as elegant as accomplishing that visual effect using a style.    Manifold expects to add special style capabilities which would enable such effects to be commanded with a click or two within the Style panel.    Until then, we can use the technique illustrated in this topic.


See Also



Editing Drawings




Contents Pane


Contents - Transform


Transform Templates


Transform Templates - Drawings


Edit - Schema


Example: Create a Geocoded Table from a Drawing - A partner example to Example: Create a Drawing from a Geocoded Table   A geocoded table has records with a latitude and longitude for each record.   This example starts with a table for a drawing of points where the geom field in the table contains geometry information for each point.   We extract the Y and X locations for each point  from the geom field to create latitude and longitude fields in the table for each record.


Example: Repair a Wrong Edit using a Backup - How to quickly make a backup table and to then copy and paste geometry from that table to repair errors made when editing objects.  This technique is a life-saver when edits go astray.


Example: Contour Areas and Contour Lines - In this example we use the Contour Areas transform template in the Transform panel for images to create a drawing with vector areas showing height contours at desired altitude steps.   We color the areas using the attribute fields automatically created by the template.  Next, we apply a similar procedure using the Contour Lines transform template to create a drawing with vector lines showing height contours at the desired intervals.


Example: Trace Vector Areas from Raster Pixels - This example follows the Trace Vector Areas from Raster Pixels video on the Gallery page.   We use the Trace Areas template in the Transform panel for images to create a drawing with vector areas covering regions of similarly-colored pixels.  Next, we use a simple query to add classification codes from a USGS table of classes to the resulting drawing, using a simple INNER JOIN SQL statement.