def segments_intersect_or_coincide(a, b, c, d):
    """Return True if segments intersect or coincide"""

    def overlapping():
        if ((c.x < a.x < d.x) or (c.x < b.x < d.x) or
                (c.y < a.y < d.y) or (c.y < b.y < d.y) or
                (c in (a, b)) or (d in (a, b))):
            return True
        else:
            return False

    denom = (b.x - a.x) * (d.y - c.y) - (b.y - a.y) * (d.x - c.x)
    tnumerator = (a.y - c.y) * (d.x - c.x) - (a.x - c.x) * (d.y - c.y)
    if denom == 0:  # if segments coincident or parallel
        if tnumerator == 0 and overlapping():  # if coincident and overlapping
            return True
        else:  # ...else parallel or nonoverlapping
            return False
    # now we know an intersection exists
    t = tnumerator / denom
    u = ((a.y - c.y) * (b.x - a.x) - (a.x - c.x) * (b.y - a.y)) / denom
    if (0 <= t <= 1) and (0 <= u <= 1):  # if intersection is not on extension
        return True  # of either segment
    return False