]> granicus.if.org Git - postgis/commitdiff
Some fixes to the ST_DWithin code.
authorPaul Ramsey <pramsey@cleverelephant.ca>
Sun, 4 Oct 2009 00:51:00 +0000 (00:51 +0000)
committerPaul Ramsey <pramsey@cleverelephant.ca>
Sun, 4 Oct 2009 00:51:00 +0000 (00:51 +0000)
git-svn-id: http://svn.osgeo.org/postgis/trunk@4585 b70326c6-7e19-0410-871a-916f4a2858ee

install-sh
liblwgeom/cunit/cu_geodetic.c
liblwgeom/lwgeodetic.c
postgis/geography.sql.in.c
postgis/geography_distance.c
postgis/geography_estimate.c
postgis/geography_gist.c

index e4160c991dc958a11b89654e365c72a13639f6b2..a5897de6ea7f74f83fd793474bb4738d32884719 100755 (executable)
@@ -1,7 +1,7 @@
 #!/bin/sh
 # install - install a program, script, or datafile
 
-scriptversion=2004-04-01.17
+scriptversion=2006-12-25.00
 
 # This originates from X11R5 (mit/util/scripts/install.sh), which was
 # later released in X11R6 (xc/config/util/install.sh) with the
@@ -39,120 +39,157 @@ scriptversion=2004-04-01.17
 # when there is no Makefile.
 #
 # This script is compatible with the BSD install script, but was written
-# from scratch.  It can only install one file at a time, a restriction
-# shared with many OS's install programs.
+# from scratch.
+
+nl='
+'
+IFS=" ""       $nl"
 
 # set DOITPROG to echo to test this script
 
 # Don't use :- since 4.3BSD and earlier shells don't like it.
-doit="${DOITPROG-}"
-
-# put in absolute paths if you don't have them in your path; or use env. vars.
-
-mvprog="${MVPROG-mv}"
-cpprog="${CPPROG-cp}"
-chmodprog="${CHMODPROG-chmod}"
-chownprog="${CHOWNPROG-chown}"
-chgrpprog="${CHGRPPROG-chgrp}"
-stripprog="${STRIPPROG-strip}"
-rmprog="${RMPROG-rm}"
-mkdirprog="${MKDIRPROG-mkdir}"
-
-transformbasename=
-transform_arg=
-instcmd="$mvprog"
-chmodcmd="$chmodprog 0755"
-chowncmd=
+doit=${DOITPROG-}
+if test -z "$doit"; then
+  doit_exec=exec
+else
+  doit_exec=$doit
+fi
+
+# Put in absolute file names if you don't have them in your path;
+# or use environment vars.
+
+chgrpprog=${CHGRPPROG-chgrp}
+chmodprog=${CHMODPROG-chmod}
+chownprog=${CHOWNPROG-chown}
+cmpprog=${CMPPROG-cmp}
+cpprog=${CPPROG-cp}
+mkdirprog=${MKDIRPROG-mkdir}
+mvprog=${MVPROG-mv}
+rmprog=${RMPROG-rm}
+stripprog=${STRIPPROG-strip}
+
+posix_glob='?'
+initialize_posix_glob='
+  test "$posix_glob" != "?" || {
+    if (set -f) 2>/dev/null; then
+      posix_glob=
+    else
+      posix_glob=:
+    fi
+  }
+'
+
+posix_mkdir=
+
+# Desired mode of installed file.
+mode=0755
+
 chgrpcmd=
-stripcmd=
+chmodcmd=$chmodprog
+chowncmd=
+mvcmd=$mvprog
 rmcmd="$rmprog -f"
-mvcmd="$mvprog"
+stripcmd=
+
 src=
 dst=
 dir_arg=
+dst_arg=
+
+copy_on_change=false
+no_target_directory=
 
-usage="Usage: $0 [OPTION]... SRCFILE DSTFILE
+usage="\
+Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE
    or: $0 [OPTION]... SRCFILES... DIRECTORY
-   or: $0 -d DIRECTORIES...
+   or: $0 [OPTION]... -t DIRECTORY SRCFILES...
+   or: $0 [OPTION]... -d DIRECTORIES...
 
-In the first form, install SRCFILE to DSTFILE, removing SRCFILE by default.
-In the second, create the directory path DIR.
+In the 1st form, copy SRCFILE to DSTFILE.
+In the 2nd and 3rd, copy all SRCFILES to DIRECTORY.
+In the 4th, create DIRECTORIES.
 
 Options:
--b=TRANSFORMBASENAME
--c         copy source (using $cpprog) instead of moving (using $mvprog).
--d         create directories instead of installing files.
--g GROUP   $chgrp installed files to GROUP.
--m MODE    $chmod installed files to MODE.
--o USER    $chown installed files to USER.
--s         strip installed files (using $stripprog).
--t=TRANSFORM
---help     display this help and exit.
---version  display version info and exit.
+     --help     display this help and exit.
+     --version  display version info and exit.
+
+  -c            (ignored)
+  -C            install only if different (preserve the last data modification time)
+  -d            create directories instead of installing files.
+  -g GROUP      $chgrpprog installed files to GROUP.
+  -m MODE       $chmodprog installed files to MODE.
+  -o USER       $chownprog installed files to USER.
+  -s            $stripprog installed files.
+  -t DIRECTORY  install into DIRECTORY.
+  -T            report an error if DSTFILE is a directory.
 
 Environment variables override the default commands:
-  CHGRPPROG CHMODPROG CHOWNPROG CPPROG MKDIRPROG MVPROG RMPROG STRIPPROG
+  CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG
+  RMPROG STRIPPROG
 "
 
-while test -n "$1"; do
+while test $# -ne 0; do
   case $1 in
-    -b=*) transformbasename=`echo $1 | sed 's/-b=//'`
-        shift
-        continue;;
+    -c) ;;
 
-    -c) instcmd=$cpprog
-        shift
-        continue;;
+    -C) copy_on_change=true;;
 
-    -d) dir_arg=true
-        shift
-        continue;;
+    -d) dir_arg=true;;
 
     -g) chgrpcmd="$chgrpprog $2"
-        shift
-        shift
-        continue;;
+       shift;;
 
-    --help) echo "$usage"; exit 0;;
+    --help) echo "$usage"; exit $?;;
 
-    -m) chmodcmd="$chmodprog $2"
-        shift
-        shift
-        continue;;
+    -m) mode=$2
+       case $mode in
+         *' '* | *'    '* | *'
+'*       | *'*'* | *'?'* | *'['*)
+           echo "$0: invalid mode: $mode" >&2
+           exit 1;;
+       esac
+       shift;;
 
     -o) chowncmd="$chownprog $2"
-        shift
-        shift
-        continue;;
-
-    -s) stripcmd=$stripprog
-        shift
-        continue;;
-
-    -t=*) transformarg=`echo $1 | sed 's/-t=//'`
-        shift
-        continue;;
-
-    --version) echo "$0 $scriptversion"; exit 0;;
-
-    *)  # When -d is used, all remaining arguments are directories to create.
-       test -n "$dir_arg" && break
-        # Otherwise, the last argument is the destination.  Remove it from $@.
-       for arg
-       do
-          if test -n "$dstarg"; then
-           # $@ is not empty: it contains at least $arg.
-           set fnord "$@" "$dstarg"
-           shift # fnord
-         fi
-         shift # arg
-         dstarg=$arg
-       done
+       shift;;
+
+    -s) stripcmd=$stripprog;;
+
+    -t) dst_arg=$2
+       shift;;
+
+    -T) no_target_directory=true;;
+
+    --version) echo "$0 $scriptversion"; exit $?;;
+
+    --)        shift
        break;;
+
+    -*)        echo "$0: invalid option: $1" >&2
+       exit 1;;
+
+    *)  break;;
   esac
+  shift
 done
 
-if test -z "$1"; then
+if test $# -ne 0 && test -z "$dir_arg$dst_arg"; then
+  # When -d is used, all remaining arguments are directories to create.
+  # When -t is used, the destination is already specified.
+  # Otherwise, the last argument is the destination.  Remove it from $@.
+  for arg
+  do
+    if test -n "$dst_arg"; then
+      # $@ is not empty: it contains at least $arg.
+      set fnord "$@" "$dst_arg"
+      shift # fnord
+    fi
+    shift # arg
+    dst_arg=$arg
+  done
+fi
+
+if test $# -eq 0; then
   if test -z "$dir_arg"; then
     echo "$0: no input file specified." >&2
     exit 1
@@ -162,25 +199,48 @@ if test -z "$1"; then
   exit 0
 fi
 
+if test -z "$dir_arg"; then
+  trap '(exit $?); exit' 1 2 13 15
+
+  # Set umask so as not to create temps with too-generous modes.
+  # However, 'strip' requires both read and write access to temps.
+  case $mode in
+    # Optimize common cases.
+    *644) cp_umask=133;;
+    *755) cp_umask=22;;
+
+    *[0-7])
+      if test -z "$stripcmd"; then
+       u_plus_rw=
+      else
+       u_plus_rw='% 200'
+      fi
+      cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;;
+    *)
+      if test -z "$stripcmd"; then
+       u_plus_rw=
+      else
+       u_plus_rw=,u+rw
+      fi
+      cp_umask=$mode$u_plus_rw;;
+  esac
+fi
+
 for src
 do
   # Protect names starting with `-'.
   case $src in
-    -*) src=./$src ;;
+    -*) src=./$src;;
   esac
 
   if test -n "$dir_arg"; then
     dst=$src
-    src=
-
-    if test -d "$dst"; then
-      instcmd=:
-      chmodcmd=
-    else
-      instcmd=$mkdirprog
-    fi
+    dstdir=$dst
+    test -d "$dstdir"
+    dstdir_status=$?
   else
-    # Waiting for this to be detected by the "$instcmd $src $dsttmp" command
+
+    # Waiting for this to be detected by the "$cpprog $src $dsttmp" command
     # might cause directories to be created, which would be especially bad
     # if $src (and thus $dsttmp) contains '*'.
     if test ! -f "$src" && test ! -d "$src"; then
@@ -188,135 +248,269 @@ do
       exit 1
     fi
 
-    if test -z "$dstarg"; then
+    if test -z "$dst_arg"; then
       echo "$0: no destination specified." >&2
       exit 1
     fi
 
-    dst=$dstarg
+    dst=$dst_arg
     # Protect names starting with `-'.
     case $dst in
-      -*) dst=./$dst ;;
+      -*) dst=./$dst;;
     esac
 
     # If destination is a directory, append the input filename; won't work
     # if double slashes aren't ignored.
     if test -d "$dst"; then
-      dst=$dst/`basename "$src"`
+      if test -n "$no_target_directory"; then
+       echo "$0: $dst_arg: Is a directory" >&2
+       exit 1
+      fi
+      dstdir=$dst
+      dst=$dstdir/`basename "$src"`
+      dstdir_status=0
+    else
+      # Prefer dirname, but fall back on a substitute if dirname fails.
+      dstdir=`
+       (dirname "$dst") 2>/dev/null ||
+       expr X"$dst" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+            X"$dst" : 'X\(//\)[^/]' \| \
+            X"$dst" : 'X\(//\)$' \| \
+            X"$dst" : 'X\(/\)' \| . 2>/dev/null ||
+       echo X"$dst" |
+           sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+                  s//\1/
+                  q
+                }
+                /^X\(\/\/\)[^/].*/{
+                  s//\1/
+                  q
+                }
+                /^X\(\/\/\)$/{
+                  s//\1/
+                  q
+                }
+                /^X\(\/\).*/{
+                  s//\1/
+                  q
+                }
+                s/.*/./; q'
+      `
+
+      test -d "$dstdir"
+      dstdir_status=$?
     fi
   fi
 
-  # This sed command emulates the dirname command.
-  dstdir=`echo "$dst" | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'`
+  obsolete_mkdir_used=false
+
+  if test $dstdir_status != 0; then
+    case $posix_mkdir in
+      '')
+       # Create intermediate dirs using mode 755 as modified by the umask.
+       # This is like FreeBSD 'install' as of 1997-10-28.
+       umask=`umask`
+       case $stripcmd.$umask in
+         # Optimize common cases.
+         *[2367][2367]) mkdir_umask=$umask;;
+         .*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;;
+
+         *[0-7])
+           mkdir_umask=`expr $umask + 22 \
+             - $umask % 100 % 40 + $umask % 20 \
+             - $umask % 10 % 4 + $umask % 2
+           `;;
+         *) mkdir_umask=$umask,go-w;;
+       esac
+
+       # With -d, create the new directory with the user-specified mode.
+       # Otherwise, rely on $mkdir_umask.
+       if test -n "$dir_arg"; then
+         mkdir_mode=-m$mode
+       else
+         mkdir_mode=
+       fi
+
+       posix_mkdir=false
+       case $umask in
+         *[123567][0-7][0-7])
+           # POSIX mkdir -p sets u+wx bits regardless of umask, which
+           # is incompatible with FreeBSD 'install' when (umask & 300) != 0.
+           ;;
+         *)
+           tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$
+           trap 'ret=$?; rmdir "$tmpdir/d" "$tmpdir" 2>/dev/null; exit $ret' 0
+
+           if (umask $mkdir_umask &&
+               exec $mkdirprog $mkdir_mode -p -- "$tmpdir/d") >/dev/null 2>&1
+           then
+             if test -z "$dir_arg" || {
+                  # Check for POSIX incompatibilities with -m.
+                  # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or
+                  # other-writeable bit of parent directory when it shouldn't.
+                  # FreeBSD 6.1 mkdir -m -p sets mode of existing directory.
+                  ls_ld_tmpdir=`ls -ld "$tmpdir"`
+                  case $ls_ld_tmpdir in
+                    d????-?r-*) different_mode=700;;
+                    d????-?--*) different_mode=755;;
+                    *) false;;
+                  esac &&
+                  $mkdirprog -m$different_mode -p -- "$tmpdir" && {
+                    ls_ld_tmpdir_1=`ls -ld "$tmpdir"`
+                    test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1"
+                  }
+                }
+             then posix_mkdir=:
+             fi
+             rmdir "$tmpdir/d" "$tmpdir"
+           else
+             # Remove any dirs left behind by ancient mkdir implementations.
+             rmdir ./$mkdir_mode ./-p ./-- 2>/dev/null
+           fi
+           trap '' 0;;
+       esac;;
+    esac
 
-  # Make sure that the destination directory exists.
+    if
+      $posix_mkdir && (
+       umask $mkdir_umask &&
+       $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir"
+      )
+    then :
+    else
 
-  # Skip lots of stat calls in the usual case.
-  if test ! -d "$dstdir"; then
-    defaultIFS='
-        '
-    IFS="${IFS-$defaultIFS}"
+      # The umask is ridiculous, or mkdir does not conform to POSIX,
+      # or it failed possibly due to a race condition.  Create the
+      # directory the slow way, step by step, checking for races as we go.
 
-    oIFS=$IFS
-    # Some sh's can't handle IFS=/ for some reason.
-    IFS='%'
-    set - `echo "$dstdir" | sed -e 's@/@%@g' -e 's@^%@/@'`
-    IFS=$oIFS
+      case $dstdir in
+       /*) prefix='/';;
+       -*) prefix='./';;
+       *)  prefix='';;
+      esac
 
-    pathcomp=
+      eval "$initialize_posix_glob"
 
-    while test $# -ne 0 ; do
-      pathcomp=$pathcomp$1
+      oIFS=$IFS
+      IFS=/
+      $posix_glob set -f
+      set fnord $dstdir
       shift
-      if test ! -d "$pathcomp"; then
-        $mkdirprog "$pathcomp" || lasterr=$?
-       # mkdir can fail with a `File exist' error in case several
-       # install-sh are creating the directory concurrently.  This
-       # is OK.
-       test ! -d "$pathcomp" && { (exit ${lasterr-1}); exit; }
+      $posix_glob set +f
+      IFS=$oIFS
+
+      prefixes=
+
+      for d
+      do
+       test -z "$d" && continue
+
+       prefix=$prefix$d
+       if test -d "$prefix"; then
+         prefixes=
+       else
+         if $posix_mkdir; then
+           (umask=$mkdir_umask &&
+            $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break
+           # Don't fail if two instances are running concurrently.
+           test -d "$prefix" || exit 1
+         else
+           case $prefix in
+             *\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;;
+             *) qprefix=$prefix;;
+           esac
+           prefixes="$prefixes '$qprefix'"
+         fi
+       fi
+       prefix=$prefix/
+      done
+
+      if test -n "$prefixes"; then
+       # Don't fail if two instances are running concurrently.
+       (umask $mkdir_umask &&
+        eval "\$doit_exec \$mkdirprog $prefixes") ||
+         test -d "$dstdir" || exit 1
+       obsolete_mkdir_used=true
       fi
-      pathcomp=$pathcomp/
-    done
+    fi
   fi
 
   if test -n "$dir_arg"; then
-    $doit $instcmd "$dst" \
-      && { test -z "$chowncmd" || $doit $chowncmd "$dst"; } \
-      && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } \
-      && { test -z "$stripcmd" || $doit $stripcmd "$dst"; } \
-      && { test -z "$chmodcmd" || $doit $chmodcmd "$dst"; }
-
+    { test -z "$chowncmd" || $doit $chowncmd "$dst"; } &&
+    { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } &&
+    { test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false ||
+      test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1
   else
-    # If we're going to rename the final executable, determine the name now.
-    if test -z "$transformarg"; then
-      dstfile=`basename "$dst"`
-    else
-      dstfile=`basename "$dst" $transformbasename \
-               | sed $transformarg`$transformbasename
-    fi
-
-    # don't allow the sed command to completely eliminate the filename.
-    test -z "$dstfile" && dstfile=`basename "$dst"`
 
     # Make a couple of temp file names in the proper directory.
     dsttmp=$dstdir/_inst.$$_
     rmtmp=$dstdir/_rm.$$_
 
     # Trap to clean up those temp files at exit.
-    trap 'status=$?; rm -f "$dsttmp" "$rmtmp" && exit $status' 0
-    trap '(exit $?); exit' 1 2 13 15
+    trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0
 
-    # Move or copy the file name to the temp name
-    $doit $instcmd "$src" "$dsttmp" &&
+    # Copy the file name to the temp name.
+    (umask $cp_umask && $doit_exec $cpprog "$src" "$dsttmp") &&
 
     # and set any options; do chmod last to preserve setuid bits.
     #
     # If any of these fail, we abort the whole thing.  If we want to
     # ignore errors from any of these, just make sure not to ignore
-    # errors from the above "$doit $instcmd $src $dsttmp" command.
+    # errors from the above "$doit $cpprog $src $dsttmp" command.
     #
-    { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } \
-      && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } \
-      && { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } \
-      && { test -z "$chmodcmd" || $doit $chmodcmd "$dsttmp"; } &&
-
-    # Now rename the file to the real destination.
-    { $doit $mvcmd -f "$dsttmp" "$dstdir/$dstfile" 2>/dev/null \
-      || {
-          # The rename failed, perhaps because mv can't rename something else
-          # to itself, or perhaps because mv is so ancient that it does not
-          # support -f.
-
-          # Now remove or move aside any old file at destination location.
-          # We try this two ways since rm can't unlink itself on some
-          # systems and the destination file might be busy for other
-          # reasons.  In this case, the final cleanup might fail but the new
-          # file should still install successfully.
-          {
-            if test -f "$dstdir/$dstfile"; then
-              $doit $rmcmd -f "$dstdir/$dstfile" 2>/dev/null \
-              || $doit $mvcmd -f "$dstdir/$dstfile" "$rmtmp" 2>/dev/null \
-              || {
-                echo "$0: cannot unlink or rename $dstdir/$dstfile" >&2
-                (exit 1); exit
-              }
-            else
-              :
-            fi
-          } &&
-
-          # Now rename the file to the real destination.
-          $doit $mvcmd "$dsttmp" "$dstdir/$dstfile"
-        }
-    }
-  fi || { (exit 1); exit; }
+    { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } &&
+    { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } &&
+    { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } &&
+    { test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } &&
+
+    # If -C, don't bother to copy if it wouldn't change the file.
+    if $copy_on_change &&
+       old=`LC_ALL=C ls -dlL "$dst"    2>/dev/null` &&
+       new=`LC_ALL=C ls -dlL "$dsttmp" 2>/dev/null` &&
+
+       eval "$initialize_posix_glob" &&
+       $posix_glob set -f &&
+       set X $old && old=:$2:$4:$5:$6 &&
+       set X $new && new=:$2:$4:$5:$6 &&
+       $posix_glob set +f &&
+
+       test "$old" = "$new" &&
+       $cmpprog "$dst" "$dsttmp" >/dev/null 2>&1
+    then
+      rm -f "$dsttmp"
+    else
+      # Rename the file to the real destination.
+      $doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null ||
+
+      # The rename failed, perhaps because mv can't rename something else
+      # to itself, or perhaps because mv is so ancient that it does not
+      # support -f.
+      {
+       # Now remove or move aside any old file at destination location.
+       # We try this two ways since rm can't unlink itself on some
+       # systems and the destination file might be busy for other
+       # reasons.  In this case, the final cleanup might fail but the new
+       # file should still install successfully.
+       {
+         test ! -f "$dst" ||
+         $doit $rmcmd -f "$dst" 2>/dev/null ||
+         { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null &&
+           { $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; }
+         } ||
+         { echo "$0: cannot unlink or rename $dst" >&2
+           (exit 1); exit 1
+         }
+       } &&
+
+       # Now rename the file to the real destination.
+       $doit $mvcmd "$dsttmp" "$dst"
+      }
+    fi || exit 1
+
+    trap '' 0
+  fi
 done
 
-# The final little trick to "correctly" pass the exit status to the exit trap.
-{
-  (exit 0); exit
-}
-
 # Local variables:
 # eval: (add-hook 'write-file-hooks 'time-stamp)
 # time-stamp-start: "scriptversion="
index f33151c7c6bf7bc5d860731b580f70a2d8a542b7..589ffe289e3f4f3a1a882b67d74cbceeb890e818 100644 (file)
@@ -32,9 +32,9 @@ CU_pSuite register_geodetic_suite(void)
            (NULL == CU_add_test(pSuite, "test_gbox_from_spherical_coordinates()", test_gbox_from_spherical_coordinates))  ||
            (NULL == CU_add_test(pSuite, "test_gserialized_get_gbox_geocentric()", test_gserialized_get_gbox_geocentric))  ||
            (NULL == CU_add_test(pSuite, "test_clairaut()", test_clairaut))  || 
-           (NULL == CU_add_test(pSuite, "test_edge_intersection()", test_edge_intersection)) ||
+           (NULL == CU_add_test(pSuite, "test_edge_intersection()", test_edge_intersection))  ||
            (NULL == CU_add_test(pSuite, "test_edge_distance_to_point()", test_edge_distance_to_point)) ||
-           (NULL == CU_add_test(pSuite, "test_edge_distance_to_edge()", test_edge_distance_to_edge)) ||
+           (NULL == CU_add_test(pSuite, "test_edge_distance_to_edge()", test_edge_distance_to_edge)) || 
            (NULL == CU_add_test(pSuite, "test_lwgeom_distance_sphere()", test_lwgeom_distance_sphere)) 
 
 
@@ -265,8 +265,22 @@ void test_edge_intersection(void)
        GEOGRAPHIC_POINT g;
        int rv;
 
-       edge_set(-1.0, 0.0, 1.0, 0.0, &e1);
-       edge_set(0.0, -1.0, 0.0, 1.0, &e2);
+       /* Medford case, very short segment vs very long one */
+       e1.start.lat = 0.74123572595649878103;
+       e1.start.lon = -2.1496353191142714145;
+       e1.end.lat = 0.74123631950116664058;
+       e1.end.lon = -2.1496353248304860273;
+       e2.start.lat = 0.73856343764436815924;
+       e2.start.lon = -2.1461493501950630325;
+       e2.end.lat = 0.70971354024834598651;
+       e2.end.lon = 2.1082194552519770703;
+       rv = edge_intersection(e1, e2, &g);
+       CU_ASSERT_EQUAL(rv, LW_FALSE);
+
+       /* Again, this time with a less exact input edge. */
+       edge_set(-123.165031277506, 42.4696787216231, -123.165031605021, 42.4697127292275, &e1);
+       rv = edge_intersection(e1, e2, &g);
+       CU_ASSERT_EQUAL(rv, LW_FALSE);  
 
        /* Intersection at (0 0) */
        edge_set(-1.0, 0.0, 1.0, 0.0, &e1);
@@ -482,6 +496,16 @@ void test_lwgeom_distance_sphere(void)
        lwgeom_free(lwg1);
        lwgeom_free(lwg2);
 
+       /* Medford test case #1 */
+       lwg1 = lwgeom_from_ewkt("0105000020E610000001000000010200000002000000EF7B8779C7BD5EC0FD20D94B852845400E539C62B9BD5EC0F0A5BE767C284540", PARSER_CHECK_NONE);
+       lwg2 = lwgeom_from_ewkt("0106000020E61000000100000001030000000100000007000000280EC3FB8CCA5EC0A5CDC747233C45402787C8F58CCA5EC0659EA2761E3C45400CED58DF8FCA5EC0C37FAE6E1E3C4540AE97B8E08FCA5EC00346F58B1F3C4540250359FD8ECA5EC05460628E1F3C45403738F4018FCA5EC05DC84042233C4540280EC3FB8CCA5EC0A5CDC747233C4540", PARSER_CHECK_NONE);
+       lwgeom_calculate_gbox_geodetic(lwg1, &gbox1);
+       lwgeom_calculate_gbox_geodetic(lwg2, &gbox2);
+       d = lwgeom_distance_sphere(lwg1, lwg2, &gbox1, &gbox2, 0.0);
+       CU_ASSERT_DOUBLE_EQUAL(d * 6371009.0, 23630.8003, 0.1);
+       lwgeom_free(lwg1);
+       lwgeom_free(lwg2);
+
 }
 
 
index 6e84c84c85d14ea62113be00cec77ad624442fbc..89869ede77de938f0018cd19c61e3fb12bf6ba26 100644 (file)
@@ -397,12 +397,12 @@ int edge_point_in_cone(GEOGRAPHIC_EDGE e, GEOGRAPHIC_POINT p)
        normalize(&vcp);
        /* The projection of start onto the center defines the minimum similarity */
        vs_dot_vcp = dot_product(vs, vcp);
-       LWDEBUGF(4,"vs_dot_vcp %.9g",vs_dot_vcp);
+       LWDEBUGF(4,"vs_dot_vcp %.19g",vs_dot_vcp);
        /* The projection of candidate p onto the center */
        vp_dot_vcp = dot_product(vp, vcp);
-       LWDEBUGF(4,"vp_dot_vcp %.9g",vp_dot_vcp);
+       LWDEBUGF(4,"vp_dot_vcp %.19g",vp_dot_vcp);
        /* If p is more similar than start then p is inside the cone */
-       if ( FP_GTEQ(vp_dot_vcp, vs_dot_vcp) )
+       if ( vp_dot_vcp >= vs_dot_vcp )
        {
                LWDEBUG(4, "point is in cone");
                return LW_TRUE;
@@ -575,12 +575,21 @@ int clairaut_geographic(GEOGRAPHIC_POINT start, GEOGRAPHIC_POINT end, GEOGRAPHIC
 int edge_intersection(GEOGRAPHIC_EDGE e1, GEOGRAPHIC_EDGE e2, GEOGRAPHIC_POINT *g)
 {
        POINT3D ea, eb, v;
+       LWDEBUGF(4, "e1 start(%.20g %.20g) end(%.20g %.20g)", e1.start.lat, e1.start.lon, e1.end.lat, e1.end.lon);
+       LWDEBUGF(4, "e2 start(%.20g %.20g) end(%.20g %.20g)", e2.start.lat, e2.start.lon, e2.end.lat, e2.end.lon);
+       
+       LWDEBUGF(4, "e1 start(%.20g %.20g) end(%.20g %.20g)", rad2deg(e1.start.lon), rad2deg(e1.start.lat), rad2deg(e1.end.lon), rad2deg(e1.end.lat));
+       LWDEBUGF(4, "e2 start(%.20g %.20g) end(%.20g %.20g)", rad2deg(e2.start.lon), rad2deg(e2.start.lat), rad2deg(e2.end.lon), rad2deg(e2.end.lat));
+
        robust_cross_product(e1.start, e1.end, &ea);
        normalize(&ea);
        robust_cross_product(e2.start, e2.end, &eb);
        normalize(&eb);
+       LWDEBUGF(4, "e1 cross product == POINT(%.8g %.8g %.8g)", ea.x, ea.y, ea.z);
+       LWDEBUGF(4, "e2 cross product == POINT(%.8g %.8g %.8g)", eb.x, eb.y, eb.z);
        if( FP_EQUALS(fabs(dot_product(ea, eb)), 1.0) )
        {
+               LWDEBUGF(4, "parallel edges found! dot_product = %.12g", dot_product(ea, eb));
                /* Parallel (maybe equal) edges! */
                /* Hack alert, only returning ONE end of the edge right now, most do better later. */
                if ( edge_contains_point(e1, e2.start) )
@@ -604,13 +613,12 @@ int edge_intersection(GEOGRAPHIC_EDGE e1, GEOGRAPHIC_EDGE e2, GEOGRAPHIC_POINT *
                        return LW_TRUE;
                }
        }
-       LWDEBUGF(4, "e1 cross product == POINT(%.8g %.8g %.8g)", ea.x, ea.y, ea.z);
-       LWDEBUGF(4, "e2 cross product == POINT(%.8g %.8g %.8g)", eb.x, eb.y, eb.z);
        unit_normal(ea, eb, &v);
        LWDEBUGF(4, "v == POINT(%.8g %.8g %.8g)", v.x, v.y, v.z);
        g->lat = atan2(v.z, sqrt(v.x * v.x + v.y * v.y));
        g->lon = atan2(v.y, v.x);
        LWDEBUGF(4, "g == GPOINT(%.6g %.6g)", g->lat, g->lon);
+       LWDEBUGF(4, "g == POINT(%.12g %.12g)", rad2deg(g->lon), rad2deg(g->lat));
        if ( edge_contains_point(e1, *g) && edge_contains_point(e2, *g) )
        {
                return LW_TRUE;
@@ -1146,8 +1154,10 @@ static int ptarray_point_in_ring(POINTARRAY *pa, POINT2D pt_outside, POINT2D pt_
 
                /* Does stab line cross, and if so, not on the first point. We except the
                   first point to avoid double counting crossings at vertices. */
+               LWDEBUG(4,"testing edge crossing");
                if( edge_intersection(edge, crossing_edge, &g) && ! geographic_point_equals(g, edge.start) )
                {
+                       LWDEBUG(4,"edge crossing found!");
                        count++;
                }
        }
@@ -1242,17 +1252,26 @@ static double ptarray_distance_sphere(POINTARRAY *pa1, POINTARRAY *pa2, double t
                        getPoint2d_p(pa2, j, &p);
                        geographic_point_init(p.x, p.y, &(e2.end));
 
+                       LWDEBUGF(4, "e1.start == GPOINT(%.6g %.6g) ", e1.start.lat, e1.start.lon);
+                       LWDEBUGF(4, "e1.end == GPOINT(%.6g %.6g) ", e1.end.lat, e1.end.lon);
+                       LWDEBUGF(4, "e2.start == GPOINT(%.6g %.6g) ", e2.start.lat, e2.start.lon);
+                       LWDEBUGF(4, "e2.end == GPOINT(%.6g %.6g) ", e2.end.lat, e2.end.lon);
+
                        if ( edge_intersection(e1, e2, &g) )
                        {
+                               LWDEBUG(4,"edge intersection! returning 0.0");
                                return 0.0;
                        }
                        d = edge_distance_to_edge(e1, e2, 0, 0);
+                       LWDEBUGF(4,"got edge_distance_to_edge %.8g", d);
                        if( d < distance )
                                distance = d;
                        if( d < tolerance )
                                return distance;
                }
        }
+       LWDEBUGF(4,"finished all loops, returning %.8g", distance);
+       
        return distance;
 }
 
@@ -1269,6 +1288,8 @@ double lwgeom_distance_sphere(LWGEOM *lwgeom1, LWGEOM *lwgeom2, GBOX *gbox1, GBO
        assert(lwgeom1);
        assert(lwgeom2);
        
+       LWDEBUGF(4, "entered function, tolerance %.8g", tolerance);
+
        /* What's the distance to an empty geometry? We don't know. */
        if( lwgeom_is_empty(lwgeom1) || lwgeom_is_empty(lwgeom2) )
        {
@@ -1369,19 +1390,25 @@ double lwgeom_distance_sphere(LWGEOM *lwgeom1, LWGEOM *lwgeom2, GBOX *gbox1, GBO
                }
                getPoint2d_p(lwline->points, 0, &p);
 
+               LWDEBUG(4, "checking if a point of line is in polygon");
+
                /* Point in polygon implies zero distance */
                if( lwpoly_covers_point2d(lwpoly, gbox, p) )
                        return 0.0;
-               
+
+               LWDEBUG(4, "checking ring distances");
+
                /* Not contained, so what's the actual distance? */
                for( i = 0; i < lwpoly->nrings; i++ )
                {
                        double ring_distance = ptarray_distance_sphere(lwpoly->rings[i], lwline->points, tolerance);
+                       LWDEBUGF(4, "ring[%d] ring_distance = %.8g", i, ring_distance);
                        if( ring_distance < distance )
                                distance = ring_distance;
                        if( distance < tolerance )
                                return distance;
                }
+               LWDEBUGF(4, "all rings checked, returning distance = %.8g", distance);
                return distance;
 
        }
@@ -1485,6 +1512,7 @@ int lwpoly_covers_point2d(const LWPOLY *poly, GBOX *gbox, POINT2D pt_to_test)
        /* Nulls and empties don't contain anything! */
        if( ! poly || lwgeom_is_empty((LWGEOM*)poly) )
        {
+               LWDEBUG(4,"returning false, geometry is empty or null");
                return LW_FALSE;
        }
 
@@ -1494,23 +1522,38 @@ int lwpoly_covers_point2d(const LWPOLY *poly, GBOX *gbox, POINT2D pt_to_test)
        pt_outside.x = rad2deg(g.lon);
        pt_outside.y = rad2deg(g.lat);
 
+       LWDEBUGF(4, "pt_outside POINT(%.8g %.8g)", pt_outside.x, pt_outside.y);
+       LWDEBUGF(4, "pt_to_test POINT(%.8g %.8g)", pt_to_test.x, pt_to_test.y);
+       LWDEBUGF(4, "polygon %s", lwgeom_to_ewkt((LWGEOM*)poly, PARSER_CHECK_NONE));
+       LWDEBUGF(4, "gbox %s", gbox_to_string(gbox));
+
        /* Not in outer ring? We're done! */
        if( ! ptarray_point_in_ring(poly->rings[0], pt_outside, pt_to_test) )
        {
+               LWDEBUG(4,"returning false, point is outside ring");
                return LW_FALSE;
        }
+
+       LWDEBUGF(4, "testing %d rings", poly->nrings);
        
        /* But maybe point is in a hole... */
        for( i = 1; i < poly->nrings; i++ )
        {
+               LWDEBUGF(4, "ring test loop %d", i);
                /* Count up hole containment. Odd => outside boundary. */
                if( ptarray_point_in_ring(poly->rings[i], pt_outside, pt_to_test) )
                        in_hole_count++;
        }
+
+       LWDEBUGF(4, "in_hole_count == %d", in_hole_count);
        
-       if( in_hole_count % 2 )
+       if( in_hole_count % 2 ) 
+       {
+               LWDEBUG(4,"returning false, inner ring containment count is odd");
                return LW_FALSE;
-               
+       }
+
+       LWDEBUG(4,"returning true, inner ring containment count is even");
        return LW_TRUE;
 }
 
index 774d6154926a566ff01b8bf947fe855ad0c81c67..b00f3e1ee5f7a525a37fb8a8becdbb01ea0f9fc9 100644 (file)
@@ -228,9 +228,9 @@ CREATE OR REPLACE FUNCTION geography_overlaps(geography, geography)
 -- Availability: 1.5.0
 CREATE OPERATOR && (
        LEFTARG = geography, RIGHTARG = geography, PROCEDURE = geography_overlaps,
-       COMMUTATOR = '&&'
---     ,RESTRICT = geography_gist_selectivity, 
---     JOIN = geography_gist_join_selectivity
+       COMMUTATOR = '&&',
+       RESTRICT = geography_gist_selectivity, 
+       JOIN = geography_gist_join_selectivity
 );
 
 
index 5a81cecfd4bf3b008924fe246e83acafaa249bb0..6e07e8faade26a1e979f814c742ec21a2b23b73e 100644 (file)
@@ -51,6 +51,8 @@ Datum geography_distance_sphere(PG_FUNCTION_ARGS)
        geography_datum_gidx(PG_GETARG_DATUM(0), gidx2);
        gbox_from_gidx(gidx1, &gbox1);
        gbox_from_gidx(gidx2, &gbox2);
+       gbox1.flags = FLAGS_SET_GEODETIC(gbox1.flags,1);
+       gbox2.flags = FLAGS_SET_GEODETIC(gbox2.flags,1);
        pfree(gidx1);
        pfree(gidx2);
        
index 3ba1da7148d2fe52e9ab5fe5662776ce2906b584..206a54f35ae0a4fe979897953ba4da910813aef1 100644 (file)
 
 #include "lwgeom_pg.h"
 
+/* Prototypes */
+Datum geography_gist_selectivity(PG_FUNCTION_ARGS);
+Datum geography_gist_join_selectivity(PG_FUNCTION_ARGS);
+Datum geography_analyze(PG_FUNCTION_ARGS);
+
+
+/**
+* Place holder selectivity calculations to make the index work in
+* the absence of real selectivity calculations.
+*/
+
+#define DEFAULT_GEOGRAPHY_SEL 0.000005
+
+PG_FUNCTION_INFO_V1(geography_gist_selectivity);
+Datum geography_gist_selectivity(PG_FUNCTION_ARGS)
+{
+       PG_RETURN_FLOAT8(DEFAULT_GEOGRAPHY_SEL);
+}
+
+PG_FUNCTION_INFO_V1(geography_gist_join_selectivity);
+Datum geography_gist_join_selectivity(PG_FUNCTION_ARGS)
+{
+       PG_RETURN_FLOAT8(DEFAULT_GEOGRAPHY_SEL);
+}
+
 
 /**
  * This function is called by the analyze function iff
index c11e72dc936c558027b395522b99e91cfa0a66ce..16283e15670f06c09a5a611ef89958e595bdc436 100644 (file)
@@ -196,7 +196,7 @@ static float gidx_volume(GIDX *a)
        int i;
        if ( a == NULL ) 
        {
-               elog(ERROR, "gidx_volume received a null argument");
+/*             elog(ERROR, "gidx_volume received a null argument"); */
                return 0.0;
        }
        result = GIDX_GET_MAX(a,0) - GIDX_GET_MIN(a,0);