Exemple #1
0
    def test_square_outside_grid(self):
        grid_x = np.arange(5)
        grid_y = np.arange(5)

        # Polygon outside x-extent.
        poly_xy = np.array([[5, 7.5, 7.5, 5], [1, 1, 3.5, 3.5]])
        render = float_raster.raster_2D(poly_xy, grid_x, grid_y)
        np.testing.assert_array_almost_equal(render, np.zeros((4, 4)), 7)
        # Polygon outside y-extent.
        poly_xy = np.array([[1, 3.5, 3.5, 1], [5, 5, 7.5, 7.5]])
        render = float_raster.raster_2D(poly_xy, grid_x, grid_y)
        np.testing.assert_array_almost_equal(render, np.zeros((4, 4)), 7)

        # Polygon outside x-extent and y-extent.
        poly_xy = np.array([[5, 7.5, 7.5, 5], [5, 5, 7.5, 7.5]])
        render = float_raster.raster_2D(poly_xy, grid_x, grid_y)
        np.testing.assert_array_almost_equal(render, np.zeros((4, 4)), 7)
Exemple #2
0
 def test_square_nonuniform(self):
     grid_x = np.array([0, 1, 3, 3.5, 4.2])
     grid_y = np.array([0, 2.5, 3, 3.7])
     poly_xy = np.array([[1, 3.5, 3.5, 1], [1, 1, 3.5, 3.5]])
     render = float_raster.raster_2D(poly_xy, grid_x, grid_y)
     np.testing.assert_array_almost_equal(
         render,
         np.array([[0, 0, 0], [0.6, 1, 5.0 / 7.0], [0.6, 1, 5.0 / 7.0],
                   [0, 0, 0]]), 7)
Exemple #3
0
 def test_square_partially_outside_grid(self):
     grid_x = np.arange(5)
     grid_y = np.arange(5)
     poly_xy = np.array([[1, 5, 5, 1], [1, 1, 3.5, 3.5]])
     render = float_raster.raster_2D(poly_xy, grid_x, grid_y)
     np.testing.assert_array_almost_equal(
         render,
         np.array([[0, 0, 0, 0], [0, 1, 1, 0.5], [0, 1, 1, 0.5],
                   [0, 1, 1, 0.5]]), 7)
Exemple #4
0
 def test_triangle_inside_pixel(self):
     grid_x = np.arange(5)
     grid_y = np.arange(5)
     poly_xy = np.array([[1, 1.5, 1.5], [1, 1, 2]])
     render = float_raster.raster_2D(poly_xy, grid_x, grid_y)
     np.testing.assert_array_almost_equal(
         render,
         np.array([[0, 0, 0, 0], [0, 0.25, 0, 0], [0, 0, 0, 0],
                   [0, 0, 0, 0]]), 7)
Exemple #5
0
 def test_triangle(self):
     grid_x = np.arange(5)
     grid_y = np.arange(5)
     poly_xy = np.array([[1, 3, 3], [1, 1, 4]])
     render = float_raster.raster_2D(poly_xy, grid_x, grid_y)
     np.testing.assert_array_almost_equal(
         render,
         np.array([[0, 0, 0, 0], [0, 2.0 / 3.0, 1.0 / 12.0, 0],
                   [0, 1, 11.0 / 12.0, 1.0 / 3.0], [0, 0, 0, 0]]), 7)
Exemple #6
0
 def test_square_inside_pixel(self):
     grid_x = np.arange(5)
     grid_y = np.arange(5)
     poly_xy = np.array([[1.1, 1.9, 1.9, 1.1], [1.1, 1.1, 1.9, 1.9]])
     render = float_raster.raster_2D(poly_xy, grid_x, grid_y)
     np.testing.assert_array_almost_equal(
         render,
         np.array([[0, 0, 0, 0], [0, 0.64, 0, 0], [0, 0, 0, 0],
                   [0, 0, 0, 0]]), 7)
Exemple #7
0
 def test_square_overlap_pixel(self):
     grid_x = np.arange(5)
     grid_y = np.arange(5)
     poly_xy = np.array([[1, 2, 2, 1], [1, 1, 2, 2]])
     render = float_raster.raster_2D(poly_xy, grid_x, grid_y)
     np.testing.assert_array_almost_equal(
         render,
         np.array([[0, 0, 0, 0], [0, 1, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]]),
         7)
Exemple #8
0
 def test_raise_value_error_invalid_grid_x(self):
     with self.assertRaisesRegex(
             ValueError,
             "Expected both `grid_x` and `grid_y` to have atleast 2*"):
         float_raster.raster_2D(np.array([[1, 2, 4], [1, 2, 1]]),
                                np.array([0, 1, 2]), np.array([]))
Exemple #9
0
 def test_raise_value_error_invalid_poly_xy(self):
     with self.assertRaisesRegex(ValueError,
                                 "Expected `poly_xy` to have 2 rows, got*"):
         float_raster.raster_2D(np.array([[1, 2, 4]]), np.arange(5),
                                np.arange(5))
Exemple #10
0
    def render_polygon(self, polygon: np.ndarray, z_extent: np.ndarray,
                       eps: np.ndarray):
        """
        Function to render grid with contribution due to polygon 'polygon'.
        
        INPUTS:
        polygon - list of (x,y) vertices of the polygon being rendered
        z_extent - extent (z_1, z_2) along the extrusion direction of the polygon being rendered
        eps - permittivity of the polygon being rendered
        
        OUTPUTS:
        updates self.grids with the properly aliased polygon permittivity
        reduces self.frac_bg by the fraction of space occupied by the polygon 'polygon'
        """

        # Validating input arguments
        if polygon.ndim != 2 or polygon.shape[1] != 2:
            raise GridError(
                'Invalid format for specifying polygon - must be a Nx2 array')
        if polygon.shape[0] <= 2:
            raise GridError(
                'Malformed Polygon - must contain more than two points')
        if z_extent.ndim != 1 or z_extent.size != 2:
            raise GridError(
                'Invalid format for specifying z-extent - must be a vector of length 2'
            )

        def to_3D(vector: List or np.ndarray,
                  z: float = 0.5 * (z_extent[0] + z_extent[1])):
            return np.insert(vector, self.ext_dir, z)

        def get_zi(z: float, which_shifts: float):
            pos_3D = to_3D([0, 0], z)
            grid_coords = self.pos2ind(pos_3D,
                                       which_shifts,
                                       which_grid=GridType.PRIM,
                                       check_bounds=False)
            return grid_coords[self.ext_dir]

        # Calculating slice affected by polygon
        pbd_min = polygon.min(axis=0)
        pbd_max = polygon.max(axis=0)
        z_min = z_extent.min()
        z_max = z_extent.max()

        for n, grid in enumerate(self.grids):
            '''
            Computing the in-plane pixel values
            '''
            # Shape of the complementary grid
            comp_shape = np.array([self.shape[a]+2 if self.comp_shifts[n][a] == 0 else self.shape[a]+1 \
                          for a in range(3)])

            # Calculating the indices of the maximum and minimum polygon coordinate
            ind_xy_min = self.pos2ind(to_3D(pbd_min),
                                      which_shifts=n,
                                      which_grid=GridType.PRIM,
                                      round_ind=True,
                                      check_bounds=False)

            ind_xy_max = self.pos2ind(to_3D(pbd_max),
                                      which_shifts=n,
                                      which_grid=GridType.PRIM,
                                      round_ind=True,
                                      check_bounds=False)

            # Calculating the points on the grid that are affected by the drawn polygons
            corner_xy_min = ind_xy_min[self.planar_dir].astype(int)
            corner_xy_max = np.minimum(ind_xy_max[self.planar_dir] + 1,
                                       self.shape[self.planar_dir] -
                                       1).astype(int)

            # Calculating the points of the complementary grid that need to be passed
            comp_corner_xy_min = corner_xy_min.astype(int)
            comp_corner_xy_max = np.minimum(
                corner_xy_max + 1, comp_shape[self.planar_dir] - 1).astype(int)

            # Setting up slices
            edge_slice_xy = [
                np.s_[j:f + 1]
                for j, f in zip(comp_corner_xy_min, comp_corner_xy_max)
            ]

            # Calling the rastering function
            aa_x, aa_y = (self.shifted_exyz(which_shifts = n, which_grid = GridType.COMP)[a][s] \
                          for a,s in zip(self.planar_dir, edge_slice_xy))
            w_xy = raster_2D(polygon.T, aa_x, aa_y)
            '''
            Computing the pixel value along the surface normal
            '''
            # Calculating the indices of the start and stop point
            ind_z_min = get_zi(z_min, which_shifts=n)
            ind_z_max = get_zi(z_max, which_shifts=n)
            corner_z_min = ind_z_min.astype(int)
            corner_z_max = np.minimum(ind_z_max + 1,
                                      self.shape[self.ext_dir] - 1).astype(int)
            comp_corner_z_min = corner_z_min.astype(int)
            comp_corner_z_max = np.minimum(
                corner_z_max + 1, comp_shape[self.ext_dir] - 1).astype(int)

            edge_slice_z = np.s_[comp_corner_z_min:comp_corner_z_max + 1]
            aa_z = self.shifted_exyz(
                which_shifts=n,
                which_grid=GridType.COMP)[self.ext_dir][edge_slice_z]
            w_z = raster_1D(z_extent, aa_z)

            # Combining the extrusion and planar area calculation
            w = (w_xy[:, :, np.newaxis] * w_z).transpose(
                np.insert([0, 1], self.ext_dir, (2, )))

            # Adding to the grid
            center_slice = [None for a in range(3)]
            center_slice[self.ext_dir] = np.s_[corner_z_min:corner_z_max + 1]
            for i in range(2):
                center_slice[self.planar_dir[i]] = np.s_[
                    corner_xy_min[i]:corner_xy_max[i] + 1]

            # Updating permittivity
            self.grids[n][tuple(center_slice)] += eps[n] * w
            self.frac_bg[n][tuple(center_slice)] -= w