Unit 4 - Loop Line

In this guide, we will cover loop lines in the context of the Glasgow Subway. While the SVG Strip Map Generator is not explicitly made for this type of map, it is possible to build a loop line using locknumstations and copious amounts of xshift. Do note that one of the limitations of the Strip Map Generator is that it only supports direct lines and not curves - while it is possible to add curves in manually, we will not cover that usage and if that is a necessity, this tool may not be the best option.

Initial Setup

We will begin by placing all of our stations on a single line like usual. Nothing special here yet.

Creating the Loop

And now the difficulty begins. To achieve the loop, we will need to segment the line, apply locknumstations, and move the stations. There are 15 in total, so we will use 8 for our locknumstations field.

For visibility, we will only use the orange line for now (and add the other one back in later).

To start, let's move the stations. Similarly to when we add in stations, we will need to apply an xshift as well as a change in the y coordinate. However, with a loop we are not merely shifting - we want to wrap backwards, which will require two shifts per station.

    "stations": [
        {
            "name": ["Govan"],
            "stationtype": "STATION_TYPE_GLASGOW",
            "icons": [
            ],
            "xshift": 0.5,
            "dy": 128
        },
        {
            "name": ["Ibrox"],
            "stationtype": "STATION_TYPE_GLASGOW",
            "icons": [
            ],
            "xshift": 0.5,
            "dy": 128
        },
        ...
        {
            "name": ["Bridge Street"],
            "stationtype": "STATION_TYPE_GLASGOW",
            "icons": [
            ],
            "xshift": 0.5,
            "dy": 128
        },
        {
            "name": ["St. Enoch"],
            "stationtype": "STATION_TYPE_GLASGOW",
            "icons": [
            ],
            "dy": -64
        },
        {
            "name": ["Buchanan Street"],
            "stationtype": "STATION_TYPE_GLASGOW",
            "icons": [
            ],
            "xshift": -2,
            "dy": -64
        },
        {
            "name": ["Cowcaddens"],
            "stationtype": "STATION_TYPE_GLASGOW",
            "icons": [
            ],
            "xshift": -4,
            "dy": -64
        },
        ...
    ]

The first thing to notice is that we have shifted the seven stations on the south side of the river over by 0.5 units. This is to make them symmetric. Now, note how for the north side stations, we shift further by two units each station - one to counter the automatic shift done by the system and the other to shift it further back.

Now let's move the strokes.

This is how it looks when we have two parallel strokes that cover the full length (no preset start or end points). On each end, we will add three supplementary strokes. These will handle the transitions on each end.

"locknumstations": 8,
    "strokes": [
        {
            "color": "rgb(255, 102, 0)",
            "strokewidth": "14px",
            "linecap": "round",
            "dy": 128,
            "startpoint": -0.25,
            "endpoint": 14.25
        },
        {
            "color": "rgb(255, 102, 0)",
            "strokewidth": "14px",
            "linecap": "round",
            "dy": -64,
            "startpoint": -0.25,
            "endpoint": 14.25
        },
        {
            "color": "rgb(255, 102, 0)",
            "strokewidth": "14px",
            "linecap": "round",
            "startpoint": -0.75,
            "endpoint": -0.75,
            "startlinkheight": 0,
            "endlinkheight": 64
        },
        {
            "color": "rgb(255, 102, 0)",
            "strokewidth": "14px",
            "linecap": "round",
            "startpoint": -0.75,
            "endpoint": -0.25,
            "startlinkheight": 0,
            "endlinkheight": -64
        },
        {
            "color": "rgb(255, 102, 0)",
            "strokewidth": "14px",
            "linecap": "round",
            "startpoint": -0.75,
            "endpoint": -0.25,
            "startlinkheight": 64,
            "endlinkheight": 128
        },
        {
            "color": "rgb(255, 102, 0)",
            "strokewidth": "14px",
            "linecap": "round",
            "startpoint": 14.75,
            "endpoint": 14.75,
            "startlinkheight": 0,
            "endlinkheight": 64
        },
        {
            "color": "rgb(255, 102, 0)",
            "strokewidth": "14px",
            "linecap": "round",
            "startpoint": 14.25,
            "endpoint": 14.75,
            "startlinkheight": -64,
            "endlinkheight": 0
        },
        {
            "color": "rgb(255, 102, 0)",
            "strokewidth": "14px",
            "linecap": "round",
            "startpoint": 14.25,
            "endpoint": 14.75,
            "startlinkheight": 128,
            "endlinkheight": 64
        }
    ],

In the above, we now have eight different strokes. The first two are the main parallel strokes. Note that we have extended them by 0.25 units on each end - mainly so that the stations on the north side are not subject to a sharp angle.

There are then three strokes per side. First, the vertical stroke. Note that we MUST specify both the start and end points to be the same as well as provide our start and end link heights. This ensures that the stroke renders as a vertical line segment. After the vertical, we link up the points with another stroke.

Below is our final map.

To allow for the dual lines to align nicely, we utilize startdx and enddx to shift the start and endpoints of a stroke in pixel space. This allows for the spacing between the vertical lines to be consistent.

Source is below. Note that we took some liberties when adding the dual lines for the edges for aesthetic effect, so the lines are overlapping slightly. However, the end product is quite acceptable.

var obj_line4_v1 = {
    "linename": "Glasgow Subway",
    "iconID": ["ICON_GLASGOW"],
    "locknumstations": 8,
    "strokes": [
        {
            "color": "rgb(255, 102, 0)",
            "strokewidth": "14px",
            "linecap": "round",
            "dy": 128 + 7,
            "startpoint": -0.25,
            "endpoint": 14.25
        },
        {
            "color": "rgb(85, 85, 86)",
            "strokewidth": "14px",
            "linecap": "round",
            "dy": 128 - 7,
            "startpoint": -0.25,
            "endpoint": 14.25
        },
        {
            "color": "rgb(255, 102, 0)",
            "strokewidth": "14px",
            "linecap": "round",
            "dy": -64 - 7,
            "startpoint": -0.25,
            "endpoint": 14.25
        },
        {
            "color": "rgb(85, 85, 86)",
            "strokewidth": "14px",
            "linecap": "round",
            "dy": -64 + 7,
            "startpoint": -0.25,
            "endpoint": 14.25
        },
        {
            "color": "rgb(255, 102, 0)",
            "strokewidth": "14px",
            "linecap": "round",
            "startpoint": -0.7,
            "endpoint": -0.7,
            "startlinkheight": 0 - 7,
            "endlinkheight": 64 + 7,
            "startdx": -7,
            "enddx": -7
        },
        {
            "color": "rgb(255, 102, 0)",
            "strokewidth": "14px",
            "linecap": "round",
            "startpoint": -0.7,
            "endpoint": -0.25,
            "startlinkheight": 0 - 7,
            "endlinkheight": -64 - 7,
            "startdx": -7
        },
        {
            "color": "rgb(255, 102, 0)",
            "strokewidth": "14px",
            "linecap": "round",
            "startpoint": -0.7,
            "endpoint": -0.25,
            "startlinkheight": 64 + 7,
            "endlinkheight": 128 + 7,
            "startdx": -7
        },
        {
            "color": "rgb(85, 85, 86)",
            "strokewidth": "14px",
            "linecap": "round",
            "startpoint": -0.7,
            "endpoint": -0.7,
            "startlinkheight": 0 - 2,
            "endlinkheight": 64 + 2,
            "startdx": 7,
            "enddx": 7
        },
        {
            "color": "rgb(85, 85, 86)",
            "strokewidth": "14px",
            "linecap": "round",
            "startpoint": -0.7,
            "endpoint": -0.20,
            "startlinkheight": 0 - 2,
            "endlinkheight": -64 + 7,
            "startdx": 7
        },
        {
            "color": "rgb(85, 85, 86)",
            "strokewidth": "14px",
            "linecap": "round",
            "startpoint": -0.7,
            "endpoint": -0.20,
            "startlinkheight": 64 + 2,
            "endlinkheight": 128 - 7,
            "startdx": 7
        },
        {
            "color": "rgb(255, 102, 0)",
            "strokewidth": "14px",
            "linecap": "round",
            "startpoint": 14.7,
            "endpoint": 14.7,
            "startlinkheight": 0 - 7,
            "endlinkheight": 64 + 7,
            "startdx": 7,
            "enddx": 7
        },
        {
            "color": "rgb(255, 102, 0)",
            "strokewidth": "14px",
            "linecap": "round",
            "startpoint": 14.25,
            "endpoint": 14.7,
            "startlinkheight": -64 - 7,
            "endlinkheight": 0 - 7,
            "enddx": 7
        },
        {
            "color": "rgb(255, 102, 0)",
            "strokewidth": "14px",
            "linecap": "round",
            "startpoint": 14.25,
            "endpoint": 14.7,
            "startlinkheight": 128 + 7,
            "endlinkheight": 64 + 7,
            "enddx": 7
        },
        {
            "color": "rgb(85, 85, 86)",
            "strokewidth": "14px",
            "linecap": "round",
            "startpoint": 14.7,
            "endpoint": 14.7,
            "startlinkheight": 0 - 2,
            "endlinkheight": 64 + 2,
            "startdx": -7,
            "enddx": -7
        },
        {
            "color": "rgb(85, 85, 86)",
            "strokewidth": "14px",
            "linecap": "round",
            "startpoint": 14.7,
            "endpoint": 14.20,
            "startlinkheight": 0 - 2,
            "endlinkheight": -64 + 7,
            "startdx": -7
        },
        {
            "color": "rgb(85, 85, 86)",
            "strokewidth": "14px",
            "linecap": "round",
            "startpoint": 14.7,
            "endpoint": 14.20,
            "startlinkheight": 64 + 2,
            "endlinkheight": 128 - 7,
            "startdx": -7
        }
    ],
    "stationtypes": [
        {
            "stypeID": "STATION_TYPE_GLASGOW",
            "stnnodes": [
                {
                    "stationradius": 7,
                    "stationstrokewidth": 0,
                    "fcolor": "white",
                    "scolor": "none"
                }
            ]
        }
    ],
    "stations": [
        {
            "name": ["Govan"],
            "stationtype": "STATION_TYPE_GLASGOW",
            "icons": [
            ],
            "xshift": 0.5,
            "dy": 128
        },
        {
            "name": ["Ibrox"],
            "stationtype": "STATION_TYPE_GLASGOW",
            "icons": [
            ],
            "xshift": 0.5,
            "dy": 128
        },
        {
            "name": ["Cessnock"],
            "stationtype": "STATION_TYPE_GLASGOW",
            "icons": [
            ],
            "xshift": 0.5,
            "dy": 128
        },
        {
            "name": ["Kinning Park"],
            "stationtype": "STATION_TYPE_GLASGOW",
            "icons": [
            ],
            "xshift": 0.5,
            "dy": 128
        },
        {
            "name": ["Shields Road"],
            "stationtype": "STATION_TYPE_GLASGOW",
            "icons": [
            ],
            "xshift": 0.5,
            "dy": 128
        },
        {
            "name": ["West Street"],
            "stationtype": "STATION_TYPE_GLASGOW",
            "icons": [
            ],
            "xshift": 0.5,
            "dy": 128
        },
        {
            "name": ["Bridge Street"],
            "stationtype": "STATION_TYPE_GLASGOW",
            "icons": [
            ],
            "xshift": 0.5,
            "dy": 128
        },
        {
            "name": ["St. Enoch"],
            "stationtype": "STATION_TYPE_GLASGOW",
            "icons": [
            ],
            "dy": -64
        },
        {
            "name": ["Buchanan Street"],
            "stationtype": "STATION_TYPE_GLASGOW",
            "icons": [
            ],
            "xshift": -2,
            "dy": -64
        },
        {
            "name": ["Cowcaddens"],
            "stationtype": "STATION_TYPE_GLASGOW",
            "icons": [
            ],
            "xshift": -4,
            "dy": -64
        },
        {
            "name": ["St. George's Cross"],
            "stationtype": "STATION_TYPE_GLASGOW",
            "icons": [
            ],
            "xshift": -6,
            "dy": -64
        },
        {
            "name": ["Kelvinbridge"],
            "stationtype": "STATION_TYPE_GLASGOW",
            "icons": [
            ],
            "xshift": -8,
            "dy": -64
        },
        {
            "name": ["Hillhead"],
            "stationtype": "STATION_TYPE_GLASGOW",
            "icons": [
            ],
            "xshift": -10,
            "dy": -64
        },
        {
            "name": ["Kelvinhall"],
            "stationtype": "STATION_TYPE_GLASGOW",
            "icons": [
            ],
            "xshift": -12,
            "dy": -64
        },
        {
            "name": ["Partick"],
            "stationtype": "STATION_TYPE_GLASGOW",
            "icons": [
            ],
            "xshift": -14,
            "dy": -64
        }
    ]
};