예제 #1
0
def add_slice(_glob, _groups, *_zs):
    globber = pather.format_glob(_glob, *_zs)
    zFinder = lambda x: map(str, _zs)
    # Test if any files exist
    if not _zs:
        matcher = fnmatch.translate(globber) 
        grouper = matcher.replace('.*','(.*)')
        rematch = re.compile(grouper).match
        def zFinder(x):
            m = rematch(x)
            g = m.groups('') if m else ()
            return (i for i in g if i.isdigit())
    # For all files that match
    for ifile in glob.iglob(globber):
        # Look for Plane in SUB and VOL GROUPS
        sub_vol = [_groups['SUB'], _groups['VOL']]
        g_planes = mover.in_groups(sub_vol, 'Plane*')
        g_plane = next(g_planes, None)
        # Format name of z slice
        znum = int(next(zFinder(ifile)))
        zname = '{:d}'.format(znum)
        # Add plane if needed
        if not g_plane:
            g_plane = add_plane(_groups, zname, ifile)
        else:
            c_mat = g_plane.active_material
            cycler.tex(c_mat, zname, ifile)

        # Scale to current Z
        mover.move_z(g_plane, znum)

    log.yaml('Imported', globber)
    return {'FINISHED'}
예제 #2
0
def import_id(_glob, _groups, *_ids):
    status = set()
    context = bpy.context
    globber = pather.format_glob(_glob, *_ids)
    idFinder = lambda x: map(str, _ids)
    # Test if any files exist
    if not _ids:
        matcher = fnmatch.translate(globber)
        grouper = matcher.replace('.*', '(.*)')
        rematch = re.compile(grouper).match

        def idFinder(x):
            m = rematch(x)
            g = m.groups('') if m else ()
            return (i for i in g if i.isdigit())

    # For all files that match
    for ifile in glob.iglob(globber):
        try:
            status |= read_id(ifile, idFinder, _groups)
        except err.MeshLabelError:
            raise err.MeshLabelError(globber, ifile)
        # Set scale for newly imported mesh
        new_obj = context.active_object
        new_obj.scale = _groups['SRC'].from_mesh
        # Translate mesh by origin and offset
        vol_origin = Vector(_groups['VOL'].origin)
        sub_offset = Vector(_groups['SUB'].offset)
        new_obj.location = vol_origin + sub_offset
        # add modifiers
        mod0 = new_obj.modifiers.new('Simple', 'DECIMATE')
        mod1 = new_obj.modifiers.new('Smooth', 'SUBSURF')
        mod1.render_levels = 2
        mod0.ratio = 0.16
        # Apply modifiers
        full_mesh = new_obj.data
        applier = context.scene, True, 'RENDER'
        new_mesh = new_obj.to_mesh(*applier)
        new_obj.modifiers.clear()
        new_obj.data = new_mesh
        bpy.data.meshes.remove(full_mesh)
        # add to all groups
        for g in _groups.values():
            bpy.ops.object.group_link(group=g.name)
    if not status:
        log.yaml('Warning, No files match', globber)
        return {'CANCELLED'}
    log.yaml('Imported', globber)
    return status
예제 #3
0
def add_slices(versions, arg):

    _groups = {}
    # Get group matching arguments
    for s,n in linker.groups(versions, arg):
        _groups[s] = bpy.data.groups[n]

    # Set default image paths
    _glob = os.path.join(arg.folder, arg.file)
    status = set()
    if arg.list:
        # Try to add all given slices
        for _z in sizer.parse_list(arg.list):
            status |= add_slice(_glob, _groups, _z)
    else:
        # Try to import all slices in folder
        status |= add_slice(_glob, _groups)

    # Warn if any imports did not finish
    unfinished = status - set(['FINISHED'])
    if len(unfinished):
        log.yaml('Warning, some slices', unfinished)
예제 #4
0
def import_all(versions, arg):

    _groups = {}
    # Get group matching arguments
    for s, n in linker.groups(versions, arg):
        _groups[s] = bpy.data.groups[n]

    # Set default mesh paths
    _glob = os.path.join(arg.folder, arg.file)
    status = set()
    if arg.list:
        # Try to import all given IDs
        for _id in sizer.parse_list(arg.list):
            status |= import_id(_glob, _groups, _id)
    else:
        # Try to import all IDs in folder
        status |= import_id(_glob, _groups)

    # Warn if any imports did not finish
    unfinished = status - set(['FINISHED'])
    if len(unfinished):
        log.yaml('Warning, some meshes', unfinished)
예제 #5
0
def read_id(_path, idFinder, _groups):
    context = bpy.context
    ext = _path.split(".")[-1]
    tmp_root = _groups['VOL'].tmp
    attributes = {
        '3ds': 'autodesk_3ds',
    }
    ext = attributes.get(ext, ext)
    # Need to know name
    if ext in ['stl', 'ply']:
        try:
            name = next(idFinder(_path))
        except StopIteration:
            raise err.MeshLabelError('', _path)
        log.yaml('Importing {}'.format(name), _path)
        importer = getattr(bpy.ops.import_mesh, ext)
        # Create a symbolic link to change path name
        tmp_link = pather.link(_path, tmp_root, name, ext)
        status = importer(filepath=tmp_link)
        if 'FINISHED' in status:
            # Set color for new object
            new_obj = context.active_object
            mat = bpy.data.materials.new(name=name)
            mat.diffuse_color = color_label(name)
            new_obj.data.materials.append(mat)
        return status

    # Names and details in file
    if ext in ['autodesk_3ds', 'obj', 'x3d']:
        log.yaml('Importing Scene', _path)
        importer = getattr(bpy.ops.import_scene, ext)
        return importer(filepath=_path)

    # Cannot import
    log.yaml('Warning, unknown extension', _path)
    return {'CANCELLED'}
예제 #6
0
def find_links(word_loop):
    """
    Arguments
    ----------
    word_loop: iter(str)
    """
    def fmt_fwd(p,q):
        return ' '.join([
        'SELECT ?item ?V WHERE {',
        'VALUES ?roots {wd:Q%s}  .' % q,
        '?tree (wdt:p{})* ?item'.format(p),
        'OPTIONAL {',
        '?item wdt:P{} ?V'.format(p),
        '} }'])
    def fmt_rev(p,q):
        return ' '.join([
        'SELECT ?item ?V WHERE {',
        'VALUES ?roots {wd:Q%s}  .' % q,
        '?item (wdt:P{})* ?roots'.format(p),
        'OPTIONAL {',
        '?item wdt:P{} ?V'.format(p),
        '} }'])

    WIKI_BASE = "query.wikidata.org/sparql?{}"
    WIKI_ID = "www.wikidata.org/w/api.php?format=json&formatversion=2&action=wbsearchentities&continue=0&language={l}&search={0}&type={t}&uselang={l}"
    WIKI_NAME = "www.wikidata.org/w/api.php?format=json&action=wbgetentities&props=labels&ids={t}{0}&languages={l}"
    rev_verb_fmt = lambda x: WIKI_NAME.format(x, t='P', l='en')
    rev_noun_fmt = lambda x: WIKI_NAME.format(x, t='Q', l='en')
    verb_fmt = lambda x: WIKI_ID.format(x, t='property', l='en')
    noun_fmt = lambda x: WIKI_ID.format(x, t='item', l='en')

    # Try to get items or properties
    for word in word_loop:
        props = wget_key(verb_fmt(word),'search')
        items = wget_key(noun_fmt(word),'search')
        if not len(items):
            log.yaml('ERR, No item', word)
            #raise err.Tree('no item', 'word', word)
        # Filter for matching labels (no spaces)
        label_props = filter_all(props,'label','description')
        label_items = filter_all(items,'label','description')
        ok_props = filter_label(label_props, no=' ')
        ok_items = filter_label(label_items, no=' ')

        # Get queries and properties
        get_ld = get_keys('label', 'description')
        word_log = {
            'verb': list(map(get_ld, ok_props)),
            'noun': list(map(get_ld, ok_items)),
        }
        word_log = {
            k: v for k, v in word_log.items() if len(v)
        }
        get_label = lambda x: x.get('labels', {}).get('en', {}).get('value')
        # Make tree request:
        if 'noun' in word_log:
            ok_i = next(iter(ok_items), None)
            if not ok_i:
                log.yaml('ERR {}'.format(word), 'No item matches')
                break
            ok_title = ''.join(i for i in ok_i['title'] if i.isdigit())
            tree_ql = fmt_rev(31, ok_title)
            tree_param = urllib.parse.urlencode({
                'query': tree_ql,
                'format': 'json',
            })
            tree_url = WIKI_BASE.format(tree_param)
            res_key = ' '.join(get_ld(ok_i))
            res = wget_key(tree_url,'results')
            short_res = []
            for r in res.get('bindings',[]):
                v_raw = r.get('V', {}).get('value',None)
                if not v_raw:
                    short_res.append('?')
                    continue
                # Get the short name of the result
                v_id = v_raw.split('/')[-1]
                v_url = rev_noun_fmt(v_id[1:])
                v_search = wget_key(v_url, 'entities')
                v_vals = v_search.values()
                v_en = filter(None,map(get_label, v_vals))
                short_res.append(next(v_en, None))
            log.yaml(res_key, short_res)

    URL = "tools.wmflabs.org/wikidata-todo/tree.html"
    UI = "https://angryloki.github.io/wikidata-graph-builder"
예제 #7
0
파일: scroll.py 프로젝트: afcarl/3dxp
def animate(arg, versions):
    context = bpy.context
    scene = context.scene
    # Rate must be positive
    if arg.zps <= 0:
        'zps {} must be >0'.format(arg.zps)
        log.yaml('Error', msg)
        return
    # Convert inputs to world units
    known = {
        'um/w': [
            sizer.UM,
        ] * 3,
        'um/XYZ': sizer.parse_list(arg.XYZ, 3),
        'um/VOL': sizer.parse_list(arg.VOL, 3),
    }
    w_VOL = sizer.convert(known, ['um/VOL'], ['um/w'])
    w_XYZ = sizer.convert(known, ['um/XYZ'], ['um/w'])
    # Where to animate (in world units)
    given = {
        'volume': w_VOL,
        'origin': w_XYZ,
    }
    # Select group to animate
    vol_k = list(given.keys())
    vol_v = versions[0]['Items']['VOL']
    groups = linker.match(given, vol_v, vol_k)
    group, likeness = next(groups)
    if not group:
        log.yaml('Error', 'No group')
        return
    # Get planes in group
    planes = set(mover.in_groups([group], 'Plane*'))
    if not planes:
        log.yaml('Error', 'No plane')
        return
    # Get sources for planes
    def plane_src(src, x):
        x_g = x.users_group
        x_s = mover.match_name(x_g, 'SRC*')
        return src | set(x_s)

    sources = reduce(plane_src, planes, set())
    if not sources:
        log.yaml('Error', 'No source')
        return
    # Convert between world and voxels
    any_source = next(iter(sources))
    vox_w = list(any_source['to_vox'])
    zvox_w = vox_w[-1]

    # World resolution
    w_min = w_XYZ[-1]
    w_max = w_XYZ[-1] + w_VOL[-1]
    # Voxel resolution
    v_min = int(w_min * zvox_w)
    v_max = int(w_max * zvox_w)
    log.yaml('Voxel bounds', [v_min, v_max])
    if arg.zspan:

        def v_clamp(v):
            return sorted([v, v_min, v_max])[1]

        zspan = sizer.parse_list(arg.zspan, 2)
        v_span = [v_clamp(v) for v in zspan]
        w_min, w_max = [v / zvox_w for v in v_span]
        v_min, v_max = v_span
        log.yaml('Voxel span', [v_min, v_max])
    # World step size and step count
    w_step = arg.zps / zvox_w
    slices = len(range(v_min, v_max, arg.zps))
    slicer = lambda i: w_min + w_step * i

    # Set frames per second
    scene.render.fps = arg.fps
    # Clear all keyframes
    for p in planes:
        p.animation_data_clear()

    # Actually animate
    current_frame = 0
    msg = '{1} seconds × {0:.3g} × %dμm' % sizer.UM
    log.yaml('Debug', msg.format(w_step, slices))
    # Use world Z value for all slices
    for world_z in map(slicer, range(slices)):
        # Jump frames per z slice
        current_frame += arg.fps
        scene.frame_set(current_frame)
        # Move slice and change texture
        keyframe(group, planes, world_z)
    # Set first and last frame
    scene.frame_start = arg.fps
    scene.frame_end = current_frame
    # Return group for callbacks
    return group