Beispiel #1
0
uint32_t
pc_schema_is_valid(const PCSCHEMA *s)
{
	int i;
	
	if ( s->x_position < 0 )
	{
		pcwarn("schema does not include an X coordinate");
		return PC_FALSE;
	}

	if ( s->y_position < 0 )
	{
		pcwarn("schema does not include a Y coordinate");
		return PC_FALSE;
	}
	
	if ( ! s->ndims )
	{
		pcwarn("schema has no dimensions");
		return PC_FALSE;
	}
	
	for ( i = 0; i < s->ndims; i++ )
	{
		if ( ! s->dims[i] )
		{
			pcwarn("schema is missing a dimension at position %d", i);
			return PC_FALSE;
		}
	}
	
	return PC_TRUE;
}
Beispiel #2
0
/** Population a PCSCHEMA struct from the XML representation */
int
pc_schema_from_xml(const char *xml_str, PCSCHEMA **schema)
{
	xmlDocPtr xml_doc = NULL;
	xmlNodePtr xml_root = NULL;
	xmlNsPtr xml_ns = NULL;
	xmlXPathContextPtr xpath_ctx; 
	xmlXPathObjectPtr xpath_obj; 
	xmlNodeSetPtr nodes;
	PCSCHEMA *s;
	const char *xml_ptr = xml_str;
	
	/* Roll forward to start of XML string */
	while( (*xml_ptr != '\0') && (*xml_ptr != '<') )
	{
		xml_ptr++;
	}
		
	size_t xml_size = strlen(xml_ptr);
	static xmlChar *xpath_str = "/pc:PointCloudSchema/pc:dimension";
	static xmlChar *xpath_metadata_str = "/pc:PointCloudSchema/pc:metadata/Metadata";

	
	/* Parse XML doc */
	*schema = NULL;
	xmlInitParser();
	xml_doc = xmlReadMemory(xml_ptr, xml_size, NULL, NULL, 0);
	if ( ! xml_doc )
	{
		xmlCleanupParser();
		pcwarn("unable to parse schema XML");
		return PC_FAILURE;
	}
	
	/* Capture the namespace */
	xml_root = xmlDocGetRootElement(xml_doc);
	if ( xml_root->ns )
		xml_ns = xml_root->ns;
	
	/* Create xpath evaluation context */
	xpath_ctx = xmlXPathNewContext(xml_doc);
	if( ! xpath_ctx )
	{
		xmlFreeDoc(xml_doc);
		xmlCleanupParser();
		pcwarn("unable to create new XPath context to read schema XML");
		return PC_FAILURE;
	}

	/* Register the root namespace if there is one */
	if ( xml_ns )
		xmlXPathRegisterNs(xpath_ctx, "pc", xml_ns->href);
	
	/* Evaluate xpath expression */
	xpath_obj = xmlXPathEvalExpression(xpath_str, xpath_ctx);
	if( ! xpath_obj )
	{
	    xmlXPathFreeContext(xpath_ctx); 
		xmlFreeDoc(xml_doc);
		xmlCleanupParser();
		pcwarn("unable to evaluate xpath expression \"%s\" against schema XML", xpath_str);
		return PC_FAILURE;
	}

	/* Iterate on the dimensions we found */
	if ( nodes = xpath_obj->nodesetval )
	{
		int ndims = nodes->nodeNr;
		int i;
		s = pc_schema_new(ndims);
		*schema = s;
				
		for ( i = 0; i < ndims; i++ )
		{
			/* This is a "dimension" */
			if( nodes->nodeTab[i]->type == XML_ELEMENT_NODE )
			{
				xmlNodePtr cur = nodes->nodeTab[i];
				xmlNodePtr child;
				PCDIMENSION *d = pc_dimension_new();
				char xydim = 0;
				
				/* These are the values of the dimension */
				for ( child = cur->children; child; child = child->next )
				{
					if( child->type == XML_ELEMENT_NODE )
					{
						if ( strcmp(child->name, "name") == 0 )
						{
							if ( strcasecmp(child->children->content, "X") == 0 ||
							     strcasecmp(child->children->content, "Longitude") == 0 ||
							     strcasecmp(child->children->content, "Lon") == 0 )
							{
								xydim = 'x';
							}
							if ( strcasecmp(child->children->content, "Y") == 0 ||
							     strcasecmp(child->children->content, "Latitude") == 0 ||
							     strcasecmp(child->children->content, "Lat") == 0 )
							{
								xydim = 'y';
							}
							d->name = pcstrdup(child->children->content);
						}
						else if ( strcmp(child->name, "description") == 0 )
							d->description = pcstrdup(child->children->content);
						else if ( strcmp(child->name, "size") == 0 )
							d->size = atoi(child->children->content);
						else if ( strcmp(child->name, "active") == 0 )
							d->active = atoi(child->children->content);
						else if ( strcmp(child->name, "position") == 0 )
							d->position = atoi(child->children->content) - 1;
						else if ( strcmp(child->name, "interpretation") == 0 )
							d->interpretation = pc_interpretation_number(child->children->content);
						else if ( strcmp(child->name, "scale") == 0 )
							d->scale = atof(child->children->content);
						else if ( strcmp(child->name, "offset") == 0 )
							d->offset = atof(child->children->content);
						else if ( strcmp(child->name, "uuid") == 0 )
							/* Ignore this tag for now */ 1;
						else if ( strcmp(child->name, "parent_uuid") == 0 )
							/* Ignore this tag for now */ 1;
						else
							pcinfo("unhandled schema type element \"%s\" encountered", child->name);
					}
				}
				
				/* Convert interprestation to size */
				d->size = pc_interpretation_size(d->interpretation);
				
				/* Store the dimension in the schema */
				if ( d->position >= 0 && d->position < ndims )
				{
					if ( s->dims[d->position] )
					{
						xmlXPathFreeObject(xpath_obj);
					    xmlXPathFreeContext(xpath_ctx); 
						xmlFreeDoc(xml_doc);
						xmlCleanupParser();
						pc_schema_free(s);
						pcwarn("schema dimension at position \"%d\" is declared twice", d->position + 1, ndims);
						return PC_FAILURE;
					}
					if ( xydim == 'x' ) { s->x_position = d->position; }
					if ( xydim == 'y' ) { s->y_position = d->position; }
                    pc_schema_set_dimension(s, d);
				}
				else
				{
					xmlXPathFreeObject(xpath_obj);
				    xmlXPathFreeContext(xpath_ctx); 
					xmlFreeDoc(xml_doc);
					xmlCleanupParser();
					pc_schema_free(s);
					pcwarn("schema dimension states position \"%d\", but number of XML dimensions is \"%d\"", d->position + 1, ndims);
					return PC_FAILURE;
				}
			}
		}
		
		/* Complete the byte offsets of dimensions from the ordered sizes */
		pc_schema_calculate_byteoffsets(s);
		/* Check X/Y positions */
		pc_schema_check_xy(s);
	}
	
	xmlXPathFreeObject(xpath_obj);
	
	/* SEARCH FOR METADATA ENTRIES */
	xpath_obj = xmlXPathEvalExpression(xpath_metadata_str, xpath_ctx);
	if( ! xpath_obj )
	{
	    xmlXPathFreeContext(xpath_ctx); 
		xmlFreeDoc(xml_doc);
		xmlCleanupParser();
		pcwarn("unable to evaluate xpath expression \"%s\" against schema XML", xpath_metadata_str);
		return PC_FAILURE;
	}
	
	/* Iterate on the <Metadata> we find */
	if ( nodes = xpath_obj->nodesetval )
	{
		int i;

		for ( i = 0; i < nodes->nodeNr; i++ )
		{
            char *metadata_name = "";
            char *metadata_value = "";
		    /* Read the metadata name and value from the node */
		    /* <Metadata name="somename">somevalue</Metadata> */
		    xmlNodePtr cur = nodes->nodeTab[i];
            if( cur->type == XML_ELEMENT_NODE && strcmp(cur->name, "Metadata") == 0 )
            {
                metadata_name = xmlGetProp(cur, "name");
                metadata_value = xml_node_get_content(cur);
            }
            
            /* Store the compression type on the schema */
            if ( strcmp(metadata_name, "compression") == 0 )
            {
                int compression = pc_compression_number(metadata_value);
                if ( compression >= 0 )
                {
                    s->compression = compression;
                }
            }
            xmlFree(metadata_name);
        }
	}
	
	xmlXPathFreeObject(xpath_obj);
	
    xmlXPathFreeContext(xpath_ctx); 
	xmlFreeDoc(xml_doc);
	xmlCleanupParser();
	
	return PC_SUCCESS;
}
PCPATCH_UNCOMPRESSED *
pc_patch_uncompressed_from_pointlist(const PCPOINTLIST *pl)
{
	PCPATCH_UNCOMPRESSED *pch;
	const PCSCHEMA *s;
	PCPOINT *pt;
	uint8_t *ptr;
	int i;
	uint32_t numpts;

	if ( ! pl )
	{
		pcerror("%s: null PCPOINTLIST passed in", __func__);
		return NULL;
	}

	numpts = pl->npoints;
	if ( ! numpts )
	{
		pcerror("%s: zero size PCPOINTLIST passed in", __func__);
		return NULL;
	}

	/* Assume the first PCSCHEMA is the same as the rest for now */
	/* We will check this as we go along */
	pt = pc_pointlist_get_point(pl, 0);
	s = pt->schema;

	/* Confirm we have a schema pointer */
	if ( ! s )
	{
		pcerror("%s: null schema encountered", __func__);
		return NULL;
	}

	/* Confirm width of a point data buffer */
	if ( ! s->size )
	{
		pcerror("%s: invalid point size", __func__);
		return NULL;
	}

	/* Make our own data area */
	pch = pcalloc(sizeof(PCPATCH_UNCOMPRESSED));
	pch->datasize = s->size * numpts;
	pch->data = pcalloc(pch->datasize);
	ptr = pch->data;

	/* Initialize bounds */
	pc_bounds_init(&(pch->bounds));

	/* Set up basic info */
	pch->readonly = PC_FALSE;
	pch->maxpoints = numpts;
	pch->type = PC_NONE;
	pch->schema = s;
	pch->npoints = 0;

	for ( i = 0; i < numpts; i++ )
	{
		pt = pc_pointlist_get_point(pl, i);
		if ( pt )
		{
			if ( pt->schema->pcid != s->pcid )
			{
				pcerror("%s: points do not share a schema", __func__);
				return NULL;
			}
			memcpy(ptr, pt->data, s->size);
			pch->npoints++;
			ptr += s->size;
		}
		else
		{
			pcwarn("%s: encountered null point", __func__);
		}
	}

	if ( PC_FAILURE == pc_patch_uncompressed_compute_extent(pch) )
	{
		pcerror("%s: failed to compute patch extent", __func__);
		return NULL;
	}

	if ( PC_FAILURE == pc_patch_uncompressed_compute_stats(pch) )
	{
		pcerror("%s: failed to compute patch stats", __func__);
		return NULL;
	}

	return pch;
}