I tried to fix what was amiss in your adaptation of \shape, but I didn't get very far. This problem seems very complex, and I was only able to get results by "starting from the ground up" -- namely, adding to the function I initially sent. It's awfully compressed. Hopefully, this is another step in the right direction.
\version "2.15.40"
shapeTieColumn =
#(define-music-function (parser location all-offsets) (list?)
#{
\override TieColumn #'after-line-breaking =
#(lambda (grob)
(let ((ties (ly:grob-array->list (ly:grob-object grob 'ties))))
(for-each
(lambda (tie offsets-for-broken-pair)
(let* ((orig (ly:grob-original tie))
(siblings (ly:spanner-broken-into orig)))
(for-each
(lambda (piece offsets-for-piece)
(if (pair? offsets-for-piece)
(set! (ly:grob-property piece 'control-points)
(map
(lambda (x y) (coord-translate x y))
(ly:tie::calc-control-points piece)
offsets-for-piece))))
(if (null? siblings)
(list orig)
siblings)
offsets-for-broken-pair)))
ties all-offsets)))
#})
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
{
<d' e' g' a'>1 ~ q
q ~
\shapeTieColumn #'(
( ((0 . 0) (0 . -1) (0 . -1) (0 . 0)) ) ; (bottom) first half only
() ; or ( () () ) = skip
( ((0 . 0) (-0.25 . 0.5) (0.25 . 0.5) (0 . 0))
((0 . 0) (-0.25 . 0.5) (0.25 . 0.5) (0 . 0)) ) ; both halves
( () ((0 . 0) (0 . 1) (0 . 1) (0 . 0)) ) ; (top) second half only
)
\break
q
}
\layout {
ragged-right = ##t
}