Draw Translucent Boxes

note: the string art might look horrible here because of SE font weirdness :P :(

Given a list of four-tuples representing the corners of rectangles, draw translucent rectangles over each other in that order.

For this challenge, you are required to have the smallest coordinate in the top-left corner and the x-axis increasing to the right and the y-axis increasing downwards.

A four-tuple (x0, y0, x1, y1) or (x0, x1, y0, y1) represents the (x, y) coordinate pairs of the top-left and bottom-right corners of a rectangle (you may choose either of the two formats for rectangles but it must be consistent)

What do I mean by "translucent rectangle"? Well, for this challenge, you will be using the space character and most of the box-drawing characters; specifically, all of the ones used to draw rectangles, including "bold" characters. When a translucent rectangle is drawn, first all thin lines in the space being occupied disappear and all bold lines become thin, and then the rectangle itself is drawn over in bold lines.

For example, if you draw a rectangle in the top-left and then in the bottom-right, it might look something like this:

┏━━━━┓
┃    ┃
┃    ┃
┃ ┏━━╇━━┓
┃ ┃  │  ┃
┗━╉──┘  ┃
┃     ┃
┃     ┃
┗━━━━━┛


To be clear, lines are lightened (bold -> thin -> none) for all lines strictly within the rectangle (for example, downwards facing lines are affected for the top edge but not the bottom edge).

Test Cases

Some number of lines of input will be given, followed by unicode-art, for each test case.

0 0 5 5
5 5 10 10
3 3 7 7
2 2 8 8

┏━━━━┓
┃    ┃
┃ ┏━━╇━━┓
┃ ┃┌─┴─┐┃
┃ ┃│   │┃
┗━╉┤   ├╊━┓
┃│   │┃ ┃
┃└─┬─┘┃ ┃
┗━━╈━━┛ ┃
┃    ┃
┗━━━━┛

14 5 15 9
13 2 15 16
6 4 15 11

┏━┓
┃ ┃
┏━━━━━━╇━┫
┃      │ ┃
┃      │ ┃
┃      │ ┃
┃      │ ┃
┃      │ ┃
┃      │ ┃
┗━━━━━━╈━┫
┃ ┃
┃ ┃
┃ ┃
┃ ┃
┗━┛

6 8 10 11
15 12 16 16
14 10 16 16
9 1 15 15

┏━━━━━┓
┃     ┃
┃     ┃
┃     ┃
┃     ┃
┃     ┃
┃     ┃
┏━━╉┐    ┃
┃  ┃│    ┃
┃  ┃│   ┌╊┓
┗━━╉┘   │┃┃
┃    │┠┨
┃    │┃┃
┃    │┃┃
┗━━━━╈┩┃
┗┷┛


Generate more test cases!

Rules

• Input can be in any reasonable format for a list of four-tuples. Input can be one-indexed or zero-indexed along either axis (i.e. the top-left corner can be any of (0, 0), (0, 1), (1, 0), (1, 1).
• Output must be as unicode-art as described. Output may not have leading newlines and can have at most one trailing newline (after the last line). Trailing whitespace will be ignored for the purposes of this challenge.

Code-points

The bold and light horizontal and vertical pipes are in the range [U+2500, U+2503]. The various corner pipes are in the range [U+250C, U+251C). The three-armed pipes are in the range [U+251C, U+253C). The four-armed pipes are in the range [U+253C, U+254C). The remaining pipes that can be found in my program are never actually used.

• Is this really ascii art? Aside from spaces, it doesn't use any ascii characters. – caird coinheringaahing Sep 11 '17 at 14:04
• @cairdcoinheringaahing From the ascii-art info, Typically this uses only 95 printable (from a total of 128) characters defined by the ASCII Standard from 1963. – totallyhuman Sep 11 '17 at 14:05
• @cairdcoinheringaahing codegolf.meta.stackexchange.com/questions/10218/… – HyperNeutrino Sep 11 '17 at 14:05
• can we use the character b/w 220 - 223 from here ? for the bold lines dochome.programbl.com/dochome/sites/default/files/image169.png – Mukul Kumar Sep 12 '17 at 6:14
• @MukulKumar No, you must use those exact characters. You are allowed to take any unduplicated substring of any permutation of the entire set of characters as input so you don't have to waste bytes/chars hardcoding the characters in. – HyperNeutrino Sep 14 '17 at 12:01

Python 3, 289 286 bytes

l,u=eval(input())
*_,w,h=map(max,zip(*l))
r=[*map(list,[' '*-~w]*-~h)]
R=range
for x,y,X,Y in l:
for i in R(x,X+1):
for j in R(y,Y+1):Q=i<X,y<j,x<i,j<Y;r[j][i]=u[sum(3**o*max(Q[o]*[j in(y,Y),i in(x,X)][o%2]*2,u.index(r[j][i])//3**o%3-Q[o])for o in R(4))]
for l in r:print(''.join(l))


Try it online!

Takes input as a list of 4-tuples: (x0, y0, x1, y1), along with the pipedrawing characters as follows: " ╶╺╵└┕╹┖┗╴─╼┘┴┶┚┸┺╸╾━┙┵┷┛┹┻╷┌┍│├┝╿┞┡┐┬┮┤┼┾┦╀╄┑┭┯┥┽┿┩╃╇╻┎┏╽┟┢┃┠┣┒┰┲┧╁╆┨╂╊┓┱┳┪╅╈┫╉╋"

Supports boxes of zero width or height (uses all box drawing chars).

Based on my answer to this question, but modified to alter existing boxes when drawing.

'Ungolfed':

u=" ╶╺╵└┕╹┖┗╴─╼┘┴┶┚┸┺╸╾━┙┵┷┛┹┻╷┌┍│├┝╿┞┡┐┬┮┤┼┾┦╀╄┑┭┯┥┽┿┩╃╇╻┎┏╽┟┢┃┠┣┒┰┲┧╁╆┨╂╊┓┱┳┪╅╈┫╉╋"

#Create array of spaces:
l=eval(input())
w,h=list(map(max,zip(*l)))[2:]
r=[[' ']*w for _ in' '*h]

for x,y,X,Y in l:
n,m=X-1,Y-1
for i in range(x,X):
for j in range(y,Y):
A,B=j in(y,m),i in(x,n)
P=(i<n*A,y<j*B,x<i*A,j<m*B)   # Pipe sides of the new box
Q=(i<n,y<j,x<i,j<m)           # Pipe sides that are inside the new box, and should be thinned.
# Get new pipe (sides of new box, on top of thinned pipes of existing boxes. (u.index... is existing pipe))
l=sum(3**o*max(P[o]*2,(u.index(r[j][i])//3**o%3)-Q[o])for o in range(4))
r[j][i]=u[l]

print('\n'.join(''.join(l)for l in r))

• You can take u as input. – HyperNeutrino Sep 14 '17 at 11:59
• @HyperNeutrino thanks :) – TFeld Sep 14 '17 at 12:11
• You can save a byte by starring your unnecessary variable, replacing _,_,w,h= with *_,w,h=. – Jonathan Frech Sep 15 '17 at 0:31
• Also, your tuple assignment to Q does not need any parentheses, Q=(i<X,y<j,x<i,j<Y); can be replaced with Q=i<X,y<j,x<i,j<Y; for two saved bytes. – Jonathan Frech Sep 15 '17 at 0:34
• @JonathanFrech Thanks :) – TFeld Sep 15 '17 at 6:18

JavaScript (ES6), 298 261 bytes

(a,u,m=n=>[...Array(1+Math.max(...a.map(t=>t[n])))])=>m(3).map((_,j)=>m(2).map((_,i)=>u[a.reduce((c,[x,y,v,w])=>i<x|j<y|i>v|j>w?c:(g=n=>c-=c/n%3|0&&n,h=n=>c+=n*(2-(c/n%3|0)),[i>x&&9,i<v].map(j>y&j<w?g:h),[j>y&&3,j<w&&27].map(i>x&i<v?g:h),c),0)]).join).join\n


Where \n represents the literal newline character. Based on my answer to Unicode rectangles. Explanation: An array of strings of spaces is created to draw in. Each spaces is then processed by looping over all the boxes in the input. Characters that lie outside of the box are then ignored but those on the edge or inside are processed further. For each of the four line segments making up a character (each represented by a power of 3) there are then three possibilities; a) the segment lies just outside the box and should be ignored (achieved by passing a parameter of 0 instead of the power of 3) b) the segment lies on the edge of the box and should be bold (achieved by calling the h function) c) the segment lies inside the box and should be lightened (achieved be calling the g function). The character is then indexed into the Unicode string. Once all the boxes have been processed the array is then joined on newlines.

f=
(a,u,m=n=>[...Array(1+Math.max(...a.map(t=>t[n])))])=>m(3).map((_,j)=>m(2).map((_,i)=>u[a.reduce((c,[x,y,v,w])=>i<x|j<y|i>v|j>w?c:(g=n=>c-=c/n%3|0&&n,h=n=>c+=n*(2-(c/n%3|0)),[i>x&&9,i<v].map(j>y&j<w?g:h),[j>y&&3,j<w&&27].map(i>x&i<v?g:h),c),0)]).join).join

;u=" ╶╺╵└┕╹┖┗╴─╼┘┴┶┚┸┺╸╾━┙┵┷┛┹┻╷┌┍│├┝╿┞┡┐┬┮┤┼┾┦╀╄┑┭┯┥┽┿┩╃╇╻┎┏╽┟┢┃┠┣┒┰┲┧╁╆┨╂╊┓┱┳┪╅╈┫╉╋";
[[
[0, 0, 5, 5],
[5, 5, 10, 10],
[3, 3, 7, 7],
[2, 2, 8, 8],
],[
[14, 5, 15, 9],
[13, 2, 15, 16],
[6, 4, 15, 11],
],[
[6, 8, 10, 11],
[15, 12, 16, 16],
[14, 10, 16, 16],
[9, 1, 15, 15],
]].map(a=>document.write(<pre style="font-family:Consolas,Menlo,Monaco,Lucida Console,Liberation Mono,DejaVu Sans Mono,Bitstream Vera Sans Mono,Courier New,monospace,sans-serif">\${f(a,u)}</pre>));