Show
Ignore:
Timestamp:
01/21/10 22:19:43 (2 years ago)
Author:
ol
Message:

Use PostGIS 1.5 GeomFromGML to parse GML instead of TinyOWS one. Add check_schema and check_valid_geom config properties to allow to bypass schema and is_valid check, cf #44.

Files:
1 modified

Legend:

Unmodified
Added
Removed
  • src/fe/fe_spatial_ops.c

    r177 r195  
    5757 
    5858/* 
     59 * Transform syntax coordinates from GML 2.1.2 (x1,y1 x2,y2) into Postgis (x1 y1,x2 y2) 
     60 */ 
     61static  buffer *fe_transform_coord_gml_to_psql(buffer * coord) 
     62{ 
     63    size_t i; 
     64    assert(coord != NULL); 
     65 
     66    /*check if the first separator is a comma else do nothing */ 
     67    if (check_regexp(coord->buf, "^[0-9.-]+,")) { 
     68        for (i = 0; i < coord->use; i++) { 
     69            if (coord->buf[i] == ' ')       coord->buf[i] = ','; 
     70            else if (coord->buf[i] == ',')  coord->buf[i] = ' '; 
     71        } 
     72    } 
     73 
     74    return coord; 
     75} 
     76 
     77 
     78/* 
    5979 * Write a polygon geometry according to postgresql syntax from GML bbox 
    6080 */ 
     
    161181 
    162182/* 
    163  * Transform syntax coordinates from GML 2.1.2 (x1,y1 x2,y2) into Postgis (x1 y1,x2 y2) 
    164  */ 
    165 buffer *fe_transform_coord_gml_to_psql(buffer * coord) 
    166 { 
    167     size_t i; 
    168  
    169     assert(coord != NULL); 
    170  
    171     /*check if the first separator is a comma else do nothing */ 
    172     if (check_regexp(coord->buf, "^[0-9.-]+,")) { 
    173         for (i = 0; i < coord->use; i++) { 
    174             if (coord->buf[i] == ' ') 
    175                 coord->buf[i] = ','; 
    176             else if (coord->buf[i] == ',') 
    177                 coord->buf[i] = ' '; 
    178         } 
    179     } 
    180  
    181     return coord; 
    182 } 
    183  
    184  
    185 /* 
    186  * Transform syntax coordinates from GML 3.1.1 (x1 y1 x2 y2) into Postgis' (x1 y1,x2 y2) 
    187  */ 
    188 buffer *fe_transform_coord_gml3_to_psql(buffer * coord) 
    189 { 
    190     size_t i; 
    191     int nb_spaces; 
    192  
    193     assert(coord != NULL); 
    194  
    195     nb_spaces = 0; 
    196  
    197     for (i = 0; i < coord->use; i++) { 
    198         if (coord->buf[i] == ' ') { 
    199             nb_spaces++; 
    200  
    201             /* transform the second space separator into comma */ 
    202             if (nb_spaces == 2) { 
    203                 coord->buf[i] = ','; 
    204                 nb_spaces = 0; 
    205             } 
    206         } 
    207     } 
    208  
    209     return coord; 
    210 } 
    211  
    212  
    213 /* 
    214  * Transform a geometry expressed in GML into Postgis geometry syntax 
    215  */ 
    216 buffer *fe_transform_geometry_gml_to_psql(ows * o, buffer * typename, 
    217         filter_encoding * fe, xmlNodePtr n) 
    218 { 
    219     xmlChar *content; 
    220     xmlNodePtr node, node_coord; 
    221     buffer *tmp, *geom; 
    222     bool first_ring = true; 
    223     int bracket; 
     183 * Return the SQL request matching the spatial operator 
     184 */ 
     185static buffer *fe_spatial_functions(ows * o, buffer * typename, 
     186                                    filter_encoding * fe, xmlNodePtr n) 
     187{ 
     188    bool transform = false; 
     189    buffer *sql; 
    224190 
    225191    assert(o != NULL); 
     
    228194    assert(n != NULL); 
    229195 
    230     content = NULL; 
    231  
    232     /* jump to the next element if there are spaces */ 
    233     while (n->type != XML_ELEMENT_NODE) n = n->next; 
    234  
    235     buffer_add_str(fe->sql, "setsrid('"); 
    236  
    237     geom = buffer_init(); 
    238     if (strcmp((char *) n->name, "MultiSurface") == 0) 
    239         buffer_add_str(geom, "MultiPolygon"); 
    240     else 
    241         buffer_add_str(geom, (char *) n->name); 
    242  
    243     /* print the geometry type */ 
    244     if (buffer_cmp(geom, "MultiPolygon") || buffer_cmp(geom, "MultiSurface")) { 
    245         buffer_add_str(geom, "((("); 
    246         bracket = 3; 
    247     } else if (buffer_cmp(geom, "MultiLineString") 
    248                || buffer_cmp(geom, "Polygon")) { 
    249         buffer_add_str(geom, "(("); 
    250         bracket =2; 
    251     } else if (buffer_cmp(geom, "MultiPoint") 
    252                || buffer_cmp(geom, "Point")  
    253                || buffer_cmp(geom, "LineString")) { 
    254         buffer_add_str(geom, "("); 
    255         bracket = 1; 
    256     } else { 
    257         fe->error_code = FE_ERROR_GEOMETRY; 
    258         buffer_free(geom); 
    259         return fe->sql; 
    260     } 
    261     n = n->children; 
    262  
    263     /* jump to the next element if there are spaces */ 
    264     while (n->type != XML_ELEMENT_NODE) n = n->next; 
    265  
    266     /* print the coordinates */ 
    267     for (node = n; node != NULL; node = node->next) { 
    268  
    269         /* 
    270          * Ignore GML properties if any 
    271          */ 
    272         if ((strcmp((char *) node->name, "description") == 0  
    273             || strcmp((char *) node->name, "name") == 0   
    274             || strcmp((char *) node->name, "metaDataProperty") == 0)   
    275                 && strcmp((char *) node->ns->href, "http://www.opengis.net/gml")  == 0) 
    276             node = node->next; 
    277  
    278         if (node->type == XML_ELEMENT_NODE) { 
    279             node_coord = node; 
    280  
    281  
    282             /* go to node <coordinates> */ 
    283             while (strcmp((char *) node_coord->name, "coordinates") != 0 
    284                     && strcmp((char *) node_coord->name, "posList") != 0 
    285                     && strcmp((char *) node_coord->name, "pos") != 0) { 
    286  
    287                 while (node_coord != NULL && node_coord->type != XML_ELEMENT_NODE) { 
    288                     node_coord = node_coord->next; 
    289                 } 
    290  
    291                 if (node_coord == NULL) { 
    292                     fe->error_code = FE_ERROR_GEOMETRY; 
    293                     buffer_free(geom); 
    294                     return fe->sql; 
    295                } 
    296  
    297                 if (node_coord != NULL && node_coord->type == XML_ELEMENT_NODE  
    298                         && strcmp((char *) node_coord->name, "LinearRing") == 0) { 
    299                     buffer_pop(geom, 1); /* remove last coord comma or ( */ 
    300                     if (!first_ring) buffer_add_str(geom, "),"); 
    301                     buffer_add_str(geom, "("); 
    302                     first_ring = false; 
    303                 } 
    304  
    305                 /* jump to the next element if there are spaces */ 
    306                 if (strcmp((char *) node_coord->name, "coordinates") != 0 
    307                         && strcmp((char *) node_coord->name, "posList") != 0 
    308                         && strcmp((char *) node_coord->name, "pos") != 0) 
    309                     node_coord = node_coord->children; 
    310             } 
    311  
    312             tmp = buffer_init(); 
    313  
    314             content = xmlNodeGetContent(node_coord); 
    315             buffer_add_str(tmp, (char *) content); 
    316  
    317             if (strcmp((char *) node_coord->name, "coordinates") == 0) 
    318                 tmp = fe_transform_coord_gml_to_psql(tmp); 
    319             else 
    320                 tmp = fe_transform_coord_gml3_to_psql(tmp); 
    321  
    322             buffer_copy(geom, tmp); 
    323             buffer_free(tmp); 
    324             xmlFree(content); 
    325         } 
    326  
    327         if (node->next != NULL) { 
    328             if (node->next->type == XML_ELEMENT_NODE) { 
    329                 if (strcmp((char *) node->next->name, 
    330                            "lineStringMember") == 0) 
    331                     buffer_add_str(geom, "),("); 
    332                 else if (strcmp((char *) node->next->name, "polygonMember") == 0 
    333                      || strcmp((char *) node->next->name, "surfaceMember") == 0) 
    334                     buffer_add_str(geom, ")),(("); 
    335                 else 
    336                     buffer_add_str(geom, ","); 
    337             } 
    338         } 
    339     } 
    340  
    341     /* print the geometry type */ 
    342     if (bracket == 3) buffer_add_str(geom, ")))"); 
    343     else if (bracket == 2) buffer_add_str(geom, "))"); 
    344     else buffer_add_str(geom, ")"); 
    345  
    346     if (!ows_psql_is_geometry_valid(o, geom)) { 
    347         fe->error_code = FE_ERROR_GEOMETRY; 
    348         buffer_free(geom); 
    349         return fe->sql; 
    350     } 
    351  
    352     buffer_add_str(geom, "'::geometry,"); 
    353     buffer_copy(fe->sql, geom); 
    354  
    355     /* print the srid */ 
    356     buffer_add_int(fe->sql, ows_srs_get_srid_from_layer(o, typename)); 
    357     buffer_add_str(fe->sql, ")"); 
    358  
    359     buffer_free(geom); 
    360  
    361     return fe->sql; 
    362 } 
    363  
    364  
    365 /* 
    366  * Return the SQL request matching the spatial operator 
    367  */ 
    368 static buffer *fe_spatial_functions(ows * o, buffer * typename, 
    369                                     filter_encoding * fe, xmlNodePtr n) 
    370 { 
    371     bool transform = false; 
    372  
    373     assert(o != NULL); 
    374     assert(typename != NULL); 
    375     assert(fe != NULL); 
    376     assert(n != NULL); 
    377  
    378196    if (strcmp((char *) n->name, "Equals") == 0) 
    379         buffer_add_str(fe->sql, " Equals("); 
     197        buffer_add_str(fe->sql, " ST_Equals("); 
    380198 
    381199    if (strcmp((char *) n->name, "Disjoint") == 0) 
    382         buffer_add_str(fe->sql, " Disjoint("); 
     200        buffer_add_str(fe->sql, " ST_Disjoint("); 
    383201 
    384202    if (strcmp((char *) n->name, "Touches") == 0) 
    385         buffer_add_str(fe->sql, " Touches("); 
     203        buffer_add_str(fe->sql, " ST_Touches("); 
    386204 
    387205    if (strcmp((char *) n->name, "Within") == 0) 
    388         buffer_add_str(fe->sql, " Within("); 
     206        buffer_add_str(fe->sql, " ST_Within("); 
    389207 
    390208    if (strcmp((char *) n->name, "Overlaps") == 0) 
    391         buffer_add_str(fe->sql, " Overlaps("); 
     209        buffer_add_str(fe->sql, " ST_Overlaps("); 
    392210 
    393211    if (strcmp((char *) n->name, "Crosses") == 0) 
    394         buffer_add_str(fe->sql, " Crosses("); 
     212        buffer_add_str(fe->sql, " ST_Crosses("); 
    395213 
    396214    if (strcmp((char *) n->name, "Intersects") == 0) 
    397         buffer_add_str(fe->sql, " Intersects("); 
     215        buffer_add_str(fe->sql, " ST_Intersects("); 
    398216 
    399217    if (strcmp((char *) n->name, "Contains") == 0) 
    400         buffer_add_str(fe->sql, " Contains("); 
     218        buffer_add_str(fe->sql, " ST_Contains("); 
    401219 
    402220    n = n->children; 
     
    424242    while (n->type != XML_ELEMENT_NODE) n = n->next; 
    425243 
    426     buffer_add(fe->sql, ','); 
     244    buffer_add_str(fe->sql, ",'"); 
    427245 
    428246    if (strcmp((char *) n->name, "Box") == 0 
    429247            || strcmp((char *) n->name, "Envelope") == 0) 
    430248        fe->sql = fe_envelope(o, typename, fe, n); 
    431     else 
    432         fe->sql = fe_transform_geometry_gml_to_psql(o, typename, fe, n); 
    433  
    434     buffer_add(fe->sql, ')'); 
     249    else  { 
     250        sql = ows_psql_gml_to_sql(o, n); 
     251        if (sql != NULL) {  
     252            buffer_copy(fe->sql, sql); 
     253            buffer_free(sql); 
     254        } /* TODO else case */ 
     255    } 
     256 
     257    buffer_add_str(fe->sql, "')"); 
    435258 
    436259    return fe->sql; 
     
    446269{ 
    447270    xmlChar *content, *units; 
     271    buffer *tmp, *op, *sql; 
    448272    float km; 
    449     buffer *tmp, *op; 
    450273 
    451274    assert(o != NULL); 
     
    482305    fe->sql = fe_property_name(o, typename, fe, fe->sql, n, true); 
    483306 
    484     buffer_add_str(fe->sql, "),ST_centroid("); 
     307    buffer_add_str(fe->sql, "),ST_centroid('"); 
    485308 
    486309    n = n->next; 
     
    490313 
    491314    /* display the geometry */ 
    492     fe->sql = fe_transform_geometry_gml_to_psql(o, typename, fe, n); 
    493  
    494     buffer_add_str(fe->sql, "))"); 
     315    sql = ows_psql_gml_to_sql(o, n); 
     316    if (sql != NULL) { 
     317        buffer_copy(fe->sql, sql); 
     318        buffer_free(sql); 
     319    } /* TODO else case */ 
     320 
     321    buffer_add_str(fe->sql, "'))"); 
    495322 
    496323    n = n->next;