Exemple #1
0
def test_mesh3d_init_from_face_vertices():
    """Test the initialization of Mesh3D from_face_vertices."""
    face_1 = (Point3D(0, 0, 2), Point3D(0, 2, 2), Point3D(2, 2,
                                                          2), Point3D(2, 0, 2))
    face_2 = (Point3D(2, 2, 2), Point3D(2, 0, 2), Point3D(4, 0, 2))
    mesh_1 = Mesh3D.from_face_vertices([face_1, face_2])
    mesh_2 = Mesh3D.from_face_vertices([face_1, face_2], False)

    assert len(mesh_1.vertices) == 5
    assert len(mesh_2.vertices) == 7
    assert len(mesh_1.faces) == len(mesh_2.faces) == 2
    assert mesh_1.area == mesh_2.area == 6

    assert mesh_1.min == mesh_2.min == Point3D(0, 0, 2)
    assert mesh_1.max == mesh_2.max == Point3D(4, 2, 2)
    assert mesh_1.center == mesh_2.center == Point3D(2, 1, 2)

    assert len(mesh_1.face_areas) == len(mesh_2.face_areas) == 2
    assert mesh_1.face_areas[0] == mesh_2.face_areas[0] == 4
    assert mesh_1.face_areas[1] == mesh_2.face_areas[1] == 2
    assert len(mesh_1.face_centroids) == len(mesh_2.face_centroids) == 2
    assert mesh_1.face_centroids[0] == mesh_2.face_centroids[0] == Point3D(
        1, 1, 2)
    assert mesh_1.face_centroids[1].x == mesh_2.face_centroids[
        1].x == pytest.approx(2.67, rel=1e-2)
    assert mesh_1.face_centroids[1].y == mesh_2.face_centroids[
        1].y == pytest.approx(0.67, rel=1e-2)
    assert mesh_1.face_centroids[1].z == mesh_2.face_centroids[
        1].z == pytest.approx(2, rel=1e-2)

    assert mesh_1._is_color_by_face is mesh_1._is_color_by_face is False
    assert mesh_1.colors is mesh_1.colors is None
def test_to_from_stl_ascii():
    """Test from_stl method with an ascii STL file."""
    file_path = 'tests/stl/cube_ascii.stl'
    mesh = Mesh3D.from_stl(file_path)
    centroids = [
        Point3D(3.33, 0.00, 1.67),
        Point3D(1.67, 0.00, 3.33),
        Point3D(5.00, 3.33, 1.67),
        Point3D(5.00, 1.67, 3.33),
        Point3D(1.67, 5.00, 1.67),
        Point3D(3.33, 5.00, 3.33),
        Point3D(0.00, 1.67, 1.67),
        Point3D(0.00, 3.33, 3.33),
        Point3D(1.67, 1.67, 0.00),
        Point3D(3.33, 3.33, 0.00),
        Point3D(1.67, 1.67, 5.00),
        Point3D(3.33, 3.33, 5.00),
        Point3D(3.33, 0.00, 1.67)
    ]
    for count, cent in enumerate(mesh.face_centroids):
        assert cent.distance_to_point(centroids[count]) <= 0.01

    new_folder, new_name = 'tests/stl/', 'cube_ascii_new.stl'
    new_file = mesh.to_stl(new_folder, new_name)
    assert os.path.isfile(new_file)
    Mesh3D.from_stl(new_file)
    os.remove(new_file)
Exemple #3
0
def test_mesh3d_to_from_dict():
    """Test the to/from dict of Mesh3D objects."""
    pts = (Point3D(0, 0), Point3D(0, 2), Point3D(2, 2), Point3D(2, 0))
    mesh = Mesh3D(pts, [(0, 1, 2, 3)])
    mesh_dict = mesh.to_dict()
    new_mesh = Mesh3D.from_dict(mesh_dict)
    assert isinstance(new_mesh, Mesh3D)
    assert new_mesh.to_dict() == mesh_dict
Exemple #4
0
    def _generate_bottom_from_top(m_top, v_top):
        """Get a joined mesh and vectors for top and bottom from only top vectors."""
        # reverse the vectors and negate all the z values of the sky patch mesh
        verts = tuple(Point3D(pt.x, pt.y, -pt.z) for pt in m_top.vertices)
        faces = tuple(face[::-1] for face in m_top.faces)
        m_bottom = Mesh3D(verts, faces)
        v_bottom = tuple(Vector3D(v.x, v.y, -v.z) for v in v_top)

        # join everything together
        patch_mesh = Mesh3D.join_meshes([m_top, m_bottom])
        patch_vectors = v_top + v_bottom
        return patch_mesh, patch_vectors
def test_mesh3d_incorrect():
    """Test the initialization of Mesh3D objects with incorrect values."""
    pts = (Point3D(0, 0), Point3D(0, 2), Point3D(2, 2), Point3D(2, 0), Point3D(4, 0))
    with pytest.raises(AssertionError):
        Mesh3D(pts, [(0, 1, 2, 3, 5)])  # too many vertices in a face
    with pytest.raises(AssertionError):
        Mesh3D(pts, [])  # we need at least one face
    with pytest.raises(AssertionError):
        Mesh3D(pts, (0, 1, 2, 3))  # incorrect input type for face
    with pytest.raises(IndexError):
        Mesh3D(pts, [(0, 1, 2, 6)])  # incorrect index used by face
    with pytest.raises(TypeError):
        Mesh3D(pts, [(0.0, 1, 2, 6)])  # incorrect use of floats for face index
def test_equality():
    """Test the equality of Mesh3D objects."""
    pts = (Point3D(0, 0, 2), Point3D(0, 2, 2), Point3D(2, 2, 2), Point3D(2, 0, 2))
    pts_2 = (Point3D(0.1, 0, 2), Point3D(0, 2, 2), Point3D(2, 2, 2), Point3D(2, 0, 2))
    mesh = Mesh3D(pts, [(0, 1, 2, 3)])
    mesh_dup = mesh.duplicate()
    mesh_alt = Mesh3D(pts_2, [(0, 1, 2, 3)])

    assert mesh is mesh
    assert mesh is not mesh_dup
    assert mesh == mesh_dup
    assert hash(mesh) == hash(mesh_dup)
    assert mesh != mesh_alt
    assert hash(mesh) != hash(mesh_alt)
Exemple #7
0
def test_mesh3d_to_from_json():
    """Test the to/from dict with JSON serialization of Mesh3D objects."""
    pts = (Point3D(0, 0), Point3D(0, 2), Point3D(2, 2), Point3D(2, 0))
    mesh = Mesh3D(pts, [(0, 1, 2, 3)])
    mesh_dict = mesh.to_dict()
    geo_file = './tests/json/json_mesh.json'
    with open(geo_file, 'w') as fp:
        json.dump(mesh_dict, fp)
    with open(geo_file, 'r') as fp:
        new_mesh_dict = json.load(fp)
    new_mesh = Mesh3D.from_dict(new_mesh_dict)
    assert isinstance(new_mesh, Mesh3D)
    assert new_mesh.to_dict() == mesh_dict
    os.remove(geo_file)
def test_offset_mesh():
    """Test the offset_mesh method."""
    pts = (Point3D(0, 0, 2), Point3D(0, 2, 2), Point3D(2, 2, 2), Point3D(2, 0, 2))
    pts_rev = tuple(reversed(pts))
    mesh = Mesh3D(pts, [(0, 1, 2, 3)])
    mesh_rev = Mesh3D(pts_rev, [(0, 1, 2, 3)])

    new_mesh = mesh.offset_mesh(2)
    for v in new_mesh.vertices:
        assert v.z == 0

    new_mesh_rev = mesh_rev.offset_mesh(2)
    for v in new_mesh_rev.vertices:
        assert v.z == 4
Exemple #9
0
    def from_dict(cls, ag_dict):
        """Create a sensor grid from a dictionary in the following format.

        .. code-block:: python

            {
            "type": "SensorGrid",
            "identifier": str,  # SensorGrid identifier
            "display_name": str,  # SensorGrid display name
            "sensors": [],  # list of Sensor dictionaries
            'room_identifier': str,  # optional room identifier
            'group_identifier': str,  # optional group identifier
            'light_path':  []  # optional list of lists for light path
            }
        """
        assert ag_dict['type'] == 'SensorGrid', \
            'Expected SensorGrid dictionary. Got {}.'.format(ag_dict['type'])
        sensors = (Sensor.from_dict(sensor) for sensor in ag_dict['sensors'])
        new_obj = cls(identifier=ag_dict["identifier"], sensors=sensors)
        if 'display_name' in ag_dict and ag_dict['display_name'] is not None:
            new_obj.display_name = ag_dict['display_name']
        if 'room_identifier' in ag_dict and ag_dict[
                'room_identifier'] is not None:
            new_obj.room_identifier = ag_dict['room_identifier']
        if 'group_identifier' in ag_dict and ag_dict[
                'group_identifier'] is not None:
            new_obj.group_identifier = ag_dict['group_identifier']
        if 'light_path' in ag_dict and ag_dict['light_path'] is not None:
            new_obj.light_path = ag_dict['light_path']
        if 'mesh' in ag_dict and ag_dict['mesh'] is not None:
            new_obj.mesh = Mesh3D.from_dict(ag_dict['mesh'])
        if 'base_geometry' in ag_dict and ag_dict['base_geometry'] is not None:
            new_obj.base_geometry = \
                tuple(Face3D.from_dict(face) for face in ag_dict['base_geometry'])
        return new_obj
Exemple #10
0
    def generate_grid(self, x_dim, y_dim=None, offset=1.0):
        """Get a list of gridded Mesh3D objects offset from the floors of this room.

        Note that the x_dim and y_dim refer to dimensions within the XY coordinate
        system of the floor faces's planes. So rotating the planes of the floor faces
        will result in rotated grid cells.

        Will be None if the Room has no floor faces.

        Args:
            x_dim: The x dimension of the grid cells as a number.
            y_dim: The y dimension of the grid cells as a number. Default is None,
                which will assume the same cell dimension for y as is set for x.
            offset: A number for how far to offset the grid from the base face.
                Default is 1.0, which will not offset the grid to be 1 unit above
                the floor.

        Usage:

        .. code-block:: python

            room = Room.from_box(3.0, 6.0, 3.2, 180)
            floor_mesh = room.generate_grid(0.5, 0.5, 1)
            test_points = floor_mesh.face_centroids
        """
        floor_grids = []
        for face in self._faces:
            if isinstance(face.type, Floor):
                floor_grids.append(
                    face.geometry.mesh_grid(x_dim, y_dim, offset, True))
        if len(floor_grids) == 1:
            return floor_grids[0]
        elif len(floor_grids) > 1:
            return Mesh3D.join_meshes(floor_grids)
        return None
Exemple #11
0
def test_mesh3d_init():
    """Test the initialization of Mesh3D objects and basic properties."""
    pts = (Point3D(0, 0, 2), Point3D(0, 2, 2), Point3D(2, 2,
                                                       2), Point3D(2, 0, 2))
    mesh = Mesh3D(pts, [(0, 1, 2, 3)])
    str(mesh)  # test the string representation of the object

    assert len(mesh.vertices) == 4
    assert len(mesh.faces) == 1
    assert mesh[0] == Point3D(0, 0, 2)
    assert mesh[1] == Point3D(0, 2, 2)
    assert mesh[2] == Point3D(2, 2, 2)
    assert mesh[3] == Point3D(2, 0, 2)
    assert mesh.area == 4

    assert mesh.min == Point3D(0, 0, 2)
    assert mesh.max == Point3D(2, 2, 2)
    assert mesh.center == Point3D(1, 1, 2)

    assert len(mesh.face_areas) == 1
    assert mesh.face_areas[0] == 4
    assert len(mesh.face_centroids) == 1
    assert mesh.face_centroids[0] == Point3D(1, 1, 2)
    assert mesh._is_color_by_face is False
    assert mesh.colors is None
    assert len(mesh.vertex_connected_faces) == 4
    for vf in mesh.vertex_connected_faces:
        assert len(vf) == 1

    mesh.colors = []
    assert mesh.colors is None
def test_join_meshes():
    """Test the join_meshes method."""
    pts1 = (Point3D(0, 0, 2), Point3D(0, 2, 2), Point3D(2, 2, 2), Point3D(2, 0, 2))
    pts2 = (Point3D(2, 2, 2), Point3D(2, 4, 2), Point3D(4, 4, 2), Point3D(4, 2, 2))
    mesh1 = Mesh3D(pts1, [(0, 1, 2, 3)])
    mesh2 = Mesh3D(pts2, [(0, 1, 2, 3)])
    mesh1.face_centroids
    mesh2.face_centroids
    mesh1.face_normals
    mesh2.face_normals

    joined_mesh = Mesh3D.join_meshes([mesh1, mesh2])

    assert isinstance(joined_mesh, Mesh3D)
    assert len(joined_mesh.faces) == 2
    assert len(joined_mesh.vertices) == 8
Exemple #13
0
def test_rotate():
    """Test the Mesh3D rotate method."""
    pts = (Point3D(0, 0, 2), Point3D(0, 2, 2), Point3D(2, 2, 2),
           Point3D(2, 0, 2), Point3D(4, 0, 2))
    mesh = Mesh3D(pts, [(0, 1, 2, 3), (2, 3, 4)])
    origin = Point3D(0, 0, 0)
    axis = Vector3D(1, 0, 0)

    test_1 = mesh.rotate(axis, math.pi, origin)
    assert test_1[0].x == pytest.approx(0, rel=1e-3)
    assert test_1[0].y == pytest.approx(0, rel=1e-3)
    assert test_1[0].z == pytest.approx(-2, rel=1e-3)
    assert test_1[2].x == pytest.approx(2, rel=1e-3)
    assert test_1[2].y == pytest.approx(-2, rel=1e-3)
    assert test_1[2].z == pytest.approx(-2, rel=1e-3)
    assert mesh.area == test_1.area
    assert len(mesh.vertices) == len(test_1.vertices)
    assert len(mesh.faces) == len(test_1.faces)

    test_2 = mesh.rotate(axis, math.pi / 2, origin)
    assert test_2[0].x == pytest.approx(0, rel=1e-3)
    assert test_2[0].y == pytest.approx(-2, rel=1e-3)
    assert test_2[0].z == pytest.approx(0, rel=1e-3)
    assert test_2[2].x == pytest.approx(2, rel=1e-3)
    assert test_2[2].y == pytest.approx(-2, rel=1e-3)
    assert test_2[2].z == pytest.approx(2, rel=1e-3)
    assert mesh.area == test_2.area
    assert len(mesh.vertices) == len(test_2.vertices)
    assert len(mesh.faces) == len(test_2.faces)
Exemple #14
0
def test_remove_faces():
    """Test the Mesh3D remove_faces method."""
    mesh_2d = Mesh2D.from_grid(Point2D(1, 1), 8, 2, 0.25, 1)
    mesh = Mesh3D.from_mesh2d(mesh_2d)
    assert len(mesh.vertices) == 27
    assert len(mesh.faces) == 16
    assert mesh.area == 4

    pattern_1 = []
    for i in range(4):
        pattern_1.extend([True, False, False, False])
    mesh_1, vert_pattern = mesh.remove_faces(pattern_1)
    assert len(mesh_1.vertices) == 16
    assert len(mesh_1.faces) == 4
    assert mesh_1.area == 1
    for face in mesh_1.faces:
        for i in face:
            mesh_1[i]  # make sure all face indices reference current vertices

    pattern_2 = []
    for i in range(8):
        pattern_2.extend([True, False])
    mesh_2, vert_pattern = mesh.remove_faces(pattern_2)
    assert len(mesh_2.vertices) == 18
    assert len(mesh_2.faces) == 8
    assert mesh_2.area == 2
    for face in mesh_2.faces:
        for i in face:
            mesh_2[i]  # make sure all face indices reference current vertices
Exemple #15
0
def test_init_graphic_con():
    """Test the initialization of GraphicContainer objects."""
    mesh2d = Mesh2D.from_grid(num_x=2, num_y=2)
    mesh3d = Mesh3D.from_mesh2d(mesh2d)
    data = [0, 1, 2, 3]
    graphic_con = GraphicContainer(data, mesh3d.min, mesh3d.max)

    str(graphic_con)  # Test the GraphicContainer representation

    assert len(graphic_con) == 4
    assert graphic_con[0] == 0
    assert graphic_con[-1] == 3
    for item in graphic_con:
        assert isinstance(item, (float, int))

    assert len(graphic_con.values) == 4
    assert isinstance(graphic_con.legend, Legend)
    assert graphic_con.value_colors == graphic_con.legend.value_colors

    assert graphic_con.legend_parameters.is_base_plane_default is False
    assert graphic_con.legend_parameters.is_segment_height_default is False
    assert graphic_con.legend_parameters.is_segment_width_default is True
    assert graphic_con.legend_parameters.is_text_height_default is True
    assert graphic_con.legend_parameters.base_plane != Plane()

    assert isinstance(graphic_con.lower_title_location, Plane)
    assert isinstance(graphic_con.upper_title_location, Plane)
    assert graphic_con.lower_title_location != Plane()
    assert graphic_con.upper_title_location != Plane()
Exemple #16
0
def test_reflect():
    """Test the Mesh3D reflect method."""
    pts = (Point3D(1, 1, 2), Point3D(2, 1, 2), Point3D(2, 2,
                                                       2), Point3D(1, 2, 2))
    mesh = Mesh3D(pts, [(0, 1, 2, 3)])
    origin_1 = Point3D(1, 0, 2)
    normal_1 = Vector3D(1, 0, 0)
    normal_2 = Vector3D(-1, -1, 0).normalize()

    test_1 = mesh.reflect(normal_1, origin_1)
    assert test_1[0].x == pytest.approx(1, rel=1e-3)
    assert test_1[0].y == pytest.approx(1, rel=1e-3)
    assert test_1[0].z == pytest.approx(2, rel=1e-3)
    assert test_1[2].x == pytest.approx(0, rel=1e-3)
    assert test_1[2].y == pytest.approx(2, rel=1e-3)
    assert test_1[2].z == pytest.approx(2, rel=1e-3)

    test_1 = mesh.reflect(normal_2, Point3D(0, 0, 0))
    assert test_1[0].x == pytest.approx(-1, rel=1e-3)
    assert test_1[0].y == pytest.approx(-1, rel=1e-3)
    assert test_1[0].z == pytest.approx(2, rel=1e-3)
    assert test_1[2].x == pytest.approx(-2, rel=1e-3)
    assert test_1[2].y == pytest.approx(-2, rel=1e-3)
    assert test_1[2].z == pytest.approx(2, rel=1e-3)

    test_2 = mesh.reflect(normal_2, origin_1)
    assert test_2[0].x == pytest.approx(0, rel=1e-3)
    assert test_2[0].y == pytest.approx(0, rel=1e-3)
    assert test_2[0].z == pytest.approx(2, rel=1e-3)
    assert test_2[2].x == pytest.approx(-1, rel=1e-3)
    assert test_2[2].y == pytest.approx(-1, rel=1e-3)
    assert test_2[2].z == pytest.approx(2, rel=1e-3)
Exemple #17
0
def test_mesh3d_init_two_faces():
    """Test the initialization of Mesh3D objects with two faces."""
    pts = (Point3D(0, 0, 2), Point3D(0, 2, 2), Point3D(2, 2, 2),
           Point3D(2, 0, 2), Point3D(4, 0, 2))
    mesh = Mesh3D(pts, [(0, 1, 2, 3), (2, 3, 4)])

    assert len(mesh.vertices) == 5
    assert len(mesh.faces) == 2
    assert mesh[0] == Point3D(0, 0, 2)
    assert mesh[1] == Point3D(0, 2, 2)
    assert mesh[2] == Point3D(2, 2, 2)
    assert mesh[3] == Point3D(2, 0, 2)
    assert mesh[4] == Point3D(4, 0, 2)
    assert mesh.area == 6

    assert mesh.min == Point3D(0, 0, 2)
    assert mesh.max == Point3D(4, 2, 2)
    assert mesh.center == Point3D(2, 1, 2)

    assert len(mesh.face_areas) == 2
    assert mesh.face_areas[0] == 4
    assert mesh.face_areas[1] == 2
    assert len(mesh.face_centroids) == 2
    assert mesh.face_centroids[0] == Point3D(1, 1, 2)
    assert mesh.face_centroids[1].x == pytest.approx(2.67, rel=1e-2)
    assert mesh.face_centroids[1].y == pytest.approx(0.67, rel=1e-2)
    assert mesh.face_centroids[1].z == pytest.approx(2, rel=1e-2)
    assert mesh._is_color_by_face is False
    assert mesh.colors is None
    def radial_positions_mesh(positions,
                              dir_count=8,
                              start_vector=Vector3D(0, -1, 0),
                              mesh_radius=1):
        """Generate a Mesh3D resembling a circle around each position.

        Args:
            positions: A list of (x, y ,z) tuples for position of sensors.
            dir_count: A positive integer for the number of radial directions
                to be generated around each position. (Default: 8).
            start_vector: A Vector3D to set the start direction of the generated
                directions. (Default: (0, -1, 0)).
            mesh_radius: A number for the radius of the radial mesh to be
                generated around each sensor. (Default: 1).
        """
        # set up the start vector and rotation angles
        st_vec = Vector3D(start_vector.x, start_vector.y, 0).normalize()
        st_vec = st_vec * mesh_radius
        inc_ang = (math.pi * 2) / dir_count
        st_vec = st_vec.rotate_xy(-inc_ang / 2)
        # loop through the positions and angles to create the mesh
        verts, faces = [], []
        v_count = 0
        for pt in positions:
            st_pt = Point3D(*pt)
            nxt_pt = st_pt.move(st_vec)
            verts.extend([st_pt, nxt_pt])
            for i in range(dir_count - 1):
                new_pt = verts[-1].rotate_xy(inc_ang, st_pt)
                new_f = (v_count, v_count + i + 1, v_count + i + 2)
                verts.append(new_pt)
                faces.append(new_f)
            faces.append((v_count, v_count + dir_count, v_count + 1))
            v_count += (dir_count + 1)
        return Mesh3D(verts, faces)
Exemple #19
0
 def _compute_colored_mesh3d(self):
     """Compute a colored mesh from this object's data collection."""
     _colored_mesh3d = Mesh3D.from_mesh2d(
         self.colored_mesh2d,
         Plane(o=Point3D(0, 0, self._container.min_point.z)))
     if self.z_dim != 0:
         _colored_mesh3d = _colored_mesh3d.height_field_mesh(
             self.data_collection.values, (0, self.z_dim))
     return _colored_mesh3d
Exemple #20
0
    def test_init_graphic_con_invalid(self):
        """Test the initialization of GraphicContainer objects with invalid inputs."""
        mesh2d = Mesh2D.from_grid(num_x=2, num_y=2)
        mesh3d = Mesh3D.from_mesh2d(mesh2d)
        data = [0, 1, 2, 3, 4]

        with pytest.raises(Exception):
            GraphicContainer(data, mesh3d.min, mesh3d.max,
                             data_type=Temperature(), unit='NotAUnit')
Exemple #21
0
def test_from_mesh3d():
    mesh_2d = Mesh2D.from_grid(Point2D(1, 1), 8, 2, 0.25, 1)
    mesh = Mesh3D.from_mesh2d(mesh_2d)
    sg = SensorGrid.from_mesh3d('sg_1', mesh)

    assert len(sg.sensors) == 16
    assert len(sg.mesh.vertices) == 27
    assert len(sg.mesh.faces) == 16
    assert mesh.area == 4
def to_mesh3d(mesh, color_by_face=True):
    """Ladybug Mesh3D from Rhino Mesh."""
    if isinstance(mesh, Mesh3D):
        return mesh
    elif isinstance(mesh, bpy.types.Object):
        lb_verts = tuple(
            to_point3d(mesh.matrix_world @ pt.co) for pt in mesh.data.vertices)
        lb_faces, colors = _extract_mesh_faces_colors(mesh, mesh.data,
                                                      color_by_face)
        return Mesh3D(lb_verts, lb_faces, colors)
Exemple #23
0
def test_to_from_dict():
    """Test the to/from dict methods."""
    mesh2d = Mesh2D.from_grid(num_x=2, num_y=2)
    mesh3d = Mesh3D.from_mesh2d(mesh2d)
    data = [0, 1, 2, 3]
    graphic_con = GraphicContainer(data, mesh3d.min, mesh3d.max)

    graphic_con_dict = graphic_con.to_dict()
    new_graphic_con = GraphicContainer.from_dict(graphic_con_dict)
    assert new_graphic_con.to_dict() == graphic_con_dict
def test_face_normals():
    """Test the Mesh3D face_normals property."""
    pts = (Point3D(0, 0, 2), Point3D(0, 2, 2), Point3D(2, 2, 2), Point3D(2, 0, 2))
    mesh = Mesh3D(pts, [(0, 1, 2, 3)])

    assert len(mesh.face_normals) == 1
    assert mesh.face_normals[0] == Vector3D(0, 0, -1)
    assert len(mesh.vertex_normals) == 4
    for vert_norm in mesh.vertex_normals:
        assert vert_norm == Vector3D(0, 0, -1)
    def _aperture_view_factor(project_folder,
                              apertures,
                              size=0.2,
                              ambient_division=1000,
                              receiver='rflux_sky.sky',
                              octree='scene.oct',
                              calc_folder='dmtx_aperture_grouping'):
        """Calculates the view factor for each aperture by sensor points."""

        # Instantiate dictionary that will store the sensor count for each aperture. We need
        # a OrderedDict so that we can split the rfluxmtx output file by each aperture
        # (sensor count) in the correct order.
        ap_dict = OrderedDict()

        meshes = []
        # Create a mesh for each aperture and add the the sensor count to dict.
        for aperture in apertures:
            ap_mesh = aperture.geometry.mesh_grid(size,
                                                  flip=True,
                                                  generate_centroids=False)
            meshes.append(ap_mesh)
            ap_dict[aperture.display_name] = {
                'sensor_count': len(ap_mesh.faces)
            }

        # Create a sensor grid from joined aperture mesh.
        grid_mesh = SensorGrid.from_mesh3d('aperture_grid',
                                           Mesh3D.join_meshes(meshes))

        # Write sensor grid to pts file.
        sensors = grid_mesh.to_file(os.path.join(project_folder, calc_folder),
                                    file_name='apertures')

        # rfluxmtx options
        rfluxOpt = RfluxmtxOptions()
        rfluxOpt.ad = ambient_division
        rfluxOpt.lw = 1.0 / float(rfluxOpt.ad)
        rfluxOpt.I = True
        rfluxOpt.h = True

        # rfluxmtx command
        rflux = Rfluxmtx()
        rflux.options = rfluxOpt
        rflux.receivers = receiver
        rflux.sensors = sensors
        rflux.octree = octree
        rflux.output = os.path.join(calc_folder, 'apertures_vf.mtx')

        # Run rfluxmtx command
        rflux.run(cwd=project_folder)

        # Get the output file of the rfluxmtx command.
        mtx_file = os.path.join(project_folder, rflux.output)

        return mtx_file, ap_dict
def test_height_field_mesh():
    """Test the height_field_mesh method."""
    pts = (Point3D(0, 0, 0), Point3D(2, 0, 0), Point3D(2, 2, 0), Point3D(0, 2, 0))
    mesh = Mesh3D(pts, [(0, 1, 2, 3)])
    values = [-1, 0, 1, 2]

    new_mesh = mesh.height_field_mesh(values, (0, 3))
    assert new_mesh[0].z == 0
    assert new_mesh[1].z == 1
    assert new_mesh[2].z == 2
    assert new_mesh[3].z == 3
Exemple #27
0
    def dome_radial_patches(self, azimuth_count=72, altitude_count=18):
        """Get Vector3Ds and a correcponding Mesh3D for a a radial dome.

        Args:
            azimuth_count: A positive integer for the number of times that
                the horizontal circle will be subdivided into azimuth
                patches. (Default: 72).
            altitude_count: A positive integer for the number of times that
                the dome quarter-circle will be subdivided into altitude
                patches. (Default: 18).

        Returns:
            A tuple with two elements

            -   patch_mesh: A ladybug_geometry Mesh3D that represents the patches at
                the input azimuth_count and altitude_count.

            -   patch_vectors: A list of ladybug_geometry Vector3D with one vector
                per mesh face. These will align with the faces of the patch_mesh.
                All vectors are unit vectors.
        """
        # set up starting vectors and points
        base_vec, rotate_axis = Vector3D(0, 1, 0), Vector3D(1, 0, 0)
        horiz_angle = -2 * math.pi / azimuth_count
        vertical_angle = math.pi / (2 * altitude_count)

        # loop through the patch values and generate points for each vertex
        vertices, faces = [], []
        pt_i = -2  # track the number of vertices in the mesh
        for row_i in range(altitude_count - 1):
            pt_i += 2  # advance the number of vertices by two
            vec1 = base_vec.rotate(rotate_axis, vertical_angle * row_i)
            vec2 = vec1.rotate(rotate_axis, vertical_angle)
            vertices.extend((Point3D(v.x, v.y, v.z) for v in (vec1, vec2)))
            for _ in range(azimuth_count):  # generate the row of patches
                vec3 = vec1.rotate_xy(horiz_angle)
                vec4 = vec2.rotate_xy(horiz_angle)
                vertices.extend((Point3D(v.x, v.y, v.z) for v in (vec3, vec4)))
                faces.append((pt_i, pt_i + 1, pt_i + 3, pt_i + 2))
                pt_i += 2  # advance the number of vertices by two
                vec1, vec2 = vec3, vec4  # reset vec1 and vec2 for the next patch

        # add triangular faces to represent the last circular patch
        end_vert_i = len(vertices)
        start_vert_i = len(vertices) - azimuth_count * 2 - 1
        vertices.append(Point3D(0, 0, 1))
        for tr_i in range(0, azimuth_count * 2, 2):
            faces.append((start_vert_i + tr_i, end_vert_i, start_vert_i + tr_i + 2))

        # create the Mesh3D object and derive the patch vectors from the mesh
        patch_mesh = Mesh3D(vertices, faces)
        patch_vectors = patch_mesh.face_normals
        return patch_mesh, patch_vectors
Exemple #28
0
def test_height_field_mesh_faces():
    """Test the height_field_mesh method with values for faces."""
    pts = (Point3D(0, 0, 0), Point3D(2, 0, 0), Point3D(2, 2, 0),
           Point3D(0, 2, 0), Point3D(4, 0, 0))
    mesh = Mesh3D(pts, [(0, 1, 2, 3), (2, 3, 4)])
    values = [-1, 1]

    new_mesh = mesh.height_field_mesh(values, (1, 2))
    assert new_mesh[0].z == 1
    assert new_mesh[1].z == 1
    assert new_mesh[2].z == 1.5
    assert new_mesh[3].z == 1.5
    assert new_mesh[4].z == 2
Exemple #29
0
def test_scale_world_origin():
    """Test the Mesh2D scale method with None origin."""
    pts = (Point3D(0, 0, 2), Point3D(0, 2, 2), Point3D(2, 2, 2),
           Point3D(2, 0, 2), Point3D(4, 0, 2))
    mesh = Mesh3D(pts, [(0, 1, 2, 3), (2, 3, 4)])

    new_mesh_1 = mesh.scale(2)
    assert new_mesh_1[0] == Point3D(0, 0, 4)
    assert new_mesh_1[1] == Point3D(0, 4, 4)
    assert new_mesh_1[2] == Point3D(4, 4, 4)
    assert new_mesh_1[3] == Point3D(4, 0, 4)
    assert new_mesh_1[4] == Point3D(8, 0, 4)
    assert new_mesh_1.area == 24
    assert len(mesh.vertices) == len(new_mesh_1.vertices)
    assert len(mesh.faces) == len(new_mesh_1.faces)
Exemple #30
0
def test_init_graphic_con_vertex_based():
    """Test the initialization of ResultMesh objects with vertex-based input."""
    mesh2d = Mesh2D.from_grid(num_x=2, num_y=2)
    mesh3d = Mesh3D.from_mesh2d(mesh2d)
    data = [0, 1, 2, 3, 4, 5, 6, 7, 8]
    graphic_con = GraphicContainer(data, mesh3d.min, mesh3d.max)

    assert len(graphic_con) == 9
    assert graphic_con[0] == 0
    assert graphic_con[-1] == 8

    assert len(graphic_con.values) == 9
    assert isinstance(graphic_con.legend_parameters, LegendParameters)
    assert isinstance(graphic_con.legend, Legend)
    assert graphic_con.value_colors == graphic_con.legend.value_colors