Sunday, November 12, 2017

Labeling the Coast (Part Five)

In the previous posting on labeling islands, I implemented multi-line labels, as shown for example on this map:
Now that I have multi-line labels working, I wanted to return to labeling the coastline and see about labeling bays.

Bays are recessed portions of the coastline joined to a larger sea, as in these examples:
So how can I detect a bay on my map?

I've talked a couple of times on this blog about the notion of sinuosity -- which is the ratio of the length of a curve to the straight-line distance between the end-points of the curve.  For a straight line, this number is 1.  For a half-circle, this number is the length of a half circle (Pi*D/2) over the diameter of the half-circle (D), or about 1.5:
So I can detect "bays" on the map by walking along the shoreline and testing the sinuosity.  Values close to 1.5 should indicate a bay.

Here's an initial attempt to detect bays.  The red dot is the start of the bay on the coastline and the purple dot is the end of the bay. 
Let me outline the bay to make the area clearer:
That's kind of odd -- the bay skips part of the coastline.  It turns out I was identifying bays too early in the world construction process -- the coastline was still changing after bays had been identified. So I can move bay identification later in the world construction and tweak the size a bit:
Okay, that looks pretty reasonable.  It's definitely a bay.  But looking at this bay raises some questions about how big the bay should be.   On this map, the "bay" could reasonably stretch from near El Od to the point across, or even further to (say) a point near the Kupik Islands label.  For example, here's the bay the algorithm finds if I set the length of the bay much longer:
That also looks reasonable.  I think I want to search a number of possible bay lengths and keep the best one (whatever that is).  Offhand, I can't think of any way to do this efficiently, so I'll implement a straightforward brute force search and keep the candidate with the highest sinuosity.  That yields this solution on this map:
This seems like a pretty reasonable choice.  I might personally include more of the opening to the north in the "bay" but this choice (essentially marking the opening of the bay at the narrowest point) certainly seems good enough for an initial cut.

Now let's see about adding a label to the bay.  I'm going to use a multi-line area label, meaning that the algorithm will try to place the label somewhere within the area of the bay.  As an initial spot and anchor for the label, I'll generate the visual center of the bay, shown here as the green dot above the Inzek label:
Now I need to make up a name, create a label and let the algorithm at it:
Okay, at least the label is showing up.  But it is weirdly placed with respect to the anchor point.  Let's look at the diagnostics.
Hmm.  It looks like the corner is being pulled towards the anchor point.  Ah, I've got a mistake in the code that is treating area labels like point labels (which try to get a corner near the anchor point). That's easily repaired:
And with the debug off and the size tweaked a bit:
For some reason I've been focused on using multi-line labels for bays, but single line labels are also an option:
I should note that right now area labels can only be horizontal.  For bay labels, it might make some sense to allow the labels to sit an angle or have some arc (take a look back at the example maps at the beginning of this post).

Here's a map with multiple bays:
That seems fine to me.

Here's a problem that popped up while testing:
Here "Dummo" meets the definition of a bay and has a pretty high sinuosity, but doesn't seem to be quite the sort of thing I'm trying to identify.  It's more like a fjord or an inlet.  That might be useful at some point, if I have a need to identify "inlets".  But for now I'm working on bays.

How can I distinguish between "bays" and "inlets"?  The key difference is that the bay encloses more water -- in fact, I suspect that I can do a better job detecting bays by looking for stretches of shoreline that enclose a lot of water rather than shorelines that are sinuous.  One subtlety is that I want to try to maximize the amount of water enclosed per the length of shoreline.  Otherwise I'm going to be biased towards picking the bays with the longest shorelines over those that are the most "bay shaped".  So I need to use a combination of the area, the length of the bay shoreline, and sinuosity to identify "bay shaped" areas.

This approach works better:
Here it does a good job of identifying two bays.  Note that the algorithm has placed "Bipdem Harbor" rather nicely.  That bay could be extended along both shorelines a considerable distance, but the spot the algorithm has chosen provides a more definitive boundary that seems to mark off a separate body of water.  The stretch of coastline from from "skug Kal" north has bay characteristics but doesn't quite look to be separate enough, and the algorithm correctly passes it over.  (Obviously some of this is personal preference, and I could tweak the algorithm to pick out a bay here if I liked that.)

By the way, in the real world, plenty of features get labeled as bays that I think look problematic, e.g., from Google Maps:
But I want my fantasy maps to be "better than real life".

Here's an interesting problem that cropped up:
Two bays facing each other.  I think people would be inclined to call that whole area a single bay.  Pretty unusual, but I don't think it's worth trying to prevent.

3 comments:

  1. This series is very interesting. Something with your last example made me think of this, near where I live:

    https://www.google.com/maps/place/Grand+Traverse+Bay/@44.9720843,-85.6187063,11z/data=!4m5!3m4!1s0x4d4ad6b052b660c9:0x2d5e26eaa75a2089!8m2!3d45.096437!4d-85.449339

    The entire bay is "Grand Traverse Bay", with 4 bays within the bay, the two largest being "West Arm Grand Traverse Bay" and "East Arm Grand Traverse Bay". Your last example could fit into such a category, where you could name the overarching bay, and identify different arms of said bay.

    ReplyDelete
    Replies
    1. Or maybe some sort of functionality to determine how much area of the bay is water, to distinguish between bays, gulfs, etc.

      Delete
  2. Interesting ideas. I hadn't thought about creating bays within bays. Regarding the naming, right now the name chosen is random. But I think you're right that there's at least a rough correspondence between names and the size of the bay.

    ReplyDelete