Exemple #1
0
def tileset(table, column, server_url, work_dir):
    """
    (Re)build a tileset.json for a given table
    """
    # intialize flask application
    create_app()

    work_dir = Path(work_dir)

    if '.' not in table:
        table = 'public.{}'.format(table)

    lpsession = Session(table, column)
    # initialize range for level of details
    fullbbox = lpsession.boundingbox
    bbox = [
        fullbbox['xmin'], fullbbox['ymin'], fullbbox['zmin'], fullbbox['xmax'],
        fullbbox['ymax'], fullbbox['zmax']
    ]
    pending('Building tileset from database')
    hcy = threedtiles.build_hierarchy_from_pg(lpsession, server_url, bbox)
    ok()
    tileset = os.path.join(str(work_dir.resolve()),
                           'tileset-{}.{}.json'.format(table, column))
    pending('Writing tileset to disk')
    with io.open(tileset, 'wb') as out:
        out.write(hcy.encode())
    ok()
Exemple #2
0
def tileset(table, column, server_url, work_dir):
    """
    (Re)build a tileset.json for a given table
    """
    # intialize flask application
    create_app()

    work_dir = Path(work_dir)

    if '.' not in table:
        table = 'public.{}'.format(table)

    lpsession = Session(table, column)
    # initialize range for level of details
    fullbbox = lpsession.boundingbox
    bbox = [
        fullbbox['xmin'], fullbbox['ymin'], fullbbox['zmin'],
        fullbbox['xmax'], fullbbox['ymax'], fullbbox['zmax']
    ]
    pending('Building tileset from database')
    hcy = threedtiles.build_hierarchy_from_pg(
        lpsession, server_url, bbox
    )
    ok()
    tileset = os.path.join(str(work_dir.resolve()), 'tileset-{}.{}.json'.format(table, column))
    pending('Writing tileset to disk')
    with io.open(tileset, 'wb') as out:
        out.write(hcy.encode())
    ok()
Exemple #3
0
def _load(filename,
          table,
          column,
          work_dir,
          server_url,
          capacity,
          usewith,
          srid=0):
    '''load pointclouds data using pdal and add metadata needed by lopocs'''
    # intialize flask application
    app = create_app()

    filename = Path(filename)
    work_dir = Path(work_dir)
    extension = filename.suffix[1:].lower()
    # laz uses las reader in PDAL
    extension = extension if extension != 'laz' else 'las'
    basename = filename.stem
    basedir = filename.parent

    pending('Creating metadata table')
    Session.create_pointcloud_lopocs_table()
    ok()

    pending('Reading summary with PDAL')
    json_path = os.path.join(
        str(work_dir.resolve()),
        '{basename}_{table}_pipeline.json'.format(**locals()))

    # tablename should be always prefixed
    if '.' not in table:
        table = 'public.{}'.format(table)

    cmd = "pdal info --summary {}".format(filename)
    try:
        output = check_output(shlex.split(cmd))
    except CalledProcessError as e:
        fatal(e)

    summary = json.loads(output.decode())['summary']
    ok()

    if 'srs' not in summary and not srid:
        fatal(
            'Unable to find the spatial reference system, please provide a SRID with option --srid'
        )

    if not srid:
        # find authority code in wkt string
        srid = re.findall('EPSG","(\d+)"', summary['srs']['wkt'])[-1]

    p = Proj(init='epsg:{}'.format(srid))

    if p.is_latlong():
        # geographic
        scale_x, scale_y, scale_z = (1e-6, 1e-6, 1e-2)
    else:
        # projection or geocentric
        scale_x, scale_y, scale_z = (0.01, 0.01, 0.01)
    offset_x = summary['bounds']['X']['min'] + (
        summary['bounds']['X']['max'] - summary['bounds']['X']['min']) / 2
    offset_y = summary['bounds']['Y']['min'] + (
        summary['bounds']['Y']['max'] - summary['bounds']['Y']['min']) / 2
    offset_z = summary['bounds']['Z']['min'] + (
        summary['bounds']['Z']['max'] - summary['bounds']['Z']['min']) / 2

    reproject = ""

    if usewith == 'cesium':
        from_srid = srid
        # cesium only use epsg:4978, so we must reproject before loading into pg
        srid = 4978

        reproject = """
        {{
           "type":"filters.reprojection",
           "in_srs":"EPSG:{from_srid}",
           "out_srs":"EPSG:{srid}"
        }},""".format(**locals())
        # transform bounds in new coordinate system
        pini = Proj(init='epsg:{}'.format(from_srid))
        pout = Proj(init='epsg:{}'.format(srid))
        # recompute offset in new space and start at 0
        pending('Reprojected bounds', nl=True)
        # xmin, ymin, zmin = transform(pini, pout, offset_x, offset_y, offset_z)
        xmin, ymin, zmin = transform(pini, pout, summary['bounds']['X']['min'],
                                     summary['bounds']['Y']['min'],
                                     summary['bounds']['Z']['min'])
        xmax, ymax, zmax = transform(pini, pout, summary['bounds']['X']['max'],
                                     summary['bounds']['Y']['max'],
                                     summary['bounds']['Z']['max'])
        offset_x, offset_y, offset_z = xmin, ymin, zmin
        click.echo('{} < x < {}'.format(xmin, xmax))
        click.echo('{} < y < {}'.format(ymin, ymax))
        click.echo('{} < z < {}  '.format(zmin, zmax), nl=False)
        ok()
        pending('Computing best scales for cesium')
        # override scales for cesium if possible we try to use quantized positions
        scale_x = min(compute_scale_for_cesium(xmin, xmax), 1)
        scale_y = min(compute_scale_for_cesium(ymin, ymax), 1)
        scale_z = min(compute_scale_for_cesium(zmin, zmax), 1)
        ok('[{}, {}, {}]'.format(scale_x, scale_y, scale_z))

    pg_host = app.config['PG_HOST']
    pg_name = app.config['PG_NAME']
    pg_port = app.config['PG_PORT']
    pg_user = app.config['PG_USER']
    pg_password = app.config['PG_PASSWORD']
    realfilename = str(filename.resolve())
    schema, tab = table.split('.')

    pending('Loading point clouds into database')

    with io.open(json_path, 'w') as json_file:
        json_file.write(PDAL_PIPELINE.format(**locals()))

    cmd = "pdal pipeline {}".format(json_path)

    try:
        check_call(shlex.split(cmd), stderr=DEVNULL, stdout=DEVNULL)
    except CalledProcessError as e:
        fatal(e)
    ok()

    pending("Creating indexes")
    Session.execute("""
        create index on {table} using gist(pc_envelopegeometry(points));
        alter table {table} add column morton bigint;
        select Morton_Update('{table}', 'points', 'morton', 128, TRUE);
        create index on {table}(morton);
    """.format(**locals()))
    ok()

    pending("Adding metadata for lopocs")
    Session.update_metadata(table, column, srid, scale_x, scale_y, scale_z,
                            offset_x, offset_y, offset_z)
    lpsession = Session(table, column)
    ok()

    # retrieve boundingbox
    fullbbox = lpsession.boundingbox
    bbox = [
        fullbbox['xmin'], fullbbox['ymin'], fullbbox['zmin'], fullbbox['xmax'],
        fullbbox['ymax'], fullbbox['zmax']
    ]

    if usewith == 'potree':
        lod_min = 0
        lod_max = 5
        # add schema currently used by potree (version 1.5RC)
        Session.add_output_schema(table, column, 0.01, 0.01, 0.01, offset_x,
                                  offset_y, offset_z, srid, potree_schema)
        cache_file = ("{0}_{1}_{2}_{3}_{4}.hcy".format(
            lpsession.table, lpsession.column, lod_min, lod_max,
            '_'.join(str(e) for e in bbox)))
        pending("Building greyhound hierarchy")
        new_hcy = greyhound.build_hierarchy_from_pg(lpsession, lod_min,
                                                    lod_max, bbox)
        greyhound.write_in_cache(new_hcy, cache_file)
        ok()
        create_potree_page(str(work_dir.resolve()), server_url, table, column)

    if usewith == 'cesium':
        pending("Building 3Dtiles tileset")
        hcy = threedtiles.build_hierarchy_from_pg(lpsession, server_url, bbox)

        tileset = os.path.join(str(work_dir.resolve()),
                               'tileset-{}.{}.json'.format(table, column))

        with io.open(tileset, 'wb') as out:
            out.write(hcy.encode())
        ok()
        create_cesium_page(str(work_dir.resolve()), table, column)
Exemple #4
0
def _load(filename, table, column, work_dir, server_url, capacity, usewith, srid=0):
    '''load pointclouds data using pdal and add metadata needed by lopocs'''
    # intialize flask application
    app = create_app()

    filename = Path(filename)
    work_dir = Path(work_dir)
    extension = filename.suffix[1:].lower()
    # laz uses las reader in PDAL
    extension = extension if extension != 'laz' else 'las'
    basename = filename.stem
    basedir = filename.parent

    pending('Creating metadata table')
    Session.create_pointcloud_lopocs_table()
    ok()

    pending('Reading summary with PDAL')
    json_path = os.path.join(
        str(work_dir.resolve()),
        '{basename}_{table}_pipeline.json'.format(**locals()))

    # tablename should be always prefixed
    if '.' not in table:
        table = 'public.{}'.format(table)

    cmd = "pdal info --summary {}".format(filename)
    try:
        output = check_output(shlex.split(cmd))
    except CalledProcessError as e:
        fatal(e)

    summary = json.loads(output.decode())['summary']
    ok()

    if 'srs' not in summary and not srid:
        fatal('Unable to find the spatial reference system, please provide a SRID with option --srid')

    if not srid:
        # find authority code in wkt string
        srid = re.findall('EPSG","(\d+)"', summary['srs']['wkt'])[-1]

    p = Proj(init='epsg:{}'.format(srid))

    if p.is_latlong():
        # geographic
        scale_x, scale_y, scale_z = (1e-6, 1e-6, 1e-2)
    else:
        # projection or geocentric
        scale_x, scale_y, scale_z = (0.01, 0.01, 0.01)

    offset_x = summary['bounds']['X']['min'] + (summary['bounds']['X']['max'] - summary['bounds']['X']['min']) / 2
    offset_y = summary['bounds']['Y']['min'] + (summary['bounds']['Y']['max'] - summary['bounds']['Y']['min']) / 2
    offset_z = summary['bounds']['Z']['min'] + (summary['bounds']['Z']['max'] - summary['bounds']['Z']['min']) / 2

    reproject = ""

    if usewith == 'cesium':
        from_srid = srid
        # cesium only use epsg:4978, so we must reproject before loading into pg
        srid = 4978

        reproject = """
        {{
           "type":"filters.reprojection",
           "in_srs":"EPSG:{from_srid}",
           "out_srs":"EPSG:{srid}"
        }},""".format(**locals())
        # transform bounds in new coordinate system
        pini = Proj(init='epsg:{}'.format(from_srid))
        pout = Proj(init='epsg:{}'.format(srid))
        # recompute offset in new space and start at 0
        pending('Reprojected bounds', nl=True)
        # xmin, ymin, zmin = transform(pini, pout, offset_x, offset_y, offset_z)
        xmin, ymin, zmin = transform(pini, pout, summary['bounds']['X']['min'], summary['bounds']['Y']['min'], summary['bounds']['Z']['min'])
        xmax, ymax, zmax = transform(pini, pout, summary['bounds']['X']['max'], summary['bounds']['Y']['max'], summary['bounds']['Z']['max'])
        offset_x, offset_y, offset_z = xmin, ymin, zmin
        click.echo('{} < x < {}'.format(xmin, xmax))
        click.echo('{} < y < {}'.format(ymin, ymax))
        click.echo('{} < z < {}  '.format(zmin, zmax), nl=False)
        ok()
        pending('Computing best scales for cesium')
        # override scales for cesium if possible we try to use quantized positions
        scale_x = min(compute_scale_for_cesium(xmin, xmax), 1)
        scale_y = min(compute_scale_for_cesium(ymin, ymax), 1)
        scale_z = min(compute_scale_for_cesium(zmin, zmax), 1)
        ok('[{}, {}, {}]'.format(scale_x, scale_y, scale_z))

    pg_host = app.config['PG_HOST']
    pg_name = app.config['PG_NAME']
    pg_port = app.config['PG_PORT']
    pg_user = app.config['PG_USER']
    pg_password = app.config['PG_PASSWORD']
    realfilename = str(filename.resolve())
    schema, tab = table.split('.')

    pending('Loading point clouds into database')

    with io.open(json_path, 'w') as json_file:
        json_file.write(PDAL_PIPELINE.format(**locals()))

    cmd = "pdal pipeline {}".format(json_path)

    try:
        check_call(shlex.split(cmd), stderr=DEVNULL, stdout=DEVNULL)
    except CalledProcessError as e:
        fatal(e)
    ok()

    pending("Creating indexes")
    Session.execute("""
        create index on {table} using gist(pc_envelopegeometry(points));
        alter table {table} add column morton bigint;
        select Morton_Update('{table}', 'points', 'morton', 128, TRUE);
        create index on {table}(morton);
    """.format(**locals()))
    ok()

    pending("Adding metadata for lopocs")
    Session.update_metadata(
        table, column, srid, scale_x, scale_y, scale_z,
        offset_x, offset_y, offset_z
    )
    lpsession = Session(table, column)
    ok()

    # retrieve boundingbox
    fullbbox = lpsession.boundingbox
    bbox = [
        fullbbox['xmin'], fullbbox['ymin'], fullbbox['zmin'],
        fullbbox['xmax'], fullbbox['ymax'], fullbbox['zmax']
    ]

    if usewith == 'potree':
        lod_min = 0
        lod_max = 5
        # add schema currently used by potree (version 1.5RC)
        Session.add_output_schema(
            table, column, 0.01, 0.01, 0.01,
            offset_x, offset_y, offset_z, srid, potree_schema
        )
        cache_file = (
            "{0}_{1}_{2}_{3}_{4}.hcy".format(
                lpsession.table,
                lpsession.column,
                lod_min,
                lod_max,
                '_'.join(str(e) for e in bbox)
            )
        )
        pending("Building greyhound hierarchy")
        new_hcy = greyhound.build_hierarchy_from_pg(
            lpsession, lod_min, lod_max, bbox
        )
        greyhound.write_in_cache(new_hcy, cache_file)
        ok()
        create_potree_page(str(work_dir.resolve()), server_url, table, column)

    if usewith == 'cesium':
        pending("Building 3Dtiles tileset")
        hcy = threedtiles.build_hierarchy_from_pg(
            lpsession, server_url, bbox
        )

        tileset = os.path.join(str(work_dir.resolve()), 'tileset-{}.{}.json'.format(table, column))

        with io.open(tileset, 'wb') as out:
            out.write(hcy.encode())
        ok()
        create_cesium_page(str(work_dir.resolve()), table, column)
Exemple #5
0
    print(fullbbox)

    lod_min = 0
    lod_max = ymlconf_db['DEPTH'] - 1
    bbox_str = '_'.join(str(e) for e in bbox)

    if args.t == "greyhound":
        h = greyhound.build_hierarchy_from_pg(lod_max, bbox, lod_min)

        name = ("{0}_{1}_{2}_{3:.3f}_{4:.3f}_{5:.3f}_{6:.3f}_{7:.3f}_"
                "{8:.3f}.hcy".format(ymlconf_db['PG_NAME'], lod_min, lod_max,
                                     bbox[0], bbox[1], bbox[2], bbox[3],
                                     bbox[4], bbox[5]))

        path = os.path.join(args.outdir, name)
        f = open(path, 'w')
        f.write(json.dumps(h))
        f.close()
    else:
        baseurl = args.u
        h = threedtiles.build_hierarchy_from_pg(baseurl, lod_max, bbox,
                                                lod_min)
        name = "tileset.json"

        path = os.path.join(args.outdir, name)
        f = open(path, 'w')
        f.write(h)
        f.close()

#    print(h)