PostGIS  2.3.8dev-r@@SVN_REVISION@@

◆ ptarray_substring()

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

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