PostGIS 3.0.6dev-r@@SVN_REVISION@@
Loading...
Searching...
No Matches

◆ ptarray_substring()

POINTARRAY * ptarray_substring ( POINTARRAY pa,
double  d1,
double  d2,
double  tolerance 
)
extern

@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 1066 of file ptarray.c.

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