PostGIS  3.0.6dev-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 1058 of file ptarray.c.

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

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: