4-way intersection generator
Javascript (ES6), 190 187 185 bytes

This is an attempt to build this ASCII art character per character by iterating on a 17x15 matrix. Therefore, the output is always made of 15 rows of 17 columns with the intersection of the roads centered in the middle.

p=&gt;eval("for(y=15,s='';y--;s+=`\n`)for(x=17;x--;)s+=' |-+'[+[a=y&gt;4,b=y&lt;10,c=x&gt;4,d=x&lt;12].every((c,i)=&gt;c|p.search('SNEW'[i])+1)&amp;&amp;!((z=x-8||y&amp;1|a&amp;b)&amp;&amp;z*z-9)+2*!((z=y-7||x&amp;1|c&amp;d)&amp;&amp;z*z-4)]")


Ungolfed and commented

for(y = 15, s = ''; y--; s += `\n`)   // iterate on y, from 14 to 0 / append line feeds
  for(x = 17; x--;)                   // iterate on x, from 16 to 0
    s += ' |-+' [                     // append next character to string
      +[ a = y &gt; 4,                   // a = outside South area?
         b = y &lt; 10,                  // b = outside North area?
         c = x &gt; 4,                   // c = outside East area?
         d = x &lt; 12 ]                 // d = outside West area?
      .every((c, i) =&gt;                // for each area, see if either:
        c |                           //   - we're currently outside it
        p.search('SNEW' [i]) + 1      //   - or it's an allowed area (p = function param.)
      )                               // if all tests pass, add a:
      &amp;&amp;                              //   - vertical bar (encoded as 1) if:
      !((z = x - 8 || y &amp; 1 | a &amp; b)  //     - x=8, y is even and we're not in the middle
      &amp;&amp; z * z - 9)                   //     - OR x=5 OR x=11 (&lt;=&gt; (x-8)*(x-8) = 9)
      + 2 *                           //   - horizontal bar (encoded as 2) if:
      !((z = y - 7 || x &amp; 1 | c &amp; d)  //     - y=7, x is even and we're not in the middle
      &amp;&amp; z * z - 4)                   //     - OR y=5 OR y=9 (&lt;=&gt; (y-7)*(y-7) = 4)
    ]                                 // (vertical + horizontal = 3, which leads to '+')


Matrix

Below is the matrix with the coordinates used in the code.



Demo

The following snippet allows to try any road configuration.



let f =
p=&gt;eval("for(y=15,s='';y--;s+=`\n`)for(x=17;x--;)s+=' |-+'[+[a=y&gt;4,b=y&lt;10,c=x&gt;4,d=x&lt;12].every((c,i)=&gt;c|p.search('SNEW'[i])+1)&amp;&amp;!((z=x-8||y&amp;1|a&amp;b)&amp;&amp;z*z-9)+2*!((z=y-7||x&amp;1|c&amp;d)&amp;&amp;z*z-4)]")

function update() {
  document.getElementById("o").innerHTML = f(document.getElementById("s").value);
}
update();
&lt;input id="s" size=4 value="NSEW" oninput="update()"&gt;
&lt;pre id="o" style="font-size:9px"&gt;&lt;/pre&gt;