@pimms.value<EOL><INDENT>def edge_data(addresses, closed):<DEDENT>
<EOL>(faces, coords) = address_data(addresses, <NUM_LIT:2>)<EOL>coords = np.vstack([coords, [<NUM_LIT:1> - np.sum(coords, axis=<NUM_LIT:0>)]])<EOL>n = faces.shape[<NUM_LIT:1>]<EOL>(u,v,wu,wv,fs,ps) = ([],[],[],[], [], [])<EOL>pcur = []<EOL>lastf = faces[:, -<NUM_LIT:1>] if closed else None<EOL>maxv = np.max(faces) + <NUM_LIT:1><EOL>mtx = sps.dok_matrix((maxv,maxv))<EOL>for (ii,f,w) in zip(range(n), faces.T, coords.T):<EOL><INDENT>zs = np.isclose(w, <NUM_LIT:0>, atol=<NUM_LIT>)<EOL>nz = np.sum(zs)<EOL>pcur.append(ii)<EOL>if nz == <NUM_LIT:0>: <EOL><INDENT>lastf = f<EOL>continue<EOL><DEDENT>elif nz == <NUM_LIT:2>: <EOL><INDENT>vtx = f[~zs][<NUM_LIT:0>]<EOL>for q in [u,v]:   q.append(vtx)<EOL>for q in [wu,wv]: q.append(<NUM_LIT:0.5>)<EOL><DEDENT>elif nz == <NUM_LIT:1>: <EOL><INDENT>k = [<NUM_LIT:0>,<NUM_LIT:1>] if zs[<NUM_LIT:2>] else [<NUM_LIT:1>,<NUM_LIT:2>] if zs[<NUM_LIT:0>] else [<NUM_LIT:2>,<NUM_LIT:0>]<EOL>rev = <NUM_LIT:5> if lastf is None else len(np.unique([lastf, f])) <EOL>if   rev == <NUM_LIT:3>: k = list(reversed(k))<EOL>elif rev == <NUM_LIT:4>:<EOL><INDENT>rev = len(np.unique(np.concatenate([lastf, f[k]])))<EOL>if rev == <NUM_LIT:4> and (len(u) < <NUM_LIT:1> or not (u[-<NUM_LIT:1>] not in f or v[-<NUM_LIT:1>] not in f)):<EOL><INDENT>k = list(reversed(k))<EOL><DEDENT><DEDENT>if len(u) == <NUM_LIT:0>: (uv,vtx) = (f[k],None)<EOL>else:<EOL><INDENT>uvl = [u[-<NUM_LIT:1>],v[-<NUM_LIT:1>]]<EOL>sdif = np.setdiff1d(f[k], uvl)<EOL>if len(sdif) == <NUM_LIT:0>: (uv,vtx) = (uvl[::-<NUM_LIT:1>], np.setdiff1d(lastf, uv)[<NUM_LIT:0>])<EOL>else:              (uv,vtx) = (f[k],      sdif[<NUM_LIT:0>])<EOL><DEDENT>for (q,qq) in zip([u,v],   uv):   q.append(qq)<EOL>for (q,qq) in zip([wu,wv], w[k]): q.append(qq)<EOL><DEDENT>else: raise ValueError('<STR_LIT>',<EOL>dict(faces=faces, coords=coords, ii=ii, f=f, w=w, pcur=pcur,<EOL>u=u, v=v, vtx=vtx))<EOL>if u[-<NUM_LIT:1>] != v[-<NUM_LIT:1>]: mtx[u[-<NUM_LIT:1>],v[-<NUM_LIT:1>]] += <NUM_LIT:1><EOL>if lastf is None or vtx is None: ff = None<EOL>elif u[-<NUM_LIT:2>] == v[-<NUM_LIT:2>]:<EOL><INDENT>if   u[-<NUM_LIT:2>] in f: ff = f<EOL>elif nz == <NUM_LIT:1>:    ff = (u[-<NUM_LIT:2>], f[k[<NUM_LIT:1>]], f[k[<NUM_LIT:0>]])<EOL>else: raise ValueError('<STR_LIT>',<EOL>dict(faces=faces, coords=coords, ii=ii, f=f, w=w, pcur=pcur,<EOL>u=u, v=v, vtx=vtx))<EOL><DEDENT>elif vtx == u[-<NUM_LIT:2>] or vtx == v[-<NUM_LIT:2>]:<EOL><INDENT>if nz == <NUM_LIT:2>:<EOL><INDENT>ff = f<EOL><DEDENT>else: raise ValueError(<EOL>'<STR_LIT>',<EOL>dict(faces=faces,coords=coords,ii=ii,f=f,w=w,pcur=pcur,u=u,v=v,vtx=vtx))<EOL><DEDENT>else: ff = (u[-<NUM_LIT:2>], v[-<NUM_LIT:2>], vtx)<EOL>assert(ff is None or len(np.unique(ff)) == <NUM_LIT:3>)<EOL>fs.append(ff)<EOL>ps.append(tuple(pcur))<EOL>pcur = [ii]<EOL>lastf = f<EOL><DEDENT>if closed:<EOL><INDENT>tmp = np.setdiff1d((u[<NUM_LIT:0>],v[<NUM_LIT:0>]), (u[-<NUM_LIT:1>],v[-<NUM_LIT:1>])) if len(u) > <NUM_LIT:1> else []<EOL>if len(tmp) == <NUM_LIT:0>:<EOL><INDENT>(f0,f1) = faces[:,[<NUM_LIT:0>,-<NUM_LIT:1>]].T<EOL>(x0,x1) = coords[:,[<NUM_LIT:0>,-<NUM_LIT:1>]].T<EOL>f0but1 = np.setdiff1d(f0,f1)<EOL>if len(f0but1) == <NUM_LIT:0>:<EOL><INDENT>if len(fs) > <NUM_LIT:0>: fs[<NUM_LIT:0>] = f0<EOL>if len(ps) > <NUM_LIT:0>: pcur = (ps[-<NUM_LIT:1>][-<NUM_LIT:1>],) + ps[<NUM_LIT:0>]<EOL>else:           pcur = pcur + [pcur[<NUM_LIT:0>]]<EOL><DEDENT>elif len(f0but1) == <NUM_LIT:1>:<EOL><INDENT>f0ii = np.where(f0 == f0but1[<NUM_LIT:0>])[<NUM_LIT:0>]<EOL>if np.isclose(x0[foii], <NUM_LIT:0>): fs[<NUM_LIT:0>] = f1<EOL>else: fs[<NUM_LIT:0>] = f0<EOL><DEDENT>else: raise ValueError('<STR_LIT>',<EOL>dict(faces=faces, coords=coords, u=u, v=v, vtx=vtx,<EOL>pcur=pcur, f0=f0, f1=f1, x0=x0, x1=x1))<EOL>if len(ps) > <NUM_LIT:0>: ps[<NUM_LIT:0>] = tuple(pcur)<EOL><DEDENT>elif len(tmp) == <NUM_LIT:1>:<EOL><INDENT>fs[<NUM_LIT:0>] = (u[-<NUM_LIT:1>], v[-<NUM_LIT:1>], tmp[<NUM_LIT:0>])<EOL>ps[<NUM_LIT:0>] = tuple(pcur)[:-<NUM_LIT:1>] + ps[<NUM_LIT:0>]<EOL><DEDENT>else: raise ValueError('<STR_LIT>',<EOL>dict(faces=faces, coords=coords, u=u, v=v, vtx=vtx))<EOL><DEDENT>else:<EOL><INDENT>fs[<NUM_LIT:0>] = None<EOL>ps[<NUM_LIT:0>] = None<EOL><DEDENT>(u,v,wu,wv) = [np.asarray(x) for x in (u,v,wu,wv)]<EOL>(ii,jj,qq) = sps.find(mtx + mtx.T)<EOL>k = np.where(np.mod(qq, <NUM_LIT:2>) == <NUM_LIT:0>)[<NUM_LIT:0>]<EOL>for (uu,vv) in zip(ii[k], jj[k]):<EOL><INDENT>wu[u == uu] = <NUM_LIT><EOL>wv[v == vv] = <NUM_LIT><EOL><DEDENT>fs = np.roll(fs, -<NUM_LIT:1>, axis=<NUM_LIT:0>) if len(fs) > <NUM_LIT:0> else np.zeros((<NUM_LIT:0>,<NUM_LIT:3>), dtype=np.int)<EOL>ps = np.roll(ps, -<NUM_LIT:1>, axis=<NUM_LIT:0>) if len(ps) > <NUM_LIT:0> else np.array([],    dtype=np.object)<EOL>if not closed: (wu,wv) = [np.asarray(w) * <NUM_LIT:0.5> for w in (wu,wv)]<EOL>return tuple(map(pimms.imm_array, (u,v,wu,wv,fs,ps)))<EOL>
path.edge_data is a tuple of (u, v, wu, wv, fs, ps) where u and v are arrays such that each
edge in path.surface that intersects the given path is given by one of the (u[i],v[i]), and
the relative distancea along the path is specified by the arrays of weights, wu and wv. If
the given path is closed, then for each edge, one weight will be > 0.5 and one weight will
be smaller; the relative position of 0.5 exactly specifies the relative distance along the
edge that the intersection occurs. If the given path is not closed, then wu[i] + wv[i] will
equal 0.5 instead of equalling 1.  The final two tuple element, fs and ps, are also tuples
the same length as u and v. In fs[i], the face formed by the edges (u[i], v[i]) and
(u[i+1], v[i+1]) is given; in ps[i], a tuple of all path point indices (i.e., into the
path.addresses data arrays) in order that pass through fs[i] is given. If path is closed,
then the final element of ps and fs will wrap around to the beginning of the path;
otherwise both will be None. For any instance in which u[i] and v[i] are equal (i.e., the
path passes through a vertex), fs[i] will be None and ps[i] will be a tuple containing
only the vertex.

If the path is closed, the the u are always on the inside of the label while the v are
always on the outside.