PostGIS  2.4.9dev-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 1061 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().

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