Пример #1
0
def mesh_geometry(mesh, seg):
    # TODO: SFF format data structure mix vertices and normals, calling both vertices -- a nightmare.
    #   Semantics of which normal belong with which vertices unclear (consecutive in polygon?).
    #   Efficiency reading is horrible.  Ask Paul K to make separate vertex and normal lists.
    nv = mesh.num_vertices // 2
    from numpy import empty, float32
    va = empty((nv, 3), float32)
    na = empty((nv, 3), float32)
    for i, v in enumerate(mesh.vertices):
        vid = v.id
        if vid != i:
            raise ValueError(
                'Require mesh vertices be numbers consecutively from 0, got vertex id %d in position %d'
                % (vid, i))
        d = v.designation  # 'surface' or 'normal'
        if d == 'surface':
            if vid % 2 == 1:
                raise ValueError(
                    'Require odd mesh indices to be normals, got a vertex at position %d'
                    % vid)
            va[vid // 2] = v.point
        elif d == 'normal':
            if vid % 2 == 0:
                raise ValueError(
                    'Require even mesh indices to be vertices, got a normal at position %d'
                    % vid)
            na[vid // 2] = v.point
        else:
            raise ValueError(
                'Vertex %d designation "%s" is not "surface" or "normal"' %
                (v.id, d))
    '''
    vids = list(set(v.id for v in mesh.vertices if v.designation == 'surface'))
    vids.sort()
    print ('vertex ids', vids[:3], 'num', len(vids), 'last', vids[-1])
    '''

    if mesh.transform_id is None:
        from chimerax.geometry import Place, scale
        #        transform = scale((160,160,160)) * Place(seg.transforms[0].data_array)
        transform = Place(seg.transforms[0].data_array) * scale(
            (160, 160, 160))
    else:
        transform = transform_by_id(seg, mesh.transform_id)
    transform.transform_points(va, in_place=True)
    transform.transform_normals(na, in_place=True)

    tri = []
    for p in mesh.polygons:
        #        print ('poly', len(p.vertex_ids), p.vertex_ids[:6])
        t = tuple(vid // 2 for vid in p.vertices if vid % 2 == 0)
        if len(t) != 3:
            raise ValueError(
                'Require polygons to be single triangles, got polygon with %d vertices'
                % len(t))
        tri.append(t)
        '''
        last_vid = None
        for vid in p.vertex_ids:
            if vid % 2 == 0:
                if last_vid is not None:
#                    tri.append((vid//2,last_vid//2))
                    tri.append((vid//2,last_vid//2,vid//2))
                last_vid = vid
        first_vid = p.vertex_ids[0]
        tri.append((last_vid//2,first_vid//2,last_vid//2))
        '''
    from numpy import array, int32
    ta = array(tri, int32)

    return va, na, ta
Пример #2
0
def draw_slab(nd, residue, name, params):
    shapes = []
    standard = standard_bases[name]
    ring_atom_names = standard["ring atom names"]
    atoms = get_ring(residue, ring_atom_names)
    if not atoms:
        return shapes
    plane = Plane([a.coord for a in atoms])
    info = find_dimensions(params.dimensions)
    tag = standard['tag']
    slab_corners = info[tag]
    origin = residue.find_atom(anchor(info[ANCHOR], tag)).coord
    origin = plane.nearest(origin)

    pts = [plane.nearest(a.coord) for a in atoms[0:2]]
    y_axis = pts[0] - pts[1]
    normalize_vector(y_axis)
    x_axis = numpy.cross(y_axis, plane.normal)
    xf = Place(matrix=((x_axis[0], y_axis[0], plane.normal[0], origin[0]),
                       (x_axis[1], y_axis[1], plane.normal[1], origin[1]),
                       (x_axis[2], y_axis[2], plane.normal[2], origin[2])))
    xf = xf * standard["correction factor"]

    color = residue.ring_color
    half_thickness = params.thickness / 2

    llx, lly = slab_corners[0]
    llz = -half_thickness
    urx, ury = slab_corners[1]
    urz = half_thickness
    center = (llx + urx) / 2, (lly + ury) / 2, 0
    if params.shape == 'box':
        llb = (llx, lly, llz)
        urf = (urx, ury, urz)
        xf2 = xf
        va, na, ta = box_geometry(llb, urf)
        pure_rotation = True
    elif params.shape == 'muffler':
        radius = (urx - llx) / 2 * _SQRT2
        xf2 = xf * translation(center)
        xf2 = xf2 * scale((1, 1, half_thickness * _SQRT2 / radius))
        height = ury - lly
        va, na, ta = get_cylinder(radius, numpy.array((0, -height / 2, 0)),
                                  numpy.array((0, height / 2, 0)))
        pure_rotation = False
    elif params.shape == 'ellipsoid':
        # need to reach anchor atom
        xf2 = xf * translation(center)
        sr = (ury - lly) / 2 * _SQRT3
        xf2 = xf2 * scale(
            ((urx - llx) / 2 * _SQRT3 / sr, 1, half_thickness * _SQRT3 / sr))
        va, na, ta = get_sphere(sr, (0, 0, 0))
        pure_rotation = False
    else:
        raise RuntimeError('unknown base shape')

    description = '%s %s' % (residue, tag)
    xf2.transform_points(va, in_place=True)
    xf2.transform_normals(na, in_place=True, is_rotation=pure_rotation)
    shapes.append(AtomicShapeInfo(va, na, ta, color, atoms, description))

    if not params.orient:
        return shapes

    # show slab orientation by putting "bumps" on surface
    if tag == PYRIMIDINE:
        center = (llx + urx) / 2.0, (lly + ury) / 2, half_thickness
        va, na, ta = get_sphere(half_thickness, center)
        xf.transform_points(va, in_place=True)
        xf.transform_normals(na, in_place=True, is_rotation=True)
        shapes.append(AtomicShapeInfo(va, na, ta, color, atoms, description))
    else:
        # purine
        center = (llx + urx) / 2.0, lly + (ury - lly) / 3, half_thickness
        va, na, ta = get_sphere(half_thickness, center)
        xf.transform_points(va, in_place=True)
        xf.transform_normals(na, in_place=True, is_rotation=True)
        shapes.append(AtomicShapeInfo(va, na, ta, color, atoms, description))
        center = (llx + urx) / 2.0, lly + (ury - lly) * 2 / 3, half_thickness
        va, na, ta = get_sphere(half_thickness, center)
        xf.transform_points(va, in_place=True)
        xf.transform_normals(na, in_place=True, is_rotation=True)
        shapes.append(AtomicShapeInfo(va, na, ta, color, atoms, description))
    return shapes