Measuring Rectangles Challenge

Your goal is to write a program which will output the 8 measurements of a rectangle, with only some measurements in the input. Your program should throw an error if it cant be done.

Here is what each measurement means:

|          left
|          |      centerX
|          |      |      right
|          |      |      |
|          v      v      v
|           _____________ 
|       ^  |             |  &lt;---top 
|       |  |             |
|       |  |             | 
|height |  |             |  &lt;---centerY
|       |  |             | 
|       |  |             |
|       v  |_____________|  &lt;---bottom 
|                             
|          &lt;----width----&gt;      
|________________________________________


Input/Output Formats:

Input is in the form of some measurements of a box, one on each line. Output should be all 8 measurements of the corresponding box (or an error if the given measurements can not be used to find the other measurements).

For example, an input of 

left 6
centerX 10
top 40
height 20


should print out

left 6
right 14
top 40
bottom 20
centerX 10
centerY 30
width 8
height 20


This is code-golf, so the shortest code wins.
Python 2 with SWI Prolog ('typical' install), on Windows, 595 565 bytes.
import sys,subprocess as w;o='left right top bottom centerX centerY width height'
g={k:v for k,v in [l.strip().split() for l in sys.stdin.readlines()]};s='L,R,T,B,C,D,W,H';
open('t','w').write(
&quot;:-use_module(library(clpfd)).\nr(%s):-L#=R-2*(R-C),L#=R-W,L#=C-W//2,B#=T-2*(T-D),B#=T-H,B#=D-H//2,%s.&quot;%
(s,','.join('writeln(%s)'%x for x in s.split(','))));r='\n'.join([a+' '+b for (
a,b) in zip(o.split(),w.check_output(&quot;swipl -q -f t -t r(%s).&quot;%(','.join(g.get(
x,x[0].replace('centerY','d').upper()) for x in o.split()))).split('\r\n'))])
print '!' if '_' in r else r

e.g. with a text file for input, containing:
right 14
centerX 10
top 40
height 20

it does this:
D:\&gt;type rectin.txt|c:\python27\python.exe d:\rect.py
left 6
right 14
top 40
bottom 20
centerX 10
centerY 30
width 8
height 20

And in the error condition if the contents of the stdin file are not enough to calculate the other values, it does this:
D:\&gt;type rectin.txt|c:\python27\python.exe d:\rect.py
!

NB. It relies on swipl.exe being in the PATH
Explanation
I started writing in Python, got bored of expressing all the possible combinations of relationship (each one can be derived from three different combinations). I thought &quot;must be a job for Prolog&quot;. So I installed a Prolog, headed for a tutorial, and got something that just about works. It's this:
:-use_module(library(clpfd)).

r(L,R,T,B,C,D,W,H):-
    L#=R-2*(R-C),
    L#=R-W,
    L#=C-W//2,
    B#=T-2*(T-D),
    B#=T-H,
    B#=D-H//2,

    writeln(L),
    writeln(R),
    writeln(T),
    writeln(B),
    writeln(C),
    writeln(D),
    writeln(W),
    writeln(H).

It uses the clpfd library (part of the 'typical install' requirement), which provides 'declarative integer arithmetic'. This gives the big advantage that I only need to define Left in terms of (Right and CenterX), (Right and Width), (CenterX and Width). From that, it can derive Right, Center and Width. (Same with the vertical set Top/Bottom/CenterY/Height).
This also means I don't have to check which specific values are provided; I give all the available values and placeholders for the rest, and it either calculates the answers, or outputs some unknown variable placeholders.
Being extremely novice at Prolog, handling STDIN was too much for me right now, so I wrapped it with Python. I don't have an ungolfed version of the Python, but it's not doing anything too amazing; it reads STDIN into a dictionary of {measurement:value} pairs, then puts them in the preset order the Prolog code is expecting, merged with the uppercase first letter of the unknowns.
(There's an annoyance where all the measurements are unique by first letter, except centerX and centerY, so it replaces centerY with D).
Then it writes the Prolog script out to a file, shells out to Prolog to run it and read the result, parses the number output and pairs them up with the measurements in order.
Then checks if any of the outputs were uncomputable and throws an error (!), otherwise prints the result.