PostGIS  3.7.0dev-r@@SVN_REVISION@@

◆ ptarray_substring()

POINTARRAY* ptarray_substring ( POINTARRAY pa,
double  d1,
double  d2,
double  tolerance 
)

@d1 start location (distance from start / total distance) @d2 end location (distance from start / total distance)

Parameters
tolerancesnap to vertices at locations < tolerance away from given ones

Definition at line 1083 of file ptarray.c.

1084 {
1085  POINTARRAY *dpa;
1086  POINT4D pt;
1087  POINT4D p1, p2;
1088  POINT4D *p1ptr=&p1; /* don't break strict-aliasing rule */
1089  POINT4D *p2ptr=&p2;
1090  int nsegs, i;
1091  double length, slength, tlength;
1092  int state = 0; /* 0=before, 1=inside */
1093 
1094  /*
1095  * Create a dynamic pointarray with an initial capacity
1096  * equal to full copy of input points
1097  */
1099 
1100  /* Compute total line length */
1101  length = ptarray_length_2d(ipa);
1102 
1103 
1104  LWDEBUGF(3, "Total length: %g", length);
1105 
1106 
1107  /* Get 'from' and 'to' lengths */
1108  from = length*from;
1109  to = length*to;
1110 
1111 
1112  LWDEBUGF(3, "From/To: %g/%g", from, to);
1113 
1114 
1115  tlength = 0;
1116  getPoint4d_p(ipa, 0, &p1);
1117  nsegs = ipa->npoints - 1;
1118  for ( i = 0; i < nsegs; i++ )
1119  {
1120  double dseg;
1121 
1122  getPoint4d_p(ipa, i+1, &p2);
1123 
1124 
1125  LWDEBUGF(3 ,"Segment %d: (%g,%g,%g,%g)-(%g,%g,%g,%g)",
1126  i, p1.x, p1.y, p1.z, p1.m, p2.x, p2.y, p2.z, p2.m);
1127 
1128 
1129  /* Find the length of this segment */
1130  slength = distance2d_pt_pt((POINT2D *)p1ptr, (POINT2D *)p2ptr);
1131 
1132  /*
1133  * We are before requested start.
1134  */
1135  if ( state == 0 ) /* before */
1136  {
1137 
1138  LWDEBUG(3, " Before start");
1139 
1140  if ( fabs ( from - ( tlength + slength ) ) <= tolerance )
1141  {
1142 
1143  LWDEBUG(3, " Second point is our start");
1144 
1145  /*
1146  * Second point is our start
1147  */
1148  ptarray_append_point(dpa, &p2, LW_FALSE);
1149  state=1; /* we're inside now */
1150  goto END;
1151  }
1152 
1153  else if ( fabs(from - tlength) <= tolerance )
1154  {
1155 
1156  LWDEBUG(3, " First point is our start");
1157 
1158  /*
1159  * First point is our start
1160  */
1161  ptarray_append_point(dpa, &p1, LW_FALSE);
1162 
1163  /*
1164  * We're inside now, but will check
1165  * 'to' point as well
1166  */
1167  state=1;
1168  }
1169 
1170  /*
1171  * Didn't reach the 'from' point,
1172  * nothing to do
1173  */
1174  else if ( from > tlength + slength ) goto END;
1175 
1176  else /* tlength < from < tlength+slength */
1177  {
1178 
1179  LWDEBUG(3, " Seg contains first point");
1180 
1181  /*
1182  * Our start is between first and
1183  * second point
1184  */
1185  dseg = (from - tlength) / slength;
1186 
1187  interpolate_point4d(&p1, &p2, &pt, dseg);
1188 
1189  ptarray_append_point(dpa, &pt, LW_FALSE);
1190 
1191  /*
1192  * We're inside now, but will check
1193  * 'to' point as well
1194  */
1195  state=1;
1196  }
1197  }
1198 
1199  if ( state == 1 ) /* inside */
1200  {
1201 
1202  LWDEBUG(3, " Inside");
1203 
1204  /*
1205  * 'to' point is our second point.
1206  */
1207  if ( fabs(to - ( tlength + slength ) ) <= tolerance )
1208  {
1209 
1210  LWDEBUG(3, " Second point is our end");
1211 
1212  ptarray_append_point(dpa, &p2, LW_FALSE);
1213  break; /* substring complete */
1214  }
1215 
1216  /*
1217  * 'to' point is our first point.
1218  * (should only happen if 'to' is 0)
1219  */
1220  else if ( fabs(to - tlength) <= tolerance )
1221  {
1222 
1223  LWDEBUG(3, " First point is our end");
1224 
1225  ptarray_append_point(dpa, &p1, LW_FALSE);
1226 
1227  break; /* substring complete */
1228  }
1229 
1230  /*
1231  * Didn't reach the 'end' point,
1232  * just copy second point
1233  */
1234  else if ( to > tlength + slength )
1235  {
1236  ptarray_append_point(dpa, &p2, LW_FALSE);
1237  goto END;
1238  }
1239 
1240  /*
1241  * 'to' point falls on this segment
1242  * Interpolate and break.
1243  */
1244  else if ( to < tlength + slength )
1245  {
1246 
1247  LWDEBUG(3, " Seg contains our end");
1248 
1249  dseg = (to - tlength) / slength;
1250  interpolate_point4d(&p1, &p2, &pt, dseg);
1251 
1252  ptarray_append_point(dpa, &pt, LW_FALSE);
1253 
1254  break;
1255  }
1256 
1257  else
1258  {
1259  LWDEBUG(3, "Unhandled case");
1260  }
1261  }
1262 
1263 
1264 END:
1265 
1266  tlength += slength;
1267  memcpy(&p1, &p2, sizeof(POINT4D));
1268  }
1269 
1270  LWDEBUGF(3, "Out of loop, ptarray has %d points", dpa->npoints);
1271 
1272  return dpa;
1273 }
#define LW_FALSE
Definition: liblwgeom.h:94
double distance2d_pt_pt(const POINT2D *p1, const POINT2D *p2)
Definition: measures.c:2445
void interpolate_point4d(const POINT4D *A, const POINT4D *B, POINT4D *I, double F)
Find interpolation point I between point A and point B so that the len(AI) == len(AB)*F and I falls o...
Definition: lwgeom_api.c:646
#define FLAGS_GET_Z(flags)
Definition: liblwgeom.h:165
#define FLAGS_GET_M(flags)
Definition: liblwgeom.h:166
int getPoint4d_p(const POINTARRAY *pa, uint32_t n, POINT4D *point)
Definition: lwgeom_api.c:125
#define LWDEBUG(level, msg)
Definition: lwgeom_log.h:101
#define LWDEBUGF(level, msg,...)
Definition: lwgeom_log.h:106
double ptarray_length_2d(const POINTARRAY *pts)
Find the 2d length of the given POINTARRAY (even if it's 3d)
Definition: ptarray.c:1840
POINTARRAY * ptarray_construct_empty(char hasz, char hasm, uint32_t maxpoints)
Create a new POINTARRAY with no points.
Definition: ptarray.c:59
int ptarray_append_point(POINTARRAY *pa, const POINT4D *pt, int repeated_points)
Append a point to the end of an existing POINTARRAY If allow_duplicate is LW_FALSE,...
Definition: ptarray.c:147
double m
Definition: liblwgeom.h:414
double x
Definition: liblwgeom.h:414
double z
Definition: liblwgeom.h:414
double y
Definition: liblwgeom.h:414
lwflags_t flags
Definition: liblwgeom.h:431
uint32_t npoints
Definition: liblwgeom.h:427

References distance2d_pt_pt(), POINTARRAY::flags, FLAGS_GET_M, FLAGS_GET_Z, getPoint4d_p(), interpolate_point4d(), LW_FALSE, LWDEBUG, LWDEBUGF, POINT4D::m, POINTARRAY::npoints, ptarray_append_point(), ptarray_construct_empty(), ptarray_length_2d(), POINT4D::x, POINT4D::y, and POINT4D::z.

Referenced by LWGEOM_line_substring().

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