PostGIS  3.1.6dev-r@@SVN_REVISION@@

◆ parse_gml_curve()

static LWGEOM* parse_gml_curve ( xmlNodePtr  xnode,
bool *  hasz,
int *  root_srid 
)
static

Parse GML Curve (3.1.1)

Definition at line 1135 of file lwgeom_in_gml.c.

1136 {
1137  xmlNodePtr xa;
1138  size_t lss;
1139  bool found=false;
1140  gmlSrs srs;
1141  LWGEOM *geom=NULL;
1142  POINTARRAY *pa=NULL;
1143  POINTARRAY **ppa=NULL;
1144  uint32 npoints=0;
1145  xmlChar *interpolation=NULL;
1146 
1147  if (is_xlink(xnode)) xnode = get_xlink_node(xnode);
1148  if (xnode == NULL)
1149  gml_lwpgerror("invalid GML representation", 30);
1150 
1151  /* Looking for gml:segments */
1152  for (xa = xnode->children ; xa != NULL ; xa = xa->next)
1153  {
1154  if (xa->type != XML_ELEMENT_NODE) continue;
1155  if (!is_gml_namespace(xa, false)) continue;
1156  if (is_gml_element(xa, "segments"))
1157  {
1158  found = true;
1159  break;
1160  }
1161  }
1162  if (!found) gml_lwpgerror("invalid GML representation", 37);
1163 
1164  ppa = (POINTARRAY**) lwalloc(sizeof(POINTARRAY*));
1165 
1166  /* Processing each gml:LineStringSegment */
1167  for (xa = xa->children, lss=0; xa != NULL ; xa = xa->next)
1168  {
1169  if (xa->type != XML_ELEMENT_NODE) continue;
1170  if (!is_gml_namespace(xa, false)) continue;
1171 
1172  if (!is_gml_element(xa, "LineStringSegment")) continue;
1173 
1174  /* GML SF is restricted to linear interpolation */
1175  interpolation = gmlGetProp(xa, "interpolation");
1176  if (interpolation != NULL)
1177  {
1178  if (strcmp((char *) interpolation, "linear"))
1179  gml_lwpgerror("invalid GML representation", 38);
1180  xmlFree(interpolation);
1181  }
1182 
1183  if (lss > 0) ppa = (POINTARRAY**) lwrealloc((POINTARRAY *) ppa,
1184  sizeof(POINTARRAY*) * (lss + 1));
1185 
1186  ppa[lss] = parse_gml_data(xa->children, hasz, root_srid);
1187  npoints += ppa[lss]->npoints;
1188  if (ppa[lss]->npoints < 2)
1189  gml_lwpgerror("invalid GML representation", 39);
1190  lss++;
1191  }
1192  if (lss == 0) gml_lwpgerror("invalid GML representation", 40);
1193 
1194  /* Most common case, a single segment */
1195  if (lss == 1) pa = ppa[0];
1196 
1197  if (lss > 1)
1198  {
1199  /*
1200  * "The curve segments are connected to one another, with the end point
1201  * of each segment except the last being the start point of the next
1202  * segment" from ISO 19107:2003 -> 6.3.16.1 (p43)
1203  *
1204  * So we must aggregate all the segments into a single one and avoid
1205  * to copy the redundant points
1206  */
1207  size_t cp_point_size = sizeof(POINT3D); /* All internals are done with 3D */
1208  size_t final_point_size = *hasz ? sizeof(POINT3D) : sizeof(POINT2D);
1209  pa = ptarray_construct(1, 0, npoints - lss + 1);
1210 
1211  /* Copy the first linestring fully */
1212  memcpy(getPoint_internal(pa, 0), getPoint_internal(ppa[0], 0), cp_point_size * (ppa[0]->npoints));
1213  npoints = ppa[0]->npoints;
1214  lwfree(ppa[0]);
1215 
1216  /* For the rest of linestrings, ensure the first point matches the
1217  * last point of the previous one, and copy all points except the
1218  * first one (since it'd be repeated)
1219  */
1220  for (size_t i = 1; i < lss; i++)
1221  {
1222  if (memcmp(getPoint_internal(pa, npoints - 1), getPoint_internal(ppa[i], 0), final_point_size))
1223  gml_lwpgerror("invalid GML representation", 41);
1224 
1225  memcpy(getPoint_internal(pa, npoints),
1226  getPoint_internal(ppa[i], 1),
1227  cp_point_size * (ppa[i]->npoints - 1));
1228 
1229  npoints += ppa[i]->npoints - 1;
1230  lwfree(ppa[i]);
1231  }
1232  }
1233 
1234  lwfree(ppa);
1235 
1236  parse_gml_srs(xnode, &srs);
1237  if (srs.reverse_axis) pa = ptarray_flip_coordinates(pa);
1238  if (srs.srid != *root_srid && *root_srid != SRID_UNKNOWN)
1239  gml_reproject_pa(pa, srs.srid, *root_srid);
1240  geom = (LWGEOM *) lwline_construct(*root_srid, NULL, pa);
1241 
1242  return geom;
1243 }
POINTARRAY * ptarray_construct(char hasz, char hasm, uint32_t npoints)
Construct an empty pointarray, allocating storage and setting the npoints, but not filling in any inf...
Definition: ptarray.c:51
LWLINE * lwline_construct(int32_t srid, GBOX *bbox, POINTARRAY *points)
Definition: lwline.c:42
void * lwrealloc(void *mem, size_t size)
Definition: lwutil.c:235
void lwfree(void *mem)
Definition: lwutil.c:242
void * lwalloc(size_t size)
Definition: lwutil.c:227
#define SRID_UNKNOWN
Unknown SRID value.
Definition: liblwgeom.h:229
POINTARRAY * ptarray_flip_coordinates(POINTARRAY *pa)
Reverse X and Y axis on a given POINTARRAY.
Definition: ptarray.c:368
static xmlNodePtr get_xlink_node(xmlNodePtr xnode)
Return a xmlNodePtr on a node referenced by a XLink or NULL otherwise.
static bool is_xlink(xmlNodePtr node)
Return true if current node contains a simple XLink Return false otherwise.
static POINTARRAY * gml_reproject_pa(POINTARRAY *pa, int32_t epsg_in, int32_t epsg_out)
Use Proj to reproject a given POINTARRAY.
static xmlChar * gmlGetProp(xmlNodePtr xnode, const char *charProp)
Retrieve a GML property from a node or NULL otherwise Respect namespaces if presents in the node elem...
static bool is_gml_namespace(xmlNodePtr xnode, bool is_strict)
Return false if current element namespace is not a GML one Return true otherwise.
static void parse_gml_srs(xmlNodePtr xnode, gmlSrs *srs)
Parse gml srsName attribute.
static POINTARRAY * parse_gml_data(xmlNodePtr xnode, bool *hasz, int *root_srid)
Parse data coordinates.
static void gml_lwpgerror(char *msg, __attribute__((__unused__)) int error_code)
Definition: lwgeom_in_gml.c:81
static bool is_gml_element(xmlNodePtr xn, const char *gml_name)
static uint8_t * getPoint_internal(const POINTARRAY *pa, uint32_t n)
Definition: lwinline.h:77
uint32_t npoints
Definition: liblwgeom.h:441

References get_xlink_node(), getPoint_internal(), gml_lwpgerror(), gml_reproject_pa(), gmlGetProp(), is_gml_element(), is_gml_namespace(), is_xlink(), lwalloc(), lwfree(), lwline_construct(), lwrealloc(), POINTARRAY::npoints, parse_gml_data(), parse_gml_srs(), ptarray_construct(), ptarray_flip_coordinates(), struct_gmlSrs::reverse_axis, struct_gmlSrs::srid, and SRID_UNKNOWN.

Referenced by parse_gml().

Here is the call graph for this function:
Here is the caller graph for this function: