Thursday, October 28, 2021

Map Compasses (Part 1): Introduction

This posting will start a new series on drawing map compasses.  This topic has been on my TODO list since the great Oleg Dolya (aka watawatabou) did a compass generator about a year ago.  Oleg's generator is very good and Oleg was kind enough to share his code with me, so honestly I could probably adapt that code for my own use.  But for a few different reasons, I'd like to write my own generator.

First, I want the learning experience of breaking down map compasses and figuring out how to generate them.  This process helps me understand a lot about what makes something work and what doesn't, and hopefully also gives me insights into the creative process.  Second, I want my compass generator to be based on a procedural grammar (as I did with map borders) so that it is easier to expand the generator to create new kinds of compasses.  Third, I want to use this as an opportunity to share code and give some deeper insight into my development process.


Sharing code like this will be a new adventure for me.  Details are below, but each week I'll release both a new blog posting as well as the code that it discusses so that you can download it and play with it yourself.  I've tried to make this as simple as possible, so that each download is complete and runs right out of the box without any further installs.  (I guess you will need to supply your favorite text editor!)  I'm going to start from bare ground, so even if you don't have any previous experience with building procedural generation or Javascript apps you should be able to follow along.  (And you more expert readers will be bored initially.)  Hopefully we'll end up with a fun and working compass generator,  but the idea is really to walk through the whole process of development and give you a chance to understand and participate.  To that end, each post will also end with some suggested topics that you can explore using that week's code.

As always when I'm tackling a new topic, I like to gather up some good examples from existing fantasy maps as a guide.  I've collected the compasses from all my reference maps as well as from maps on the Cartographers' Guild and from Oleg's generator.  (All of the examples are available in the code repository for you to peruse.)  Like map borders, compasses are an artistic element and there are a wide variety of styles and approaches.  I couldn't find any definitive guide to the parts of a compass rose, so I'll use my own (hopefully self-descriptive) terminology.

The simplest compasses are nothing more than an arrow and a letter:
The most complex are works of art:
Obviously these are beyond my capability to generate.  However, there are a large number of compasses based upon “circles and arrows":
This style of compass has various sorts of arrows toward the different map directions (these are called compass points) and then various circular ornaments interleaved with the pointers.  The parts of these style compasses are fairly simple, but can be combined in many ways to create a nice variety.  For what I imagine are many of the same reasons, these are also the sorts of compasses Oleg's generator produces:

So let's talk about pointers.

The most common pointer by far is the kind of triangle/diamond shape seen above.  It is often split into two halves with one half black and the other white, but entirely black and outlined white are common as well.  Typically near the center of the compass it narrows back to a point to create a diamond shape, but this is often covered by a circle ornament, so it appears to be a triangle.

One variant of triangle style pointers is to make them wavy as in this example:

A very particular variant of the triangle pointer style turns all the pointers into rays and adds a central sun:

Apart from the triangle style, the next most common pointer is some variant on an arrowhead:
Occasionally there will be a more artistic version of a pointer, although typically still some variant on an arrowhead:

In very artistic compasses, the pointers may be swords or some other figurative element.

The arrangement of the pointers always includes the four cardinal directions (N/S/E/W).  (Very occasionally a compass will have only a North pointer, but this is usually a very simple compass or a very artistic one.)  The pointers for the cardinal directions are always the longest pointers in the compass.  Other pointers are usually shorter than the cardinal pointers, but sometimes they're all the same length.  Very occasionally the North pointer is longer than the other cardinal directions:


Or the North pointer may be distinguished with an ornament, such as a fleur de lis:
There can be many pointers between the cardinal pointers, but they're always symmetric.  In some cases the finer pointers are just lines:
The pointers are often labeled with directions.  Most commonly the cardinal directions are labeled, but sometimes the intercardinal directions (NE/SE/SW/NW) are labeled as well.  Very occasionally even finer divisions are labeled:

There are a variety of different names for the compass points:
If the directions are labeled, they are (almost always) the outermost elements of the compass.  They often stand alone, but are sometimes placed in a ring as in this example:
If a map contains windrose (or compass) lines, at least one set originates at the compass:
But these aren't properly part of the compass and I won't be concerned with generating them.

It's not unusual for a compass rose to be only pointers (as in the example immediately above) but they often include circular elements as well.  So let's talk about circle elements.

One simple case is a circle or two set behind the pointers:
A variant of this replaces the circle with a scale of alternating black and white bars, similar to the scales used in map borders:
The scale serves much the same purpose as the pointers, breaking up the circumference of the rose into additional directions.

A more complex version of the scale is a kind of vernier scale that provides finer graduations:
As in this case, the vernier scale may be marked as well, although this is a modern invention and not usually seen on fantasy maps.

Generally a scale or vernier scale is outside of the pointers but occasionally (as in one of the examples above) the scale is inside the pointers.  Here's an example where there is a vernier scale of sorts inside the pointers:

Another common design is a sequence of circles of differing radii:
A variant is to draw the circles as bands -- two lines with a contrasting color between:
This may be more common in colored compass roses, where it is easy to distinguish the band.  In a mono-color rose, something of the same effect can be accomplished by filling the space between two circles with a repeated ornament, as in this rose:
The addition of simple dots between two lines makes it read as a band.  This example has a more complex pattern within a band:
While it is common for all of the circle elements to lie entirely behind the pointers, it is also common for some of the circle elements to lie atop the pointers:
Here the outer band is atop the pointers while the inner band is behind the pointers.

Occasionally a circular element lies atop some pointers and below others:
In these cases, the band is almost always “between" the cardinal pointers and the intercardinal pointers.

It is very common to have circle elements covering the middle part of the rose where the pointers meet:
   
It's not unusual for the center to be filled with a decorative element of some sort:
 
There are many variants of this vocabulary, but the basic elements of pointers and circles is sufficient to create a wide variety of compasses, as this sample from Oleg's generator shows:
These are all stylistically quite different, but all made up from the same base elements of pointers and circles.

For this posting I'm going to share the code to set up a basic web page with a button on it to run some Javascript code.  I gave some thought to the different ways I might share code.  There are some online playgrounds that let you mix code and text in interesting ways, and I considered using one of these but I thought that might create some limitations in how I could structure the code.  I also thought that might make it difficult for people to incorporate the code into their own projects.  So I decided to do a more traditional approach and provide code that you can download and run on your own computer.   My plan is to do a separate code release along with every posting in the series, so no matter when you're reading through this you should be able to see the code associated with this posting.  At the suggestion of the inimitable Azgaar, I will also use Netlify to build a website from each code release, so you can visit this code on the web at https://dragonsabound-part1.netlify.app/test.html.  (You'll be able to run the code and examine it in the browser, but you obviously won't be able to modify it yourself.)  So this will hopefully provide the best of both worlds.

After consulting with some (presumably more experienced) voices on my Twitter feed, I've decided to keep the code in a GitHub repository called Procedural Map Compasses.  That repository will have a branch for each part in this series, so the release for this posting can be found in the “Part 1" branch.  Each release should be self-contained and include all the code necessary to recreate what I've done in the blog post.  I'll use this posting to establish a basic framework for loading the code into the browser and running it.  

Note that I develop on Windows and do no testing on MacOS or Linux!  I've made a small attempt to accommodate those users by including MacOS and Linux versions of the Mongoose web server (see below) but I'd welcome contributions from Mac and Linux savvy folks to make the repository better for those users.  Contact me in one of the usual ways if you can help!

To start with, you should download the code repository by cloning the Git repository at “https://github.com/srt19170/Procedural-Map-Compasses.git" and selecting the “Part 1" branch.  (Cloning a repository means making a new copy of the repository, usually on your own computer.  The link above contains instructions if you don't know how to do this.) That should get you a folder that looks like approximately like this:
The main element in the framework is the HTML file called “test.html".  In a web server, this will load the Javascript code and create a simple web page that will provide a button for executing the code.  To make things simple, the Javascript code for generating compasses will live in the same folder as the HTML file.  Javascript libraries (code I did not write myself) will live in a sub-folder called Libraries (although there are no libraries in the code as of yet).

Also in the main folder I have included a simple Web server.  I use Mongoose, and since that's a single file that doesn't require any installation, I will include it in the project code so that you don't have to download it separately.  (I've included versions of Mongoose for Windows, MacOS and Linux, but as noted above, I've only tested these instructions on Windows.  For Linux, you can also see this page for some alternate ways to run a web server.  Remember that you need to run it in the directory with test.html!)  Double-clicking on the Mongoose executable should open up a page in your Web browser that shows the current directory:
In some cases I've had trouble with the URL that Mongoose tries to open.  If you have any trouble, try using “http://127.0.0.1:8080."  If that doesn't work, you're on your own!

At this point, you can click on test.html to open that page, which should display a blank page with a Test button in the upper left:
Let's take a look at what is inside the test.html page:
<html lang="en">
  <body>
    <div id="all" style="display: flex; flex-direction: row;">
      <div id="controls"
    style="display: flex; flex-direction: column; flex: 0 0 30px">
 <button id="testButton">Test</button>
      </div>
      <div id="map"
    style="margin-left:10px;">
 <svg id="svg" width="500" height="500">
 </svg>
      </div>
    </div>
    <script type="module">
      import Compass from './compass.js';
      var testButton = document.getElementById("testButton");
      var svg = document.getElementById("svg");
      testButton.onclick = function () {
   Compass.test(svg); };
    </script>
  </body>
</html>
This is a stripped down vanilla web page.  First it sets up some <div>s for controls and the map (really just a compass, but this is copied from Dragons Abound).  The controls div contains a simple button labeled “Test."  The map div contains an SVG element that will actually display the compass.

It also includes a <script> that does a couple of things.  First the script loads the Compass module from the same folder as the web page.  (Note that Dragons Abound uses ES6 module syntax; this should work in all modern browsers.)  Second, the script attaches the “test" function from the Compass module to the onclick action of Test button.  (This means that when you click the Test button, the “test" function will get executed.  And eventually that function will draw a compass into the SVG element so that it will show up on the page.)  The SVG element gets passed into the test function so that it will know where to draw the compass.

Now let's take a look inside the test.js file:
//
//  Top level file for Map Compass Procedural Generation
//
function test() {
    console.log('Well, at least we got this far.');
};

export default {
    test: test
};
There's not much here yet.  The test() function is defined, but all it does is print a message to the console.  Then test function is exported so that it can be used outside of the module.

To actually see the code work, you will have to open the browser console.  To see the console in Chrome, you need to open the Developer Tools with CTRL + SHIFT + I or F12 and then hit the Escape key if the console is not showing.  On Firefox you can open the console from the Web Developer sub-menu or by hitting CTRL + SHIFT + J.  (Just different enough to be confusing!)  On Chrome you'll see something like this on the left side of your browser window:
The console is the part at the bottom showing the two error messages.  Your messages and layout might be different.  There are many tutorials on the Web to help you understand and use the Web Developer tools in Chrome and Firefox, so please refer to those if you have further questions.

Meanwhile, try clicking on the Test button.  The console should show the test message:
The “onclick()" function I attached to the test button in the HTML page is calling the test() function from the compass.js file.  And that function is using console.log() to print a message to the console.  The console is very handy for these sorts of debug messages and testing.  

In addition to the code files, the compass examples I used above (and others) can be seen in a folder called “Examples" in the repository.  I'd be happy to expand the collection, so please submit any examples you think should be added.  I'm not exactly sure how to best do this, but please submit a change request to that branch with your contribution and we'll see how that works.  Please try to submit compasses that are different from the existing examples and  demonstrate some new variant of compass style.  Include your explanation of the value of the new compass in your submission.

And as mentioned above, I'll also end each posting with “Suggestion to Explore" with some ideas on how you can expand or play with the ideas from the posting.   (You'll see that below.)  Next time I'll start on drawing a compass from a description.

Suggestions to Explore

  • Test.html puts a 500x500 SVG element on the web page.  How would you put a border around that element to make it easier to see?

  • The test function prints a message to the console log.  That requires having the console open.  It would nice to be able to put a message on the web page.  Modify the code so that test() returns a string and display that on the web page below the Test button.

7 comments:

  1. No need to include a web server for Linux - see https://gist.github.com/willurd/5720255 for a big list of one-liners that all work on Linux (and probably other operating systems too). My personal go-to is "npx serve", which works if you have Node.js installed.

    ReplyDelete
  2. Thanks! I've updated the page to include that information.

    ReplyDelete
  3. Wonderful!! I hope this foray into sharing the technical details/code doesn't disrupt your creative flow, know that it is appreciated.

    ReplyDelete
  4. I believe it would also make sense to deploy the latest version to the web, just to see it in action without copying the repo. I can be done is seconds with something like Netlify

    ReplyDelete
  5. I'd never heard of Netlify, but that's a great idea. I've done that and added it, thanks for the idea.

    ReplyDelete
    Replies
    1. It's not only Netlify that can do it (e.g. Heroku can do the same or even GitHub actions), but it allows you to select a branch that is getting auto-deployed to the web. So you have a repo branch that is always available online

      Delete
  6. Cool! BTW if you want to let people play with it without cloning and running their own server, GitHub Pages works too. Go to https://github.com/srt19170/Procedural-Map-Compasses/settings/pages and tell it to serve from the Part 2 branch. Then https://srt19170.github.io/Procedural-Map-Compasses/test.html will be the page to visit. However as you point out, people can't edit the page that way.

    For Linux and Mac users, running "python3 -m http.server" will show the current folder as http://localhost:8000/

    ReplyDelete