/** * @param schema we want to partially clone * @param an array with the position of the dimension we want to *keep* * @param the total number of dimension we want to keep * @return a cloned schema with only the dimension whose position are provided, the new position of dimension is there index+1 in provided array, NULL if something wen wrong * */ PCSCHEMA * pc_schema_clone_subset( PCSCHEMA *s, uint32_t * dimensions_position_array, uint32_t dimensions_number) { int i; PCDIMENSION* temp_dim; PCSCHEMA *pcs = pc_schema_new(dimensions_number); pcs->pcid = s->pcid; pcs->srid = s->srid; pcs->compression = s->compression; //printf("\n for loop \n"); for ( i = 0; i < dimensions_number; i++ ) { if ( s->dims[dimensions_position_array[i]] ) { temp_dim = pc_dimension_clone(s->dims[dimensions_position_array[i]]);//cloning the dimension temp_dim->position=i ; //changing the position so to have continuous dimension position pc_schema_set_dimension(pcs,temp_dim); //printf("cloning the dimension %s in new position %d",temp_dim->name,i); } } //the new x_position and y_position should be found according to where X and Y dimension are //looking for X and Y in dimension, to get the dimension position pcs->x_position=pc_schema_get_dimension_position_by_name(pcs,"x"); pcs->y_position=pc_schema_get_dimension_position_by_name(pcs,"y"); //pcinfo("updating schema : x_position : %d, y_position : %d",pcs->x_position,pcs->y_position); pc_schema_calculate_byteoffsets(pcs); return pcs; }
PCSCHEMA* pc_schema_clone(const PCSCHEMA *s) { int i; PCSCHEMA *pcs = pc_schema_new(s->ndims); pcs->pcid = s->pcid; pcs->srid = s->srid; pcs->x_position = s->x_position; pcs->y_position = s->y_position; pcs->compression = s->compression; for ( i = 0; i < pcs->ndims; i++ ) { if ( s->dims[i] ) { pc_schema_set_dimension(pcs, pc_dimension_clone(s->dims[i])); } } pc_schema_calculate_byteoffsets(pcs); return pcs; }
/** 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; }