PostGIS  2.1.10dev-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 1022 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(), and lwline_split_by_point_to().

1023 {
1024  POINTARRAY *dpa;
1025  POINT4D pt;
1026  POINT4D p1, p2;
1027  POINT4D *p1ptr=&p1; /* don't break strict-aliasing rule */
1028  POINT4D *p2ptr=&p2;
1029  int nsegs, i;
1030  double length, slength, tlength;
1031  int state = 0; /* 0=before, 1=inside */
1032 
1033  /*
1034  * Create a dynamic pointarray with an initial capacity
1035  * equal to full copy of input points
1036  */
1037  dpa = ptarray_construct_empty(FLAGS_GET_Z(ipa->flags), FLAGS_GET_M(ipa->flags), ipa->npoints);
1038 
1039  /* Compute total line length */
1040  length = ptarray_length_2d(ipa);
1041 
1042 
1043  LWDEBUGF(3, "Total length: %g", length);
1044 
1045 
1046  /* Get 'from' and 'to' lengths */
1047  from = length*from;
1048  to = length*to;
1049 
1050 
1051  LWDEBUGF(3, "From/To: %g/%g", from, to);
1052 
1053 
1054  tlength = 0;
1055  getPoint4d_p(ipa, 0, &p1);
1056  nsegs = ipa->npoints - 1;
1057  for ( i = 0; i < nsegs; i++ )
1058  {
1059  double dseg;
1060 
1061  getPoint4d_p(ipa, i+1, &p2);
1062 
1063 
1064  LWDEBUGF(3 ,"Segment %d: (%g,%g,%g,%g)-(%g,%g,%g,%g)",
1065  i, p1.x, p1.y, p1.z, p1.m, p2.x, p2.y, p2.z, p2.m);
1066 
1067 
1068  /* Find the length of this segment */
1069  slength = distance2d_pt_pt((POINT2D *)p1ptr, (POINT2D *)p2ptr);
1070 
1071  /*
1072  * We are before requested start.
1073  */
1074  if ( state == 0 ) /* before */
1075  {
1076 
1077  LWDEBUG(3, " Before start");
1078 
1079  if ( fabs ( from - ( tlength + slength ) ) <= tolerance )
1080  {
1081 
1082  LWDEBUG(3, " Second point is our start");
1083 
1084  /*
1085  * Second point is our start
1086  */
1087  ptarray_append_point(dpa, &p2, LW_FALSE);
1088  state=1; /* we're inside now */
1089  goto END;
1090  }
1091 
1092  else if ( fabs(from - tlength) <= tolerance )
1093  {
1094 
1095  LWDEBUG(3, " First point is our start");
1096 
1097  /*
1098  * First point is our start
1099  */
1100  ptarray_append_point(dpa, &p1, LW_FALSE);
1101 
1102  /*
1103  * We're inside now, but will check
1104  * 'to' point as well
1105  */
1106  state=1;
1107  }
1108 
1109  /*
1110  * Didn't reach the 'from' point,
1111  * nothing to do
1112  */
1113  else if ( from > tlength + slength ) goto END;
1114 
1115  else /* tlength < from < tlength+slength */
1116  {
1117 
1118  LWDEBUG(3, " Seg contains first point");
1119 
1120  /*
1121  * Our start is between first and
1122  * second point
1123  */
1124  dseg = (from - tlength) / slength;
1125 
1126  interpolate_point4d(&p1, &p2, &pt, dseg);
1127 
1128  ptarray_append_point(dpa, &pt, LW_FALSE);
1129 
1130  /*
1131  * We're inside now, but will check
1132  * 'to' point as well
1133  */
1134  state=1;
1135  }
1136  }
1137 
1138  if ( state == 1 ) /* inside */
1139  {
1140 
1141  LWDEBUG(3, " Inside");
1142 
1143  /*
1144  * 'to' point is our second point.
1145  */
1146  if ( fabs(to - ( tlength + slength ) ) <= tolerance )
1147  {
1148 
1149  LWDEBUG(3, " Second point is our end");
1150 
1151  ptarray_append_point(dpa, &p2, LW_FALSE);
1152  break; /* substring complete */
1153  }
1154 
1155  /*
1156  * 'to' point is our first point.
1157  * (should only happen if 'to' is 0)
1158  */
1159  else if ( fabs(to - tlength) <= tolerance )
1160  {
1161 
1162  LWDEBUG(3, " First point is our end");
1163 
1164  ptarray_append_point(dpa, &p1, LW_FALSE);
1165 
1166  break; /* substring complete */
1167  }
1168 
1169  /*
1170  * Didn't reach the 'end' point,
1171  * just copy second point
1172  */
1173  else if ( to > tlength + slength )
1174  {
1175  ptarray_append_point(dpa, &p2, LW_FALSE);
1176  goto END;
1177  }
1178 
1179  /*
1180  * 'to' point falls on this segment
1181  * Interpolate and break.
1182  */
1183  else if ( to < tlength + slength )
1184  {
1185 
1186  LWDEBUG(3, " Seg contains our end");
1187 
1188  dseg = (to - tlength) / slength;
1189  interpolate_point4d(&p1, &p2, &pt, dseg);
1190 
1191  ptarray_append_point(dpa, &pt, LW_FALSE);
1192 
1193  break;
1194  }
1195 
1196  else
1197  {
1198  LWDEBUG(3, "Unhandled case");
1199  }
1200  }
1201 
1202 
1203 END:
1204 
1205  tlength += slength;
1206  memcpy(&p1, &p2, sizeof(POINT4D));
1207  }
1208 
1209  LWDEBUGF(3, "Out of loop, ptarray has %d points", dpa->npoints);
1210 
1211  return dpa;
1212 }
double x
Definition: liblwgeom.h:308
double m
Definition: liblwgeom.h:308
int npoints
Definition: liblwgeom.h:327
#define LWDEBUG(level, msg)
Definition: lwgeom_log.h:50
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_TRUE, then a duplicate point will not be added.
Definition: ptarray.c:141
double distance2d_pt_pt(const POINT2D *p1, const POINT2D *p2)
The old function nessecary for ptarray_segmentize2d in ptarray.c.
Definition: measures.c:2123
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:771
#define LW_FALSE
Definition: liblwgeom.h:52
#define FLAGS_GET_Z(flags)
Macros for manipulating the 'flags' byte.
Definition: liblwgeom.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:1586
double z
Definition: liblwgeom.h:308
POINTARRAY * ptarray_construct_empty(char hasz, char hasm, uint32_t maxpoints)
Create a new POINTARRAY with no points.
Definition: ptarray.c:57
#define FLAGS_GET_M(flags)
Definition: liblwgeom.h:107
double y
Definition: liblwgeom.h:308
#define LWDEBUGF(level, msg,...)
Definition: lwgeom_log.h:55
int getPoint4d_p(const POINTARRAY *pa, int n, POINT4D *point)
Definition: lwgeom_api.c:217

Here is the call graph for this function:

Here is the caller graph for this function: