Example #1
0
def test_dict_to_object_view():
    """Test the dict_to_object method with View objects."""
    v_obj = View('test_view', (0, 0, 10), (0, 1, 0), (0, 0, 1), 'l', 240, 300,
                 -10, -25)
    v_dict = v_obj.to_dict()
    new_v = dict_to_object(v_dict)
    assert isinstance(new_v, View)
Example #2
0
def test_to_from_dict():
    view = View('test_view', (0, 0, 10), (0, 1, 0), (0, 0, 1), 'l', 240, 300,
                -10, -25)
    view.room_identifier = 'Test_room'

    view_dict = view.to_dict()
    new_view = View.from_dict(view_dict)
    assert new_view == view
    assert view_dict == new_view.to_dict()
Example #3
0
def test_rotate():
    v = View('test_view', (0, 0, 0), (1, 0, 0), (0, 0, 1))
    v.rotate(90, pv.Vector3D(0, 1, 1), pv.Point3D(0, 0, 20))
    assert round(v.position[0], 3) == -14.142
    assert round(v.position[1]) == -10
    assert round(v.position[2]) == 10
    assert round(v.up_vector[0], 3) == 0.707
    assert round(v.up_vector[1], 1) == 0.5
    assert round(v.up_vector[2], 1) == 0.5
    assert round(v.direction[0], 1) == 0.0
    assert round(v.direction[1], 3) == 0.707
    assert round(v.direction[2], 3) == -0.707
Example #4
0
def test_scale():
    v = View('test_view', (1, 0, 2), (2, 0, 0), (0, 0, 3))
    v.scale(2)

    assert round(v.position[0]) == 2
    assert round(v.position[1]) == 0
    assert round(v.position[2]) == 4
    assert round(v.up_vector[0]) == 0
    assert round(v.up_vector[1]) == 0
    assert round(v.up_vector[2]) == 6
    assert round(v.direction[0]) == 4
    assert round(v.direction[1]) == 0
    assert round(v.direction[2]) == 0
Example #5
0
def test_rotate_xy():
    v = View('test_view', (1, 0, 2), (2, 0, 0), (0, 0, 3))
    v.rotate_xy(90, pv.Point3D(0, 0, 0))

    assert round(v.position[0]) == 0
    assert round(v.position[1]) == 1
    assert round(v.position[2]) == 2
    assert round(v.up_vector[0]) == 0
    assert round(v.up_vector[1]) == 0
    assert round(v.up_vector[2]) == 3
    assert round(v.direction[0]) == 0
    assert round(v.direction[1]) == 2
    assert round(v.direction[2]) == 0
Example #6
0
def test_reflect():
    v = View('test_view', (1, 0, 2), (2, 0, 0), (0, 0, 3))
    v.reflect(Plane(pv.Vector3D(1, 0, 0), pv.Point3D(0, 0, 0)))

    assert round(v.position[0]) == -1
    assert round(v.position[1]) == 0
    assert round(v.position[2]) == 2
    assert round(v.up_vector[0]) == 0
    assert round(v.up_vector[1]) == 0
    assert round(v.up_vector[2]) == 3
    assert round(v.direction[0]) == -2
    assert round(v.direction[1]) == 0
    assert round(v.direction[2]) == 0
Example #7
0
def test_value_assignment():
    v = View('test_view', (0, 0, 10), (0, 1, 0), (0, 0, 1), 'l', 240, 300, -10,
             -25)
    assert v.position == (0, 0, 10)
    assert v.direction == (0, 1, 0)
    assert v.up_vector == (0, 0, 1)
    assert v.type == 'l'
    assert v.h_size == 240
    assert v.v_size == 300
    assert v.shift == -10
    assert v.lift == -25
    assert v.vo == ''
    assert v.to_radiance() == '-vtl -vp 0.0 0.0 10.0 -vd 0.0 1.0 0.0' \
        ' -vu 0.0 0.0 1.0 -vh 240.0 -vv 300.0 -vs -10.0 -vl -25.0'
Example #8
0
def test_default_values():
    v = View('test_view')
    str(v)  # test string representation
    hash(v)  # test hashability

    assert v.position == (0, 0, 0)
    assert v.direction == (0, 0, 1)
    assert v.up_vector == (0, 1, 0)
    assert v.type == 'v'
    assert v.h_size == 60
    assert v.v_size == 60
    assert v.vo == ''
    assert v.va == ''
    assert v.to_radiance() == '-vtv -vp 0.0 0.0 0.0 -vd 0.0 0.0 1.0' \
        ' -vu 0.0 1.0 0.0 -vh 60.0 -vv 60.0'
Example #9
0
def test_dimensions():
    view_string = 'rvu -vtv -vp 1.000 8.000 2.000 -vd 3.000 -2.000 0.000' \
        ' -vu 0.000 0.000 1.000 -vh 120.000 -vv 45.000'
    view = View.from_string('test_view', view_string)
    x, y = view.dimension_x_y(512, 512)
    assert x == 512
    assert y == 122

    assert view.dimension(512, 512) == '-x 512 -y 122 -ld-'
def test_from_grid_unf():
    v = View('test_vta')
    v.position = (3, 7, 1.8)
    v.direction = (0, 1, 0)
    v.up_vector = (0, 0, 1)
    v.type = 'a'
    v.h_size = 360
    v.v_size = 360

    grid = [
        './tests/assets/view/view_0000.unf',
        './tests/assets/view/view_0001.unf',
        './tests/assets/view/view_0002.unf',
        './tests/assets/view/view_0003.unf',
        './tests/assets/view/view_0004.unf'
    ]

    from_grid = View.from_grid(grid)
    assert v.to_radiance() == from_grid.to_radiance()
Example #11
0
def test_from_file():
    vw = View.from_file('./tests/assets/view.vf')
    assert vw.identifier == 'view'
    assert list(vw.position) == [0, 0, 0]
    assert list(vw.direction) == [0, 0, 1]
    assert list(vw.up_vector) == [0, 1, 0]
    assert vw.h_size == 29.341
    assert vw.v_size == 32.204
    assert vw.shift == -0.500
    assert vw.lift == -0.500
    assert vw.fore_clip == 100
    assert vw.aft_clip == 200
Example #12
0
def test_from_string():
    view = 'rvu -vtv -vp 0.000 0.000 0.000 -vd 0.000 0.000 1.000 ' \
        '-vu 0.000 1.000 0.000 -vh 29.341 -vv 32.204 ' \
        '-vs -0.500 -vl -0.500 -vo 100.000 -va 200.000'

    vw = View.from_string('test_view', view)
    assert list(vw.position) == [0, 0, 0]
    assert list(vw.direction) == [0, 0, 1]
    assert list(vw.up_vector) == [0, 1, 0]
    assert vw.h_size == 29.341
    assert vw.v_size == 32.204
    assert vw.shift == -0.500
    assert vw.lift == -0.500
    assert vw.fore_clip == 100
    assert vw.aft_clip == 200
Example #13
0
    def from_view_file(cls: Camera, file_path: str) -> Camera:
        """Create a Camera object from a radiance view file.

        Args:
            file_path: A valid path to a radiance view file with .vf extension.

        Returns:
            A Camera object.
        """

        view_file = Path(file_path)

        if view_file.is_file() and view_file.as_posix()[-3:] == '.vf':
            return Camera.from_view(view=View.from_file(view_file.as_posix()))
        else:
            raise FileNotFoundError('Radiance view file not found.')
Example #14
0
def view_perspective(directory):
    vw = View('test_view_perspective', (0, 0, 10), (0, 1, 0), (0, 0, 1))
    dest_file = os.path.join(directory, 'view_perspective.json')
    with open(dest_file, 'w') as fp:
        json.dump(vw.to_dict(), fp, indent=4)
Example #15
0
ghenv.Component.AdditionalHelpFromDocStrings = '4'

try:  # import the core honeybee dependencies
    from honeybee.typing import clean_and_id_rad_string
except ImportError as e:
    raise ImportError('\nFailed to import honeybee:\n\t{}'.format(e))

try:
    from honeybee_radiance.view import View
except ImportError as e:
    raise ImportError('\nFailed to import honeybee:\n\t{}'.format(e))

try:  # import ladybug_rhino dependencies
    from ladybug_rhino.grasshopper import all_required_inputs
    from ladybug_rhino.viewport import viewport_by_name, viewport_properties
except ImportError as e:
    raise ImportError('\nFailed to import ladybug_rhino:\n\t{}'.format(e))

VIEW_TYPES = ('v', 'h', 'l', 'c', 'a')

# set the default values
_name_ = 'RadianceView' if _name_ is None else _name_
viewp = viewport_by_name(_viewport_)
v_props = viewport_properties(viewp, _view_type_)

view = View(clean_and_id_rad_string(_name_), v_props['position'],
            v_props['direction'], v_props['up_vector'],
            VIEW_TYPES[v_props['view_type']], v_props['h_angle'],
            v_props['v_angle'])
view.display_name = _name_
def test_from_grid_vth():
    v = View('test_vth')
    v.position = (0, 0, 0)
    v.direction = (0, 1, 0)
    v.up_vector = (0, 0, 1)
    v.type = 'h'
    v.h_size = 180
    v.v_size = 180

    grid = v.grid(x_div_count=2, y_div_count=5)
    from_grid = View.from_grid(grid)

    assert v.to_radiance() == from_grid.to_radiance()
Example #17
0
def test_move():
    v = View('test_view')
    v.move(pv.Vector3D(10, 20, 30))

    assert v.position == (10, 20, 30)
    assert v.up_vector == (0, 1, 0)
def main():
    argc = len(sys.argv)
    if argc < 2:
        print("Error: .rad file not specified, usage: python3 genParallelViews.py <file.rad>")
        return -1
    
    filePath = sys.argv[1]
    if not filePath.endswith(".rad"):
        print("Error: .rad file not specified, usage: python3 genParallelViews.py <file.rad>")
        return -1

    print("Scene up direction: [{0}, {1}, {2}]".format(SCENE_UP[0], SCENE_UP[1], SCENE_UP[2]))

    # Read in the RAD file
    stringObjects = reader.parse_from_file(filePath)
    polygons = []
    materials = []
    currentModifier = None
    for stringObject in stringObjects:
        if not "polygon" in stringObject:
            validMaterial = False
            for material in VALID_MATERIALS:
                if material in stringObject:
                    validMaterial = True
                    break
            
            # This is a bit hacky right now. We get an exception if we try and parse a non-material or non-polygon
            if not validMaterial:
                print("Error: Can't parse '{0}' from RAD file. If this is a material try manually adding it to the script, else ignore.".format(stringObject))
                continue

        primitiveDict = reader.string_to_dict(stringObject)
        if primitiveDict["type"] == "polygon":
            primitiveDict["modifier"] = None
            polygon = Polygon.from_primitive_dict(primitiveDict)
            polygon.modifier = currentModifier
            polygons.append(polygon)
        elif primitiveDict["type"] == "plastic":
            plastic = Plastic.from_primitive_dict(primitiveDict)
            currentModifier = plastic
            materials.append(plastic)
        elif primitiveDict["type"] == "metal":
            metal = Metal.from_primitive_dict(primitiveDict)
            currentModifier = metal
            materials.append(metal)
        elif primitiveDict["type"] == "glass":
            glass = Glass.from_primitive_dict(primitiveDict)
            currentModifier = glass
            materials.append(glass)
        else:
            print("Error: Unable to assign material from '{0}'.".format(stringObject))

    # Loop through all the polygons read in from the RAD file and classify them as triangles or quads
    triangles = []
    quads = []
    for polygon in polygons:
        if len(polygon.vertices) == 3:
            triangles.append(polygon)
        elif len(polygon.vertices) == 4:
            quads.append(polygon)

    # Loop through all the triangles read in from the RAD file and attempt to form quads from them
    trianglesMissed = []
    i = 0
    while True:
        if i >= len(triangles) - 1:
            break

        triangleA = triangles[i]
        triangleB = triangles[i+1]
        if formsQuad(triangleA, triangleB):
            quad = formQuad(triangleA, triangleB)
            quads.append(quad)
            i += 2
        else:
            trianglesMissed.append(triangleA)
            i += 1

    if len(trianglesMissed) != 0:    
        print("The following triangles from the RAD file couldn't be formed into quads: ", end="")
        for triangle in trianglesMissed:
            print("{0}".format(triangle.identifier), end=" ")
        print()
    
    # Loop through all the quads and generate a Radiance parallel projection view for it
    viewDict = {}
    for quad in quads:
        # type 'l' defines this view as a parallel projection
        view = View(quad.identifier, type='l')
         
        # Get the dimensions of the quad. 
        # One of these should be approximately 0.0 because a quad is two dimensional
        dimensions = [0, 0, 0]
        for i in range(3):
            dimensions[i] = getDimensionLength(quad, i)
        
        # Set the view's horizontal and vertical size based on the dimensions of the quad
        # The projection will contain the entire quad
        horizontalSet = False
        verticalSet = False
        for i in range(3):
            if dimensions[i] > SIGMA:
                if not horizontalSet:
                    view.h_size = dimensions[i]
                    horizontalSet = True
                else:
                    view.v_size = dimensions[i]
                    verticalSet = True
                    break
        
        if not horizontalSet or not verticalSet:
            print("Error: " + view.identifier + " vh and/or vv not set")
            continue

        # Set view direction
        normal = getQuadNormal(quad)
        if len(normal) == 0:
            print("Error: " + view.identifier + " vn not set")
            continue

        direction = (-normal[0], -normal[1], -normal[2])
        view.direction = direction

        # Set view position
        position = getViewPosition(quad, dimensions, normal)
        view.position = position

        # Set view up
        view.up_vector = SCENE_UP
        if listsSame(SCENE_UP, direction) or listsSame(SCENE_UP, normal):
            if not listsSame(SCENE_UP, [0.0, 0.0, 1.0]):
                view.up_vector = [0.0, 0.0, 1.0]
            elif not listsSame(SCENE_UP, [0.0, 1.0, 0.0]):
                view.up_vector = [0.0, 1.0, 0.0]
            else:
                view.up_vector = [1.0, 0.0, 0.0]

        viewDict[quad.identifier] = view

    print("\n-----Radiance Parallel Views-----")
    for view in viewDict.values():
        print("view=" + view.identifier + " " + view.to_radiance())
    print("----------\n\nTotal view count: {0}, Total quad count: {1}".format(len(viewDict.values()), len(quads)))

    writeOBJFile(BASE_FILE_NAME, quads, viewDict)
    writeMTLFile(BASE_FILE_NAME, quads)

    return 0
try:
    from honeybee_radiance.view import View
except ImportError as e:
    raise ImportError('\nFailed to import honeybee:\n\t{}'.format(e))

try:  # import ladybug_rhino dependencies
    from ladybug_rhino.grasshopper import all_required_inputs
except ImportError as e:
    raise ImportError('\nFailed to import ladybug_rhino:\n\t{}'.format(e))

VIEW_TYPES = ('v', 'h', 'l', 'c', 'a')

if all_required_inputs(ghenv.Component):
    # process the points/vectors into tuples
    _pos = (_position.X, _position.Y, _position.Z)
    _dir = (_direction.X, _direction.Y, _direction.Z)

    # set the default values
    name = clean_and_id_rad_string('View') if _name_ is None else _name_
    _up_vec = (_up_vector_.X, _up_vector_.Y, _up_vector_.Z) if _up_vector_ \
        is not None else (0, 0, 1)
    _type_ = 'v' if _view_type_ is None else VIEW_TYPES[_view_type_]
    _h_angle_ = 60 if _h_angle_ is None else _h_angle_
    _v_angle_ = 60 if _v_angle_ is None else _v_angle_

    view = View(clean_rad_string(name), _pos, _dir, _up_vec, _type_, _h_angle_,
                _v_angle_)
    if _name_ is not None:
        view.display_name = _name_
Example #20
0
def test_value_update():
    v = View('__')
    v.position = (0, 0, 10)
    v.direction = (0, 1, 0)
    v.up_vector = (0, 0, 1)
    v.type = 'l'
    v.h_size = 240
    v.v_size = 300
    v.shift = -10
    v.lift = -25
    v.fore_clip = 30
    v.aft_clip = 50

    assert v.position == (0, 0, 10)
    assert v.direction == (0, 1, 0)
    assert v.up_vector == (0, 0, 1)
    assert v.type == 'l'
    assert v.h_size == 240
    assert v.v_size == 300
    assert v.shift == -10
    assert v.lift == -25
    assert v.fore_clip == 30
    assert v.aft_clip == 50
    assert v.to_radiance() == '-vtl -vp 0.0 0.0 10.0 -vd 0.0 1.0 0.0' \
        ' -vu 0.0 0.0 1.0 -vh 240.0 -vv 300.0 -vs -10.0 -vl -25.0 ' \
        '-vo 30.0 -va 50.0'
Example #21
0
def merge_view(input_folder, base_name, extension, scale_factor, folder, name):
    """Merge several radiance HDR image files into a single file.

    This command will also perform an anti-aliasing operation on the output and
    replace the view information in the header of the merged file if a single .vf
    file is found within the root of the input-folder.

    \b
    Args:
        input_folder: Input folder.
        base_name: File base name. All of the files must start with base name and
            continue with _ and an integer values.
        extension: File extention. [Default: .unf]
    """
    try:
        # get all of the files in the folder with the given extension
        pattern = r'{}_\d+{}'.format(base_name, extension)
        images = sorted(f for f in os.listdir(input_folder)
                        if re.match(pattern, f))
        if len(images) == 0:
            raise ValueError('Found no files to merge.')
        name = name or base_name

        # get the new dir name as view name might be group/name
        dirname = os.path.dirname(os.path.normpath(os.path.join(folder, name)))
        if dirname and not os.path.exists(dirname):
            os.makedirs(dirname)
        temp_output = os.path.join(dirname, name + '_temp.HDR')
        output_file = os.path.join(dirname, name + '.HDR')

        # set up the pcompos command
        in_dirname = os.path.normpath(input_folder)
        pcompos = Pcompos(output=temp_output)
        pcompos.input = [os.path.join(in_dirname, img) for img in images]
        pcompos.options.a = 1

        # setup the pfilt command to perform anti-aliasing on the output
        pfilt = Pfilt(input=temp_output)
        pfilt.options.r = 0.6
        if scale_factor != 1:
            pfilt.options.x = '/{}'.format(scale_factor)
            pfilt.options.y = '/{}'.format(scale_factor)

        # search for a single .vf in the folder and, if it's found, grab the info
        views = sorted(f for f in os.listdir(input_folder)
                       if f.endswith('.vf'))
        if len(views) == 1:  # replace the header with the info in the view
            view_obj = View.from_file(os.path.join(input_folder, views[0]))
            getinfo = Getinfo(output=output_file)
            getinfo.options.a = 'VIEW= {}'.format(view_obj)
            pfilt.pipe_to = getinfo
        else:  # just let the output of pfilt be the final output
            pfilt.output = output_file

        # run the commands in series
        env = None
        if folders.env != {}:
            env = folders.env
        env = dict(os.environ, **env) if env else None
        for r_cmd in (pcompos, pfilt):
            r_cmd.run(env)

    except Exception:
        _logger.exception('Failed to merge image files.')
        sys.exit(1)
    else:
        sys.exit(0)
def test_grid_dimension():
    v = View('test_vtv')
    v.position = (0, 0, 0)
    v.direction = (0, 1, 0)
    v.up_vector = (0, 0, 1)
    v.type = 'v'
    v.h_size = 60
    v.v_size = 60

    grid = v.grid(x_div_count=1, y_div_count=1)
    from_grid = View.from_grid(grid)
    assert v.to_radiance() == from_grid.to_radiance()

    grid = v.grid(x_div_count=2, y_div_count=4)
    from_grid = View.from_grid(grid)
    assert v.to_radiance() == from_grid.to_radiance()

    grid = v.grid(x_div_count=1, y_div_count=10)
    from_grid = View.from_grid(grid)
    assert v.to_radiance() == from_grid.to_radiance()

    grid = v.grid(x_div_count=10, y_div_count=100)
    from_grid = View.from_grid(grid)
    assert v.to_radiance() == from_grid.to_radiance()
Example #23
0
def view_parallel(directory):
    vw = View('test_view', (0, 0, 10), (0, 1, 0), (0, 0, 1), 'l', 240, 300, -10, -25)
    dest_file = os.path.join(directory, 'view_parallel.json')
    with open(dest_file, 'w') as fp:
        json.dump(vw.to_dict(), fp, indent=4)
Example #24
0
def split_view(view, count, skip_overture, octree, rad_params, folder,
               log_file):
    """Split a radiance view file into smaller views based on count.

    \b
    Args:
        view: Full path to input sensor view file.
        count: Maximum number of sensors in new files. The number will be rounded to
            closest round number for each file. For example if the input file has 21
            sensors and input count is set to 5 this command will generate 4 files where
            the first three files will have 5 sensors and the last file will have 6.
    """
    try:
        # split the view into smaller views
        view_obj = View.from_file(view)
        views = view_obj.grid(y_div_count=count)
        views_info = []
        for c, v in enumerate(views):
            name = '%s_%04d' % (view_obj.identifier, c)
            path = '%s.vf' % name
            full_path = os.path.join(folder, path)
            v.to_file(folder, path, mkdir=True)
            views_info.append({
                'name': name,
                'path': path,
                'full_path': full_path
            })

        # create the ambient cache file if specified
        amb_file = os.path.basename(view).replace('.vf', '.amb')
        if not skip_overture:
            options = RpictOptions()
            if rad_params:
                options.update_from_string(rad_params.strip())
            # overwrite default image size to be small for the ambient cache (64 x 64)
            options.x = 64
            options.y = 64
            options.af = amb_file

            # create command and run it to get the .amb file
            assert octree is not None, \
                'Octree  must be specified for an overture calculation.'
            out_file = os.path.basename(view).replace('.vf', '.unf')
            rpict = Rpict(options=options,
                          output=out_file,
                          octree=octree,
                          view=view)
            env = None
            if folders.env != {}:
                env = folders.env
            env = dict(os.environ, **env) if env else None
            rpict.run(env=env, cwd=folder)
            os.remove(os.path.join(folder, out_file))
        else:  # write a dummy ambient file so that queenbee does not crash
            write_to_file_by_name(folder, amb_file, '')

        # record all of the view files that were generated
        log_file.write(json.dumps(views_info))
    except Exception:
        _logger.exception('Failed to split view file.')
        sys.exit(1)
    else:
        sys.exit(0)