PCPATCH_GHT *
pc_patch_ght_from_uncompressed(const PCPATCH_UNCOMPRESSED *pa)
{
#ifndef HAVE_LIBGHT
	pcerror("%s: libght support is not enabled", __func__);
	return NULL;
#else

	int i, j;
	int pointcount = 0;
	GhtSchemaPtr schema;
	GhtTreePtr tree;
	GhtCoordinate coord;
	GhtNodePtr node;
	PCPOINT pt;
	PCDIMENSION *xdim, *ydim;
	PCPATCH_GHT *paght = NULL;
	size_t pt_size = pa->schema->size;

	/* Cannot handle empty patches */
	if ( ! pa || ! pa->npoints ) return NULL;

	pt.schema = pa->schema;
	pt.readonly = PC_TRUE;

	xdim = pa->schema->dims[pa->schema->x_position];
	ydim = pa->schema->dims[pa->schema->y_position];

	schema = ght_schema_from_pc_schema(pa->schema);
	if ( ght_tree_new(schema, &tree) != GHT_OK ) {
		pcerror("ght_tree_new failed");
		return NULL;
	}

	/* Build up the tree from the points. */
	for ( i = 0; i < pa->npoints; i++ )
	{
		pt.data = pa->data + pt_size * i;
		pc_point_get_double(&pt, xdim, &(coord.x));
		pc_point_get_double(&pt, ydim, &(coord.y));

		/* Build a node from the x/y information */
		/* TODO, make resolution configurable from the schema */
		if ( ght_node_new_from_coordinate(&coord, GHT_MAX_HASH_LENGTH, &node) == GHT_OK )
		{
			unsigned int num_dims;
			ght_schema_get_num_dimensions(schema, &num_dims);
			/* Add attributes to the node */
			for ( j = 0; j < num_dims; j++ )
			{
				PCDIMENSION *dim;
				GhtDimensionPtr ghtdim;
				GhtAttributePtr attr;
				double val;

				/* Don't add X or Y as attributes, they are already embodied in the hash */
				if ( j == pa->schema->x_position || j == pa->schema->y_position )
					continue;

				dim = pc_schema_get_dimension(pa->schema, j);
				pc_point_get_double(&pt, dim, &val);

				ght_schema_get_dimension_by_index(schema, j, &ghtdim);
				ght_attribute_new_from_double(ghtdim, val, &attr);
				ght_node_add_attribute(node, attr);
			}

			/* Add the node to the tree */
			/* TODO, make duplicate handling configurable from the schema */
			if ( ght_tree_insert_node(tree, node) == GHT_OK )
			{
				pointcount++;
			}
			else
			{
				// ght_tree_free(tree);
				pcerror("ght_tree_insert_node failed");
				return NULL;
			}
		}
		else
		{
			ght_tree_free(tree);
			pcerror("ght_node_new_from_coordinate failed");
			return NULL;
		}
	}

	/* Compact the tree */
	if ( ght_tree_compact_attributes(tree) == GHT_OK )
	{
		GhtWriterPtr writer;
		paght = pcalloc(sizeof(PCPATCH_GHT));
		paght->type = PC_GHT;
		paght->readonly = PC_FALSE;
		paght->schema = pa->schema;
		paght->npoints = pointcount;
		paght->bounds = pa->bounds;
		paght->stats = pc_stats_clone(pa->stats);

		/* Convert the tree to a memory buffer */
		ght_writer_new_mem(&writer);
		ght_tree_write(tree, writer);
		ght_writer_get_size(writer, &(paght->ghtsize));
		paght->ght = pcalloc(paght->ghtsize);
		ght_writer_get_bytes(writer, paght->ght);
		ght_writer_free(writer);
	}

	// Let the hierarchical memory manager clean up the tree
	// ght_tree_free(tree);
	return paght;
#endif
}
Exemple #2
0
int
main (int argc, char **argv)
{
    Las2GhtConfig config;
    Las2GhtState state;
    GhtTreePtr tree;
    int num_points;

    /* Set up to use the GHT system memory management / logging */
    ght_init();
    
    /* We can't do anything if we don't have GDAL/GeoTIFF support in libLAS */
    if ( ! (LAS_IsGDALEnabled() && LAS_IsLibGeoTIFFEnabled()) )
    {
        ght_error("%s: requires LibLAS built with GDAL and GeoTIFF support", EXENAME);
        return 1;
    }
    
    /* Ensure state is clean */
    memset(&state, 0, sizeof(Las2GhtState));

    /* If no options are specified, display l2g_usage */
    if (argc <= 1)
    {
        l2g_usage();
        return 1;
    }

    /* Parse command line options and set configuration */
    if ( ! l2g_getopts(argc, argv, &config) )
    {
        l2g_usage();
        return 1;
    }
     
    /* Hard code resolution for now */
    config.resolution = GHT_MAX_HASH_LENGTH;
    config.maxpoints = 2000000;
    
    /* Temporary info printout */
    l2g_config_printf(&config);

    /* Input file exists? */
    if ( ! l2g_fexists(config.lasfile) )
    {
        ght_error("%s: LAS file '%s' does not exist\n", EXENAME, config.lasfile);
        return 1;
    }
    
    /* Output file is writeable? */
    if ( ! l2g_writable(config.ghtfile) )
    {
        ght_error("%s: GHT file '%s' is not writable\n", EXENAME, config.ghtfile);
        return 1;
    }

    /* Can we open the LAS file? */
    state.reader = LASReader_Create(config.lasfile);
    if ( ! state.reader )
    {
        ght_error("%s: unable to open LAS file '%s'\n", EXENAME, config.lasfile);
        return 1;
    }
    
    ght_info("Opened LAS file '%s' for reading", config.lasfile);
    
    /* Get the header */
    state.header = LASReader_GetHeader(state.reader);
    if ( ! state.header) 
    {
        l2g_state_free(&state);
        ght_error("%s: unable to read LAS header in '%s'\n", EXENAME, config.lasfile);
        return 1;
    }
    
    /* Schema is needed to create nodes/attributes */
    if ( GHT_OK != l2g_build_schema(&config, &state) )
    {
        l2g_state_free(&state);
        ght_error("%s: unable to build schema!", EXENAME);
        return 1;
    }
    
    /* Project info is needed to get points into lat/lon space */
    if ( GHT_OK != l2g_read_projection(&config, &state) )
    {
        l2g_state_free(&state);
        ght_error("%s: unable to build projection information", EXENAME);
        return 1;
    }

    // char *xmlstr;
    // size_t xmlsize;
    // ght_schema_to_xml_str(schema, &xmlstr, &xmlsize);
    // printf("\n%s\n\n", xmlstr);


    /* Break the problem into chunks. We might get a really really */
    /* big LAS file, and we don't want to blow out memory, so we need to */
    /* do this a few million records at a file */
    do 
    {
        num_points = l2g_build_tree(&config, &state, &tree);
        if ( num_points )
        {
            GhtErr err;
            ght_tree_compact_attributes(tree);
            err = l2g_save_tree(&config, &state, tree);
            ght_tree_free(tree);
            if ( err != GHT_OK )
                return 1;
        }
    } 
    while ( num_points > 0 );

    l2g_state_free(&state);
    l2g_config_free(&config);

    ght_info("conversion complete");

    return 0;
}