Coverage Report

Created: 2025-12-31 06:48

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/MapServer/src/mapsearch.c
Line
Count
Source
1
/******************************************************************************
2
 * $Id$
3
 *
4
 * Project:  MapServer
5
 * Purpose:  Various geospatial search operations.
6
 * Author:   Steve Lime and the MapServer team.
7
 *
8
 * Notes: For information on point in polygon function please see:
9
 *
10
 *   http://www.ecse.rpi.edu/Homepages/wrf/Research/Short_Notes/pnpoly.html
11
 *
12
 * The appropriate copyright notice accompanies the function definition.
13
 *
14
 ******************************************************************************
15
 * Copyright (c) 1996-2005 Regents of the University of Minnesota.
16
 *
17
 * Permission is hereby granted, free of charge, to any person obtaining a
18
 * copy of this software and associated documentation files (the "Software"),
19
 * to deal in the Software without restriction, including without limitation
20
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
21
 * and/or sell copies of the Software, and to permit persons to whom the
22
 * Software is furnished to do so, subject to the following conditions:
23
 *
24
 * The above copyright notice and this permission notice shall be included in
25
 * all copies of this Software or works derived from this Software.
26
 *
27
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
28
 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
29
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
30
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
31
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
32
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
33
 * DEALINGS IN THE SOFTWARE.
34
 ****************************************************************************/
35
36
#include "mapserver.h"
37
38
0
#define LASTVERT(v, n) ((v) == 0 ? n - 2 : v - 1)
39
0
#define NEXTVERT(v, n) ((v) == n - 2 ? 0 : v + 1)
40
41
/*
42
** Returns MS_TRUE if rectangles a and b overlap
43
*/
44
0
int msRectOverlap(const rectObj *a, const rectObj *b) {
45
0
  if (a->minx > b->maxx)
46
0
    return (MS_FALSE);
47
0
  if (a->maxx < b->minx)
48
0
    return (MS_FALSE);
49
0
  if (a->miny > b->maxy)
50
0
    return (MS_FALSE);
51
0
  if (a->maxy < b->miny)
52
0
    return (MS_FALSE);
53
0
  return (MS_TRUE);
54
0
}
55
56
/*
57
** Computes the intersection of two rectangles, updating the first
58
** to be only the intersection of the two.  Returns MS_FALSE if
59
** the intersection is empty.
60
*/
61
0
int msRectIntersect(rectObj *a, const rectObj *b) {
62
0
  if (a->maxx > b->maxx)
63
0
    a->maxx = b->maxx;
64
0
  if (a->minx < b->minx)
65
0
    a->minx = b->minx;
66
0
  if (a->maxy > b->maxy)
67
0
    a->maxy = b->maxy;
68
0
  if (a->miny < b->miny)
69
0
    a->miny = b->miny;
70
71
0
  if (a->maxx < a->minx || b->maxx < b->minx)
72
0
    return MS_FALSE;
73
0
  else
74
0
    return MS_TRUE;
75
0
}
76
77
/*
78
** Returns MS_TRUE if rectangle a is contained in rectangle b
79
*/
80
0
int msRectContained(const rectObj *a, const rectObj *b) {
81
0
  if (a->minx >= b->minx && a->maxx <= b->maxx)
82
0
    if (a->miny >= b->miny && a->maxy <= b->maxy)
83
0
      return (MS_TRUE);
84
0
  return (MS_FALSE);
85
0
}
86
87
/*
88
** Merges rect b into rect a. Rect a changes, b does not.
89
*/
90
0
void msMergeRect(rectObj *a, rectObj *b) {
91
0
  a->minx = MS_MIN(a->minx, b->minx);
92
0
  a->maxx = MS_MAX(a->maxx, b->maxx);
93
0
  a->miny = MS_MIN(a->miny, b->miny);
94
0
  a->maxy = MS_MAX(a->maxy, b->maxy);
95
0
}
96
97
0
int msPointInRect(const pointObj *p, const rectObj *rect) {
98
0
  if (p->x < rect->minx)
99
0
    return (MS_FALSE);
100
0
  if (p->x > rect->maxx)
101
0
    return (MS_FALSE);
102
0
  if (p->y < rect->miny)
103
0
    return (MS_FALSE);
104
0
  if (p->y > rect->maxy)
105
0
    return (MS_FALSE);
106
0
  return (MS_TRUE);
107
0
}
108
109
0
int msPolygonDirection(lineObj *c) {
110
0
  double mx, my, area;
111
0
  int i, v = 0, lv, nv;
112
113
  /* first find lowest, rightmost point of polygon */
114
0
  mx = c->point[0].x;
115
0
  my = c->point[0].y;
116
117
0
  for (i = 0; i < c->numpoints - 1; i++) {
118
0
    if ((c->point[i].y < my) ||
119
0
        ((c->point[i].y == my) && (c->point[i].x > mx))) {
120
0
      v = i;
121
0
      mx = c->point[i].x;
122
0
      my = c->point[i].y;
123
0
    }
124
0
  }
125
126
0
  lv = LASTVERT(v, c->numpoints);
127
0
  nv = NEXTVERT(v, c->numpoints);
128
129
0
  area = c->point[lv].x * c->point[v].y - c->point[lv].y * c->point[v].x +
130
0
         c->point[lv].y * c->point[nv].x - c->point[lv].x * c->point[nv].y +
131
0
         c->point[v].x * c->point[nv].y - c->point[nv].x * c->point[v].y;
132
0
  if (area > 0)
133
0
    return (1);      /* counter clockwise orientation */
134
0
  else if (area < 0) /* clockwise orientation */
135
0
    return (-1);
136
0
  else
137
0
    return (0); /* shouldn't happen unless the polygon is self intersecting */
138
0
}
139
140
/*
141
** Copyright (c) 1970-2003, Wm. Randolph Franklin
142
**
143
** Permission is hereby granted, free of charge, to any person obtaining a copy
144
*of this software and
145
** associated documentation files (the "Software"), to deal in the Software
146
*without restriction, including
147
** without limitation the rights to use, copy, modify, merge, publish,
148
*distribute, sublicense, and/or sell
149
** copies of the Software, and to permit persons to whom the Software is
150
*furnished to do so, subject to the
151
** following conditions:
152
**
153
** 1. Redistributions of source code must retain the above copyright notice,
154
*this list of conditions and the
155
**    following disclaimers.
156
** 2. Redistributions in binary form must reproduce the above copyright notice
157
*in the documentation and/or
158
**    other materials provided with the distribution.
159
** 3. The name of W. Randolph Franklin may not be used to endorse or promote
160
*products derived from this
161
**    Software without specific prior written permission.
162
**
163
** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
164
*IMPLIED, INCLUDING BUT NOT
165
** LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
166
*PURPOSE AND NONINFRINGEMENT. IN
167
** NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
168
*DAMAGES OR OTHER LIABILITY,
169
** WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
170
*IN CONNECTION WITH THE
171
** SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
172
*/
173
0
int msPointInPolygon(pointObj *p, lineObj *c) {
174
0
  int i, j, status = MS_FALSE;
175
176
0
  for (i = 0, j = c->numpoints - 1; i < c->numpoints; j = i++) {
177
0
    if ((((c->point[i].y <= p->y) && (p->y < c->point[j].y)) ||
178
0
         ((c->point[j].y <= p->y) && (p->y < c->point[i].y))) &&
179
0
        (p->x < (c->point[j].x - c->point[i].x) * (p->y - c->point[i].y) /
180
0
                        (c->point[j].y - c->point[i].y) +
181
0
                    c->point[i].x))
182
0
      status = !status;
183
0
  }
184
0
  return status;
185
0
}
186
187
/*
188
** Note: the following functions are brute force implementations. Some fancy
189
** computational geometry algorithms would speed things up nicely in many
190
** cases. In due time... -SDL-
191
*/
192
193
int msIntersectSegments(
194
    const pointObj *a, const pointObj *b, const pointObj *c,
195
    const pointObj *d) /* from comp.graphics.algorithms FAQ */
196
0
{
197
198
0
  double r, s;
199
0
  double denominator, numerator;
200
201
0
  numerator = ((a->y - c->y) * (d->x - c->x) - (a->x - c->x) * (d->y - c->y));
202
0
  denominator = ((b->x - a->x) * (d->y - c->y) - (b->y - a->y) * (d->x - c->x));
203
204
0
  if ((denominator == 0) &&
205
0
      (numerator == 0)) { /* lines are coincident, intersection is a line
206
                             segment if it exists */
207
0
    if (a->y == c->y) {   /* coincident horizontally, check x's */
208
0
      if (((a->x >= MS_MIN(c->x, d->x)) && (a->x <= MS_MAX(c->x, d->x))) ||
209
0
          ((b->x >= MS_MIN(c->x, d->x)) && (b->x <= MS_MAX(c->x, d->x))))
210
0
        return (MS_TRUE);
211
0
      else
212
0
        return (MS_FALSE);
213
0
    } else { /* test for y's will work fine for remaining cases */
214
0
      if (((a->y >= MS_MIN(c->y, d->y)) && (a->y <= MS_MAX(c->y, d->y))) ||
215
0
          ((b->y >= MS_MIN(c->y, d->y)) && (b->y <= MS_MAX(c->y, d->y))))
216
0
        return (MS_TRUE);
217
0
      else
218
0
        return (MS_FALSE);
219
0
    }
220
0
  }
221
222
0
  if (denominator == 0) /* lines are parallel, can't intersect */
223
0
    return (MS_FALSE);
224
225
0
  r = numerator / denominator;
226
227
0
  if ((r < 0) || (r > 1))
228
0
    return (MS_FALSE); /* no intersection */
229
230
0
  numerator = ((a->y - c->y) * (b->x - a->x) - (a->x - c->x) * (b->y - a->y));
231
0
  s = numerator / denominator;
232
233
0
  if ((s < 0) || (s > 1))
234
0
    return (MS_FALSE); /* no intersection */
235
236
0
  return (MS_TRUE);
237
0
}
238
239
/*
240
** Instead of using ring orientation we count the number of parts the
241
** point falls in. If odd the point is in the polygon, if 0 or even
242
** then the point is in a hole or completely outside.
243
*/
244
0
int msIntersectPointPolygon(pointObj *point, shapeObj *poly) {
245
0
  int i;
246
0
  int status = MS_FALSE;
247
248
0
  for (i = 0; i < poly->numlines; i++) {
249
0
    if (msPointInPolygon(point, &poly->line[i]) ==
250
0
        MS_TRUE) /* ok, the point is in a line */
251
0
      status = !status;
252
0
  }
253
254
0
  return (status);
255
0
}
256
257
0
int msIntersectMultipointPolygon(shapeObj *multipoint, shapeObj *poly) {
258
0
  int i, j;
259
260
  /* The change to loop through all the lines has been made for ticket
261
   * #2443 but is no more needed since ticket #2762. PostGIS now put all
262
   * points into a single line.  */
263
0
  for (i = 0; i < multipoint->numlines; i++) {
264
0
    lineObj points = multipoint->line[i];
265
0
    for (j = 0; j < points.numpoints; j++) {
266
0
      if (msIntersectPointPolygon(&(points.point[j]), poly) == MS_TRUE)
267
0
        return (MS_TRUE);
268
0
    }
269
0
  }
270
271
0
  return (MS_FALSE);
272
0
}
273
274
0
int msIntersectPolylines(shapeObj *line1, shapeObj *line2) {
275
0
  int c1, v1, c2, v2;
276
277
0
  for (c1 = 0; c1 < line1->numlines; c1++)
278
0
    for (v1 = 1; v1 < line1->line[c1].numpoints; v1++)
279
0
      for (c2 = 0; c2 < line2->numlines; c2++)
280
0
        for (v2 = 1; v2 < line2->line[c2].numpoints; v2++)
281
0
          if (msIntersectSegments(&(line1->line[c1].point[v1 - 1]),
282
0
                                  &(line1->line[c1].point[v1]),
283
0
                                  &(line2->line[c2].point[v2 - 1]),
284
0
                                  &(line2->line[c2].point[v2])) == MS_TRUE)
285
0
            return (MS_TRUE);
286
287
0
  return (MS_FALSE);
288
0
}
289
290
0
int msIntersectPolylinePolygon(shapeObj *line, shapeObj *poly) {
291
0
  int i;
292
293
  /* STEP 1: polygon might competely contain the polyline or one of it's parts
294
   * (only need to check one point from each part) */
295
0
  for (i = 0; i < line->numlines; i++) {
296
0
    if (msIntersectPointPolygon(&(line->line[i].point[0]), poly) ==
297
0
        MS_TRUE) /* this considers holes and multiple parts */
298
0
      return (MS_TRUE);
299
0
  }
300
301
  /* STEP 2: look for intersecting line segments */
302
0
  if (msIntersectPolylines(line, poly) == MS_TRUE)
303
0
    return (MS_TRUE);
304
305
0
  return (MS_FALSE);
306
0
}
307
308
0
int msIntersectPolygons(shapeObj *p1, shapeObj *p2) {
309
0
  int i;
310
311
  /* STEP 1: polygon 1 completely contains 2 (only need to check one point from
312
   * each part) */
313
0
  for (i = 0; i < p2->numlines; i++) {
314
0
    if (msIntersectPointPolygon(&(p2->line[i].point[0]), p1) ==
315
0
        MS_TRUE) /* this considers holes and multiple parts */
316
0
      return (MS_TRUE);
317
0
  }
318
319
  /* STEP 2: polygon 2 completely contains 1 (only need to check one point from
320
   * each part) */
321
0
  for (i = 0; i < p1->numlines; i++) {
322
0
    if (msIntersectPointPolygon(&(p1->line[i].point[0]), p2) ==
323
0
        MS_TRUE) /* this considers holes and multiple parts */
324
0
      return (MS_TRUE);
325
0
  }
326
327
  /* STEP 3: look for intersecting line segments */
328
0
  if (msIntersectPolylines(p1, p2) == MS_TRUE)
329
0
    return (MS_TRUE);
330
331
  /*
332
  ** At this point we know there are are no intersections between edges. There
333
  *may be other tests necessary
334
  ** but I haven't run into any cases that require them.
335
  */
336
337
0
  return (MS_FALSE);
338
0
}
339
340
/*
341
** Distance computations
342
*/
343
344
0
double msDistancePointToPoint(pointObj *a, pointObj *b) {
345
0
  double d;
346
347
0
  d = sqrt(msSquareDistancePointToPoint(a, b));
348
349
0
  return (d);
350
0
}
351
352
/*
353
** Quickly compute the square of the distance; avoids expensive sqrt() call on
354
*each invocation
355
*/
356
0
double msSquareDistancePointToPoint(pointObj *a, pointObj *b) {
357
0
  double dx, dy;
358
359
0
  dx = a->x - b->x;
360
0
  dy = a->y - b->y;
361
362
0
  return (dx * dx + dy * dy);
363
0
}
364
365
0
double msDistancePointToSegment(pointObj *p, pointObj *a, pointObj *b) {
366
0
  return (sqrt(msSquareDistancePointToSegment(p, a, b)));
367
0
}
368
369
0
double msSquareDistancePointToSegment(pointObj *p, pointObj *a, pointObj *b) {
370
0
  double l_squared; /* squared length of line ab */
371
0
  double r, s;
372
373
0
  l_squared = msSquareDistancePointToPoint(a, b);
374
375
0
  if (l_squared == 0.0) /* a = b */
376
0
    return (msSquareDistancePointToPoint(a, p));
377
378
0
  r = ((a->y - p->y) * (a->y - b->y) - (a->x - p->x) * (b->x - a->x)) /
379
0
      (l_squared);
380
381
0
  if (r >
382
0
      1) /* perpendicular projection of P is on the forward extension of AB */
383
0
    return (MS_MIN(msSquareDistancePointToPoint(p, b),
384
0
                   msSquareDistancePointToPoint(p, a)));
385
0
  if (r <
386
0
      0) /* perpendicular projection of P is on the backward extension of AB */
387
0
    return (MS_MIN(msSquareDistancePointToPoint(p, b),
388
0
                   msSquareDistancePointToPoint(p, a)));
389
390
0
  s = ((a->y - p->y) * (b->x - a->x) - (a->x - p->x) * (b->y - a->y)) /
391
0
      l_squared;
392
393
0
  return (fabs(s * s * l_squared));
394
0
}
395
396
0
#define SMALL_NUMBER 0.00000001
397
0
#define dot(u, v) ((u).x * (v).x + (u).y * (v).y) /* vector dot product */
398
0
#define norm(v) sqrt(dot(v, v))
399
400
#define slope(a, b) (((a)->y - (b)->y) / ((a)->x - (b)->x))
401
402
/* Segment to segment distance code is a modified version of that found at:  */
403
/*  */
404
/* http://www.geometryalgorithms.com/Archive/algorithm_0106/algorithm_0106.htm
405
 */
406
/*  */
407
/* Copyright 2001, softSurfer (www.softsurfer.com) */
408
/* This code may be freely used and modified for any purpose */
409
/* providing that this copyright notice is included with it. */
410
/* SoftSurfer makes no warranty for this code, and cannot be held */
411
/* liable for any real or imagined damage resulting from its use. */
412
/* Users of this code must verify correctness for their application. */
413
414
double msDistanceSegmentToSegment(pointObj *pa, pointObj *pb, pointObj *pc,
415
0
                                  pointObj *pd) {
416
0
  vectorObj u, v, w;
417
418
  /* check for strictly parallel segments first */
419
  /* if(((pa->x == pb->x) && (pc->x == pd->x)) || (slope(pa,pb) ==
420
   * slope(pc,pd))) { // vertical (infinite slope) || otherwise parallel */
421
  /* D = msDistancePointToSegment(pa, pc, pd); */
422
  /* D = MS_MIN(D, msDistancePointToSegment(pb, pc, pd)); */
423
  /* D = MS_MIN(D, msDistancePointToSegment(pc, pa, pb)); */
424
  /* return(MS_MIN(D, msDistancePointToSegment(pd, pa, pb))); */
425
  /* } */
426
427
0
  u.x = pb->x - pa->x; /* u = pb - pa */
428
0
  u.y = pb->y - pa->y;
429
0
  v.x = pd->x - pc->x; /* v = pd - pc  */
430
0
  v.y = pd->y - pc->y;
431
0
  w.x = pa->x - pc->x; /* w = pa - pc */
432
0
  w.y = pa->y - pc->y;
433
434
0
  const double a = dot(u, u);
435
0
  const double b = dot(u, v);
436
0
  const double c = dot(v, v);
437
0
  const double d = dot(u, w);
438
0
  const double e = dot(v, w);
439
440
0
  const double D = a * c - b * b;
441
  /* N=numerator, D=denominator */
442
0
  double sN = 0;
443
0
  double sD = D;
444
0
  double tD = D;
445
0
  double tN = D;
446
447
  /* compute the line parameters of the two closest points */
448
0
  if (D < SMALL_NUMBER) { /* lines are parallel or almost parallel */
449
0
    sD = 1.0;
450
0
    tN = e;
451
0
    tD = c;
452
0
  } else { /* get the closest points on the infinite lines */
453
0
    sN = b * e - c * d;
454
0
    tN = a * e - b * d;
455
0
    if (sN < 0) {
456
0
      sN = 0.0;
457
0
      tN = e;
458
0
      tD = c;
459
0
    } else if (sN > sD) {
460
0
      sN = sD;
461
0
      tN = e + b;
462
0
      tD = c;
463
0
    }
464
0
  }
465
466
0
  if (tN < 0) {
467
0
    tN = 0.0;
468
0
    if (-d < 0) {
469
      /* sN = 0.0 */
470
0
    } else if (-d > a)
471
0
      sN = sD;
472
0
    else {
473
0
      sN = -d;
474
0
      sD = a;
475
0
    }
476
0
  } else if (tN > tD) {
477
0
    tN = tD;
478
0
    if ((-d + b) < 0) {
479
      /* sN = 0.0 */
480
0
    } else if ((-d + b) > a)
481
0
      sN = sD;
482
0
    else {
483
0
      sN = (-d + b);
484
0
      sD = a;
485
0
    }
486
0
  }
487
488
  /* finally do the division to get sc and tc */
489
0
  const double sc = sN / sD;
490
0
  const double tc = tN / tD;
491
492
0
  vectorObj dP;
493
0
  dP.x = w.x + (sc * u.x) - (tc * v.x);
494
0
  dP.y = w.y + (sc * u.y) - (tc * v.y);
495
496
0
  return (norm(dP));
497
0
}
498
499
0
double msDistancePointToShape(pointObj *point, shapeObj *shape) {
500
0
  double d;
501
502
0
  d = msSquareDistancePointToShape(point, shape);
503
504
0
  return (sqrt(d));
505
0
}
506
507
/*
508
** As msDistancePointToShape; avoid expensive sqrt calls
509
*/
510
0
double msSquareDistancePointToShape(pointObj *point, shapeObj *shape) {
511
0
  int i, j;
512
0
  double dist, minDist = -1;
513
514
0
  switch (shape->type) {
515
0
  case (MS_SHAPE_POINT):
516
0
    for (j = 0; j < shape->numlines; j++) {
517
0
      for (i = 0; i < shape->line[j].numpoints; i++) {
518
0
        dist = msSquareDistancePointToPoint(point, &(shape->line[j].point[i]));
519
0
        if ((dist < minDist) || (minDist < 0))
520
0
          minDist = dist;
521
0
      }
522
0
    }
523
0
    break;
524
0
  case (MS_SHAPE_LINE):
525
0
    for (j = 0; j < shape->numlines; j++) {
526
0
      for (i = 1; i < shape->line[j].numpoints; i++) {
527
0
        dist = msSquareDistancePointToSegment(
528
0
            point, &(shape->line[j].point[i - 1]), &(shape->line[j].point[i]));
529
0
        if ((dist < minDist) || (minDist < 0))
530
0
          minDist = dist;
531
0
      }
532
0
    }
533
0
    break;
534
0
  case (MS_SHAPE_POLYGON):
535
0
    if (msIntersectPointPolygon(point, shape))
536
0
      minDist = 0; /* point is IN the shape */
537
0
    else {         /* treat shape just like a line */
538
0
      for (j = 0; j < shape->numlines; j++) {
539
0
        for (i = 1; i < shape->line[j].numpoints; i++) {
540
0
          dist = msSquareDistancePointToSegment(point,
541
0
                                                &(shape->line[j].point[i - 1]),
542
0
                                                &(shape->line[j].point[i]));
543
0
          if ((dist < minDist) || (minDist < 0))
544
0
            minDist = dist;
545
0
        }
546
0
      }
547
0
    }
548
0
    break;
549
0
  default:
550
0
    break;
551
0
  }
552
553
0
  return (minDist);
554
0
}
555
556
0
double msDistanceShapeToShape(shapeObj *shape1, shapeObj *shape2) {
557
0
  int i, j, k, l;
558
0
  double dist, minDist = -1;
559
560
0
  switch (shape1->type) {
561
0
  case (MS_SHAPE_POINT): /* shape1 */
562
0
    for (i = 0; i < shape1->numlines; i++) {
563
0
      for (j = 0; j < shape1->line[i].numpoints; j++) {
564
0
        dist =
565
0
            msSquareDistancePointToShape(&(shape1->line[i].point[j]), shape2);
566
0
        if ((dist < minDist) || (minDist < 0))
567
0
          minDist = dist;
568
0
      }
569
0
    }
570
0
    minDist = sqrt(minDist);
571
0
    break;
572
0
  case (MS_SHAPE_LINE): /* shape1 */
573
0
    switch (shape2->type) {
574
0
    case (MS_SHAPE_POINT):
575
0
      for (i = 0; i < shape2->numlines; i++) {
576
0
        for (j = 0; j < shape2->line[i].numpoints; j++) {
577
0
          dist =
578
0
              msSquareDistancePointToShape(&(shape2->line[i].point[j]), shape1);
579
0
          if ((dist < minDist) || (minDist < 0))
580
0
            minDist = dist;
581
0
        }
582
0
      }
583
0
      minDist = sqrt(minDist);
584
0
      break;
585
0
    case (MS_SHAPE_LINE):
586
0
      for (i = 0; i < shape1->numlines; i++) {
587
0
        for (j = 1; j < shape1->line[i].numpoints; j++) {
588
0
          for (k = 0; k < shape2->numlines; k++) {
589
0
            for (l = 1; l < shape2->line[k].numpoints; l++) {
590
              /* check intersection (i.e. dist=0) */
591
0
              if (msIntersectSegments(&(shape1->line[i].point[j - 1]),
592
0
                                      &(shape1->line[i].point[j]),
593
0
                                      &(shape2->line[k].point[l - 1]),
594
0
                                      &(shape2->line[k].point[l])) == MS_TRUE)
595
0
                return (0);
596
597
              /* no intersection, compute distance */
598
0
              dist = msDistanceSegmentToSegment(
599
0
                  &(shape1->line[i].point[j - 1]), &(shape1->line[i].point[j]),
600
0
                  &(shape2->line[k].point[l - 1]), &(shape2->line[k].point[l]));
601
0
              if ((dist < minDist) || (minDist < 0))
602
0
                minDist = dist;
603
0
            }
604
0
          }
605
0
        }
606
0
      }
607
0
      break;
608
0
    case (MS_SHAPE_POLYGON):
609
      /* shape2 (the polygon) could contain shape1 or one of it's parts       */
610
0
      for (i = 0; i < shape1->numlines; i++) {
611
0
        if (msIntersectPointPolygon(&(shape1->line[0].point[0]), shape2) ==
612
0
            MS_TRUE) /* this considers holes and multiple parts */
613
0
          return (0);
614
0
      }
615
616
      /* check segment intersection and, if necessary, distance between segments
617
       */
618
0
      for (i = 0; i < shape1->numlines; i++) {
619
0
        for (j = 1; j < shape1->line[i].numpoints; j++) {
620
0
          for (k = 0; k < shape2->numlines; k++) {
621
0
            for (l = 1; l < shape2->line[k].numpoints; l++) {
622
              /* check intersection (i.e. dist=0) */
623
0
              if (msIntersectSegments(&(shape1->line[i].point[j - 1]),
624
0
                                      &(shape1->line[i].point[j]),
625
0
                                      &(shape2->line[k].point[l - 1]),
626
0
                                      &(shape2->line[k].point[l])) == MS_TRUE)
627
0
                return (0);
628
629
              /* no intersection, compute distance */
630
0
              dist = msDistanceSegmentToSegment(
631
0
                  &(shape1->line[i].point[j - 1]), &(shape1->line[i].point[j]),
632
0
                  &(shape2->line[k].point[l - 1]), &(shape2->line[k].point[l]));
633
0
              if ((dist < minDist) || (minDist < 0))
634
0
                minDist = dist;
635
0
            }
636
0
          }
637
0
        }
638
0
      }
639
0
      break;
640
0
    }
641
0
    break;
642
0
  case (MS_SHAPE_POLYGON): /* shape1 */
643
0
    switch (shape2->type) {
644
0
    case (MS_SHAPE_POINT):
645
0
      for (i = 0; i < shape2->numlines; i++) {
646
0
        for (j = 0; j < shape2->line[i].numpoints; j++) {
647
0
          dist =
648
0
              msSquareDistancePointToShape(&(shape2->line[i].point[j]), shape1);
649
0
          if ((dist < minDist) || (minDist < 0))
650
0
            minDist = dist;
651
0
        }
652
0
      }
653
0
      minDist = sqrt(minDist);
654
0
      break;
655
0
    case (MS_SHAPE_LINE):
656
      /* shape1 (the polygon) could contain shape2 or one of it's parts       */
657
0
      for (i = 0; i < shape2->numlines; i++) {
658
0
        if (msIntersectPointPolygon(&(shape2->line[i].point[0]), shape1) ==
659
0
            MS_TRUE) /* this considers holes and multiple parts */
660
0
          return (0);
661
0
      }
662
663
      /* check segment intersection and, if necessary, distance between segments
664
       */
665
0
      for (i = 0; i < shape1->numlines; i++) {
666
0
        for (j = 1; j < shape1->line[i].numpoints; j++) {
667
0
          for (k = 0; k < shape2->numlines; k++) {
668
0
            for (l = 1; l < shape2->line[k].numpoints; l++) {
669
              /* check intersection (i.e. dist=0) */
670
0
              if (msIntersectSegments(&(shape1->line[i].point[j - 1]),
671
0
                                      &(shape1->line[i].point[j]),
672
0
                                      &(shape2->line[k].point[l - 1]),
673
0
                                      &(shape2->line[k].point[l])) == MS_TRUE)
674
0
                return (0);
675
676
              /* no intersection, compute distance */
677
0
              dist = msDistanceSegmentToSegment(
678
0
                  &(shape1->line[i].point[j - 1]), &(shape1->line[i].point[j]),
679
0
                  &(shape2->line[k].point[l - 1]), &(shape2->line[k].point[l]));
680
0
              if ((dist < minDist) || (minDist < 0))
681
0
                minDist = dist;
682
0
            }
683
0
          }
684
0
        }
685
0
      }
686
0
      break;
687
0
    case (MS_SHAPE_POLYGON):
688
      /* shape1 completely contains shape2 (only need to check one point from
689
       * each part) */
690
0
      for (i = 0; i < shape2->numlines; i++) {
691
0
        if (msIntersectPointPolygon(&(shape2->line[i].point[0]), shape1) ==
692
0
            MS_TRUE) /* this considers holes and multiple parts */
693
0
          return (0);
694
0
      }
695
696
      /* shape2 completely contains shape1 (only need to check one point from
697
       * each part) */
698
0
      for (i = 0; i < shape1->numlines; i++) {
699
0
        if (msIntersectPointPolygon(&(shape1->line[i].point[0]), shape2) ==
700
0
            MS_TRUE) /* this considers holes and multiple parts */
701
0
          return (0);
702
0
      }
703
704
      /* check segment intersection and, if necessary, distance between segments
705
       */
706
0
      for (i = 0; i < shape1->numlines; i++) {
707
0
        for (j = 1; j < shape1->line[i].numpoints; j++) {
708
0
          for (k = 0; k < shape2->numlines; k++) {
709
0
            for (l = 1; l < shape2->line[k].numpoints; l++) {
710
              /* check intersection (i.e. dist=0) */
711
0
              if (msIntersectSegments(&(shape1->line[i].point[j - 1]),
712
0
                                      &(shape1->line[i].point[j]),
713
0
                                      &(shape2->line[k].point[l - 1]),
714
0
                                      &(shape2->line[k].point[l])) == MS_TRUE)
715
0
                return (0);
716
717
              /* no intersection, compute distance */
718
0
              dist = msDistanceSegmentToSegment(
719
0
                  &(shape1->line[i].point[j - 1]), &(shape1->line[i].point[j]),
720
0
                  &(shape2->line[k].point[l - 1]), &(shape2->line[k].point[l]));
721
0
              if ((dist < minDist) || (minDist < 0))
722
0
                minDist = dist;
723
0
            }
724
0
          }
725
0
        }
726
0
      }
727
0
      break;
728
0
    }
729
0
    break;
730
0
  }
731
732
0
  return (minDist);
733
0
}