g | x | w | all
Bytes Lang Time Link
334Haskell171129T032221ZHjulle
536Node170413T202436ZNeil
129CJam170413T023500Zaditsu q
632Python 3170412T212331Zhyperneu
820PHP>=7.1170412T011014ZJör

Haskell, 388 340 338 334

-52 (!) bytes thanks to Ørjan Johansen

import Data.Bits
import Data.Array
(&)=(,)
z=maximum
r x=[minimum x..z x-1]
l=map(+1).r
e(a:b:c:d:q)=[x&y&n|((f,g),n)<-[id&l&1,id&r&2,l&id&4,r&id&8],x<-f[a,b],y<-g[c,d]]++e q;e[]=[]
f a|l<-[1..z a]=unlines[[" UD│L┘┐┤R└┌├─┴┬┼"!!(accumArray(.|.)0(1&1,z a&z a)(e a)!(x,y))|x<-l]|y<-l]
main=interact$f.map read.words

Try it online!

Ungolfed

import Data.Bits
import Data.Array
import Data.List.Split

(&) = (,) -- Alias for tuples

-- Given [a,b], returns a list of all x: a <= x < b 
halfOpenLeft x = [minimum x..maximum x-1::Int]
r = halfOpenLeft

-- Same as above, but for all x: a < x <= b
halfOpenRight = map(+1).halfOpenLeft
l = halfOpenRight

up    = ((id, halfOpenRight), 0) -- Coordinates that should have a line upwards
down  = ((id, halfOpenLeft),  1) -- Coordinates that should have a line downwards
left  = ((halfOpenRight, id), 2) -- Coordinates that should have a line leftwards
right = ((halfOpenLeft, id),  3) -- Coordinates that should have a line rightwards
-- [up, down, left, right] = [id&l&1,id&r&2,l&id&4,r&id&8]

-- Create a map between coordinates and line-segments. Each coordinate can have multiple line-segments.
lineSegments :: [[Int]] -> [((Int,Int),Int)]
lineSegments rects = [ ((x,y),n) | [x1,x2,y1,y2] <- rects, ((f,g),n) <- [up,down,left,right], x <- f [x1,x2], y <- g [y1,y2]]

-- Convert an array of bit-fields into a list of lines. 
printBitfieldArray :: Int -> Array (Int,Int) Int -> [String]
printBitfieldArray size a = [[" UD│L┘┐┤R└┌├─┴┬┼"!!(a!(x,y))|x<-[1..size]]|y<-[1..size]]

-- Merge all the line-segments for each coordinate into a bitfield
createBitFieldArray :: Int -> [((Int,Int),Int)] -> Array (Int,Int) Int
createBitFieldArray m = accumArray setBit 0 ((1,1),(m,m))

-- First split the input for each rectangle,
-- then create a list of pairs of coordinates and directions,
-- then merge all directions for each coordinate into a bitfield
-- and finally use the bitfield as an index to find out which shape to draw.
drawRectangles :: Int -> [Int] -> [String]
drawRectangles m=printBitFieldArray m.createBitFieldArray m.lineSegments.chunksOf 4

-- Parse the input, solve the problem and format the output. Use the largest number as both width and height.
main=interact$unlines.(drawRectangles=<<maximum).map read.words

Explanation

  1. First, lineSegments (or d in the golfed version) will loop over all rectangles, all directions and all coordinates that should have a line-segment in that direction from that rectangle and create a list of coordinates paired with directions.
  2. Then createBitFieldArry merges all entries with identical coordinates into an array of bitfields. Here, the 0th bit means up, 1st means down, 2nd means left and the 3rd means right. In other words, 5 is rendered as "┘", 0 is " " and 15 is "┼".
  3. Lastly, printBitFieldArray (or p) converts the bitfields into box-drawing characters by using them as indices.

Node, 536 bytes

s=''
with(process.stdin){setEncoding('utf8')
on('readable',_=>s+=read()||'')
on('end',_=>{a=s.match(/(\d+\s+){3}\d+/g).map(s=>s.match(/\d+/g).map(m=>+m)).map(([m,n,o,p])=>[m>n?n:m,m>n?m:n,o>p?p:o,o>p?o:p])
m=i=>[...Array(Math.max(...a.map(a=>a[i])))]
console.log(m(3).map((_,y)=>m(1).map((_,x)=>' ??┘?│┐┤?└─┴┌├┬┼'[x++,a.some(([m,n,o,p])=>x==m|x==n&&y>o&y<=p)+2*a.some(([m,n,o,p])=>y==o|y==p&&x>m&x<=n)+4*a.some(([m,n,o,p])=>x==m|x==n&&y>=o&y<p)+8*a.some(([m,n,o,p])=>y==o|y==p&&x>=m&x<n)],y++).join``).join`\n`)})}

Directly calculates the correct character at each coordinate. Input is annoying to perform in Node...

CJam, 129

0a80*a25*[q~]4/{:(2/:$_::-+e_534915808 6b3/\ff=C2b.+{):A;)z{_A)+\[A!A].+_A)4*+\}*;}%{~:A;_3$=@_2$=A|tt}/}/"   ┌ ─┐┬ └│├┘┴┤┼"ff=N*

Try it online

Notes:

Overview:

0a80*a25* creates a matrix of 80×25 zeros
[q~]4/ reads the input, converts to numbers and splits into quadruplets
:(2/:$_::-+e_ converts an [x1 x2 y1 y2] quadruplet to [xmin xmax ymin ymax -width -height] (negative values will be corrected later)
534915808 6b3/ generates [[1 2 5] [0 2 5] [0 3 4] [0 2 4]], to be used as indices in the previous array for extracting data about the 4 sides of the current box
\ff= extracts the data for each side, e.g. [1 2 5] -> [xmax ymin -height] for the right side
C2b.+ appends 1, 1, 0, 0 respectively to the arrays for the 4 sides (right, left, bottom, top); this number indicates the direction (0=horizontal, 1=vertical)
):A;)z{_A)+\[A!A].+_A)4*+\}*; generates line pieces for a side, as [x y bitmask] triplets; each piece is a line going from the center of the cell to one of 4 directions: 1=right, 2=bottom, 4=left, 8=top; e.g. [4 2 -3 0] (a horizontal line of length 3 starting at x=4, y=2) results in [4 2 1] [5 2 4] [5 2 1] [6 2 4] [6 2 1] [7 2 4]
{~:A;_3$=@_2$=A|tt}/ bitwise-OR's all these line pieces into the matrix, resulting in bitmasks from 0..15
" ┌ ─┐┬ └│├┘┴┤┼"ff= converts these bitmasks to the corresponding box-drawing characters
N* joins with newlines for display

Python 3, 632 bytes

i=input()
j=''
while i:j+=i+' ';i=input()
c=[int(k)-1for k in j.split()]
c=[c[k:k+4]for k in range(0,len(c),4)]
for q in c:
    for v,w in[(0,1),(2,3)]:
        if q[w]<q[v]:t=q[w];q[w]=q[v];q[v]=t
d=list(zip(*c))
w=max(d[1])+1
h=max(d[3])+1
g=[0]*w*h
def i(a,b,f):
    for k in b:
        for l in a:g[k*w+l]|=f[0];f=f[1:]
def p(k,l,m,n,o,j=0):
    for i in range(m,n,o):l[i]|=k
    if j:p(k,l,m+j,n+j,o)
for q in c:i(q[:2],q[2:],[6,12,3,9]);p(10,g,q[0]+1+q[2]*w,q[1]+q[2]*w,1,(q[3]-q[2])*w);p(5,g,q[0]+q[2]*w+w,q[0]+q[3]*w,w,q[1]-q[0])
print('\n'.join(map(lambda k: ''.join(map(lambda x: '   └ │┌├ ┘─┴┐┤┬┼'[x], k)),[g[x:x+w]for x in range(0,len(g),w)])))

PHP>=7.1, 820 Bytes

<?preg_match_all("#(\d+(\s+\d+){3})#s",$_GET[0],$t);$r=($w="array_fill")(1,25,$w(1,80," "));function u($n,$y,$x){global$r;$u=[$z=[" ","│",$c="┤","┐","└",$d="┴",$e="┬",$b="├","─","┘","┌",$a="┼"],["│",$c,$b,$a],[$c,$a],["┐",$c,$e,$a],["└",$d,$b,$a],[$d,$a],[$e,$a],[$b,$a],["─",$d,$e,$a],["┘",$c,$d,$a],["┌",$e,$b,$a],[$a]];$o=$r[$y][$x];$s=array_intersect($u[($k="array_search")($n,$z)],$u[$k($o,$z)]);$r[$y][$x]=reset($s);}foreach($t[1]as$e){[$a,$b,$c,$d]=explode(" ",preg_replace("#\s+#"," ",$e));u("┌",$h=min($c,$d),$f=min($a,$b));u("┐",$h,$g=max($a,$b));u("└",$i=max($c,$d),$f);u("┘",$i,$g);foreach(($l="array_slice")(range($f,$g),1,-1)as$x){u("─",$h,$x);u("─",$i,$x);}foreach($l(range($h,$i),1,-1)as$y){u("│",$y,$f);u("│",$y,$g);}}foreach($r as$v)echo join($v)."\n";

-6 Bytes for use "array_fill","array_search", "array_slice" without "

+19 Bytes echo ltrim(rtrim(join($v))."\n","\n"); instead of echo join($v)."\n"; to print only the necessary Chars

Online Version

Expanded

preg_match_all("#(\d+(\s+\d+){3})#s",$_GET[0],$t); # find all rects
$r=($w="array_fill")(1,25,$w(1,80," ")); # fill a empty 2 D array with spaces 
function u($n,$y,$x){ # Char , Y Coordinate, X Coordinate as parameter
global$r; # result array must be global to make changes
# The following array based on Set Theory
$u=[
$z=[" ","│",$c="┤","┐","└",$d="┴",$e="┬",$b="├","─","┘","┌",$a="┼"],
["│",$c,$b,$a],
[$c,$a],
["┐",$c,$e,$a],
["└",$d,$b,$a],
[$d,$a],
[$e,$a],
[$b,$a],
["─",$d,$e,$a],
["┘",$c,$d,$a],
["┌",$e,$b,$a]
,[$a]];
$o=$r[$y][$x]; # old value for YX
$s=array_intersect($u[($k="array_search")($n,$z)],$u[$k($o,$z)]); # make the Cut quantity
$r[$y][$x]=reset($s); # Take the first value Cut quantity and set it as new value
}
foreach($t[1]as$e){ # for each rect
[$a,$b,$c,$d]=explode(" ",preg_replace("#\s+#"," ",$e)); #split the four coordinates
# next 4 rows make edges and set minimum and maximum for X an Y values
u("┌",$h=min($c,$d),$f=min($a,$b)); 
u("┐",$h,$g=max($a,$b));
u("└",$i=max($c,$d),$f);
u("┘",$i,$g);
foreach(($l="array_slice")(range($f,$g),1,-1)as$x){u("─",$h,$x);u("─",$i,$x);} # make the X lines
foreach($l(range($h,$i),1,-1)as$y){u("│",$y,$f);u("│",$y,$g);} # make the  Y lines
}
foreach($r as$v)echo join($v)."\n"; # Output

Order of the array Set Theory

foreach($u as $k0=>$v0)
foreach($u as $k1=>$v1)
echo "\n\n'".$z[$k0]."' + '".$z[$k1]."' = '". join("','",array_intersect($v0,$v1))."'";

Examples Set Theory all possible values

The array without the use of variables to short it

$u=[
$z=[" ","│","┤","┐","└","┴","┬","├","─","┘","┌","┼"],
["│","┤","├","┼"],
["┤","┼",],
["┐","┤","┬","┼"],
["└","┴","├","┼"],
["┴","┼"],
["┬","┼"],
["├","┼"],
["─","┴","┬","┼"],
["┘","┤","┴","┼"],
["┌","┬","├","┼"]
,["┼"]];');