예제 #1
0
def basic_flattening(target_folder, raster, res, origin, size, tin = False):
    """Reads some pre-determined vector files, tiles them using
    Lisa's code and "burns" them into the output raster. The flat
    elevation of the polygons is estimated by Laplace-interpolating
    at the locations of the polygon vertices. The underlying TIN
    is constructed from the centre points of the raster pixels.
    Rasterisation takes place via rasterio's interface.
    """
    import startin
    from rasterio.features import rasterize
    from rasterio.transform import Affine
    transform = (Affine.translation(origin[0], origin[1])
                 * Affine.scale(size, size))
    x0, x1 = origin[0] + size / 2, origin[0] + ((res[0] - 0.5) * size)
    y0, y1 = origin[1] + size / 2, origin[1] + ((res[1] - 0.5) * size)
    poly_fpaths = [
                     'rest_bodies/bbg_rest_of_the_water.shp',
                     'sea_bodies/bbg_sea_and_big_bodies.shp',
                     # You can add more resources here.
                  ]
    wfs_urls =    [
                     #('http://3dbag.bk.tudelft.nl/data/wfs', 'BAG3D:pand3d'),
                     # You can add more resources here.
                  ]
    in_vecs = []
    for fpath in poly_fpaths:
        vec = vector_prepare([[x0, x1], [y0, y1]], target_folder + fpath)
        if len(vec) != 0: in_vecs.append(vec)
    for wfs in wfs_urls:
        vec = wfs_prepare([[x0, x1], [y0, y1]], wfs[0], wfs[1])
        if len(vec) != 0: in_vecs.append(vec)
    if len(in_vecs) == 0: return
    if tin is False:
        xs, ys = np.linspace(x0, x1, res[0]), np.linspace(y0, y1, res[1])
        xg, yg = np.meshgrid(xs, ys); xg = xg.flatten(); yg = yg.flatten()
        cs = np.vstack((xg, yg, raster.flatten())).transpose()
        data = cs[cs[:,2] != -9999]
        tin = startin.DT(); tin.insert(data)
    elevations = []
    for polys in in_vecs:
        for poly, i in zip(polys, range(len(polys))):
            els = []
            for vx in poly.exterior.coords:
                try: els += [tin.interpolate_laplace(vx[0], vx[1])]
                except: pass
            for interior in poly.interiors:
                for vx in interior.coords:
                    try: els += [tin.interpolate_laplace(vx[0], vx[1])]
                    except: pass
            elevations.append(np.median(els))
    shapes = []
    for polys in in_vecs:
        shapes += [(p, v) for p, v in zip(polys, elevations)]
    raspolys = rasterize(shapes, raster.shape, -9999, transform = transform)
    for yi in range(res[1]):
        for xi in range(res[0]):
            if raspolys[yi, xi] != -9999: raster[yi, xi] = raspolys[yi, xi]
    return tin
예제 #2
0
    def __init__(self, input_tile: Tile, result_type: str):
        self._tile = input_tile

        directory = os.path.dirname(os.path.realpath(__file__))

        config = configparser.ConfigParser()
        config.read(os.path.join(directory, "..", "config.ini"))

        self._to_overwrite = True if config["global"][
            "overwrite_existing_files"] == "true" else False

        self._raster_cell_size = float(
            config["global"]["base_raster_cell_size"])

        self._interpolation_variables = config[
            "interpolation_dsm"] if result_type == "dsm" else config[
                "interpolation_dtm"]
        self._stage = Stages.INTERPOLATED_DSM if result_type == "dsm" else Stages.INTERPOLATED_DTM

        tile_bounds = self._tile.get_unbuffered_geometry().bounds
        tile_bounds = [int(bound) for bound in tile_bounds]

        self._raster = None
        self._las_data = None

        self._tin = startin.DT()

        # [[minx, maxx], [miny, maxy]]
        self._extents = [[tile_bounds[0], tile_bounds[2]],
                         [tile_bounds[1], tile_bounds[3]]]

        # Use width/height / raster cell size for x/y resolution
        self._resolution = [
            int((tile_bounds[2] - tile_bounds[0]) // self._raster_cell_size),
            int((tile_bounds[3] - tile_bounds[1]) // self._raster_cell_size)
        ]

        # Origin = [minx, maxy] == topleft corner
        self._origin = [tile_bounds[0], tile_bounds[3]]

        self._y_range = reversed(
            np.arange(start=tile_bounds[1],
                      stop=tile_bounds[1] +
                      self._resolution[1] * self._raster_cell_size,
                      step=self._raster_cell_size))

        self._x_range = np.arange(start=tile_bounds[0],
                                  stop=tile_bounds[0] +
                                  self._resolution[0] * self._raster_cell_size,
                                  step=self._raster_cell_size)

        print('extents', self._extents)
        print('resolution', self._resolution)
        print('origin', self._origin)
예제 #3
0
def execute_startin(pts, res, origin, size, method):
    """Takes the grid parameters and the ground points. Interpolates
    either using the TIN-linear or the Laplace method. Uses a
    -9999 no-data value. Fully based on the startin package.
    """
    import startin
    tin = startin.DT(); tin.insert(pts)
    ras = np.zeros([res[1], res[0]])
    if method == 'startin-TINlinear':
        def interpolant(x, y): return tin.interpolate_tin_linear(x, y)
    elif method == 'startin-Laplace':
        def interpolant(x, y): return tin.interpolate_laplace(x, y)
    yi = 0
    for y in np.arange(origin[1], origin[1] + res[1] * size, size):
        xi = 0
        for x in np.arange(origin[0], origin[0] + res[0] * size, size):
            tri = tin.locate(x, y)
            if tri != [] and 0 not in tri:
                ras[yi, xi] = interpolant(x, y)
            else: ras[yi, xi] = -9999
            xi += 1
        yi += 1
    return ras, tin
예제 #4
0
def utility_tin(pts,
                bounds,
                max_dh,
                max_angle,
                r,
                pts_inserted=None,
                seeds=None):
    """Utility function that can construct a TIN from the
    segmented point cloud of an NBRS. It needs either the
    preliminary edge estimates or the optimised edges
    to work (it controls the seeding of the initial TIN,
    and then its extension). In addition to using it to
    construct a TIN from points within the NBRS edges,
    the nbrs_manager class also uses it to optionally
    extend it with points outside the edges. The procedure
    still needs edges to be inserted into the TIN,
    but we do not wish to keep these in the TIN. However,
    point removal in startin does not seem to work
    reliably, so in each iteration the TIN is constructed
    anew, and the function returns a list containing
    inserted (and meaningful) points rather than the
    startin-based TIN itself.
    Arguments:
    - 'pts': the candidate points
    - 'bounds': the coordinates of a polygon that contains
                all candidate points
    - 'max_dh': TIN insertion elevation threshold (see the
                relevant nbrs_manager docstring for more)
    - 'max_angle': TIN insertion angle threshold (see the
                   relevant nbrs_manager docstring for more)
    - 'pts_inserted': if extension is desired, then the
                      points that were already inserted
                      into the TIN, in the order in which
                      they were previously inserted
    - 'seeds': the geometry from where the TIN construction
               is seeded, Lidar points very close to these
               points are inserted unconditionally
    """
    # initialise KD-tree from input points, and TIN
    tree = cKDTree(pts)
    tree_len = tree.n
    tin = startin.DT()
    # if initial TIN (between NBRS edges) is being
    # built, then seed it by unconditionally
    # inserting points around the "skeleton" of
    # the polygon created from the NBRS edges
    if pts_inserted is None:
        pts_inserted = []
        _, nbr_ixs = tree.query(seeds, 50, distance_upper_bound=1, workers=-1)
        stack = set(nbr_ixs.flatten()) - {tree_len}
        used, buffer = stack.copy(), []
        while stack:
            pt = pts[stack.pop()]
            buffer += [pt]
            tin.insert_one_pt(*pt)
            pts_inserted.append(pt)
    # if this is not the first round (and extension
    # of a pre-existing TIN is desired), then first
    # re-construct the TIN from the already-inserted
    # points, then seed using the edges (or buffered
    # edges) from the last iteration
    else:
        for pti in pts_inserted:
            tin.insert_one_pt(*pti)
        pre_tree = cKDTree(pts_inserted)
        _, pre_ixs = pre_tree.query(seeds)
        # the seeds are the edges from the previous
        # iteration, and they are extruded to 3D using
        # the already-inserted points here
        seeds_z = []
        for vx, bix in zip(seeds, pre_ixs):
            seeds_z.append((*vx[:2], pts_inserted[bix][2]))
        used, buffer = set(), seeds_z.copy()
    # insert the bounds into the TIN, keeping them at
    # a constant elevation of zero - keep track of their
    # TIN indices, so that they can be excluded from
    # elevation discrepancy computations later on
    bound_ixs = set()
    for bound_vx in bounds:
        bound_ixs.add(tin.insert_one_pt(*bound_vx))
    # the outer iteration is based on a buffer, which
    # contains all points inserted in the previous iteration
    # of the outer loop - in the first iteration it contains
    # the seed points
    while buffer:
        # candidate points are fetched from the
        # neighbourhood of buffer points
        _, nbr_ixs = tree.query(buffer, 50, distance_upper_bound=r, workers=-1)
        # the inner loop is a stack-based one
        # all neighbours of buffer points are considered for
        # insertion, the variable "used" records which
        # points were inserted and should not be
        # considered again
        stack, buffer = set(nbr_ixs.flatten()) - {tree_len} - used, []
        while stack:
            ix = stack.pop()
            pt = pts[ix]
            # get the triangle the candidate is located in
            # because all iterations of this function insert
            # a boundary encompassing all candidate points,
            # this operation is guaranteed to always work
            tri = tin.locate(*pt[:2])
            # identify boundary points among the vertices
            # of the located triangle
            vx_ixs = np.array([tix for tix in tri if tix not in bound_ixs])
            vxs = np.array([tin.get_point(tix) for tix in vx_ixs])
            dh, grow = None, False
            # if the triangle has a boundary vertex among its vertices
            # then consider the operation a "growing" operation
            if len(vx_ixs) < 3:
                grow = True
                # else, consider it a "growing" operation only, if the
                # area or the circumference of the triangle indicates
                # that it probably does not belong to the road surface
                # (i.e. it has a large area or long circumference)
            else:
                cross = np.cross(vxs[1] - vxs[0], vxs[2] - vxs[0])
                area = dist_topoint([0, 0, 0], cross) / 2
                a = dist_topoint(vxs[0], vxs[1])
                b = dist_topoint(vxs[1], vxs[2])
                c = dist_topoint(vxs[2], vxs[0])
                if area > 50 or a + b + c > 20: grow = True
            # if this is not a "growing" operation, interpolate
            # in the TIN to get the elevation deviation
            if not grow:
                dh = abs(pt[2] - tin.interpolate_laplace(*pt[:2]))
                # if this is a "growing" operation, then compute the
                # elevation difference as the mean difference relative
                # to the elevations of the TIN vertices, excluding the
                # boundary vertex
                # NOTE: this is the only way the algorithm can grow
                # the TIN beyond the current road surface extents
            elif len(vx_ixs) == 2:
                trs0 = tin.incident_triangles_to_vertex(vx_ixs[0])
                trs1 = tin.incident_triangles_to_vertex(vx_ixs[1])
                init_ixs = set(np.concatenate((trs0, trs1)).flatten())
                nbr_trs = [
                    tin.incident_triangles_to_vertex(tix)
                    for tix in list(init_ixs)
                ]
                nbr_ixs = set(np.concatenate(nbr_trs).flatten()) | init_ixs
                nbr_ixs = nbr_ixs - bound_ixs
                r_vxs = [tin.get_point(tix) for tix in list(nbr_ixs)]
                r_vxs = np.array([tin.get_point(tix) for tix in list(nbr_ixs)])
                dh = dist_toplane(pt, *planefit_lsq(r_vxs))
            # perform the angle test - if the triangle had a boundary
            # vertex among its vertices, ignore that vertex for the
            # purposes of the angle test (it is at zero elevation)
            if dh and dh < max_dh:
                insert = True
                for vx in vxs:
                    dd = dist_topoint(pt[:2], vx[:2])
                    if not dd or abs(np.arctan(dh / dd)) > max_angle:
                        insert = False
                        break
                # if candidate passed both the elevation difference
                # and angle tests, then insert into TIN, add to the
                # buffer and mark as having been used already
                if insert:
                    used.add(ix)
                    buffer += [pt]
                    tin.insert_one_pt(*pt)
                    pts_inserted.append(pt)
    return pts_inserted
예제 #5
0
# import numpy as np
# import matplotlib.pyplot as plt
# from mpl_toolkits.mplot3d import Axes3D
# import matplotlib.tri as mtri
# from scipy.spatial import Delaunay
#
# tri = Delaunay(xyz_2)
#
# fig = plt.figure()
# ax = fig.add_subplot(1, 1, 1, projection='3d')
# ax.plot_trisurf(xyz_2[:,0], xyz_2[:,1], xyz_2[:,2], triangles=tri.simplices, cmap=plt.cm.Spectral)
# plt.show()
# =============================================================================

import startin
dt = startin.DT()
dt.insert(xyz_2)
triangles = np.asarray(dt.all_triangles())
vertices = np.asarray(dt.all_vertices())
vertices = vertices[1:, :]

threshold = 0.08
remove = []
for i in range(len(triangles)):
    tr = triangles[i, :]
    a = tr[0]
    b = tr[1]
    c = tr[2]
    a_cor = vertices[a - 1, :]
    b_cor = vertices[b - 1, :]
    c_cor = vertices[c - 1, :]
예제 #6
0
def filter_ground(jparams):
    """

  Function that reads a LAS file, performs thinning, then performs ground filtering,
  and creates a two rasters of the ground points. One with IDW interpolation and one with TIN interpolation.

  Input:
    a dictionary jparams with all the parameters that are to be used in this function:
      - input-las:        path to input .las file,
      - thinning-factor:  thinning factor, ie. the `n` in nth point thinning method,
      - gf-cellsize:      cellsize for the initial grid that is computed as part of the ground filtering algorithm,
      - gf-distance:      distance threshold used in the ground filtering algorithm,
      - gf-angle:         angle threshold used in the ground filtering algorithm,
      - idw-radius:       radius to use in the IDW interpolation,
      - idw-power:        power to use in the IDW interpolation,
      - output-las:       path to output .las file that contains your ground classification,
      - grid-cellsize:    cellsize of the output grids,
      - output-grid-tin:  filepath to the output grid with TIN interpolation,
      - output-grid-idw:  filepath to the output grid with IDW interpolation
  """

    # load las file and relevant parameters
    point_cloud = File(jparams['input-las'], mode='r')
    scale = point_cloud.header.scale[0]
    print(point_cloud.header.min)
    print('- Flattening point cloud')
    gridded_pc = point_cloud_to_grid(point_cloud=point_cloud, tf=jparams['thinning-factor'],
                                     cell_size=int(jparams['gf-cellsize'] / scale))

    ground_points, unprocessed_points, ll_origin = gridded_pc[0], gridded_pc[1], gridded_pc[2]

    print('- Growing terrain')
    dt = startin.DT()
    dt.insert(list(ground_points))
    dt = grow_terrain(tin=dt, p=unprocessed_points, gp=ground_points,
                      max_distance=int(jparams['gf-distance'] / scale),
                      max_angle=jparams['gf-angle'])

    print('- Writing point cloud')
    with File(jparams['output-las'], mode='w', header=point_cloud.header) as out_file:
        gp = dt.all_vertices()[1:]
        out_file.X = [p[0] for p in gp]
        out_file.Y = [p[1] for p in gp]
        out_file.Z = [p[2] for p in gp]

    print('- Creating raster (TIN)\n\t- Interpolating (TIN)')
    dg = tin_interp(tin=dt, cell_size=int(jparams['grid-cellsize'] / scale))

    print('\t- Writing Esri Ascii (TIN)')
    write_asc(grid=np.rot90(dg[0]) * scale + point_cloud.header.min[2],
              cell_size=jparams['grid-cellsize'],
              fn=jparams['output-grid-tin'],
              origin=(point_cloud.header.min[0]+dg[1][0]*scale, point_cloud.header.min[1] + dg[1][1]*scale),
              depth=2)

    print('- Creating raster (IDW)\n\t- Interpolating (IDW)')
    ig = idw_interp(tin=dt, cell_size=int(jparams['grid-cellsize'] / scale),
                    radius=jparams['idw-radius'] / scale, 
                    power=jparams['idw-power'])

    print('\t- Writing Esri Ascii (IDW)')
    write_asc(grid=np.rot90(ig[0]) * scale + point_cloud.header.min[2],
              cell_size=jparams['grid-cellsize'],
              fn=jparams['output-grid-idw'],
              origin=(point_cloud.header.min[0]+ig[1][0]*scale, point_cloud.header.min[1]+ig[1][1]*scale),
              depth=2)

    return
예제 #7
0
def nn_interpolation(list_pts_3d, j_nn):
    """
    !!! TO BE COMPLETED !!!
     
    Function that writes the output raster with nearest neighbour interpolation
     
    Input:
        list_pts_3d: the list of the input points (in 3D)
        j_nn:        the parameters of the input for "nn"
    Output:
        returns the value of the area
 
    """
    # print("cellsize:", j_nn['cellsize'])

    # -- to speed up the nearest neighbour us a kd-tree
    # https://docs.scipy.org/doc/scipy/reference/generated/scipy.spatial.KDTree.html#scipy.spatial.KDTree
    # https://docs.scipy.org/doc/scipy/reference/generated/scipy.spatial.KDTree.query.html#scipy.spatial.KDTree.query
    # kd = scipy.spatial.KDTree(list_pts)
    # d, i = kd.query(p, k=1)

    # find 4 boundaries
    ls_xy = [
    ]  # This is used for NN, if it is not necessary in other method. delete it
    ls_x = []
    ls_y = []
    ls_z = [
    ]  # This is used for NN, if it is not necessary in other method,delete it
    for i in range(len(list_pts_3d)):
        ls_x.append(list_pts_3d[i][0])
        ls_y.append(list_pts_3d[i][1])
        ls_xy.append((list_pts_3d[i][0], list_pts_3d[i][1]))
        ls_z.append(list_pts_3d[i][2])
    bd_lf = min(ls_x)  # left boundary, i.e XLLCORNER
    bd_rt = max(ls_x)  # right boundary
    bd_lw = min(ls_y)  # lower boundary, i.e YLLCORNER
    bd_up = max(ls_y)  # upper boundary

    cellsize = j_nn['cellsize']
    jparams = json.load(open('params.json'))
    jnn = jparams['nn']

    # NROWS
    if (bd_up - bd_lw) % cellsize != 0:
        rows_num = int((bd_up - bd_lw) // cellsize + 1)
    else:
        rows_num = int((bd_up - bd_lw) // cellsize)
    # NNCOLS
    if (bd_rt - bd_lf) % cellsize != 0:
        cols_num = int((bd_rt - bd_lf) // cellsize + 1)
    else:
        cols_num = int((bd_rt - bd_lf) // cellsize)

    kd = scipy.spatial.KDTree(ls_xy)
    tin = startin.DT()
    tin.insert(list_pts_3d)

    with open(j_nn["output-file"], 'w+') as output:
        output.write("NCOLS " + str(cols_num) + "\n")
        output.write("NROWS " + str(rows_num) + "\n")
        output.write("XLLCORNER " + str(bd_lf) + "\n")
        output.write("YLLCORNER " + str(bd_lw) + "\n")
        output.write("CELLSIZE " + str(j_nn["cellsize"]) + "\n")
        output.write('NODATA_VALUE -9999' + "\n")
        for row in range(rows_num):
            ls_row = []
            for col in range(cols_num):
                # point = cell_center(col, row, cellsize, bd_lf, bd_lw)
                center = (bd_lf + cellsize / 2 + col * cellsize, bd_lw +
                          cellsize / 2 + (rows_num - 1 - row) * cellsize)
                # print('pt:',col,row,"cc:",point)
                if not tin.locate(center[0], center[1]):
                    ls_row.append(str(-9999.0))
                else:
                    nn_pt_idx = kd.query([center], k=1)[1][0]
                    nn_pt_z = list_pts_3d[nn_pt_idx][2]
                    ls_row.append(str(nn_pt_z))
            output.write(" ".join(ls_row) + '\n')

    print("File written to", j_nn['output-file'])
예제 #8
0
def kriging_interpolation(list_pts_3d, j_kriging):
    """
    !!! TO BE COMPLETED !!!
     
    Function that writes the output raster with ordinary kriging interpolation
     
    Input:
        list_pts_3d: the list of the input points (in 3D)
        j_kriging:       the parameters of the input for "kriging"
    Output:
        returns the value of the area
 
    """

    # gaussian variogram
    def gaussian_vario(p1, p2):
        dt = distance(p1, p2)
        sill_gaussian = 1380
        range_gaussian = 295
        nugget_gaussian = 0
        gamma = nugget_gaussian + sill_gaussian * (
            1.0 - math.exp(-9.0 * (dt**2) / (range_gaussian**2)))
        return gamma

    def weighted_average(coords, values, center):
        mat_cov = []
        for pt1 in coords:
            row_vec = []
            for pt2 in coords:
                row_vec.append(gaussian_vario(pt1, pt2))
            mat_cov.append(row_vec + [1])
        mat_cov.append([1] * len(coords) + [0])
        mat_cov = numpy.array(mat_cov)

        mat_D = []
        for i in coords:
            mat_D.append([gaussian_vario(i, center)])
        mat_D.append([1])
        mat_D = numpy.array(mat_D)

        try:
            mat_wt = numpy.matmul(numpy.linalg.inv(mat_cov), mat_D)

        except:
            return -9999.0

        vec_wt = [w[0] for w in mat_wt[:-1]]
        vec_wt_normaalized = [w / sum(vec_wt)
                              for w in vec_wt] if sum(vec_wt) else vec_wt
        return sum([val * w for val, w in zip(values, vec_wt_normaalized)])

    cellsize = j_kriging['cellsize']

    # data cleaning
    temp = []
    [temp.append(i) for i in list_pts_3d if not i in temp]
    list_pts_3d = temp

    # find 4 boundaries
    ls_xy = []
    ls_x = []
    ls_y = []
    ls_z = []
    for i in range(len(list_pts_3d)):
        ls_x.append(list_pts_3d[i][0])
        ls_y.append(list_pts_3d[i][1])
        ls_xy.append((list_pts_3d[i][0], list_pts_3d[i][1]))
        ls_z.append(list_pts_3d[i][2])
    bd_lf = min(ls_x)  # left boundary, i.e XLLCORNER
    bd_rt = max(ls_x)  # right boundary
    bd_lw = min(ls_y)  # lower boundary, i.e YLLCORNER
    bd_up = max(ls_y)  # upper boundary

    # NROWS
    if (bd_up - bd_lw) % cellsize != 0:
        rows_num = int((bd_up - bd_lw) // cellsize + 1)
    else:
        rows_num = int((bd_up - bd_lw) // cellsize)
    # NNCOLS
    if (bd_rt - bd_lf) % cellsize != 0:
        cols_num = int((bd_rt - bd_lf) // cellsize + 1)
    else:
        cols_num = int((bd_rt - bd_lf) // cellsize)

    tin = startin.DT()
    tin.insert(list_pts_3d)
    kd = scipy.spatial.KDTree(ls_xy)
    dc_pts_3d = dict(zip(ls_xy, ls_z))

    with open(j_kriging["output-file"], 'w+') as output:
        output.write("NCOLS " + str(cols_num) + "\n")
        output.write("NROWS " + str(rows_num) + "\n")
        output.write("XLLCORNER " + str(bd_lf) + "\n")
        output.write("YLLCORNER " + str(bd_lw) + "\n")
        output.write("CELLSIZE " + str(int(j_kriging["cellsize"])) + "\n")
        output.write('NODATA_VALUE -9999' + "\n")
        for row in range(rows_num, 0, -1):
            ls_row = []
            for col in range(1, cols_num + 1):
                # center = cell_center(col, row, float(cellsize), bd_lf, bd_lw)
                center = (bd_lf + cellsize * col - cellsize / 2,
                          bd_lw + cellsize * row - cellsize / 2)

                if not tin.locate(center[0], center[1]):
                    ls_row.append(str(-9999.0))

                else:
                    neighbours = kd.query_ball_point(center,
                                                     j_kriging['radius'])
                    cords = [ls_xy[i] for i in neighbours]
                    vals = [ls_z[i] for i in neighbours]
                    distaances = [
                        math.sqrt((center[0] - cord[0])**2 +
                                  (center[1] - cord[1])**2) for cord in cords
                    ]

                    if not neighbours:
                        ls_row.append(str(-9999.0))

                    elif distaances.count(0):
                        i = distaances.index(0)
                        ls_row.append(str(vals[i]))

                    else:
                        ls_row.append(
                            str(weighted_average(cords, vals, center)))

            output.write(" ".join(ls_row) + '\n')

    print("File written to", j_kriging['output-file'])
예제 #9
0
def tin_interpolation(list_pts_3d, j_tin):
    """
    !!! TO BE COMPLETED !!!

    Function that writes the output raster with linear in TIN interpolation

    Input:
        list_pts_3d: the list of the input points (in 3D)
        j_tin:       the parameters of the input for "tin"
    Output:
        returns the value of the area

    """
    # -- example to construct the DT with scipy
    # https://docs.scipy.org/doc/scipy/reference/generated/scipy.spatial.Delaunay.html#scipy.spatial.Delaunay
    # dt = scipy.spatial.Delaunay([])

    # -- example to construct the DT with startin
    # minimal docs: https://github.com/hugoledoux/startin_python/blob/master/docs/doc.md
    # how to use it: https://github.com/hugoledoux/startin_python#a-full-simple-example
    # you are *not* allowed to use the function for the tin linear interpolation that I wrote for startin
    # you need to write your own code for this step
    # but you can of course read the code [dt.interpolate_tin_linear(x, y)]

    # -- create lists for x,y,z values of sample points

    cellsize = j_tin['cellsize']

    # data cleaning
    temp = []
    [temp.append(i) for i in list_pts_3d if not i in temp]
    list_pts_3d = temp

    # find 4 boundaries
    ls_xy = [
    ]  # This is used for NN, if it is not necessary in other method. delete it
    ls_x = []
    ls_y = []
    ls_z = [
    ]  # This is used for NN, if it is not necessary in other method,delete it
    for i in range(len(list_pts_3d)):
        ls_x.append(list_pts_3d[i][0])
        ls_y.append(list_pts_3d[i][1])
        ls_xy.append((list_pts_3d[i][0], list_pts_3d[i][1]))
        ls_z.append(list_pts_3d[i][2])

    bd_lf = min(ls_x)  # left boundary, i.e XLLCORNER
    bd_rt = max(ls_x)  # right boundary
    bd_lw = min(ls_y)  # lower boundary, i.e YLLCORNER
    bd_up = max(ls_y)  # upper boundary

    # NROWS
    if (bd_up - bd_lw) % cellsize != 0:
        rows_num = int((bd_up - bd_lw) // cellsize + 1)
    else:
        rows_num = int((bd_up - bd_lw) // cellsize)
    # NNCOLS
    if (bd_rt - bd_lf) % cellsize != 0:
        cols_num = int((bd_rt - bd_lf) // cellsize + 1)
    else:
        cols_num = int((bd_rt - bd_lf) // cellsize)

    raster_grid = numpy.zeros((rows_num, cols_num))
    tin = startin.DT()
    tin.insert(list_pts_3d)

    for row in range(rows_num):
        for col in range(cols_num):
            center = (bd_lf + cellsize / 2 + col * cellsize,
                      bd_lw + cellsize / 2 + (rows_num - 1 - row) * cellsize)
            # center = cell_center(col, row, cellsize, bd_lf, bd_lw)
            if not tin.locate(center[0], center[1]):
                raster_grid[row][col] = -9999

            else:
                triangle = tin.locate(center[0], center[1])
                pt1 = tin.get_point(triangle[0])
                pt2 = tin.get_point(triangle[1])
                pt3 = tin.get_point(triangle[2])
                pt4 = [center[0], center[1]]

                a0 = abs((pt1[0] * (pt2[1] - pt3[1]) + pt2[0] *
                          (pt3[1] - pt1[1]) + pt3[0] * (pt1[1] - pt2[1])) / 2)
                a1 = abs((pt4[0] * (pt2[1] - pt3[1]) + pt2[0] *
                          (pt3[1] - pt4[1]) + pt3[0] * (pt4[1] - pt2[1])) / 2)
                a2 = abs((pt4[0] * (pt3[1] - pt1[1]) + pt3[0] *
                          (pt1[1] - pt4[1]) + pt1[0] * (pt4[1] - pt3[1])) / 2)
                a3 = abs((pt4[0] * (pt1[1] - pt2[1]) + pt1[0] *
                          (pt2[1] - pt4[1]) + pt2[0] * (pt4[1] - pt1[1])) / 2)
                raster_grid[row][col] = (a1 / a0) * pt1[2] + (
                    a2 / a0) * pt2[2] + (a3 / a0) * pt3[2]

    with open(j_tin['output-file'], 'w+') as output:
        output.write('NCOLS ' + str(cols_num) + '\n')
        output.write('NROWS ' + str(rows_num) + '\n')
        output.write("XLLCORNER " + str(bd_lf) + "\n")
        output.write("YLLCORNER " + str(bd_lw) + "\n")
        output.write("CELLSIZE " + str(j_tin["cellsize"]) + "\n")
        output.write('NODATA_VALUE -9999' + "\n")
        for row in range(rows_num):
            for col in range(cols_num):
                output.write(str(raster_grid[row][col]) + ' ')
            output.write('\n')

    print("File written to", j_tin['output-file'])
예제 #10
0
def nni_interpolation(list_pts_3d, j_nni):
    """
    !!! TO BE COMPLETED !!!
     
    Function that writes the output raster with nni
     
    Input:
        list_pts_3d: the list of the input points (in 3D)
        j_nni:       the parameters of the input for "nni"
    Output:
        returns the value of the area
 
    """

    # find 4 boundaries
    ls_xy = [
    ]  # This is used for NN, if it is not necessary in other method. delete it
    ls_x = []
    ls_y = []
    ls_z = [
    ]  # This is used for NN, if it is not necessary in other method,delete it
    for i in range(len(list_pts_3d)):
        ls_x.append(list_pts_3d[i][0])
        ls_y.append(list_pts_3d[i][1])
        ls_xy.append((list_pts_3d[i][0], list_pts_3d[i][1]))
        ls_z.append(list_pts_3d[i][2])
    bd_lf = min(ls_x)  # left boundary, i.e XLLCORNER
    bd_rt = max(ls_x)  # right boundary
    bd_lw = min(ls_y)  # lower boundary, i.e YLLCORNER
    bd_up = max(ls_y)  # upper boundary

    cellsize = j_nni['cellsize']
    jparams = json.load(open('params.json'))
    jnni = jparams['nni']

    # NROWS
    if (bd_up - bd_lw) % cellsize != 0:
        rows_num = int((bd_up - bd_lw) // cellsize + 1)
    else:
        rows_num = int((bd_up - bd_lw) // cellsize)
    # NNCOLS
    if (bd_rt - bd_lf) % cellsize != 0:
        cols_num = int((bd_rt - bd_lf) // cellsize + 1)
    else:
        cols_num = int((bd_rt - bd_lf) // cellsize)

    # kd = scipy.spatial.KDTree(ls_xy)
    tin = startin.DT()
    tin.insert(list_pts_3d)
    # dt = scipy.spatial.Delaunay(ls_xy, incremental=True)
    vd = scipy.spatial.Voronoi(ls_xy, incremental=True)
    # scipy.spatial.voronoi_plot_2d(vd, show_vertices=False)
    # plt.show()

    with open(j_nni["output-file"], 'w+') as output:
        output.write("NCOLS " + str(cols_num) + "\n")
        output.write("NROWS " + str(rows_num) + "\n")
        output.write("XLLCORNER " + str(bd_lf) + "\n")
        output.write("YLLCORNER " + str(bd_lw) + "\n")
        output.write("CELLSIZE " + str(j_nni["cellsize"]) + "\n")
        output.write('NODATA_VALUE -9999' + "\n")
        for row in range(rows_num):
            ls_row = []
            for col in range(cols_num):
                # point = cell_center(col, row, cellsize, bd_lf, bd_lw)
                center = (bd_lf + cellsize / 2 + col * cellsize, bd_lw +
                          cellsize / 2 + (rows_num - 1 - row) * cellsize)
                # print('pt:',col,row,"cc:",point)

                if not tin.locate(center[0], center[1]):
                    ls_row.append(str(-9999.0))
                else:
                    in_ls_z = False
                    for idx in range(len(ls_xy)):
                        pt = ls_xy[idx]
                        if abs(center[0] - pt[0]) < 0.00001 and abs(
                                center[1] - pt[1]) < 0.00001:
                            in_ls_z = ls_z[idx]
                            break

                    if in_ls_z:
                        ls_row.append(str(in_ls_z))
                    else:
                        ls_xy_plus = ls_xy[:]
                        ls_xy_plus.append(center)

                        # insert the center point in original vd
                        vd_plus = scipy.spatial.Voronoi(ls_xy_plus)

                        # insert the current center point in original dt
                        dt_plue = scipy.spatial.Delaunay(ls_xy_plus)

                        # get all neighbor vertices of center point
                        dt_vnv = dt_plue.vertex_neighbor_vertices
                        dt_center_vnv = dt_vnv[1][dt_vnv[0][-2]:dt_vnv[0][-1]]

                        area = []
                        for region_center_idx in dt_center_vnv:
                            boundary = []

                            # add vertices of intersection polygon between
                            # each corresponding vd cell in vd and vd_plus
                            vd_p_region = vd_plus.point_region[
                                region_center_idx]
                            vd_p_region_boundary = [
                                idx for idx in vd_plus.regions[vd_p_region]
                            ]
                            vd_region = vd.point_region[region_center_idx]
                            vd_region_boundary = [
                                idx for idx in vd.regions[vd_region]
                            ]

                            for vt in vd_p_region_boundary:
                                in_boundary = False
                                pt1 = vd_plus.vertices[vt]
                                for pt2 in boundary:
                                    if abs(pt1[0] - pt2[0]) < 0.00001 and abs(
                                            pt1[1] - pt2[1]) < 0.00001:
                                        in_boundary = True

                                if vt != -1 and vd_region_boundary.count(
                                        vt) == 0 and in_boundary is False:
                                    boundary.append(vd_plus.vertices[vt])

                            for vt in vd_region_boundary:
                                in_boundary = False
                                pt1 = vd.vertices[vt]
                                for pt2 in boundary:
                                    if abs(pt1[0] - pt2[0]) < 0.00001 and abs(
                                            pt1[1] - pt2[1]) < 0.00001:
                                        in_boundary = True

                                if vt != -1 and vd_p_region_boundary.count(
                                        vt) == 0 and in_boundary is False:
                                    boundary.append(vd.vertices[vt])

                            # create the ConvexHull of this intersection polygon

                            # cannot form a ConvexHull (number of pt <= 2)
                            if len(boundary) <= 2:
                                # print(0, end=" ")
                                area.append(0)
                                # fig1 = scipy.spatial.voronoi_plot_2d(vd, show_vertices=False)
                                # plt.show()
                                # scipy.spatial.voronoi_plot_2d(vd_plus, show_vertices=False)
                                # plt.show()

                            else:  # number of pt > 2
                                # detect if these vertices are collinear
                                is_collinear = True
                                slope_std = 0
                                if boundary[0][0] - boundary[-1][0] == 0:
                                    slope_std = sys.maxsize
                                else:
                                    slope_std = (
                                        boundary[0][1] - boundary[-1][1]) / (
                                            boundary[0][0] - boundary[-1][0])

                                for i in range(1, len(boundary)):
                                    slope = 0
                                    if boundary[0][0] - boundary[i][0] == 0:
                                        slope = sys.maxsize
                                    else:
                                        slope = (
                                            boundary[0][1] - boundary[i][1]
                                        ) / (boundary[0][0] - boundary[i][0])
                                    # print(slope, end=" ")
                                    if abs(slope - slope_std) > 0.00001:
                                        is_collinear = False
                                        break

                                # print()
                                # print("row: ", row, " col: ", col, boundary)
                                if is_collinear is False:
                                    ch = scipy.spatial.ConvexHull(boundary)
                                    # print(ch.volume, end=" ")
                                    area.append(ch.volume)

                                else:
                                    area.append(0)

                        # calculate the weight of each neihbour point of center point
                        # print()
                        sum_area = sum(area)
                        weight = [area_i / sum_area for area_i in area]

                        # calculate the value of center point
                        weighted_val = 0
                        if len(weight) != len(dt_center_vnv):
                            print("wt:", weight)
                            print("vnv: ", dt_center_vnv)
                        for i in range(len(dt_center_vnv)):
                            weighted_val += weight[i] * ls_z[dt_center_vnv[i]]
                        ls_row.append(str(weighted_val))

            output.write(" ".join(ls_row) + '\n')

    print("File written to", j_nni['output-file'])
예제 #11
0
y = np.delete(y, ground_points)
z = np.delete(z, ground_points)
xyz_lowest = np.vstack((x_lowest, y_lowest, z_lowest)).T

#insert 4 extra point to create a convex hull that includes all points in the dataset
xyz_outside = np.array(
    [[xmin - gf_cellsize, ymin - gf_cellsize, z_lowest[0]],
     [xmin - gf_cellsize, ymax + gf_cellsize, z_lowest[len(y_grid) - 2]],
     [
         xmax + gf_cellsize, ymin - gf_cellsize,
         z_lowest[len(y_lowest) - (len(y_grid) - 1)]
     ], [xmax + gf_cellsize, ymax + gf_cellsize, z_lowest[len(y_lowest) - 1]]])
points_initial = np.concatenate((xyz_outside, xyz_lowest), axis=0)
added = points_initial.shape[0]

dt = startin.DT()
dt.insert(points_initial)

#list of remaining points:
remaining = np.concatenate(
    (x.reshape(-1, 1), y.reshape(-1, 1), z.reshape(-1, 1)), axis=1)
points_outside = []
k = 0
check = 0

while remaining.shape[0] > k:
    print(remaining.shape[0] - k)

    Triangle = dt.locate(remaining[k, 0], remaining[k, 1])
    x_point0 = remaining[k, 0]
    y_point0 = remaining[k, 1]