docs: def line_segment_intersection_2D(p12arg, p34arg):
      '''
      line_segment_intersection((a, b), (c, d)) yields the intersection point between the line
      passing through points a and b and the line segment that passes from point c to point d. If
      there is no intersection point, then (numpy.nan, numpy.nan) is returned.
      '''
      (p1,p2) = p12arg
      (p3,p4) = p34arg
      pi = np.asarray(line_intersection_2D(p12arg, p34arg))
      p3 = np.asarray(p3)
      u34 = p4 - p3
      cfn = lambda px,iis: (px if iis is None or len(px.shape) == 1 or px.shape[1] == len(iis) else
                            px[:,iis])
      dfn = lambda a,b:     a[0]*b[0] + a[1]*b[1]
      sfn = lambda a,b:     ((a-b)                 if len(a.shape) == len(b.shape) else
                             (np.transpose([a])-b) if len(a.shape) <  len(b.shape) else
                             (a - np.transpose([b])))
      fn  = lambda px,iis:  (1 - ((dfn(cfn(u34,iis), sfn(         px, cfn(p3,iis))) > 0) *
                                  (dfn(cfn(u34,iis), sfn(cfn(p4,iis),          px)) > 0)))
      if len(pi.shape) == 1:
          if not np.isfinite(pi[0]): return (np.nan, np.nan)
          bad = fn(pi, None)
          return (np.nan, np.nan) if bad else pi
      else:
          nonpar = np.where(np.isfinite(pi[0]))[0]
          bad = fn(cfn(pi, nonpar), nonpar)
          (xi,yi) = pi
          bad = nonpar[np.where(bad)[0]]
          xi[bad] = np.nan
          yi[bad] = np.nan
          return (xi,yi)