PostGIS  2.5.0dev-r@@SVN_REVISION@@
POINTARRAY* ptarray_substring ( POINTARRAY pa,
double  d1,
double  d2,
double  tolerance 
)

start location (distance from start / total distance) end location (distance from start / total distance)

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

Definition at line 1053 of file ptarray.c.

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().

1054 {
1055  POINTARRAY *dpa;
1056  POINT4D pt;
1057  POINT4D p1, p2;
1058  POINT4D *p1ptr=&p1; /* don't break strict-aliasing rule */
1059  POINT4D *p2ptr=&p2;
1060  int nsegs, i;
1061  double length, slength, tlength;
1062  int state = 0; /* 0=before, 1=inside */
1063 
1064  /*
1065  * Create a dynamic pointarray with an initial capacity
1066  * equal to full copy of input points
1067  */
1069 
1070  /* Compute total line length */
1071  length = ptarray_length_2d(ipa);
1072 
1073 
1074  LWDEBUGF(3, "Total length: %g", length);
1075 
1076 
1077  /* Get 'from' and 'to' lengths */
1078  from = length*from;
1079  to = length*to;
1080 
1081 
1082  LWDEBUGF(3, "From/To: %g/%g", from, to);
1083 
1084 
1085  tlength = 0;
1086  getPoint4d_p(ipa, 0, &p1);
1087  nsegs = ipa->npoints - 1;
1088  for ( i = 0; i < nsegs; i++ )
1089  {
1090  double dseg;
1091 
1092  getPoint4d_p(ipa, i+1, &p2);
1093 
1094 
1095  LWDEBUGF(3 ,"Segment %d: (%g,%g,%g,%g)-(%g,%g,%g,%g)",
1096  i, p1.x, p1.y, p1.z, p1.m, p2.x, p2.y, p2.z, p2.m);
1097 
1098 
1099  /* Find the length of this segment */
1100  slength = distance2d_pt_pt((POINT2D *)p1ptr, (POINT2D *)p2ptr);
1101 
1102  /*
1103  * We are before requested start.
1104  */
1105  if ( state == 0 ) /* before */
1106  {
1107 
1108  LWDEBUG(3, " Before start");
1109 
1110  if ( fabs ( from - ( tlength + slength ) ) <= tolerance )
1111  {
1112 
1113  LWDEBUG(3, " Second point is our start");
1114 
1115  /*
1116  * Second point is our start
1117  */
1118  ptarray_append_point(dpa, &p2, LW_FALSE);
1119  state=1; /* we're inside now */
1120  goto END;
1121  }
1122 
1123  else if ( fabs(from - tlength) <= tolerance )
1124  {
1125 
1126  LWDEBUG(3, " First point is our start");
1127 
1128  /*
1129  * First point is our start
1130  */
1131  ptarray_append_point(dpa, &p1, LW_FALSE);
1132 
1133  /*
1134  * We're inside now, but will check
1135  * 'to' point as well
1136  */
1137  state=1;
1138  }
1139 
1140  /*
1141  * Didn't reach the 'from' point,
1142  * nothing to do
1143  */
1144  else if ( from > tlength + slength ) goto END;
1145 
1146  else /* tlength < from < tlength+slength */
1147  {
1148 
1149  LWDEBUG(3, " Seg contains first point");
1150 
1151  /*
1152  * Our start is between first and
1153  * second point
1154  */
1155  dseg = (from - tlength) / slength;
1156 
1157  interpolate_point4d(&p1, &p2, &pt, dseg);
1158 
1159  ptarray_append_point(dpa, &pt, LW_FALSE);
1160 
1161  /*
1162  * We're inside now, but will check
1163  * 'to' point as well
1164  */
1165  state=1;
1166  }
1167  }
1168 
1169  if ( state == 1 ) /* inside */
1170  {
1171 
1172  LWDEBUG(3, " Inside");
1173 
1174  /*
1175  * 'to' point is our second point.
1176  */
1177  if ( fabs(to - ( tlength + slength ) ) <= tolerance )
1178  {
1179 
1180  LWDEBUG(3, " Second point is our end");
1181 
1182  ptarray_append_point(dpa, &p2, LW_FALSE);
1183  break; /* substring complete */
1184  }
1185 
1186  /*
1187  * 'to' point is our first point.
1188  * (should only happen if 'to' is 0)
1189  */
1190  else if ( fabs(to - tlength) <= tolerance )
1191  {
1192 
1193  LWDEBUG(3, " First point is our end");
1194 
1195  ptarray_append_point(dpa, &p1, LW_FALSE);
1196 
1197  break; /* substring complete */
1198  }
1199 
1200  /*
1201  * Didn't reach the 'end' point,
1202  * just copy second point
1203  */
1204  else if ( to > tlength + slength )
1205  {
1206  ptarray_append_point(dpa, &p2, LW_FALSE);
1207  goto END;
1208  }
1209 
1210  /*
1211  * 'to' point falls on this segment
1212  * Interpolate and break.
1213  */
1214  else if ( to < tlength + slength )
1215  {
1216 
1217  LWDEBUG(3, " Seg contains our end");
1218 
1219  dseg = (to - tlength) / slength;
1220  interpolate_point4d(&p1, &p2, &pt, dseg);
1221 
1222  ptarray_append_point(dpa, &pt, LW_FALSE);
1223 
1224  break;
1225  }
1226 
1227  else
1228  {
1229  LWDEBUG(3, "Unhandled case");
1230  }
1231  }
1232 
1233 
1234 END:
1235 
1236  tlength += slength;
1237  memcpy(&p1, &p2, sizeof(POINT4D));
1238  }
1239 
1240  LWDEBUGF(3, "Out of loop, ptarray has %d points", dpa->npoints);
1241 
1242  return dpa;
1243 }
double x
Definition: liblwgeom.h:351
double m
Definition: liblwgeom.h:351
#define LWDEBUG(level, msg)
Definition: lwgeom_log.h:83
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, then a duplicate point will not be added.
Definition: ptarray.c:156
double distance2d_pt_pt(const POINT2D *p1, const POINT2D *p2)
The old function nessecary for ptarray_segmentize2d in ptarray.c.
Definition: measures.c:2312
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:704
#define LW_FALSE
Definition: liblwgeom.h:76
uint8_t flags
Definition: liblwgeom.h:368
#define FLAGS_GET_Z(flags)
Macros for manipulating the 'flags' byte.
Definition: liblwgeom.h:139
double ptarray_length_2d(const POINTARRAY *pts)
Find the 2d length of the given POINTARRAY (even if it's 3d)
Definition: ptarray.c:1682
double z
Definition: liblwgeom.h:351
int getPoint4d_p(const POINTARRAY *pa, uint32_t n, POINT4D *point)
Definition: lwgeom_api.c:113
POINTARRAY * ptarray_construct_empty(char hasz, char hasm, uint32_t maxpoints)
Create a new POINTARRAY with no points.
Definition: ptarray.c:70
#define FLAGS_GET_M(flags)
Definition: liblwgeom.h:140
double y
Definition: liblwgeom.h:351
#define LWDEBUGF(level, msg,...)
Definition: lwgeom_log.h:88
uint32_t npoints
Definition: liblwgeom.h:370

Here is the call graph for this function:

Here is the caller graph for this function: