Beispiel #1
0
    def from_dict(cls, data):
        """Create DetailedWindows from a dictionary.

        .. code-block:: python

            {
            "type": "DetailedWindows",
            "polygons": [((0.5, 0.5), (2, 0.5), (2, 2), (0.5, 2)),
                         ((3, 1), (4, 1), (4, 2))]
            }
        """
        assert data['type'] == 'DetailedWindows', \
            'Expected DetailedWindows dictionary. Got {}.'.format(data['type'])
        return cls(
            tuple(
                Polygon2D(tuple(Point2D.from_array(pt) for pt in poly))
                for poly in data['polygons']))
def test_remove_vertices():
    """Test the Mesh2D remove_vertices method."""
    mesh = Mesh2D.from_grid(Point2D(1, 1), 8, 2, 0.25, 1)
    assert len(mesh.vertices) == 27
    assert len(mesh.faces) == 16
    assert mesh.area == 4

    pattern_1 = []
    for i in range(9):
        pattern_1.extend([True, True, False])
    mesh_1, vert_pattern = mesh.remove_vertices(pattern_1)
    assert len(mesh_1.vertices) == 18
    assert len(mesh_1.faces) == 8
    assert mesh_1.area == 2
    for face in mesh_1.faces:
        for i in face:
            mesh_1[i]  # make sure all face indices reference current vertices
def test_linesegment2_init():
    """Test the initalization of LineSegment2D objects and basic properties."""
    pt = Point2D(2, 0)
    vec = Vector2D(0, 2)
    seg = LineSegment2D(pt, vec)
    str(seg)  # test the string representation of the line segment

    assert seg.p == Point2D(2, 0)
    assert seg.v == Vector2D(0, 2)
    assert seg.p1 == Point2D(2, 0)
    assert seg.p2 == Point2D(2, 2)
    assert seg.midpoint == Point2D(2, 1)
    assert seg.point_at(0.25) == Point2D(2, 0.5)
    assert seg.point_at_length(1) == Point2D(2, 1)
    assert seg.length == 2

    flip_seg = seg.flip()
    assert flip_seg.p == Point2D(2, 2)
    assert flip_seg.v == Vector2D(0, -2)
Beispiel #4
0
def test_scale():
    """Test the Ray2D scale method."""
    pt = Point2D(2, 2)
    vec = Vector2D(0, 2)
    ray = Ray2D(pt, vec)

    origin_1 = Point2D(0, 2)
    origin_2 = Point2D(1, 1)
    new_ray = ray.scale(2, origin_1)
    assert new_ray.p == Point2D(4, 2)
    assert new_ray.v == Point2D(0, 4)
    assert new_ray.v.magnitude == 4

    new_ray = ray.scale(2, origin_2)
    assert new_ray.p == Point2D(3, 3)
    assert new_ray.v == Point2D(0, 4)
def test_scale():
    """Test the LineSegment2D scale method."""
    pt = Point2D(2, 2)
    vec = Vector2D(0, 2)
    seg = LineSegment2D(pt, vec)

    origin_1 = Point2D(0, 2)
    origin_2 = Point2D(1, 1)
    new_seg = seg.scale(2, origin_1)
    assert new_seg.p == Point2D(4, 2)
    assert new_seg.v == Point2D(0, 4)
    assert new_seg.length == 4

    new_seg = seg.scale(2, origin_2)
    assert new_seg.p == Point2D(3, 3)
    assert new_seg.v == Point2D(0, 4)
def test_model_init():
    """Test the initialization of Model objects and basic properties."""
    pts_1 = (Point3D(0, 0, 3), Point3D(0, 10, 3), Point3D(10, 10, 3), Point3D(10, 0, 3))
    pts_2 = (Point3D(10, 0, 3), Point3D(10, 10, 3), Point3D(20, 10, 3), Point3D(20, 0, 3))
    pts_3 = (Point3D(0, 10, 3), Point3D(0, 20, 3), Point3D(10, 20, 3), Point3D(10, 10, 3))
    pts_4 = (Point3D(10, 10, 3), Point3D(10, 20, 3), Point3D(20, 20, 3), Point3D(20, 10, 3))
    room2d_1 = Room2D('Office1', Face3D(pts_1), 3)
    room2d_2 = Room2D('Office2', Face3D(pts_2), 3)
    room2d_3 = Room2D('Office3', Face3D(pts_3), 3)
    room2d_4 = Room2D('Office4', Face3D(pts_4), 3)
    story = Story('Office_Floor', [room2d_1, room2d_2, room2d_3, room2d_4])
    story.solve_room_2d_adjacency(0.01)
    story.set_outdoor_window_parameters(SimpleWindowRatio(0.4))
    story.multiplier = 4
    building = Building('Office_Building', [story])

    tree_canopy_geo1 = Face3D.from_regular_polygon(6, 6, Plane(o=Point3D(5, -10, 6)))
    tree_canopy_geo2 = Face3D.from_regular_polygon(6, 2, Plane(o=Point3D(-5, -10, 3)))
    tree_canopy = ContextShade('Tree_Canopy', [tree_canopy_geo1, tree_canopy_geo2])

    model = Model('New_Development', [building], [tree_canopy])
    str(model)  # test the string representation of the object

    assert model.identifier == 'New_Development'
    assert model.display_name == 'New_Development'
    assert model.units == 'Meters'
    assert model.tolerance == 0.01
    assert model.angle_tolerance == 1.0
    assert len(model.buildings) == 1
    assert isinstance(model.buildings[0], Building)
    assert len(model.context_shades) == 1
    assert isinstance(model.context_shades[0], ContextShade)

    assert model.average_story_count == 4
    assert model.average_story_count_above_ground == 4
    assert model.average_height == 15
    assert model.average_height_above_ground == 12
    assert model.footprint_area == 100 * 4
    assert model.floor_area == 100 * 4 * 4
    assert model.exterior_wall_area == 60 * 4 * 4
    assert model.exterior_aperture_area == 60 * 4 * 4 * 0.4
    assert model.volume == 100 * 3 * 4 * 4
    assert model.min.x == pytest.approx(-6.73, rel=1e-2)
    assert model.min.y == pytest.approx(-16, rel=1e-2)
    assert model.max == Point2D(20, 20)
def test_mesh2d_init_from_polygon_triangulated_concave():
    """Test Mesh2D from_polygon_triangulated with a concave polygon."""
    verts = (Point2D(0, 0), Point2D(2, 0), Point2D(2, 1), Point2D(1, 1),
             Point2D(1, 2), Point2D(0, 2))
    polygon = Polygon2D(verts)
    mesh_1 = Mesh2D.from_polygon_triangulated(polygon)
    mesh_2 = Mesh2D.from_polygon_triangulated(polygon, False)

    assert len(mesh_1.vertices) == 6
    assert len(mesh_2.vertices) == 12
    assert len(mesh_1.faces) == len(mesh_2.faces) == 4
    assert mesh_1.area == mesh_2.area == 3

    assert mesh_1.min == mesh_2.min == Point2D(0, 0)
    assert mesh_1.max == mesh_2.max == Point2D(2, 2)
    assert mesh_1.center == mesh_2.center == Point2D(1, 1)
    assert mesh_1.centroid.x == mesh_2.centroid.x == pytest.approx(0.8333,
                                                                   rel=1e-2)
    assert mesh_1.centroid.y == mesh_2.centroid.y == pytest.approx(0.8333,
                                                                   rel=1e-2)

    assert len(mesh_1.face_areas) == len(mesh_2.face_areas) == 4
    assert len(mesh_1.face_centroids) == len(mesh_2.face_centroids) == 4
Beispiel #8
0
    def _compute_colored_mesh_array(hist_data, hist_data_stacked, bin_vecs,
                                    ytick_num, min_radius, max_radius,
                                    show_stack):
        """Compute a colored mesh from this object's histogram.

        Args:
            hist_data: Histogram of analysis values greater then zero.
            hist_data_stacked: Histogram of analysis values averaged by number of
                stacks.
            bin_vecs: Array of histogram bin edge vectors.
            ytick_num: Number of Y-axis intervals.
            min_radius: Minimum radius for windrose mesh.
            max_radius: Maximum radius for windrose mesh.
            show_stack: Boolean indicating if stacked histogram.
        Returns:
            A colored Mesh2D.
        """

        # Default rose is a unit circle centered at origin. We can scale and translate
        # the resulting mesh.
        vec_cpt = (0, 0)

        # Compute histogram array
        hist_array = WindRose._histogram_array_radial(bin_vecs, vec_cpt,
                                                      hist_data,
                                                      hist_data_stacked,
                                                      (min_radius, max_radius),
                                                      show_stack)

        # Flatten and add coordinates
        if not show_stack:
            hist_array = ([v] for v in hist_array)

        # Make mesh
        hist_coords = [interval for bar in hist_array for interval in bar]
        mesh_array = [[Point2D.from_array(vec) for vec in vecs]
                      for vecs in hist_coords]

        # Extract analysis values for color
        color_array = [
            interval for bar in hist_data_stacked for interval in bar
        ]

        return mesh_array, color_array
Beispiel #9
0
def test_intersect_polygon_segments_zero_tolerance():
    """Tests that the default tolerance of 0 does not update nearby polygons."""
    pts0 = (Point2D(1, 0), Point2D(4, 0), Point2D(4, 1.99), Point2D(1, 1.99))
    polygon0 = Polygon2D(pts0)
    pts1 = (Point2D(0, 2), Point2D(3, 2), Point2D(3, 4), Point2D(0, 4))
    polygon1 = Polygon2D(pts1)

    polygon2, polygon3 = Polygon2D._intersect_polygon_segments(
        polygon0, polygon1)

    assert len(polygon2.segments) == 4  # No new points
    assert all([
        polygon0.vertices[i] == polygon2.vertices[i]
        for i in range(len(polygon0.vertices))
    ])
    assert len(polygon3.segments) == 4  # No new points
    assert all([
        polygon1.vertices[i] == polygon3.vertices[i]
        for i in range(len(polygon1.vertices))
    ])
Beispiel #10
0
def test_arc2_init_radius():
    """Test the initalization of Arc2D objects with a non-unit radius."""
    pt = Point2D(2, 2)
    arc = Arc2D(pt, 2, math.pi, 0)

    assert arc.c == pt
    assert arc.r == 2
    assert arc.a1 == math.pi
    assert arc.a2 == 0
    assert arc.p1.x == pytest.approx(0, rel=1e-3)
    assert arc.p1.y == pytest.approx(2, rel=1e-3)
    assert arc.p2.x == pytest.approx(4, rel=1e-3)
    assert arc.p2.y == pytest.approx(2, rel=1e-3)
    assert arc.midpoint.x == pytest.approx(2, rel=1e-3)
    assert arc.midpoint.y == pytest.approx(0, rel=1e-3)
    assert arc.length == pytest.approx(2 * math.pi, rel=1e-3)
    assert arc.angle == pytest.approx(math.pi, rel=1e-3)
    assert arc.is_circle is False
    assert arc.is_inverted is True
Beispiel #11
0
def test_arc2_init_reveresed():
    """Test the initalization of Arc2D objects with reversed direction."""
    pt = Point2D(2, 0)
    arc = Arc2D(pt, 1, 1.5 * math.pi, 0.5 * math.pi)

    assert arc.c == pt
    assert arc.r == 1
    assert arc.a1 == 1.5 * math.pi
    assert arc.a2 == 0.5 * math.pi
    assert arc.p1.x == pytest.approx(2, rel=1e-3)
    assert arc.p1.y == pytest.approx(-1, rel=1e-3)
    assert arc.p2.x == pytest.approx(2, rel=1e-3)
    assert arc.p2.y == pytest.approx(1, rel=1e-3)
    assert arc.midpoint.x == pytest.approx(3, rel=1e-3)
    assert arc.midpoint.y == pytest.approx(0, rel=1e-3)
    assert arc.length == pytest.approx(math.pi, rel=1e-3)
    assert arc.angle == pytest.approx(math.pi, rel=1e-3)
    assert arc.is_circle is False
    assert arc.is_inverted is True
def test_polygon2d_init_from_shape_with_hole():
    """Test the initialization of Polygon2D from_shape_with_hole."""
    bound_pts = [Point2D(0, 0), Point2D(4, 0), Point2D(4, 4), Point2D(0, 4)]
    hole_pts = [Point2D(1, 1), Point2D(3, 1), Point2D(3, 3), Point2D(1, 3)]
    polygon = Polygon2D.from_shape_with_hole(bound_pts, hole_pts)

    assert isinstance(polygon.vertices, tuple)
    assert len(polygon.vertices) == 10
    for point in polygon.vertices:
        assert isinstance(point, Point2D)

    assert isinstance(polygon.segments, tuple)
    assert len(polygon.segments) == 10
    for seg in polygon.segments:
        assert isinstance(seg, LineSegment2D)

    assert polygon.area == 12
    assert polygon.perimeter == pytest.approx(26.828427, rel=1e-3)
    assert not polygon.is_clockwise
    assert not polygon.is_convex
    assert not polygon.is_self_intersecting
Beispiel #13
0
    def _hour_polylines(self, y_vals, x_hr_dist):
        """Get a polyline from a lists of Y-coordinate values.

        Args:
            y_vals: A list of lists with each sublist having y values.
            x_hr_dist: The x distance moved by each cell of the mesh.

        Returns:
            polylines: A list of Polyline2D.
        """
        plines = []
        for month in range(len(y_vals)):
            verts = []
            start_x = self._base_point.x + month * self._x_dim
            for hour in range(len(y_vals[0])):
                x_val = start_x + x_hr_dist * hour
                y_val = y_vals[month][hour]
                verts.append(Point2D(x_val, y_val))
            plines.append(Polyline2D(verts))
        return plines
def test_polygon2d_init_from_rectangle():
    """Test the initialization of Polygon2D from_rectangle."""
    polygon = Polygon2D.from_rectangle(Point2D(0, 0), Vector2D(0, 1), 2, 2)

    assert isinstance(polygon.vertices, tuple)
    assert len(polygon.vertices) == 4
    for point in polygon.vertices:
        assert isinstance(point, Point2D)

    assert isinstance(polygon.segments, tuple)
    assert len(polygon.segments) == 4
    for seg in polygon.segments:
        assert isinstance(seg, LineSegment2D)
        assert seg.length == 2

    assert polygon.area == 4
    assert polygon.perimeter == 8
    assert not polygon.is_clockwise
    assert polygon.is_convex
    assert not polygon.is_self_intersecting
def test_reflect():
    """Test the Point2D reflect method."""
    pt_1 = Point2D(2, 2)
    origin_1 = Point2D(0, 1)
    origin_2 = Point2D(1, 1)
    normal_1 = Vector2D(0, 1)
    normal_2 = Vector2D(-1, 1).normalize()

    assert pt_1.reflect(normal_1, origin_1) == Point2D(2, 0)
    assert pt_1.reflect(normal_1, origin_2) == Point2D(2, 0)
    assert pt_1.reflect(normal_2, origin_2) == Point2D(2, 2)

    test_1 = pt_1.reflect(normal_2, origin_1)
    assert test_1.x == pytest.approx(1, rel=1e-3)
    assert test_1.y == pytest.approx(3, rel=1e-3)
Beispiel #16
0
    def point3d_to_stereographic(point, radius=100, origin=Point3D()):
        """Get a Point2D for a given Point3D using a stereographic projection.

        Args:
            point: A ladybug_geometry Point3D to be projected into 2D space via
                stereographic projection.
            radius: A positive number for the radius of the sphere on which the
                point exists. (Default: 100).
            origin: An optional ladybug_geometry Point3D representing the origin
                of the coordinate system in which the projection is happening.
                (eg. the center of the compass).
        """
        # move the point to the world origin
        coords = ((point.x - origin.x), (point.y - origin.y),
                  (point.z - origin.z))
        # perform the stereographic projection while scaling it to the unit sphere
        proj_pt = (coords[0] / (radius + coords[2]),
                   coords[1] / (radius + coords[2]))
        # move the point back to its original location and scale
        return Point2D(proj_pt[0] * radius + origin.x,
                       proj_pt[1] * radius + origin.y)
Beispiel #17
0
def _normalize_contour(contour, tol):
    """
    Consumes list of x,y coordinate tuples and returns list of Point2Ds.

    Args:
        contour: list of x,y tuples from contour.
        tol: Number for point equivalence tolerance.
    Return:
         list of Point2Ds of contour.
    """
    contour = [Point2D(float(x), float(y)) for (x, y) in contour]
    normed_contour = []
    for prev, point, next in _window(contour):
        normed_prev = (point - prev).normalize()
        normed_next = (next - point).normalize()

        if not point.is_equivalent(next, tol) or \
                normed_prev.is_equivalent(normed_next, tol):
            normed_contour.append(point)

    return normed_contour
Beispiel #18
0
def test_closest_points_between_line():
    """Test the LineSegement2D distance_to_point method."""
    pt_1 = Point2D(2, 2)
    vec_1 = Vector2D(0, 2)
    seg_1 = LineSegment2D(pt_1, vec_1)

    pt_2 = Point2D(0, 3)
    vec_2 = Vector2D(1, 0)
    seg_2 = LineSegment2D(pt_2, vec_2)

    pt_3 = Point2D(0, 0)
    vec_3 = Vector2D(1, 1)
    seg_3 = LineSegment2D(pt_3, vec_3)

    assert seg_1.closest_points_between_line(seg_2) == (Point2D(2, 3), Point2D(1, 3))
    assert seg_1.closest_points_between_line(seg_3) == (Point2D(2, 2), Point2D(1, 1))

    assert seg_1.distance_to_line(seg_2) == 1
    assert seg_1.distance_to_line(seg_3) == pytest.approx(1.41421, rel=1e-3)
Beispiel #19
0
def draw_analemma_and_arcs(sp, datetimes, radius, center_pt3d):
    """Draw analemma and day arc Rhino geometry.

    Args:
        sp: Sunpath object for which geometry will be drawn.
        datetimes: A list of datetimes, which will be used to get days
            if _annual_ is False.
        radius: Number for the radius of the sun path.
        center_pt3d: Point3D for the center of the sun path.

    Returns:
        analemma: List of Rhino curves for the analemmas
        daily: List of Rhino curves for the daily arcs.
    """
    sp.daylight_saving_period = None  # set here so analemmas aren't messed up

    center_pt, z = Point2D(center_pt3d.x, center_pt3d.y), center_pt3d.z
    if _annual_:
        if projection_ is None:
            analemma = [from_polyline3d(pline) for pline in sp.hourly_analemma_polyline3d(
                center_pt3d, radius, True, solar_time_)]
            daily = [from_arc3d(arc) for arc in sp.monthly_day_arc3d(center_pt3d, radius)]
        else:
            analemma = [from_polyline2d(pline, z) for pline in sp.hourly_analemma_polyline2d(
                projection_, center_pt, radius, True, solar_time_)]
            daily = [from_polyline2d(arc, z) for arc in sp.monthly_day_polyline2d(
                projection_, center_pt3d, radius)]
    else:
        analemma = []  # No Analemmas for a daily sun path
        doys = set(dt.doy for dt in datetimes)
        dates = [Date.from_doy(doy) for doy in doys]
        if projection_ is None:
            daily = [from_arc3d(sp.day_arc3d(dat.month, dat.day, center_pt3d, radius))
                     for dat in dates]
        else:
            daily = []
            for dat in dates:
                pline = sp.day_polyline2d(dat.month, dat.day, projection_, center_pt, radius)
                daily.append(from_polyline2d(pline, z))
    return analemma, daily
Beispiel #20
0
    def flip(self, seg_length):
        """Flip the direction of the windows along a segment.

        This is needed since windows can exist asymmetrically across the wall
        segment and operations like reflecting the Room2D across a plane will
        require the window parameters to be flipped to remain in the same place.

        Args:
            seg_length: The length of the segment along which the parameters are
                being flipped.
        """
        # set values derived from the property of the segment
        normal = Vector2D(1, 0)
        origin = Point2D(seg_length / 2, 0)

        # loop through the polygons and reflect them across the midplane of the wall
        new_polygons = []
        for polygon in self.polygons:
            new_verts = tuple(
                pt.reflect(normal, origin) for pt in polygon.vertices)
            new_polygons.append(Polygon2D(tuple(reversed(new_verts))))
        return DetailedWindows(new_polygons)
Beispiel #21
0
def test_remove_faces_only():
    """Test the Mesh2D remove_faces method."""
    mesh = Mesh2D.from_grid(Point2D(1, 1), 8, 2, 0.25, 1)
    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 = mesh.remove_faces_only(pattern_1)
    assert len(mesh_1.vertices) == 27
    assert len(mesh_1.faces) == 4
    assert mesh_1.area == 1

    pattern_2 = []
    for i in range(8):
        pattern_2.extend([True, False])
    mesh_2 = mesh.remove_faces_only(pattern_2)
    assert len(mesh_2.vertices) == 27
    assert len(mesh_2.faces) == 8
    assert mesh_2.area == 2
Beispiel #22
0
    def from_epw(cls,
                 epw_file,
                 legend_parameters=None,
                 base_point=Point2D(),
                 x_dim=1,
                 y_dim=1500,
                 min_temperature=-20,
                 max_temperature=50,
                 max_humidity_ratio=0.03,
                 use_ip=False):
        """Create a psychrometric chart object using the data in an epw file.

        Args:
            epw_file: Full path to epw weather file.
            legend_parameters: An optional LegendParameter object to change the display
                of the PsychrometricChart. (Default: None).
            base_point: A Point2D to be used as a starting point to generate the geometry
                of the plot. (Default: (0, 0)).
            x_dim: A number to set the X dimension of each degree of temperature on the
                chart. (Default: 1).
            y_dim: A number to set the Y dimension of a unity humidity ratio on the chart.
                Note that most maximum humidity ratios are around 0.03. (Default: 1500).
            min_temperature: An integer for the minimum temperature on the chart in
                degrees. This should be celsius if use_ip is False and fahrenheit if
                use_ip is True. (Default: -20; suitable for celsius).
            max_temperature: An integer for the maximum temperature on the chart in
                degrees. This should be celsius if use_ip is False and fahrenheit if
                use_ip is True. (Default: 50; suitable for celsius).
            max_humidity_ratio: A value for the maximum humidity ratio in kg water / kg
                air. (Default: 0.03).
            use_ip: Boolean to note whether temperature values should be plotted in
                Fahrenheit instead of Celsius. (Default: False).
        """
        epw = EPW(epw_file)
        pressure = epw.atmospheric_station_pressure.average
        return cls(epw.dry_bulb_temperature, epw.relative_humidity, pressure,
                   legend_parameters, base_point, x_dim, y_dim,
                   min_temperature, max_temperature, max_humidity_ratio,
                   use_ip)
Beispiel #23
0
 def _compute_hour_line_pts(self, hour_labels):
     """Compute the points for the hour lines and labels."""
     st_hr = self.analysis_period.st_hour
     end_hr = self.analysis_period.end_hour + 1
     t_step = self.analysis_period.timestep
     _hour_points = []
     _hour_text = []
     last_hr = 0
     for hr in hour_labels:
         if st_hr <= hr <= end_hr:
             pt_y = self.base_point.y + (hr - st_hr) * self.y_dim * t_step
             pt = Point2D(self._container.min_point.x, pt_y)
             _hour_points.append(pt)
             hr_val = hr if hr <= 12 else hr - 12
             am_pm = 'PM' if 12 <= hr < 24 else 'AM'
             if hr_val == 0:
                 hr_val = 12
             _hour_text.append('{} {}'.format(hr_val, am_pm))
             last_hr = hr
     if self.analysis_period.timestep > 1 and last_hr == end_hr:
         _hour_points.pop(-1)
         _hour_text.pop(-1)
     return _hour_points, _hour_text
def infinite_line2d_intersection(seg1, seg2):
    """Intersects two line2D assuming they are infinite.

    This method computes the linear equation from the segments.
    Then solves the linear system to find the intersection for both:
    A * x = C
    x = A^-1 * C
    """

    # Compute the A,B coefficients
    seg1_3d = Point3D(*(seg1.p2 - seg1.p1).to_array(), 0)
    seg2_3d = Point3D(*(seg2.p2 - seg2.p1).to_array(), 0)

    z = Point3D(0, 0, 1)
    norm1 = seg1_3d.cross(z)
    norm2 = seg2_3d.cross(z)
    norm1 = norm1 / norm1.magnitude
    norm2 = norm2 / norm2.magnitude

    # Simplify naming for the A matrix (linear equation coefficeints)
    _a, _b, _c, _d = norm1.x, norm1.y, norm2.x, norm2.y

    # Substitute point in each line to solve for C array
    c1 = (_a * seg1.p2.x) + (_b * seg1.p2.y)
    c2 = (_c * seg2.p2.x) + (_d * seg2.p2.y)

    # Check the determinate
    det = (_a * _d) - (_b * _c)
    if abs(det) < 1e-10:
        return

    # Solve for x my multiplying Ainv by C
    x = [(_d / det * c1) + (-_b / det * c2),
         (-_c / det * c1) + (_a / det * c2)]
    intersection_pt = Point2D.from_array(x)

    return intersection_pt
Beispiel #25
0
def test_mesh2d_init_from_polygon_triangulated():
    """Test the initalization of Mesh2D from_polygon_triangulated."""
    verts = (Point2D(0, 0), Point2D(0, 2), Point2D(2, 2), Point2D(4, 0))
    polygon = Polygon2D(verts)
    mesh = Mesh2D.from_polygon_triangulated(polygon)

    assert len(mesh.vertices) == 4
    assert len(mesh.faces) == 2
    assert mesh.area == 6

    assert mesh.min == Point2D(0, 0)
    assert mesh.max == Point2D(4, 2)
    assert mesh.center == Point2D(2, 1)
    assert mesh.centroid.x == pytest.approx(1.56, rel=1e-2)
    assert mesh.centroid.y == pytest.approx(0.89, rel=1e-2)

    assert len(mesh.face_areas) == 2
    assert mesh.face_areas[0] == 2
    assert mesh.face_areas[1] == 4
    assert len(mesh.face_centroids) == 2

    assert mesh._is_color_by_face is False
    assert mesh.colors is None
Beispiel #26
0
def test_reflect():
    """Test the Mesh2D reflect method."""
    pts = (Point2D(1, 1), Point2D(1, 2), Point2D(2,
                                                 2), Point2D(2,
                                                             1), Point2D(3, 1))
    mesh = Mesh2D(pts, [(0, 1, 2, 3), (2, 3, 4)])

    origin_1 = Point2D(1, 0)
    normal_1 = Vector2D(1, 0)
    normal_2 = Vector2D(-1, -1).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[2].x == pytest.approx(0, rel=1e-3)
    assert test_1[2].y == 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_1 = mesh.reflect(normal_2, Point2D(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[2].x == pytest.approx(-2, rel=1e-3)
    assert test_1[2].y == 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.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[2].x == pytest.approx(-1, rel=1e-3)
    assert test_2[2].y == pytest.approx(-1, 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)
Beispiel #27
0
def test_rotate():
    """Test the Mesh2D rotate method."""
    pts = (Point2D(0, 0), Point2D(0, 2), Point2D(2, 2), Point2D(2, 0), Point2D(4, 0))
    mesh = Mesh2D(pts, [(0, 1, 2, 3), (2, 3, 4)])
    origin_1 = Point2D(1, 1)

    test_1 = mesh.rotate(math.pi, origin_1)
    assert test_1[0].x == pytest.approx(2, rel=1e-3)
    assert test_1[0].y == pytest.approx(2, rel=1e-3)
    assert test_1[2].x == pytest.approx(0, rel=1e-3)
    assert test_1[2].y == pytest.approx(0, 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(math.pi/2, origin_1)
    assert test_2[0].x == pytest.approx(2, rel=1e-3)
    assert test_2[0].y == pytest.approx(0, rel=1e-3)
    assert test_2[2].x == pytest.approx(0, rel=1e-3)
    assert test_2[2].y == 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)
    if north_ is not None:  # process the north_
        try:
            north_ = math.degrees(
                to_vector2d(north_).angle_clockwise(Vector2D(0, 1)))
        except AttributeError:  # north angle instead of vector
            north_ = float(north_)
            assert -360.0 <= north_ <= 360.0, 'The north orientation must be greater ' \
                'then -360 and less then 360 to plot the wind rose. ' \
                'Got: {}'.format(north_)
    else:
        north_ = 0.0

    # set default values for the chart dimensions
    _center_pt_ = to_point3d(
        _center_pt_) if _center_pt_ is not None else Point3D()
    center_pt_2d = Point2D(_center_pt_.x, _center_pt_.y)

    # set defaults frequency hours and distance so chart is same scale as other LB plots
    if _freq_hours_ is None:
        _freq_hours_ = 50.0
    if _freq_dist_ is None:
        _freq_dist_ = 5.0 / conversion_to_meters()

    # set default show_freq and _show_calmrose_
    _show_calmrose_ = False if _show_calmrose_ is None else _show_calmrose_
    _show_freq_ = True if _show_freq_ is None else _show_freq_

    # set up empty lists of objects to be filled
    all_wind_avg_val = []
    all_wind_frequency = []
    all_windrose_lines = []
def rectangle_plan(width, length, floor_to_floor_height, perimeter_offset,
                   story_count, orientation_angle, outdoor_roof, ground_floor,
                   units, tolerance, output_file):
    """Create a model with a rectangular floor plan.\n
    Note that the resulting Rooms in the model won't have any windows or solved
    adjacencies and the edit commands should be used for this purpose.\n
    \n
    Args:\n
        width: Number for the width of the plan (in the X direction).\n
        depth: Number for the depth of the plan (in the Y direction).\n
        floor_to_floor_height: Number for the height of each floor of the model
            (in the Z direction).
    """
    try:
        unique_id = str(uuid.uuid4())[:8]  # unique identifier for the rooms

        # create the geometry of the rooms for the first floor
        footprint = Face3D.from_rectangle(width, length)
        if perimeter_offset != 0:  # use the straight skeleton methods
            assert perimeter_offset > 0, 'perimeter_offset cannot be less than than 0.'
            try:
                footprint = []
                base = Polygon2D.from_rectangle(Point2D(), Vector2D(0, 1),
                                                width, length)
                sub_polys_perim, sub_polys_core = perimeter_core_subpolygons(
                    polygon=base, distance=perimeter_offset, tol=tolerance)
                for s_poly in sub_polys_perim + sub_polys_core:
                    sub_face = Face3D(
                        [Point3D(pt.x, pt.y, 0) for pt in s_poly])
                    footprint.append(sub_face)
            except RuntimeError as e:
                footprint = [Face3D.from_rectangle(width, length)]
        else:
            footprint = [Face3D.from_rectangle(width, length)]
        first_floor = [
            Polyface3D.from_offset_face(geo, floor_to_floor_height)
            for geo in footprint
        ]

        # rotate the geometries if an orientation angle is specified
        if orientation_angle != 0:
            angle, origin = math.radians(orientation_angle), Point3D()
            first_floor = [geo.rotate_xy(angle, origin) for geo in first_floor]

        # create the initial rooms for the first floor
        rmids = ['Room'] if len(first_floor) == 1 else [
            'Front', 'Right', 'Back', 'Left'
        ]
        if len(first_floor) == 5:
            rmids.append('Core')
        rooms = []
        for polyface, rmid in zip(first_floor, rmids):
            rooms.append(
                Room.from_polyface3d('{}_{}'.format(rmid, unique_id),
                                     polyface))

        # if there are multiple stories, duplicate the first floor rooms
        if story_count != 1:
            all_rooms = []
            for i in range(story_count):
                for room in rooms:
                    new_room = room.duplicate()
                    new_room.add_prefix('Floor{}'.format(i + 1))
                    m_vec = Vector3D(0, 0, floor_to_floor_height * i)
                    new_room.move(m_vec)
                    all_rooms.append(new_room)
            rooms = all_rooms

        # assign adiabatic boundary conditions if requested
        if not outdoor_roof and ad_bc:
            for room in rooms[-len(first_floor):]:
                room[-1].boundary_condition = ad_bc  # make the roof adiabatic
        if not ground_floor and ad_bc:
            for room in rooms[:len(first_floor)]:
                room[0].boundary_condition = ad_bc  # make the floor adiabatic

        # create the model object
        model_id = 'Rectangle_Plan_Model_{}'.format(unique_id)
        model = Model(model_id,
                      rooms,
                      units=units,
                      tolerance=tolerance,
                      angle_tolerance=1)

        # write the model out to the file or stdout
        output_file.write(json.dumps(model.to_dict()))
    except Exception as e:
        _logger.exception(
            'Rectangle plan model creation failed.\n{}'.format(e))
        sys.exit(1)
    else:
        sys.exit(0)
Beispiel #30
0
 def segment_mesh_2d(self):
     """A Ladybug Mesh2D for the legend colors."""
     _o = self.legend_parameters.base_plane.o
     return self._segment_mesh_2d(Point2D(_o.x, _o.y))