diff --git a/.github/workflows/build-and-check-windows-latest.yml b/.github/workflows/build-and-check-windows-latest.yml new file mode 100644 index 0000000..e2d7b27 --- /dev/null +++ b/.github/workflows/build-and-check-windows-latest.yml @@ -0,0 +1,95 @@ +name: Build and Check (windows-latest) + +on: + push: + pull_request: + workflow_dispatch: + schedule: + - cron: '0 0 * * 5' + +jobs: + build_and_test: + + runs-on: windows-latest + + strategy: + fail-fast: false + matrix: + pg_version: [10, 11, 12, 13, 14, 15, 16, 17] + use_healpix: [0] + + name: PostgreSQL ${{ matrix.pg_version }} - USE_HEALPIX=${{ matrix.use_healpix }} (windows-latest) + + defaults: + run: + shell: msys2 {0} + + steps: + + - name: Install MSYS2 + uses: msys2/setup-msys2@v2 + with: + update: true + msystem: mingw64 + install: >- + base-devel + curl + git + make + perl + flex + bison + diffutils + mingw-w64-x86_64-zlib + mingw-w64-x86_64-icu + mingw-w64-x86_64-gcc + + - name: Install PostgreSQL + run: | + echo "Workspace: ${GITHUB_WORKSPACE}" + git clone --single-branch -b "REL_${{ matrix.pg_version }}_STABLE" git://git.postgresql.org/git/postgresql.git + cd ${GITHUB_WORKSPACE}/postgresql + ./configure --enable-cassert --without-icu + make -j$(nproc) + make install + + - name: Clone pgSphere + uses: actions/checkout@v4 + + - name: Build pgSphere + run: | + make --keep-going -j$(nproc) PROFILE='-Werror -Wall' USE_HEALPIX=0 + make USE_HEALPIX=0 install + + - name: Test pgSphere (installcheck) + run: | + initdb -D pgdata -U postgres + pg_ctl -D pgdata -l postgres_installcheck.log start + make USE_HEALPIX=0 installcheck + pg_ctl -D pgdata stop + rm -rf pgdata + + - name: Show installcheck regression.diffs + if: ${{ failure() }} + run: cat regression.diffs + + - name: Test pgSphere (crushtest) + run: | + initdb -D pgdata -U postgres + pg_ctl -D pgdata -l postgres_crushtest.log start + make USE_HEALPIX=0 crushtest + pg_ctl -D pgdata stop + + - name: Show crushtest regression.diffs + if: ${{ failure() }} + run: cat regression.diffs + + - name: Upload artifacts + uses: actions/upload-artifact@v4 + if: success() || failure() + with: + name: ${{ env.GITHUB_REF_SLUG_URL }}-pg${{ matrix.pg_version }}-use-healpix-${{ matrix.use_healpix }}-${{ github.run_id }} + if-no-files-found: ignore + path: | + ./**/*.log + ./**/*.diffs diff --git a/.github/workflows/build-and-check.yml b/.github/workflows/build-and-check.yml index a4247b8..b89bdba 100644 --- a/.github/workflows/build-and-check.yml +++ b/.github/workflows/build-and-check.yml @@ -3,6 +3,9 @@ name: Build and Check on: push: pull_request: + workflow_dispatch: + schedule: + - cron: '0 0 * * 5' jobs: build_and_test: @@ -12,7 +15,7 @@ jobs: strategy: fail-fast: false matrix: - pg_version: [10, 11, 12, 13, 14, 15, 16] + pg_version: [10, 11, 12, 13, 14, 15, 16, 17] use_healpix: [0, 1] name: PostgreSQL ${{ matrix.pg_version }} - USE_HEALPIX=${{ matrix.use_healpix }} @@ -29,7 +32,7 @@ jobs: xsltproc \ fop - - name: Install Postgres + - name: Install PostgreSQL run: sudo /usr/share/postgresql-common/pgdg/apt.postgresql.org.sh -p -v ${{ matrix.pg_version }} -i - name: Clone pgSphere @@ -72,7 +75,7 @@ jobs: uses: rlespinasse/github-slug-action@v4 - name: Upload artifacts - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 if: success() || failure() with: name: ${{ env.GITHUB_REF_SLUG_URL }}-pg${{ matrix.pg_version }}-use-healpix-${{ matrix.use_healpix }}-${{ github.run_id }} diff --git a/Makefile b/Makefile index c9c225f..782961c 100644 --- a/Makefile +++ b/Makefile @@ -34,12 +34,15 @@ DATA_built = $(RELEASE_SQL) \ pg_sphere--1.3.0--1.3.1.sql \ pg_sphere--1.3.1--1.4.0.sql \ pg_sphere--1.4.0--1.4.1.sql \ - pg_sphere--1.4.1--1.4.2.sql + pg_sphere--1.4.1--1.4.2.sql \ + pg_sphere--1.4.2--1.5.0.sql \ + pg_sphere--1.5.0--1.5.1.sql DOCS = README.pg_sphere COPYRIGHT.pg_sphere TESTS = version tables points euler circle line ellipse poly path box \ index contains_ops contains_ops_compat bounding_box_gist gnomo \ - epochprop contains overlaps spoint_brin sbox_brin selectivity + epochprop contains overlaps spoint_brin sbox_brin selectivity \ + knn output_precision REGRESS = init $(TESTS) PG_CFLAGS += -DPGSPHERE_VERSION=$(PGSPHERE_VERSION) @@ -209,6 +212,15 @@ pg_sphere--1.3.1--1.4.0.sql: pgs_circle_sel.sql.in pgs_hash.sql.in pg_sphere--1.4.0--1.4.1.sql pg_sphere--1.4.1--1.4.2.sql: @echo "-- Nothing to upgrade in the schema" > $@ +pg_sphere--1.4.2--1.5.0.sql: + cat upgrade_scripts/$@.in $^ > $@ + +pg_sphere--1.5.0--1.5.1.sql: + cat upgrade_scripts/$@.in $^ > $@ + +pg_sphere--1.5.1--1.5.2.sql: + cat upgrade_scripts/$@.in $^ > $@ + # end of local stuff src/sscan.o : src/sparse.c @@ -254,3 +266,10 @@ pgindent: --excludes=pgindent-excludes.list \ --indent=${PGBSDINDENT} \ src + +pgindent-headers: + $(PGINDENT) \ + --typedefs=pgindent-typedefs.list \ + --excludes=pgindent-excludes.list \ + --indent=${PGBSDINDENT} \ + src/*.h diff --git a/Makefile.common.mk b/Makefile.common.mk index 9a73710..8963227 100644 --- a/Makefile.common.mk +++ b/Makefile.common.mk @@ -5,4 +5,4 @@ #---------------------------------------------------------------------------- EXTENSION := pg_sphere -PGSPHERE_VERSION := 1.4.2 +PGSPHERE_VERSION := 1.5.2 diff --git a/doc/functions.sgm b/doc/functions.sgm index 232b755..047b7f1 100644 --- a/doc/functions.sgm +++ b/doc/functions.sgm @@ -867,9 +867,12 @@ It is an error to have either pos or delta_t NULL. For all other arguments, NULLs are turned into 0s, except for parallax, - where some very small default is put in. In that case, - both parallax and radial_velocity will be NULL in the output - array. + where some very small default is put in. Whatever is NULL + on the input is NULL on the output. In addition, we null + out a non-NULL input on one component of the proper motion + if the other component is NULL, and we null out the radial + velocity if the parallax is missing, as it would be horribly + off with the propagation algorithm we use here. diff --git a/doc/indices.sgm b/doc/indices.sgm index 998b546..6b874b0 100644 --- a/doc/indices.sgm +++ b/doc/indices.sgm @@ -68,6 +68,11 @@ + + A GiST index can be also used for quickly finding the points closest to the given one + when ordering by an expression with the <-> operator, + as shown in an example below. + BRIN indexing supports just spherical points (spoint) and spherical coordinates range (sbox) at the moment. @@ -82,6 +87,13 @@ + + To find the points closest to a given spherical position, use the <-> operator: + + + spoint (0.2, 0.3) LIMIT 10 ]]> + + BRIN index can be created through the following syntax: diff --git a/expected/bounding_box_gist.out b/expected/bounding_box_gist.out index 6307ac1..ef42474 100644 --- a/expected/bounding_box_gist.out +++ b/expected/bounding_box_gist.out @@ -1,3 +1,4 @@ +SET extra_float_digits = 2; SET enable_seqscan=true; CREATE TABLE bbox_ellipse (e sellipse not null); INSERT INTO bbox_ellipse VALUES ('<{10d, 0.1d}, (0d,0d), 0d>'); @@ -20,19 +21,19 @@ SELECT COUNT(*) FROM bbox_ellipse WHERE spoint '(5d, 0d)' <@ e; (1 row) EXPLAIN (COSTS OFF) SELECT COUNT(*) FROM bbox_ellipse WHERE spoint '(5d, 0d)' @ e; - QUERY PLAN ----------------------------------------------------------- + QUERY PLAN +------------------------------------------------------------ Aggregate -> Seq Scan on bbox_ellipse - Filter: ('(0.0872664625997165 , 0)'::spoint @ e) + Filter: ('(0.087266462599716474 , 0)'::spoint @ e) (3 rows) EXPLAIN (COSTS OFF) SELECT COUNT(*) FROM bbox_ellipse WHERE spoint '(5d, 0d)' <@ e; - QUERY PLAN ------------------------------------------------------------ + QUERY PLAN +------------------------------------------------------------- Aggregate -> Seq Scan on bbox_ellipse - Filter: ('(0.0872664625997165 , 0)'::spoint <@ e) + Filter: ('(0.087266462599716474 , 0)'::spoint <@ e) (3 rows) -- The ellipse has semi-major axis length of 10 degrees along the equator, @@ -53,19 +54,19 @@ SELECT COUNT(*) FROM bbox_ellipse WHERE spoint '(5d, 0d)' <@ e; (1 row) EXPLAIN (COSTS OFF) SELECT COUNT(*) FROM bbox_ellipse WHERE spoint '(5d, 0d)' @ e; - QUERY PLAN --------------------------------------------------------------- + QUERY PLAN +---------------------------------------------------------------- Aggregate -> Index Scan using idx_bbox_ellipse on bbox_ellipse - Index Cond: ('(0.0872664625997165 , 0)'::spoint @ e) + Index Cond: ('(0.087266462599716474 , 0)'::spoint @ e) (3 rows) EXPLAIN (COSTS OFF) SELECT COUNT(*) FROM bbox_ellipse WHERE spoint '(5d, 0d)' <@ e; - QUERY PLAN ---------------------------------------------------------------- + QUERY PLAN +----------------------------------------------------------------- Aggregate -> Index Scan using idx_bbox_ellipse on bbox_ellipse - Index Cond: ('(0.0872664625997165 , 0)'::spoint <@ e) + Index Cond: ('(0.087266462599716474 , 0)'::spoint <@ e) (3 rows) SET enable_seqscan=true; @@ -170,11 +171,11 @@ SELECT COUNT(*) FROM bbox_path WHERE spoint '(0d, 0d)' <@ p; (1 row) EXPLAIN (COSTS OFF) SELECT COUNT(*) FROM bbox_path WHERE sline(spoint '(0d, -10d)', spoint '(0d, 10d)') && p; - QUERY PLAN --------------------------------------------------------------------------------------------------- + QUERY PLAN +--------------------------------------------------------------------------------------------------------- Aggregate -> Seq Scan on bbox_path - Filter: ('( 6.10865238198015, 1.5707963267949, 0, ZXZ ), 0.349065850398866'::sline && p) + Filter: ('( 6.1086523819801535, 1.5707963267948966, 0, ZXZ ), 0.34906585039886584'::sline && p) (3 rows) EXPLAIN (COSTS OFF) SELECT COUNT(*) FROM bbox_path WHERE spoint '(0d, 0d)' @ p; @@ -215,11 +216,11 @@ SELECT COUNT(*) FROM bbox_path WHERE spoint '(0d, 0d)' <@ p; (1 row) EXPLAIN (COSTS OFF) SELECT COUNT(*) FROM bbox_path WHERE sline(spoint '(0d, -10d)', spoint '(0d, 10d)') && p; - QUERY PLAN ------------------------------------------------------------------------------------------------------- + QUERY PLAN +------------------------------------------------------------------------------------------------------------- Aggregate -> Index Scan using idx_bbox_path on bbox_path - Index Cond: ('( 6.10865238198015, 1.5707963267949, 0, ZXZ ), 0.349065850398866'::sline && p) + Index Cond: ('( 6.1086523819801535, 1.5707963267948966, 0, ZXZ ), 0.34906585039886584'::sline && p) (3 rows) EXPLAIN (COSTS OFF) SELECT COUNT(*) FROM bbox_path WHERE spoint '(0d, 0d)' @ p; diff --git a/expected/bounding_box_gist_1.out b/expected/bounding_box_gist_1.out index 8c08936..48d4ff3 100644 --- a/expected/bounding_box_gist_1.out +++ b/expected/bounding_box_gist_1.out @@ -1,3 +1,4 @@ +SET extra_float_digits = 2; SET enable_seqscan=true; CREATE TABLE bbox_ellipse (e sellipse not null); INSERT INTO bbox_ellipse VALUES ('<{10d, 0.1d}, (0d,0d), 0d>'); @@ -20,19 +21,19 @@ SELECT COUNT(*) FROM bbox_ellipse WHERE spoint '(5d, 0d)' <@ e; (1 row) EXPLAIN (COSTS OFF) SELECT COUNT(*) FROM bbox_ellipse WHERE spoint '(5d, 0d)' @ e; - QUERY PLAN ----------------------------------------------------------- + QUERY PLAN +----------------------------------------------------------- Aggregate -> Seq Scan on bbox_ellipse - Filter: ('(0.0872664625997165 , 0)'::spoint @ e) + Filter: ('(0.08726646259971647 , 0)'::spoint @ e) (3 rows) EXPLAIN (COSTS OFF) SELECT COUNT(*) FROM bbox_ellipse WHERE spoint '(5d, 0d)' <@ e; - QUERY PLAN ------------------------------------------------------------ + QUERY PLAN +------------------------------------------------------------ Aggregate -> Seq Scan on bbox_ellipse - Filter: ('(0.0872664625997165 , 0)'::spoint <@ e) + Filter: ('(0.08726646259971647 , 0)'::spoint <@ e) (3 rows) -- The ellipse has semi-major axis length of 10 degrees along the equator, @@ -53,19 +54,19 @@ SELECT COUNT(*) FROM bbox_ellipse WHERE spoint '(5d, 0d)' <@ e; (1 row) EXPLAIN (COSTS OFF) SELECT COUNT(*) FROM bbox_ellipse WHERE spoint '(5d, 0d)' @ e; - QUERY PLAN --------------------------------------------------------------- + QUERY PLAN +--------------------------------------------------------------- Aggregate -> Index Scan using idx_bbox_ellipse on bbox_ellipse - Index Cond: (e ~ '(0.0872664625997165 , 0)'::spoint) + Index Cond: (e ~ '(0.08726646259971647 , 0)'::spoint) (3 rows) EXPLAIN (COSTS OFF) SELECT COUNT(*) FROM bbox_ellipse WHERE spoint '(5d, 0d)' <@ e; - QUERY PLAN ---------------------------------------------------------------- + QUERY PLAN +---------------------------------------------------------------- Aggregate -> Index Scan using idx_bbox_ellipse on bbox_ellipse - Index Cond: (e @> '(0.0872664625997165 , 0)'::spoint) + Index Cond: (e @> '(0.08726646259971647 , 0)'::spoint) (3 rows) SET enable_seqscan=true; @@ -170,11 +171,11 @@ SELECT COUNT(*) FROM bbox_path WHERE spoint '(0d, 0d)' <@ p; (1 row) EXPLAIN (COSTS OFF) SELECT COUNT(*) FROM bbox_path WHERE sline(spoint '(0d, -10d)', spoint '(0d, 10d)') && p; - QUERY PLAN --------------------------------------------------------------------------------------------------- + QUERY PLAN +--------------------------------------------------------------------------------------------------------- Aggregate -> Seq Scan on bbox_path - Filter: ('( 6.10865238198015, 1.5707963267949, 0, ZXZ ), 0.349065850398866'::sline && p) + Filter: ('( 6.1086523819801535, 1.5707963267948966, 0, ZXZ ), 0.34906585039886584'::sline && p) (3 rows) EXPLAIN (COSTS OFF) SELECT COUNT(*) FROM bbox_path WHERE spoint '(0d, 0d)' @ p; @@ -215,11 +216,11 @@ SELECT COUNT(*) FROM bbox_path WHERE spoint '(0d, 0d)' <@ p; (1 row) EXPLAIN (COSTS OFF) SELECT COUNT(*) FROM bbox_path WHERE sline(spoint '(0d, -10d)', spoint '(0d, 10d)') && p; - QUERY PLAN ------------------------------------------------------------------------------------------------------- + QUERY PLAN +------------------------------------------------------------------------------------------------------------- Aggregate -> Index Scan using idx_bbox_path on bbox_path - Index Cond: (p && '( 6.10865238198015, 1.5707963267949, 0, ZXZ ), 0.349065850398866'::sline) + Index Cond: (p && '( 6.1086523819801535, 1.5707963267948966, 0, ZXZ ), 0.34906585039886584'::sline) (3 rows) EXPLAIN (COSTS OFF) SELECT COUNT(*) FROM bbox_path WHERE spoint '(0d, 0d)' @ p; diff --git a/expected/epochprop.out b/expected/epochprop.out index 8541601..1111f1a 100644 --- a/expected/epochprop.out +++ b/expected/epochprop.out @@ -1,4 +1,5 @@ -SELECT +SET extra_float_digits = 1; +SELECT to_char(DEGREES(tp[1]), '999D9999999999'), to_char(DEGREES(tp[2]), '999D9999999999'), to_char(tp[3], '999D999'), @@ -6,7 +7,7 @@ SELECT to_char(DEGREES(tp[5])*3.6e6, '99999D999'), to_char(tp[6], '999D999') FROM ( - SELECT epoch_prop(spoint(radians(269.45207695), radians(4.693364966)), + SELECT epoch_prop(spoint(radians(269.45207695), radians(4.693364966)), 546.9759, RADIANS(-801.551/3.6e6), RADIANS(10362/3.6e6), -110, -100) AS tp) AS q; @@ -15,7 +16,7 @@ FROM ( 269.4742714391 | 4.4072939987 | 543.624 | -791.442 | 10235.412 | -110.450 (1 row) -SELECT +SELECT to_char(DEGREES(tp[1]), '999D9999999999'), to_char(DEGREES(tp[2]), '999D9999999999'), to_char(tp[3], '999D999'), @@ -23,16 +24,16 @@ SELECT to_char(DEGREES(tp[5])*3.6e6, '99999D999'), to_char(tp[6], '999D999') FROM ( - SELECT epoch_prop(spoint(radians(269.45207695), radians(4.693364966)), + SELECT epoch_prop(spoint(radians(269.45207695), radians(4.693364966)), 0, RADIANS(-801.551/3.6e6), RADIANS(10362/3.6e6), -110, -100) AS tp) AS q; - to_char | to_char | to_char | to_char | to_char | to_char ------------------+-----------------+---------+----------+------------+--------- - 269.4744079540 | 4.4055337210 | | -801.210 | 10361.762 | + to_char | to_char | to_char | to_char | to_char | to_char +-----------------+-----------------+----------+----------+------------+---------- + 269.4744079540 | 4.4055337210 | .000 | -801.210 | 10361.762 | -110.000 (1 row) -SELECT +SELECT to_char(DEGREES(tp[1]), '999D9999999999'), to_char(DEGREES(tp[2]), '999D9999999999'), to_char(tp[3], '999D999'), @@ -40,16 +41,16 @@ SELECT to_char(DEGREES(tp[5])*3.6e6, '99999D999'), to_char(tp[6], '999D999') FROM ( - SELECT epoch_prop(spoint(radians(269.45207695), radians(4.693364966)), + SELECT epoch_prop(spoint(radians(269.45207695), radians(4.693364966)), NULL, RADIANS(-801.551/3.6e6), RADIANS(10362/3.6e6), -110, -100) AS tp) AS q; - to_char | to_char | to_char | to_char | to_char | to_char ------------------+-----------------+---------+----------+------------+--------- - 269.4744079540 | 4.4055337210 | | -801.210 | 10361.762 | + to_char | to_char | to_char | to_char | to_char | to_char +-----------------+-----------------+---------+----------+------------+---------- + 269.4744079540 | 4.4055337210 | | -801.210 | 10361.762 | -110.000 (1 row) -SELECT +SELECT to_char(DEGREES(tp[1]), '999D9999999999'), to_char(DEGREES(tp[2]), '999D9999999999'), to_char(tp[3], '999D999'), @@ -57,16 +58,16 @@ SELECT to_char(DEGREES(tp[5])*3.6e6, '99999D999'), to_char(tp[6], '999D999') FROM ( - SELECT epoch_prop(spoint(radians(269.45207695), radians(4.693364966)), + SELECT epoch_prop(spoint(radians(269.45207695), radians(4.693364966)), 23, RADIANS(-801.551/3.6e6), RADIANS(10362/3.6e6), NULL, 20) AS tp) AS q; - to_char | to_char | to_char | to_char | to_char | to_char ------------------+-----------------+----------+----------+------------+---------- - 269.4476085384 | 4.7509315989 | 23.000 | -801.617 | 10361.984 | 2.159 + to_char | to_char | to_char | to_char | to_char | to_char +-----------------+-----------------+----------+----------+------------+--------- + 269.4476085384 | 4.7509315989 | 23.000 | -801.617 | 10361.984 | (1 row) -SELECT +SELECT to_char(DEGREES(tp[1]), '999D9999999999'), to_char(DEGREES(tp[2]), '999D9999999999'), to_char(tp[3], '999D999'), @@ -74,13 +75,13 @@ SELECT to_char(DEGREES(tp[5])*3.6e6, '99999D999'), to_char(tp[6], '999D999') FROM ( - SELECT epoch_prop(spoint(radians(269.45207695), radians(4.693364966)), + SELECT epoch_prop(spoint(radians(269.45207695), radians(4.693364966)), 23, NULL, RADIANS(10362/3.6e6), -110, 120) AS tp) AS q; - to_char | to_char | to_char | to_char | to_char | to_char ------------------+-----------------+----------+----------+------------+---------- - 269.4520769500 | 5.0388680565 | 23.007 | -.000 | 10368.061 | -97.120 + to_char | to_char | to_char | to_char | to_char | to_char +-----------------+-----------------+----------+---------+---------+---------- + 269.4520769500 | 4.6933649660 | 23.007 | | | -110.000 (1 row) SELECT epoch_prop(NULL, @@ -88,20 +89,20 @@ SELECT epoch_prop(NULL, 0.01 , RADIANS(10362/3.6e6), -110, 120); ERROR: NULL position not supported in epoch propagation -SELECT epoch_prop_pos(spoint(radians(269.45207695), radians(4.693364966)), +SELECT epoch_prop_pos(spoint(radians(269.45207695), radians(4.693364966)), 23, RADIANS(-801.551/3.6e6), RADIANS(10362/3.6e6), -110, 20) AS tp; - tp ------------------------------------------ - (4.70274792658313 , 0.0829194509345993) + tp +------------------------------------------- + (4.702747926583129 , 0.08291945093459933) (1 row) -SELECT epoch_prop_pos(spoint(radians(269.45207695), radians(4.693364966)), +SELECT epoch_prop_pos(spoint(radians(269.45207695), radians(4.693364966)), RADIANS(-801.551/3.6e6), RADIANS(10362/3.6e6), 20) AS tp; - tp ------------------------------------------ - (4.70274793061952 , 0.0829193989380876) + tp +------------------------------------------- + (4.702747930619516 , 0.08291939893808763) (1 row) diff --git a/expected/epochprop_1.out b/expected/epochprop_1.out new file mode 100644 index 0000000..08317fc --- /dev/null +++ b/expected/epochprop_1.out @@ -0,0 +1,108 @@ +SET extra_float_digits = 2; +SELECT + to_char(DEGREES(tp[1]), '999D9999999999'), + to_char(DEGREES(tp[2]), '999D9999999999'), + to_char(tp[3], '999D999'), + to_char(DEGREES(tp[4])*3.6e6, '999D999'), + to_char(DEGREES(tp[5])*3.6e6, '99999D999'), + to_char(tp[6], '999D999') +FROM ( + SELECT epoch_prop(spoint(radians(269.45207695), radians(4.693364966)), + 546.9759, + RADIANS(-801.551/3.6e6), RADIANS(10362/3.6e6), -110, + -100) AS tp) AS q; + to_char | to_char | to_char | to_char | to_char | to_char +-----------------+-----------------+----------+----------+------------+---------- + 269.4742714391 | 4.4072939987 | 543.624 | -791.442 | 10235.412 | -110.450 +(1 row) + +SELECT + to_char(DEGREES(tp[1]), '999D9999999999'), + to_char(DEGREES(tp[2]), '999D9999999999'), + to_char(tp[3], '999D999'), + to_char(DEGREES(tp[4])*3.6e6, '999D999'), + to_char(DEGREES(tp[5])*3.6e6, '99999D999'), + to_char(tp[6], '999D999') +FROM ( + SELECT epoch_prop(spoint(radians(269.45207695), radians(4.693364966)), + 0, + RADIANS(-801.551/3.6e6), RADIANS(10362/3.6e6), -110, + -100) AS tp) AS q; + to_char | to_char | to_char | to_char | to_char | to_char +-----------------+-----------------+---------+----------+------------+--------- + 269.4744079540 | 4.4055337210 | | -801.210 | 10361.762 | +(1 row) + +SELECT + to_char(DEGREES(tp[1]), '999D9999999999'), + to_char(DEGREES(tp[2]), '999D9999999999'), + to_char(tp[3], '999D999'), + to_char(DEGREES(tp[4])*3.6e6, '999D999'), + to_char(DEGREES(tp[5])*3.6e6, '99999D999'), + to_char(tp[6], '999D999') +FROM ( + SELECT epoch_prop(spoint(radians(269.45207695), radians(4.693364966)), + NULL, + RADIANS(-801.551/3.6e6), RADIANS(10362/3.6e6), -110, + -100) AS tp) AS q; + to_char | to_char | to_char | to_char | to_char | to_char +-----------------+-----------------+---------+----------+------------+--------- + 269.4744079540 | 4.4055337210 | | -801.210 | 10361.762 | +(1 row) + +SELECT + to_char(DEGREES(tp[1]), '999D9999999999'), + to_char(DEGREES(tp[2]), '999D9999999999'), + to_char(tp[3], '999D999'), + to_char(DEGREES(tp[4])*3.6e6, '999D999'), + to_char(DEGREES(tp[5])*3.6e6, '99999D999'), + to_char(tp[6], '999D999') +FROM ( + SELECT epoch_prop(spoint(radians(269.45207695), radians(4.693364966)), + 23, + RADIANS(-801.551/3.6e6), RADIANS(10362/3.6e6), NULL, + 20) AS tp) AS q; + to_char | to_char | to_char | to_char | to_char | to_char +-----------------+-----------------+----------+----------+------------+---------- + 269.4476085384 | 4.7509315989 | 23.000 | -801.617 | 10361.984 | 2.159 +(1 row) + +SELECT + to_char(DEGREES(tp[1]), '999D9999999999'), + to_char(DEGREES(tp[2]), '999D9999999999'), + to_char(tp[3], '999D999'), + to_char(DEGREES(tp[4])*3.6e6, '999D999'), + to_char(DEGREES(tp[5])*3.6e6, '99999D999'), + to_char(tp[6], '999D999') +FROM ( + SELECT epoch_prop(spoint(radians(269.45207695), radians(4.693364966)), + 23, + NULL, RADIANS(10362/3.6e6), -110, + 120) AS tp) AS q; + to_char | to_char | to_char | to_char | to_char | to_char +-----------------+-----------------+----------+----------+------------+---------- + 269.4520769500 | 5.0388680565 | 23.007 | -.000 | 10368.061 | -97.120 +(1 row) + +SELECT epoch_prop(NULL, + 23, + 0.01 , RADIANS(10362/3.6e6), -110, + 120); +ERROR: NULL position not supported in epoch propagation +SELECT epoch_prop_pos(spoint(radians(269.45207695), radians(4.693364966)), + 23, + RADIANS(-801.551/3.6e6), RADIANS(10362/3.6e6), -110, + 20) AS tp; + tp +------------------------------------------- + (4.702747926583129 , 0.08291945093459933) +(1 row) + +SELECT epoch_prop_pos(spoint(radians(269.45207695), radians(4.693364966)), + RADIANS(-801.551/3.6e6), RADIANS(10362/3.6e6), + 20) AS tp; + tp +------------------------------------------- + (4.702747930619516 , 0.08291939893808763) +(1 row) + diff --git a/expected/init_extended.out b/expected/init_extended.out index 382a0dc..adeaa8d 100644 --- a/expected/init_extended.out +++ b/expected/init_extended.out @@ -1,18 +1,18 @@ -- indexed operations..... -- spoint_data and scircle_data tables have to be created and indexed using -\! testsuite/gen_point.pl 1 > results/gen_point_1.sql +\! perl testsuite/gen_point.pl 1 > results/gen_point_1.sql \i results/gen_point_1.sql CREATE TABLE spoint_data (sp spoint); COPY spoint_data (sp) FROM stdin; CREATE INDEX sp_idx ON spoint_data USING gist (sp); -- and -\! testsuite/gen_circle.pl 1 0.1 > results/gen_circle_1_0.1.sql +\! perl testsuite/gen_circle.pl 1 0.1 > results/gen_circle_1_0.1.sql \i results/gen_circle_1_0.1.sql CREATE TABLE scircle_data (sc scircle); COPY scircle_data (sc) FROM stdin; CREATE INDEX sc_idx ON scircle_data USING gist (sc); -- -\! testsuite/gen_poly.pl 1 0.1 4 > results/gen_poly_1_0.1_4.sql +\! perl testsuite/gen_poly.pl 1 0.1 4 > results/gen_poly_1_0.1_4.sql \i results/gen_poly_1_0.1_4.sql CREATE TABLE spoly_data (sp spoly); COPY spoly_data (sp) FROM stdin; diff --git a/expected/knn.out b/expected/knn.out new file mode 100644 index 0000000..49c8903 --- /dev/null +++ b/expected/knn.out @@ -0,0 +1,122 @@ +CREATE TABLE points (id int, p spoint, pos int); +INSERT INTO points (id, p) SELECT x, spoint(random()*6.28, (2*random()-1)*1.57) FROM generate_series(1,314159) x; +CREATE INDEX i ON points USING gist (p); +SET enable_indexscan = true; +EXPLAIN (costs off) SELECT p <-> spoint (0.2, 0.3) FROM points ORDER BY 1 LIMIT 100; + QUERY PLAN +------------------------------------------------- + Limit + -> Index Scan using i on points + Order By: (p <-> '(0.2 , 0.3)'::spoint) +(3 rows) + +UPDATE points SET pos = n FROM + (SELECT id, row_number() OVER (ORDER BY p <-> spoint (0.2, 0.3)) n FROM points ORDER BY p <-> spoint (0.2, 0.3) LIMIT 100) sel + WHERE points.id = sel.id; +SET enable_indexscan = false; +SELECT pos, row_number() OVER (ORDER BY p <-> spoint (0.2, 0.3)) n FROM points ORDER BY p <-> spoint (0.2, 0.3) LIMIT 100; + pos | n +-----+----- + 1 | 1 + 2 | 2 + 3 | 3 + 4 | 4 + 5 | 5 + 6 | 6 + 7 | 7 + 8 | 8 + 9 | 9 + 10 | 10 + 11 | 11 + 12 | 12 + 13 | 13 + 14 | 14 + 15 | 15 + 16 | 16 + 17 | 17 + 18 | 18 + 19 | 19 + 20 | 20 + 21 | 21 + 22 | 22 + 23 | 23 + 24 | 24 + 25 | 25 + 26 | 26 + 27 | 27 + 28 | 28 + 29 | 29 + 30 | 30 + 31 | 31 + 32 | 32 + 33 | 33 + 34 | 34 + 35 | 35 + 36 | 36 + 37 | 37 + 38 | 38 + 39 | 39 + 40 | 40 + 41 | 41 + 42 | 42 + 43 | 43 + 44 | 44 + 45 | 45 + 46 | 46 + 47 | 47 + 48 | 48 + 49 | 49 + 50 | 50 + 51 | 51 + 52 | 52 + 53 | 53 + 54 | 54 + 55 | 55 + 56 | 56 + 57 | 57 + 58 | 58 + 59 | 59 + 60 | 60 + 61 | 61 + 62 | 62 + 63 | 63 + 64 | 64 + 65 | 65 + 66 | 66 + 67 | 67 + 68 | 68 + 69 | 69 + 70 | 70 + 71 | 71 + 72 | 72 + 73 | 73 + 74 | 74 + 75 | 75 + 76 | 76 + 77 | 77 + 78 | 78 + 79 | 79 + 80 | 80 + 81 | 81 + 82 | 82 + 83 | 83 + 84 | 84 + 85 | 85 + 86 | 86 + 87 | 87 + 88 | 88 + 89 | 89 + 90 | 90 + 91 | 91 + 92 | 92 + 93 | 93 + 94 | 94 + 95 | 95 + 96 | 96 + 97 | 97 + 98 | 98 + 99 | 99 + 100 | 100 +(100 rows) + +DROP TABLE points; diff --git a/expected/output_precision.out b/expected/output_precision.out new file mode 100644 index 0000000..9109c4b --- /dev/null +++ b/expected/output_precision.out @@ -0,0 +1,212 @@ +-- +-- Test default and custom output precisions for double values. +-- +SELECT set_sphere_output( 'RAD' ); + set_sphere_output +------------------- + SET RAD +(1 row) + +-- +-- Check default precision +-- +SELECT '( 1h 2m 30s , +1d 2m 30s)'::spoint; + spoint +------------------------------------------ + (0.272707695624114 , 0.0181805130416076) +(1 row) + +-- +-- Check option extra_float_digits +-- +SET extra_float_digits TO -6; +SELECT '( 1h 2m 30s , +1d 2m 30s)'::spoint; + spoint +----------------------------- + (0.272707696 , 0.018180513) +(1 row) + +SET extra_float_digits TO -2; +SELECT '( 1h 2m 30s , +1d 2m 30s)'::spoint; + spoint +-------------------------------------- + (0.2727076956241 , 0.01818051304161) +(1 row) + +SET extra_float_digits TO 0; +SELECT '( 1h 2m 30s , +1d 2m 30s)'::spoint; + spoint +------------------------------------------ + (0.272707695624114 , 0.0181805130416076) +(1 row) + +SET extra_float_digits TO 1; +SELECT '( 1h 2m 30s , +1d 2m 30s)'::spoint; + spoint +------------------------------------------ + (0.272707695624114 , 0.0181805130416076) +(1 row) + +SET extra_float_digits TO 2; +SELECT '( 1h 2m 30s , +1d 2m 30s)'::spoint; + spoint +---------------------------------------------- + (0.27270769562411401 , 0.018180513041607602) +(1 row) + +SET extra_float_digits TO 3; +SELECT '( 1h 2m 30s , +1d 2m 30s)'::spoint; + spoint +----------------------------------------------- + (0.27270769562411401 , 0.0181805130416076016) +(1 row) + +SET extra_float_digits TO 6; +ERROR: 6 is outside the valid range for parameter "extra_float_digits" (-15 .. 3) +SELECT '( 1h 2m 30s , +1d 2m 30s)'::spoint; + spoint +----------------------------------------------- + (0.27270769562411401 , 0.0181805130416076016) +(1 row) + +-- +-- Check compatibility behaviour +-- +SELECT set_sphere_output_precision(10); + set_sphere_output_precision +----------------------------- + SET 10 +(1 row) + +SELECT '( 1h 2m 30s , +1d 2m 30s)'::spoint; + spoint +-------------------------------- + (0.2727076956 , 0.01818051304) +(1 row) + +SELECT set_sphere_output_precision(12); + set_sphere_output_precision +----------------------------- + SET 12 +(1 row) + +SELECT '( 1h 2m 30s , +1d 2m 30s)'::spoint; + spoint +------------------------------------ + (0.272707695624 , 0.0181805130416) +(1 row) + +SELECT set_sphere_output_precision(15); + set_sphere_output_precision +----------------------------- + SET 15 +(1 row) + +SELECT '( 1h 2m 30s , +1d 2m 30s)'::spoint; + spoint +------------------------------------------ + (0.272707695624114 , 0.0181805130416076) +(1 row) + +SELECT set_sphere_output_precision(17); + set_sphere_output_precision +----------------------------- + SET 15 +(1 row) + +SELECT '( 1h 2m 30s , +1d 2m 30s)'::spoint; + spoint +------------------------------------------ + (0.272707695624114 , 0.0181805130416076) +(1 row) + +SELECT set_sphere_output_precision(20); + set_sphere_output_precision +----------------------------- + SET 15 +(1 row) + +SELECT '( 1h 2m 30s , +1d 2m 30s)'::spoint; + spoint +------------------------------------------ + (0.272707695624114 , 0.0181805130416076) +(1 row) + +SELECT set_sphere_output_precision(0); + set_sphere_output_precision +----------------------------- + SET 15 +(1 row) + +SELECT '( 1h 2m 30s , +1d 2m 30s)'::spoint; + spoint +------------------------------------------ + (0.272707695624114 , 0.0181805130416076) +(1 row) + +SELECT set_sphere_output_precision(-3); + set_sphere_output_precision +----------------------------- + SET 15 +(1 row) + +SELECT '( 1h 2m 30s , +1d 2m 30s)'::spoint; + spoint +------------------------------------------ + (0.272707695624114 , 0.0181805130416076) +(1 row) + +-- +-- Check extra_float_digits after set_sphere_output_precision. +-- The change of extra_float_digits should not affect the precision of pgsphere +-- output because set_sphere_output_precision enables compatibility mode. +-- +SELECT set_sphere_output_precision(10); + set_sphere_output_precision +----------------------------- + SET 10 +(1 row) + +SELECT '( 1h 2m 30s , +1d 2m 30s)'::spoint; + spoint +-------------------------------- + (0.2727076956 , 0.01818051304) +(1 row) + +SET extra_float_digits TO -6; +SELECT '( 1h 2m 30s , +1d 2m 30s)'::spoint; + spoint +-------------------------------- + (0.2727076956 , 0.01818051304) +(1 row) + +SET extra_float_digits TO -10; +SELECT '( 1h 2m 30s , +1d 2m 30s)'::spoint; + spoint +-------------------------------- + (0.2727076956 , 0.01818051304) +(1 row) + +-- +-- Check reset_sphere_output_precision. +-- It should disable compatibility mode - extra_float_digits should work. +-- +SELECT reset_sphere_output_precision(); + reset_sphere_output_precision +------------------------------- + RESET +(1 row) + +SELECT '( 1h 2m 30s , +1d 2m 30s)'::spoint; + spoint +---------------------- + (0.27271 , 0.018181) +(1 row) + +SET extra_float_digits TO -6; +SELECT '( 1h 2m 30s , +1d 2m 30s)'::spoint; + spoint +----------------------------- + (0.272707696 , 0.018180513) +(1 row) + diff --git a/expected/output_precision_1.out b/expected/output_precision_1.out new file mode 100644 index 0000000..02ca521 --- /dev/null +++ b/expected/output_precision_1.out @@ -0,0 +1,212 @@ +-- +-- Test default and custom output precisions for double values. +-- +SELECT set_sphere_output( 'RAD' ); + set_sphere_output +------------------- + SET RAD +(1 row) + +-- +-- Check default precision +-- +SELECT '( 1h 2m 30s , +1d 2m 30s)'::spoint; + spoint +------------------------------------------ + (0.272707695624114 , 0.0181805130416076) +(1 row) + +-- +-- Check option extra_float_digits +-- +SET extra_float_digits TO -6; +SELECT '( 1h 2m 30s , +1d 2m 30s)'::spoint; + spoint +----------------------------- + (0.272707696 , 0.018180513) +(1 row) + +SET extra_float_digits TO -2; +SELECT '( 1h 2m 30s , +1d 2m 30s)'::spoint; + spoint +-------------------------------------- + (0.2727076956241 , 0.01818051304161) +(1 row) + +SET extra_float_digits TO 0; +SELECT '( 1h 2m 30s , +1d 2m 30s)'::spoint; + spoint +------------------------------------------ + (0.272707695624114 , 0.0181805130416076) +(1 row) + +SET extra_float_digits TO 1; +SELECT '( 1h 2m 30s , +1d 2m 30s)'::spoint; + spoint +------------------------------------------ + (0.272707695624114 , 0.0181805130416076) +(1 row) + +SET extra_float_digits TO 2; +SELECT '( 1h 2m 30s , +1d 2m 30s)'::spoint; + spoint +------------------------------------------ + (0.272707695624114 , 0.0181805130416076) +(1 row) + +SET extra_float_digits TO 3; +SELECT '( 1h 2m 30s , +1d 2m 30s)'::spoint; + spoint +------------------------------------------ + (0.272707695624114 , 0.0181805130416076) +(1 row) + +SET extra_float_digits TO 6; +ERROR: 6 is outside the valid range for parameter "extra_float_digits" (-15 .. 3) +SELECT '( 1h 2m 30s , +1d 2m 30s)'::spoint; + spoint +------------------------------------------ + (0.272707695624114 , 0.0181805130416076) +(1 row) + +-- +-- Check compatibility behaviour +-- +SELECT set_sphere_output_precision(10); + set_sphere_output_precision +----------------------------- + SET 10 +(1 row) + +SELECT '( 1h 2m 30s , +1d 2m 30s)'::spoint; + spoint +-------------------------------- + (0.2727076956 , 0.01818051304) +(1 row) + +SELECT set_sphere_output_precision(12); + set_sphere_output_precision +----------------------------- + SET 12 +(1 row) + +SELECT '( 1h 2m 30s , +1d 2m 30s)'::spoint; + spoint +------------------------------------ + (0.272707695624 , 0.0181805130416) +(1 row) + +SELECT set_sphere_output_precision(15); + set_sphere_output_precision +----------------------------- + SET 15 +(1 row) + +SELECT '( 1h 2m 30s , +1d 2m 30s)'::spoint; + spoint +------------------------------------------ + (0.272707695624114 , 0.0181805130416076) +(1 row) + +SELECT set_sphere_output_precision(17); + set_sphere_output_precision +----------------------------- + SET 15 +(1 row) + +SELECT '( 1h 2m 30s , +1d 2m 30s)'::spoint; + spoint +------------------------------------------ + (0.272707695624114 , 0.0181805130416076) +(1 row) + +SELECT set_sphere_output_precision(20); + set_sphere_output_precision +----------------------------- + SET 15 +(1 row) + +SELECT '( 1h 2m 30s , +1d 2m 30s)'::spoint; + spoint +------------------------------------------ + (0.272707695624114 , 0.0181805130416076) +(1 row) + +SELECT set_sphere_output_precision(0); + set_sphere_output_precision +----------------------------- + SET 15 +(1 row) + +SELECT '( 1h 2m 30s , +1d 2m 30s)'::spoint; + spoint +------------------------------------------ + (0.272707695624114 , 0.0181805130416076) +(1 row) + +SELECT set_sphere_output_precision(-3); + set_sphere_output_precision +----------------------------- + SET 15 +(1 row) + +SELECT '( 1h 2m 30s , +1d 2m 30s)'::spoint; + spoint +------------------------------------------ + (0.272707695624114 , 0.0181805130416076) +(1 row) + +-- +-- Check extra_float_digits after set_sphere_output_precision. +-- The change of extra_float_digits should not affect the precision of pgsphere +-- output because set_sphere_output_precision enables compatibility mode. +-- +SELECT set_sphere_output_precision(10); + set_sphere_output_precision +----------------------------- + SET 10 +(1 row) + +SELECT '( 1h 2m 30s , +1d 2m 30s)'::spoint; + spoint +-------------------------------- + (0.2727076956 , 0.01818051304) +(1 row) + +SET extra_float_digits TO -6; +SELECT '( 1h 2m 30s , +1d 2m 30s)'::spoint; + spoint +-------------------------------- + (0.2727076956 , 0.01818051304) +(1 row) + +SET extra_float_digits TO -10; +SELECT '( 1h 2m 30s , +1d 2m 30s)'::spoint; + spoint +-------------------------------- + (0.2727076956 , 0.01818051304) +(1 row) + +-- +-- Check reset_sphere_output_precision. +-- It should disable compatibility mode - extra_float_digits should work. +-- +SELECT reset_sphere_output_precision(); + reset_sphere_output_precision +------------------------------- + RESET +(1 row) + +SELECT '( 1h 2m 30s , +1d 2m 30s)'::spoint; + spoint +---------------------- + (0.27271 , 0.018181) +(1 row) + +SET extra_float_digits TO -6; +SELECT '( 1h 2m 30s , +1d 2m 30s)'::spoint; + spoint +----------------------------- + (0.272707696 , 0.018180513) +(1 row) + diff --git a/expected/version.out b/expected/version.out index 5e361bf..c1f0efe 100644 --- a/expected/version.out +++ b/expected/version.out @@ -2,6 +2,6 @@ SELECT pg_sphere_version(); pg_sphere_version ------------------- - 1.4.2 + 1.5.2 (1 row) diff --git a/pg_sphere.control b/pg_sphere.control index 69ca772..85f7589 100644 --- a/pg_sphere.control +++ b/pg_sphere.control @@ -1,5 +1,5 @@ # pg_sphere extension comment = 'spherical objects with useful functions, operators and index support' -default_version = '1.4.2' +default_version = '1.5.2' module_pathname = '$libdir/pg_sphere' relocatable = true diff --git a/pgindent-excludes.list b/pgindent-excludes.list index c3add5c..629df90 100644 --- a/pgindent-excludes.list +++ b/pgindent-excludes.list @@ -1 +1,3 @@ pgs_process_moc.h +pgs_healpix.h +pgs_moc.h diff --git a/pgs_gist.sql.in b/pgs_gist.sql.in index e8ac119..fcd4f11 100644 --- a/pgs_gist.sql.in +++ b/pgs_gist.sql.in @@ -98,12 +98,15 @@ CREATE FUNCTION g_spoint_compress(internal) AS 'MODULE_PATHNAME', 'g_spoint_compress' LANGUAGE 'c'; - CREATE FUNCTION g_spoint_consistent(internal, internal, int4, oid, internal) RETURNS internal AS 'MODULE_PATHNAME', 'g_spoint_consistent' LANGUAGE 'c'; +CREATE FUNCTION g_spoint_distance(internal, spoint, smallint, oid, internal) + RETURNS internal + AS 'MODULE_PATHNAME', 'g_spoint_distance' + LANGUAGE 'c'; CREATE OPERATOR CLASS spoint DEFAULT FOR TYPE spoint USING gist AS @@ -114,6 +117,7 @@ CREATE OPERATOR CLASS spoint OPERATOR 14 @ (spoint, spoly), OPERATOR 15 @ (spoint, sellipse), OPERATOR 16 @ (spoint, sbox), + OPERATOR 17 <-> (spoint, spoint) FOR ORDER BY float_ops, OPERATOR 37 <@ (spoint, scircle), OPERATOR 38 <@ (spoint, sline), OPERATOR 39 <@ (spoint, spath), @@ -127,6 +131,7 @@ CREATE OPERATOR CLASS spoint FUNCTION 5 g_spherekey_penalty (internal, internal, internal), FUNCTION 6 g_spherekey_picksplit (internal, internal), FUNCTION 7 g_spherekey_same (spherekey, spherekey, internal), + FUNCTION 8 g_spoint_distance (internal, spoint, smallint, oid, internal), STORAGE spherekey; diff --git a/pgs_point.sql.in b/pgs_point.sql.in index 908707e..724a119 100644 --- a/pgs_point.sql.in +++ b/pgs_point.sql.in @@ -26,6 +26,11 @@ CREATE FUNCTION set_sphere_output_precision(INT4) AS 'MODULE_PATHNAME', 'set_sphere_output_precision' LANGUAGE 'c'; +CREATE FUNCTION reset_sphere_output_precision() + RETURNS CSTRING + AS 'MODULE_PATHNAME', 'reset_sphere_output_precision' + LANGUAGE 'c'; + CREATE FUNCTION set_sphere_output(CSTRING) RETURNS CSTRING AS 'MODULE_PATHNAME', 'set_sphere_output' @@ -175,4 +180,3 @@ CREATE OPERATOR <-> ( COMMENT ON OPERATOR <-> (spoint, spoint) IS 'distance between spherical points'; - diff --git a/sql/bounding_box_gist.sql b/sql/bounding_box_gist.sql index fb862d6..20176c4 100644 --- a/sql/bounding_box_gist.sql +++ b/sql/bounding_box_gist.sql @@ -1,3 +1,4 @@ +SET extra_float_digits = 2; SET enable_seqscan=true; CREATE TABLE bbox_ellipse (e sellipse not null); INSERT INTO bbox_ellipse VALUES ('<{10d, 0.1d}, (0d,0d), 0d>'); diff --git a/sql/epochprop.sql b/sql/epochprop.sql index fea9737..a6c69dd 100644 --- a/sql/epochprop.sql +++ b/sql/epochprop.sql @@ -1,4 +1,6 @@ -SELECT +SET extra_float_digits = 1; + +SELECT to_char(DEGREES(tp[1]), '999D9999999999'), to_char(DEGREES(tp[2]), '999D9999999999'), to_char(tp[3], '999D999'), @@ -6,12 +8,12 @@ SELECT to_char(DEGREES(tp[5])*3.6e6, '99999D999'), to_char(tp[6], '999D999') FROM ( - SELECT epoch_prop(spoint(radians(269.45207695), radians(4.693364966)), + SELECT epoch_prop(spoint(radians(269.45207695), radians(4.693364966)), 546.9759, RADIANS(-801.551/3.6e6), RADIANS(10362/3.6e6), -110, -100) AS tp) AS q; -SELECT +SELECT to_char(DEGREES(tp[1]), '999D9999999999'), to_char(DEGREES(tp[2]), '999D9999999999'), to_char(tp[3], '999D999'), @@ -19,12 +21,12 @@ SELECT to_char(DEGREES(tp[5])*3.6e6, '99999D999'), to_char(tp[6], '999D999') FROM ( - SELECT epoch_prop(spoint(radians(269.45207695), radians(4.693364966)), + SELECT epoch_prop(spoint(radians(269.45207695), radians(4.693364966)), 0, RADIANS(-801.551/3.6e6), RADIANS(10362/3.6e6), -110, -100) AS tp) AS q; -SELECT +SELECT to_char(DEGREES(tp[1]), '999D9999999999'), to_char(DEGREES(tp[2]), '999D9999999999'), to_char(tp[3], '999D999'), @@ -32,12 +34,12 @@ SELECT to_char(DEGREES(tp[5])*3.6e6, '99999D999'), to_char(tp[6], '999D999') FROM ( - SELECT epoch_prop(spoint(radians(269.45207695), radians(4.693364966)), + SELECT epoch_prop(spoint(radians(269.45207695), radians(4.693364966)), NULL, RADIANS(-801.551/3.6e6), RADIANS(10362/3.6e6), -110, -100) AS tp) AS q; -SELECT +SELECT to_char(DEGREES(tp[1]), '999D9999999999'), to_char(DEGREES(tp[2]), '999D9999999999'), to_char(tp[3], '999D999'), @@ -45,12 +47,12 @@ SELECT to_char(DEGREES(tp[5])*3.6e6, '99999D999'), to_char(tp[6], '999D999') FROM ( - SELECT epoch_prop(spoint(radians(269.45207695), radians(4.693364966)), + SELECT epoch_prop(spoint(radians(269.45207695), radians(4.693364966)), 23, RADIANS(-801.551/3.6e6), RADIANS(10362/3.6e6), NULL, 20) AS tp) AS q; -SELECT +SELECT to_char(DEGREES(tp[1]), '999D9999999999'), to_char(DEGREES(tp[2]), '999D9999999999'), to_char(tp[3], '999D999'), @@ -58,7 +60,7 @@ SELECT to_char(DEGREES(tp[5])*3.6e6, '99999D999'), to_char(tp[6], '999D999') FROM ( - SELECT epoch_prop(spoint(radians(269.45207695), radians(4.693364966)), + SELECT epoch_prop(spoint(radians(269.45207695), radians(4.693364966)), 23, NULL, RADIANS(10362/3.6e6), -110, 120) AS tp) AS q; @@ -68,11 +70,11 @@ SELECT epoch_prop(NULL, 0.01 , RADIANS(10362/3.6e6), -110, 120); -SELECT epoch_prop_pos(spoint(radians(269.45207695), radians(4.693364966)), +SELECT epoch_prop_pos(spoint(radians(269.45207695), radians(4.693364966)), 23, RADIANS(-801.551/3.6e6), RADIANS(10362/3.6e6), -110, 20) AS tp; -SELECT epoch_prop_pos(spoint(radians(269.45207695), radians(4.693364966)), +SELECT epoch_prop_pos(spoint(radians(269.45207695), radians(4.693364966)), RADIANS(-801.551/3.6e6), RADIANS(10362/3.6e6), 20) AS tp; diff --git a/sql/init_extended.sql b/sql/init_extended.sql index 800d7e4..b28f0ef 100644 --- a/sql/init_extended.sql +++ b/sql/init_extended.sql @@ -2,15 +2,15 @@ -- spoint_data and scircle_data tables have to be created and indexed using -\! testsuite/gen_point.pl 1 > results/gen_point_1.sql +\! perl testsuite/gen_point.pl 1 > results/gen_point_1.sql \i results/gen_point_1.sql -- and -\! testsuite/gen_circle.pl 1 0.1 > results/gen_circle_1_0.1.sql +\! perl testsuite/gen_circle.pl 1 0.1 > results/gen_circle_1_0.1.sql \i results/gen_circle_1_0.1.sql -- -\! testsuite/gen_poly.pl 1 0.1 4 > results/gen_poly_1_0.1_4.sql +\! perl testsuite/gen_poly.pl 1 0.1 4 > results/gen_poly_1_0.1_4.sql \i results/gen_poly_1_0.1_4.sql diff --git a/sql/knn.sql b/sql/knn.sql new file mode 100644 index 0000000..0207c98 --- /dev/null +++ b/sql/knn.sql @@ -0,0 +1,12 @@ +CREATE TABLE points (id int, p spoint, pos int); +INSERT INTO points (id, p) SELECT x, spoint(random()*6.28, (2*random()-1)*1.57) FROM generate_series(1,314159) x; +CREATE INDEX i ON points USING gist (p); +SET enable_indexscan = true; +EXPLAIN (costs off) SELECT p <-> spoint (0.2, 0.3) FROM points ORDER BY 1 LIMIT 100; +UPDATE points SET pos = n FROM + (SELECT id, row_number() OVER (ORDER BY p <-> spoint (0.2, 0.3)) n FROM points ORDER BY p <-> spoint (0.2, 0.3) LIMIT 100) sel + WHERE points.id = sel.id; +SET enable_indexscan = false; +SELECT pos, row_number() OVER (ORDER BY p <-> spoint (0.2, 0.3)) n FROM points ORDER BY p <-> spoint (0.2, 0.3) LIMIT 100; +DROP TABLE points; + diff --git a/sql/output_precision.sql b/sql/output_precision.sql new file mode 100644 index 0000000..514af1e --- /dev/null +++ b/sql/output_precision.sql @@ -0,0 +1,82 @@ +-- +-- Test default and custom output precisions for double values. +-- + +SELECT set_sphere_output( 'RAD' ); + +-- +-- Check default precision +-- +SELECT '( 1h 2m 30s , +1d 2m 30s)'::spoint; + +-- +-- Check option extra_float_digits +-- +SET extra_float_digits TO -6; +SELECT '( 1h 2m 30s , +1d 2m 30s)'::spoint; + +SET extra_float_digits TO -2; +SELECT '( 1h 2m 30s , +1d 2m 30s)'::spoint; + +SET extra_float_digits TO 0; +SELECT '( 1h 2m 30s , +1d 2m 30s)'::spoint; + +SET extra_float_digits TO 1; +SELECT '( 1h 2m 30s , +1d 2m 30s)'::spoint; + +SET extra_float_digits TO 2; +SELECT '( 1h 2m 30s , +1d 2m 30s)'::spoint; + +SET extra_float_digits TO 3; +SELECT '( 1h 2m 30s , +1d 2m 30s)'::spoint; + +SET extra_float_digits TO 6; +SELECT '( 1h 2m 30s , +1d 2m 30s)'::spoint; + +-- +-- Check compatibility behaviour +-- +SELECT set_sphere_output_precision(10); +SELECT '( 1h 2m 30s , +1d 2m 30s)'::spoint; + +SELECT set_sphere_output_precision(12); +SELECT '( 1h 2m 30s , +1d 2m 30s)'::spoint; + +SELECT set_sphere_output_precision(15); +SELECT '( 1h 2m 30s , +1d 2m 30s)'::spoint; + +SELECT set_sphere_output_precision(17); +SELECT '( 1h 2m 30s , +1d 2m 30s)'::spoint; + +SELECT set_sphere_output_precision(20); +SELECT '( 1h 2m 30s , +1d 2m 30s)'::spoint; + +SELECT set_sphere_output_precision(0); +SELECT '( 1h 2m 30s , +1d 2m 30s)'::spoint; + +SELECT set_sphere_output_precision(-3); +SELECT '( 1h 2m 30s , +1d 2m 30s)'::spoint; + +-- +-- Check extra_float_digits after set_sphere_output_precision. +-- The change of extra_float_digits should not affect the precision of pgsphere +-- output because set_sphere_output_precision enables compatibility mode. +-- +SELECT set_sphere_output_precision(10); +SELECT '( 1h 2m 30s , +1d 2m 30s)'::spoint; + +SET extra_float_digits TO -6; +SELECT '( 1h 2m 30s , +1d 2m 30s)'::spoint; + +SET extra_float_digits TO -10; +SELECT '( 1h 2m 30s , +1d 2m 30s)'::spoint; + +-- +-- Check reset_sphere_output_precision. +-- It should disable compatibility mode - extra_float_digits should work. +-- +SELECT reset_sphere_output_precision(); +SELECT '( 1h 2m 30s , +1d 2m 30s)'::spoint; + +SET extra_float_digits TO -6; +SELECT '( 1h 2m 30s , +1d 2m 30s)'::spoint; diff --git a/src/box.h b/src/box.h index 7314ac0..6444a52 100644 --- a/src/box.h +++ b/src/box.h @@ -11,8 +11,8 @@ */ typedef struct { - SPoint sw; /* South-west value of a box */ - SPoint ne; /* North-east value of a box */ + SPoint sw; /* South-west value of a box */ + SPoint ne; /* North-east value of a box */ } SBOX; @@ -56,373 +56,373 @@ typedef struct /* * Checks whether two boxes are equal. */ -bool sbox_eq(SBOX *b1, SBOX *b2); +extern bool sbox_eq(SBOX *b1, SBOX *b2); /* * Checks whether a point is contained by a box. */ -bool sbox_cont_point(const SBOX *b, const SPoint *p); +extern bool sbox_cont_point(const SBOX *b, const SPoint *p); /* * Input function of a box. */ -Datum spherebox_in(PG_FUNCTION_ARGS); +extern Datum spherebox_in(PG_FUNCTION_ARGS); /* * Input function of a box from two points. The first point * is the south-west position, the second the north-east position. */ -Datum spherebox_in_from_points(PG_FUNCTION_ARGS); +extern Datum spherebox_in_from_points(PG_FUNCTION_ARGS); /* * Returns the south-west edge of a box. */ -Datum spherebox_sw(PG_FUNCTION_ARGS); +extern Datum spherebox_sw(PG_FUNCTION_ARGS); /* * Returns the north-east edge of a box. */ -Datum spherebox_ne(PG_FUNCTION_ARGS); +extern Datum spherebox_ne(PG_FUNCTION_ARGS); /* * Returns the south-east edge of a box. */ -Datum spherebox_se(PG_FUNCTION_ARGS); +extern Datum spherebox_se(PG_FUNCTION_ARGS); /* * Returns the north-west edge of a box. */ -Datum spherebox_nw(PG_FUNCTION_ARGS); +extern Datum spherebox_nw(PG_FUNCTION_ARGS); /* * Returns the area of a box. */ -Datum spherebox_area(PG_FUNCTION_ARGS); +extern Datum spherebox_area(PG_FUNCTION_ARGS); /* * Returns the circumference of a box. */ -Datum spherebox_circ(PG_FUNCTION_ARGS); +extern Datum spherebox_circ(PG_FUNCTION_ARGS); /* * Checks whether two boxes are equal. */ -Datum spherebox_equal(PG_FUNCTION_ARGS); +extern Datum spherebox_equal(PG_FUNCTION_ARGS); /* * Checks whether two boxes are not equal. */ -Datum spherebox_equal_neg(PG_FUNCTION_ARGS); +extern Datum spherebox_equal_neg(PG_FUNCTION_ARGS); /* * Checks whether a point is contained by a box. */ -Datum spherebox_cont_point(PG_FUNCTION_ARGS); +extern Datum spherebox_cont_point(PG_FUNCTION_ARGS); /* * Checks whether a point isn't contained by a box. */ -Datum spherebox_cont_point_neg(PG_FUNCTION_ARGS); +extern Datum spherebox_cont_point_neg(PG_FUNCTION_ARGS); /* * Checks whether a point is contained by a box. */ -Datum spherebox_cont_point_com(PG_FUNCTION_ARGS); +extern Datum spherebox_cont_point_com(PG_FUNCTION_ARGS); /* * Checks whether a point isn't contained by a box. */ -Datum spherebox_cont_point_com_neg(PG_FUNCTION_ARGS); +extern Datum spherebox_cont_point_com_neg(PG_FUNCTION_ARGS); /* * Checks whether a box contains a circle. */ -Datum spherebox_cont_circle(PG_FUNCTION_ARGS); +extern Datum spherebox_cont_circle(PG_FUNCTION_ARGS); /* * Checks whether a box doesn't contain a circle. */ -Datum spherebox_cont_circle_neg(PG_FUNCTION_ARGS); +extern Datum spherebox_cont_circle_neg(PG_FUNCTION_ARGS); /* * Checks whether a box contains a circle. */ -Datum spherebox_cont_circle_com(PG_FUNCTION_ARGS); +extern Datum spherebox_cont_circle_com(PG_FUNCTION_ARGS); /* * Checks whether a box doesn't contain a circle. */ -Datum spherebox_cont_circle_com_neg(PG_FUNCTION_ARGS); +extern Datum spherebox_cont_circle_com_neg(PG_FUNCTION_ARGS); /* * Checks whether a circle contains a box. */ -Datum spherecircle_cont_box(PG_FUNCTION_ARGS); +extern Datum spherecircle_cont_box(PG_FUNCTION_ARGS); /* * Checks whether a circle doesn't contain a box. */ -Datum spherecircle_cont_box_neg(PG_FUNCTION_ARGS); +extern Datum spherecircle_cont_box_neg(PG_FUNCTION_ARGS); /* * Checks whether a circle contains a box. */ -Datum spherecircle_cont_box_com(PG_FUNCTION_ARGS); +extern Datum spherecircle_cont_box_com(PG_FUNCTION_ARGS); /* * Checks whether a circle doesn't contain a box. */ -Datum spherecircle_cont_box_com_neg(PG_FUNCTION_ARGS); +extern Datum spherecircle_cont_box_com_neg(PG_FUNCTION_ARGS); /* * Checks whether a circle and a box overlap. */ -Datum spherebox_overlap_circle(PG_FUNCTION_ARGS); +extern Datum spherebox_overlap_circle(PG_FUNCTION_ARGS); /* * Checks whether a circle and a box don't overlap. */ -Datum spherebox_overlap_circle_neg(PG_FUNCTION_ARGS); +extern Datum spherebox_overlap_circle_neg(PG_FUNCTION_ARGS); /* * Checks whether a circle and a box overlap. */ -Datum spherebox_overlap_circle_com(PG_FUNCTION_ARGS); +extern Datum spherebox_overlap_circle_com(PG_FUNCTION_ARGS); /* * Checks whether a circle and a box don't overlap. */ -Datum spherebox_overlap_circle_com_neg(PG_FUNCTION_ARGS); +extern Datum spherebox_overlap_circle_com_neg(PG_FUNCTION_ARGS); /* * Checks whether a box contains a line. */ -Datum spherebox_cont_line(PG_FUNCTION_ARGS); +extern Datum spherebox_cont_line(PG_FUNCTION_ARGS); /* * Checks whether a box doesn't contain a line. */ -Datum spherebox_cont_line_neg(PG_FUNCTION_ARGS); +extern Datum spherebox_cont_line_neg(PG_FUNCTION_ARGS); /* * Checks whether a box contains a line. */ -Datum spherebox_cont_line_com(PG_FUNCTION_ARGS); +extern Datum spherebox_cont_line_com(PG_FUNCTION_ARGS); /* * Checks whether a box doesn't contain a line. */ -Datum spherebox_cont_line_com_neg(PG_FUNCTION_ARGS); +extern Datum spherebox_cont_line_com_neg(PG_FUNCTION_ARGS); /* * Checks whether a box and a line overlap. */ -Datum spherebox_overlap_line(PG_FUNCTION_ARGS); +extern Datum spherebox_overlap_line(PG_FUNCTION_ARGS); /* * Checks whether a box and a line don't overlap. */ -Datum spherebox_overlap_line_neg(PG_FUNCTION_ARGS); +extern Datum spherebox_overlap_line_neg(PG_FUNCTION_ARGS); /* * Checks whether a box and a line overlap. */ -Datum spherebox_overlap_line_com(PG_FUNCTION_ARGS); +extern Datum spherebox_overlap_line_com(PG_FUNCTION_ARGS); /* * Checks whether a box and a line don't overlap. */ -Datum spherebox_overlap_line_com_neg(PG_FUNCTION_ARGS); +extern Datum spherebox_overlap_line_com_neg(PG_FUNCTION_ARGS); /* * Checks whether a box contains a path. */ -Datum spherebox_cont_path(PG_FUNCTION_ARGS); +extern Datum spherebox_cont_path(PG_FUNCTION_ARGS); /* * Checks whether a box doesn't contain a path. */ -Datum spherebox_cont_path_neg(PG_FUNCTION_ARGS); +extern Datum spherebox_cont_path_neg(PG_FUNCTION_ARGS); /* * Checks whether a box contains a path. */ -Datum spherebox_cont_path_com(PG_FUNCTION_ARGS); +extern Datum spherebox_cont_path_com(PG_FUNCTION_ARGS); /* * Checks whether a box doesn't contain a path. */ -Datum spherebox_cont_path_com_neg(PG_FUNCTION_ARGS); +extern Datum spherebox_cont_path_com_neg(PG_FUNCTION_ARGS); /* * Checks whether a box and a path overlap. */ -Datum spherebox_overlap_path(PG_FUNCTION_ARGS); +extern Datum spherebox_overlap_path(PG_FUNCTION_ARGS); /* * Checks whether a box and a path don't overlap. */ -Datum spherebox_overlap_path_neg(PG_FUNCTION_ARGS); +extern Datum spherebox_overlap_path_neg(PG_FUNCTION_ARGS); /* * Checks whether a box and a path overlap. */ -Datum spherebox_overlap_path_com(PG_FUNCTION_ARGS); +extern Datum spherebox_overlap_path_com(PG_FUNCTION_ARGS); /* * Checks whether a box and a path don't overlap. */ -Datum spherebox_overlap_path_com_neg(PG_FUNCTION_ARGS); +extern Datum spherebox_overlap_path_com_neg(PG_FUNCTION_ARGS); /* * Checks whether a box contains a polygon. */ -Datum spherebox_cont_poly(PG_FUNCTION_ARGS); +extern Datum spherebox_cont_poly(PG_FUNCTION_ARGS); /* * Checks whether a box doesn't contain a polygon. */ -Datum spherebox_cont_poly_neg(PG_FUNCTION_ARGS); +extern Datum spherebox_cont_poly_neg(PG_FUNCTION_ARGS); /* * Checks whether a box contains a polygon. */ -Datum spherebox_cont_poly_com(PG_FUNCTION_ARGS); +extern Datum spherebox_cont_poly_com(PG_FUNCTION_ARGS); /* * Checks whether a box doesn't contain a polygon. */ -Datum spherebox_cont_poly_com_neg(PG_FUNCTION_ARGS); +extern Datum spherebox_cont_poly_com_neg(PG_FUNCTION_ARGS); /* * Checks whether a polygon contains a box. */ -Datum spherepoly_cont_box(PG_FUNCTION_ARGS); +extern Datum spherepoly_cont_box(PG_FUNCTION_ARGS); /* * Checks whether a polygon doesn't contain a box. */ -Datum spherepoly_cont_box_neg(PG_FUNCTION_ARGS); +extern Datum spherepoly_cont_box_neg(PG_FUNCTION_ARGS); /* * Checks whether a polygon contains a box. */ -Datum spherepoly_cont_box_com(PG_FUNCTION_ARGS); +extern Datum spherepoly_cont_box_com(PG_FUNCTION_ARGS); /* * Checks whether a polygon doesn't contain a box. */ -Datum spherepoly_cont_box_com_neg(PG_FUNCTION_ARGS); +extern Datum spherepoly_cont_box_com_neg(PG_FUNCTION_ARGS); /* * Checks whether a polygon and a box overlap. */ -Datum spherebox_overlap_poly(PG_FUNCTION_ARGS); +extern Datum spherebox_overlap_poly(PG_FUNCTION_ARGS); /* * Checks whether a polygon and a box don't overlap. */ -Datum spherebox_overlap_poly_neg(PG_FUNCTION_ARGS); +extern Datum spherebox_overlap_poly_neg(PG_FUNCTION_ARGS); /* * Checks whether a polygon and a box overlap. */ -Datum spherebox_overlap_poly_com(PG_FUNCTION_ARGS); +extern Datum spherebox_overlap_poly_com(PG_FUNCTION_ARGS); /* * Checks whether a polygon and a box don't overlap. */ -Datum spherebox_overlap_poly_com_neg(PG_FUNCTION_ARGS); +extern Datum spherebox_overlap_poly_com_neg(PG_FUNCTION_ARGS); /* * Checks whether a box contains an ellipse. */ -Datum spherebox_cont_ellipse(PG_FUNCTION_ARGS); +extern Datum spherebox_cont_ellipse(PG_FUNCTION_ARGS); /* * Checks whether a box doesn't contain an ellipse. */ -Datum spherebox_cont_ellipse_neg(PG_FUNCTION_ARGS); +extern Datum spherebox_cont_ellipse_neg(PG_FUNCTION_ARGS); /* * Checks whether a box contains an ellipse. */ -Datum spherebox_cont_ellipse_com(PG_FUNCTION_ARGS); +extern Datum spherebox_cont_ellipse_com(PG_FUNCTION_ARGS); /* * Checks whether a box doesn't contain an ellipse. */ -Datum spherebox_cont_ellipse_com_neg(PG_FUNCTION_ARGS); +extern Datum spherebox_cont_ellipse_com_neg(PG_FUNCTION_ARGS); /* * Checks whether an ellipse contains a box. */ -Datum sphereellipse_cont_box(PG_FUNCTION_ARGS); +extern Datum sphereellipse_cont_box(PG_FUNCTION_ARGS); /* * Checks whether an ellipse doesn't contain a box. */ -Datum sphereellipse_cont_box_neg(PG_FUNCTION_ARGS); +extern Datum sphereellipse_cont_box_neg(PG_FUNCTION_ARGS); /* * Checks whether an ellipse contains a box. */ -Datum sphereellipse_cont_box_com(PG_FUNCTION_ARGS); +extern Datum sphereellipse_cont_box_com(PG_FUNCTION_ARGS); /* * Checks whether an ellipse doesn't contain a box. */ -Datum sphereellipse_cont_box_com_neg(PG_FUNCTION_ARGS); +extern Datum sphereellipse_cont_box_com_neg(PG_FUNCTION_ARGS); /* * Checks whether an ellipse and a box overlap. */ -Datum spherebox_overlap_ellipse(PG_FUNCTION_ARGS); +extern Datum spherebox_overlap_ellipse(PG_FUNCTION_ARGS); /* * Checks whether an ellipse and a box don't overlap. */ -Datum spherebox_overlap_ellipse_neg(PG_FUNCTION_ARGS); +extern Datum spherebox_overlap_ellipse_neg(PG_FUNCTION_ARGS); /* * Checks whether an ellipse and a box overlap. */ -Datum spherebox_overlap_ellipse_com(PG_FUNCTION_ARGS); +extern Datum spherebox_overlap_ellipse_com(PG_FUNCTION_ARGS); /* * Checks whether an ellipse and a box don't overlap. */ -Datum spherebox_overlap_ellipse_com_neg(PG_FUNCTION_ARGS); +extern Datum spherebox_overlap_ellipse_com_neg(PG_FUNCTION_ARGS); /* * Checks whether a box contains another box. */ -Datum spherebox_cont_box(PG_FUNCTION_ARGS); +extern Datum spherebox_cont_box(PG_FUNCTION_ARGS); /* * Checks whether a box doesn't contain another box. */ -Datum spherebox_cont_box_neg(PG_FUNCTION_ARGS); +extern Datum spherebox_cont_box_neg(PG_FUNCTION_ARGS); /* * Checks whether a box contains another box. */ -Datum spherebox_cont_box_com(PG_FUNCTION_ARGS); +extern Datum spherebox_cont_box_com(PG_FUNCTION_ARGS); /* * Checks whether a box doesn't contain another box. */ -Datum spherebox_cont_box_com_neg(PG_FUNCTION_ARGS); +extern Datum spherebox_cont_box_com_neg(PG_FUNCTION_ARGS); /* * Checks whether two boxes overlap. */ -Datum spherebox_overlap_box(PG_FUNCTION_ARGS); +extern Datum spherebox_overlap_box(PG_FUNCTION_ARGS); /* * Checks whether two boxes don't overlap. */ -Datum spherebox_overlap_box_neg(PG_FUNCTION_ARGS); +extern Datum spherebox_overlap_box_neg(PG_FUNCTION_ARGS); #endif diff --git a/src/circle.h b/src/circle.h index b8aa520..614b0e8 100644 --- a/src/circle.h +++ b/src/circle.h @@ -10,151 +10,151 @@ */ typedef struct { - SPoint center; /* the center of circle */ - float8 radius; /* the circle radius in radians */ + SPoint center; /* the center of circle */ + float8 radius; /* the circle radius in radians */ } SCIRCLE; /* * Checks whether two circles are equal. */ -bool scircle_eq(const SCIRCLE *c1, const SCIRCLE *c2); +extern bool scircle_eq(const SCIRCLE *c1, const SCIRCLE *c2); /* * Checks whether a circle contains a point. */ -bool spoint_in_circle(const SPoint *p, const SCIRCLE *c); +extern bool spoint_in_circle(const SPoint *p, const SCIRCLE *c); /* * Transforms a circle using an Euler transformation. */ -void euler_scircle_trans(SCIRCLE *out, const SCIRCLE *in, const SEuler *se); +extern void euler_scircle_trans(SCIRCLE *out, const SCIRCLE *in, const SEuler *se); /* * Takes the input and stores it as a spherical circle. */ -Datum spherecircle_in(PG_FUNCTION_ARGS); +extern Datum spherecircle_in(PG_FUNCTION_ARGS); /* * Checks whether two circles are equal. */ -Datum spherecircle_equal(PG_FUNCTION_ARGS); +extern Datum spherecircle_equal(PG_FUNCTION_ARGS); /* * Checks whether two circles are not equal. */ -Datum spherecircle_equal_neg(PG_FUNCTION_ARGS); +extern Datum spherecircle_equal_neg(PG_FUNCTION_ARGS); /* * Calculate the distance of two circles. If they overlap, this function * returns 0.0. */ -Datum spherecircle_distance(PG_FUNCTION_ARGS); +extern Datum spherecircle_distance(PG_FUNCTION_ARGS); /* * Calculate the distance of a circle and a point. If a circle contains a point, * this function returns 0.0. */ -Datum spherecircle_point_distance(PG_FUNCTION_ARGS); +extern Datum spherecircle_point_distance(PG_FUNCTION_ARGS); /* * Calculate the distance of a point and a circle. If a circle contains a point, * this function returns 0.0. */ -Datum spherecircle_point_distance_com(PG_FUNCTION_ARGS); +extern Datum spherecircle_point_distance_com(PG_FUNCTION_ARGS); /* * Checks whether a circle contains a point. */ -Datum spherepoint_in_circle(PG_FUNCTION_ARGS); +extern Datum spherepoint_in_circle(PG_FUNCTION_ARGS); /* * Checks whether a circle doesn't contain a point. */ -Datum spherepoint_in_circle_neg(PG_FUNCTION_ARGS); +extern Datum spherepoint_in_circle_neg(PG_FUNCTION_ARGS); /* * Checks whether a circle contains a point. */ -Datum spherepoint_in_circle_com(PG_FUNCTION_ARGS); +extern Datum spherepoint_in_circle_com(PG_FUNCTION_ARGS); /* * Checks whether a circle doesn't contain a point. */ -Datum spherepoint_in_circle_com_neg(PG_FUNCTION_ARGS); +extern Datum spherepoint_in_circle_com_neg(PG_FUNCTION_ARGS); /* * Checks whether a circle is contained by other circle. */ -Datum spherecircle_in_circle(PG_FUNCTION_ARGS); +extern Datum spherecircle_in_circle(PG_FUNCTION_ARGS); /* * Checks whether a circle is not contained by other circle. */ -Datum spherecircle_in_circle_neg(PG_FUNCTION_ARGS); +extern Datum spherecircle_in_circle_neg(PG_FUNCTION_ARGS); /* * Checks whether a circle contains other circle. */ -Datum spherecircle_in_circle_com(PG_FUNCTION_ARGS); +extern Datum spherecircle_in_circle_com(PG_FUNCTION_ARGS); /* * Checks whether circle does not contain other circle. */ -Datum spherecircle_in_circle_com_neg(PG_FUNCTION_ARGS); +extern Datum spherecircle_in_circle_com_neg(PG_FUNCTION_ARGS); /* * Checks whether two circles overlap. */ -Datum spherecircle_overlap(PG_FUNCTION_ARGS); +extern Datum spherecircle_overlap(PG_FUNCTION_ARGS); /* * Checks whether two circles overlap. */ -Datum spherecircle_overlap_neg(PG_FUNCTION_ARGS); +extern Datum spherecircle_overlap_neg(PG_FUNCTION_ARGS); /* * Returns the center of a circle. */ -Datum spherecircle_center(PG_FUNCTION_ARGS); +extern Datum spherecircle_center(PG_FUNCTION_ARGS); /* * Returns the radius of a circle. */ -Datum spherecircle_radius(PG_FUNCTION_ARGS); +extern Datum spherecircle_radius(PG_FUNCTION_ARGS); /* * Converts a point to a circle. */ -Datum spherepoint_to_circle(PG_FUNCTION_ARGS); +extern Datum spherepoint_to_circle(PG_FUNCTION_ARGS); /* * Creates a circle from center and radius. */ -Datum spherecircle_by_center(PG_FUNCTION_ARGS); +extern Datum spherecircle_by_center(PG_FUNCTION_ARGS); /* * Creates a circle from center and radius(in degrees). */ -Datum spherecircle_by_center_deg(PG_FUNCTION_ARGS); +extern Datum spherecircle_by_center_deg(PG_FUNCTION_ARGS); /* * Calculates the area of a circle in square radians. */ -Datum spherecircle_area(PG_FUNCTION_ARGS); +extern Datum spherecircle_area(PG_FUNCTION_ARGS); /* * Calculates the circumference of a circle in radians. */ -Datum spherecircle_circ(PG_FUNCTION_ARGS); +extern Datum spherecircle_circ(PG_FUNCTION_ARGS); /* * Transforms a circle using an Euler transformation. */ -Datum spheretrans_circle(PG_FUNCTION_ARGS); +extern Datum spheretrans_circle(PG_FUNCTION_ARGS); /* * Inverse transformation of a circle using an Euler transformation. */ -Datum spheretrans_circle_inverse(PG_FUNCTION_ARGS); +extern Datum spheretrans_circle_inverse(PG_FUNCTION_ARGS); #endif diff --git a/src/ellipse.h b/src/ellipse.h index b27bc3b..f600936 100644 --- a/src/ellipse.h +++ b/src/ellipse.h @@ -18,9 +18,9 @@ typedef struct */ float8 rad[2]; - float8 phi, /* the first rotation angle around z axis */ - theta, /* the second rotation angle around x axis */ - psi; /* the last rotation angle around z axis */ + float8 phi, /* the first rotation angle around z axis */ + theta, /* the second rotation angle around x axis */ + psi; /* the last rotation angle around z axis */ } SELLIPSE; /* @@ -47,258 +47,258 @@ typedef struct /* * Checks whether two ellipses are equal . */ -bool sellipse_eq(const SELLIPSE *e1, const SELLIPSE *e2); +extern bool sellipse_eq(const SELLIPSE *e1, const SELLIPSE *e2); /* * Returns the center of an ellipse. */ -void sellipse_center(SPoint *sp, const SELLIPSE *e); +extern void sellipse_center(SPoint *sp, const SELLIPSE *e); /* * Checks whether a ellipse contains point. */ -bool sellipse_cont_point(const SELLIPSE *se, const SPoint *sp); +extern bool sellipse_cont_point(const SELLIPSE *se, const SPoint *sp); /* * Returns the large axis of an ellipse as line. */ -bool sellipse_line(SLine *sl, const SELLIPSE *e); +extern bool sellipse_line(SLine *sl, const SELLIPSE *e); /* * Relationship between a line and an ellipse as PGS_ELLIPSE_LINE_REL int8 value. */ -int8 sellipse_line_pos(const SELLIPSE *se, const SLine *sl); +extern int8 sellipse_line_pos(const SELLIPSE *se, const SLine *sl); /* * Relationship between a circle and an ellipse as PGS_ELLIPSE_CIRCLE_REL int8 value. */ -int8 sellipse_circle_pos(const SELLIPSE *se, const SCIRCLE *sc); +extern int8 sellipse_circle_pos(const SELLIPSE *se, const SCIRCLE *sc); /* * Returns the Euler transformation of an ellipse. */ -void sellipse_trans(SEuler *se, const SELLIPSE *e); +extern void sellipse_trans(SEuler *se, const SELLIPSE *e); /* * Input of the spherical ellipse. */ -Datum sphereellipse_in(PG_FUNCTION_ARGS); +extern Datum sphereellipse_in(PG_FUNCTION_ARGS); /* * Input of the spherical ellipse from center, axes and inclination. */ -Datum sphereellipse_infunc(PG_FUNCTION_ARGS); +extern Datum sphereellipse_infunc(PG_FUNCTION_ARGS); /* * Returns the inclination of an ellipse. */ -Datum sphereellipse_incl(PG_FUNCTION_ARGS); +extern Datum sphereellipse_incl(PG_FUNCTION_ARGS); /* * Returns the length of the major axis of an ellipse. */ -Datum sphereellipse_rad1(PG_FUNCTION_ARGS); +extern Datum sphereellipse_rad1(PG_FUNCTION_ARGS); /* * Returns the length of the minor axis of an ellipse. */ -Datum sphereellipse_rad2(PG_FUNCTION_ARGS); +extern Datum sphereellipse_rad2(PG_FUNCTION_ARGS); /* * Returns the center of an ellipse. */ -Datum sphereellipse_center(PG_FUNCTION_ARGS); +extern Datum sphereellipse_center(PG_FUNCTION_ARGS); /* * Returns the Euler transformation of an ellipse. */ -Datum sphereellipse_trans(PG_FUNCTION_ARGS); +extern Datum sphereellipse_trans(PG_FUNCTION_ARGS); /* * Casts a spherical ellipse as circle. The created circle is the boundary * circle of ellipse. The diameter of returned circle is equal to length of * major axis of ellipse. */ -Datum sphereellipse_circle(PG_FUNCTION_ARGS); +extern Datum sphereellipse_circle(PG_FUNCTION_ARGS); /* * Casts a spherical point to an ellipse. */ -Datum spherepoint_ellipse(PG_FUNCTION_ARGS); +extern Datum spherepoint_ellipse(PG_FUNCTION_ARGS); /* * Casts a spherical circle to an ellipse. */ -Datum spherecircle_ellipse(PG_FUNCTION_ARGS); +extern Datum spherecircle_ellipse(PG_FUNCTION_ARGS); /* * Checks whether two ellipses are equal. */ -Datum sphereellipse_equal(PG_FUNCTION_ARGS); +extern Datum sphereellipse_equal(PG_FUNCTION_ARGS); /* * Checks whether two ellipses are not equal. */ -Datum sphereellipse_equal_neg(PG_FUNCTION_ARGS); +extern Datum sphereellipse_equal_neg(PG_FUNCTION_ARGS); /* * Checks whether an ellipse contains a point. */ -Datum sphereellipse_cont_point(PG_FUNCTION_ARGS); +extern Datum sphereellipse_cont_point(PG_FUNCTION_ARGS); /* * Checks whether an ellipse doesn't contain a point. */ -Datum sphereellipse_cont_point_neg(PG_FUNCTION_ARGS); +extern Datum sphereellipse_cont_point_neg(PG_FUNCTION_ARGS); /* * Checks whether an ellipse contains a point. */ -Datum sphereellipse_cont_point_com(PG_FUNCTION_ARGS); +extern Datum sphereellipse_cont_point_com(PG_FUNCTION_ARGS); /* * Checks whether an ellipse doesn't contain a point. */ -Datum sphereellipse_cont_point_com_neg(PG_FUNCTION_ARGS); +extern Datum sphereellipse_cont_point_com_neg(PG_FUNCTION_ARGS); /* * Checks whether an ellipse contains a line. */ -Datum sphereellipse_cont_line(PG_FUNCTION_ARGS); +extern Datum sphereellipse_cont_line(PG_FUNCTION_ARGS); /* * Checks whether an ellipse doesn't contain a line. */ -Datum sphereellipse_cont_line_neg(PG_FUNCTION_ARGS); +extern Datum sphereellipse_cont_line_neg(PG_FUNCTION_ARGS); /* * Checks whether an ellipse contains a line. */ -Datum sphereellipse_cont_line_com(PG_FUNCTION_ARGS); +extern Datum sphereellipse_cont_line_com(PG_FUNCTION_ARGS); /* * Checks whether an ellipse doesn't contain a line. */ -Datum sphereellipse_cont_line_com_neg(PG_FUNCTION_ARGS); +extern Datum sphereellipse_cont_line_com_neg(PG_FUNCTION_ARGS); /* * Checks whether an ellipse and a line overlap. */ -Datum sphereellipse_overlap_line(PG_FUNCTION_ARGS); +extern Datum sphereellipse_overlap_line(PG_FUNCTION_ARGS); /* * Checks whether an ellipse and a line don't overlap. */ -Datum sphereellipse_overlap_line_neg(PG_FUNCTION_ARGS); +extern Datum sphereellipse_overlap_line_neg(PG_FUNCTION_ARGS); /* * Checks whether an ellipse and a line overlap. */ -Datum sphereellipse_overlap_line_com(PG_FUNCTION_ARGS); +extern Datum sphereellipse_overlap_line_com(PG_FUNCTION_ARGS); /* * Checks whether an ellipse and a line don't overlap. */ -Datum sphereellipse_overlap_line_com_neg(PG_FUNCTION_ARGS); +extern Datum sphereellipse_overlap_line_com_neg(PG_FUNCTION_ARGS); /* * Checks whether an ellipse contains a circle. */ -Datum sphereellipse_cont_circle(PG_FUNCTION_ARGS); +extern Datum sphereellipse_cont_circle(PG_FUNCTION_ARGS); /* * Checks whether an ellipse doesn't contain a circle. */ -Datum sphereellipse_cont_circle_neg(PG_FUNCTION_ARGS); +extern Datum sphereellipse_cont_circle_neg(PG_FUNCTION_ARGS); /* * Checks whether an ellipse contains a circle. */ -Datum sphereellipse_cont_circle_com(PG_FUNCTION_ARGS); +extern Datum sphereellipse_cont_circle_com(PG_FUNCTION_ARGS); /* * Checks whether an ellipse doesn't contain a circle. */ -Datum sphereellipse_cont_circle_com_neg(PG_FUNCTION_ARGS); +extern Datum sphereellipse_cont_circle_com_neg(PG_FUNCTION_ARGS); /* * Checks whether a circle contains an ellipse. */ -Datum spherecircle_cont_ellipse(PG_FUNCTION_ARGS); +extern Datum spherecircle_cont_ellipse(PG_FUNCTION_ARGS); /* * Checks whether a circle doesn't contain an ellipse. */ -Datum spherecircle_cont_ellipse_neg(PG_FUNCTION_ARGS); +extern Datum spherecircle_cont_ellipse_neg(PG_FUNCTION_ARGS); /* * Checks whether a circle contains an ellipse. */ -Datum spherecircle_cont_ellipse_com(PG_FUNCTION_ARGS); +extern Datum spherecircle_cont_ellipse_com(PG_FUNCTION_ARGS); /* * Checks whether a circle doesn't contain an ellipse. */ -Datum spherecircle_cont_ellipse_com_neg(PG_FUNCTION_ARGS); +extern Datum spherecircle_cont_ellipse_com_neg(PG_FUNCTION_ARGS); /* * Checks whether a circle and an ellipse overlap. */ -Datum sphereellipse_overlap_circle(PG_FUNCTION_ARGS); +extern Datum sphereellipse_overlap_circle(PG_FUNCTION_ARGS); /* * Checks whether a circle and an ellipse don't overlap. */ -Datum sphereellipse_overlap_circle_neg(PG_FUNCTION_ARGS); +extern Datum sphereellipse_overlap_circle_neg(PG_FUNCTION_ARGS); /* * Checks whether a circle and an ellipse overlap. */ -Datum sphereellipse_overlap_circle_com(PG_FUNCTION_ARGS); +extern Datum sphereellipse_overlap_circle_com(PG_FUNCTION_ARGS); /* * Checks whether a circle and an ellipse don't overlap. */ -Datum sphereellipse_overlap_circle_com_neg(PG_FUNCTION_ARGS); +extern Datum sphereellipse_overlap_circle_com_neg(PG_FUNCTION_ARGS); /* * Checks whether an ellipse contains other ellipse. */ -Datum sphereellipse_cont_ellipse(PG_FUNCTION_ARGS); +extern Datum sphereellipse_cont_ellipse(PG_FUNCTION_ARGS); /* * Checks whether an ellipse doesn't contain other ellipse. */ -Datum sphereellipse_cont_ellipse_neg(PG_FUNCTION_ARGS); +extern Datum sphereellipse_cont_ellipse_neg(PG_FUNCTION_ARGS); /* * Checks whether an ellipse is contained by other ellipse. */ -Datum sphereellipse_cont_ellipse_com(PG_FUNCTION_ARGS); +extern Datum sphereellipse_cont_ellipse_com(PG_FUNCTION_ARGS); /* * Checks whether an ellipse isn't contained by other ellipse. */ -Datum sphereellipse_cont_ellipse_com_neg(PG_FUNCTION_ARGS); +extern Datum sphereellipse_cont_ellipse_com_neg(PG_FUNCTION_ARGS); /* * Checks whether two ellipses overlap. */ -Datum sphereellipse_overlap_ellipse(PG_FUNCTION_ARGS); +extern Datum sphereellipse_overlap_ellipse(PG_FUNCTION_ARGS); /* * Checks whether two ellipses don't overlap. */ -Datum sphereellipse_overlap_ellipse_neg(PG_FUNCTION_ARGS); +extern Datum sphereellipse_overlap_ellipse_neg(PG_FUNCTION_ARGS); /* * Transforms an ellipse using an Euler transformation. */ -Datum spheretrans_ellipse(PG_FUNCTION_ARGS); +extern Datum spheretrans_ellipse(PG_FUNCTION_ARGS); /* * Transforms an ellipse using an Euler transformation. */ -Datum spheretrans_ellipse_inv(PG_FUNCTION_ARGS); +extern Datum spheretrans_ellipse_inv(PG_FUNCTION_ARGS); #endif diff --git a/src/epochprop.c b/src/epochprop.c index ab9abc8..12ad621 100644 --- a/src/epochprop.c +++ b/src/epochprop.c @@ -133,6 +133,7 @@ epoch_prop(PG_FUNCTION_ARGS) { phasevec input, output; ArrayType *result; Datum retvals[6]; + bool output_null[6] = {0, 0, 0, 0, 0, 0}; if (PG_ARGISNULL(0)) { ereport(ERROR, @@ -141,25 +142,29 @@ epoch_prop(PG_FUNCTION_ARGS) { memcpy(&(input.pos), (void*)PG_GETARG_POINTER(0), sizeof(SPoint)); if (PG_ARGISNULL(1)) { input.parallax = 0; + output_null[2] = 1; + /* The way we do our computation, with a bad parallax the RV + will be horribly off, too, so null this out, too; if avaialble, + we will fiddle in the original RV below again. */ + output_null[5] = 1; } else { input.parallax = PG_GETARG_FLOAT8(1); } input.parallax_valid = fabs(input.parallax) > PX_MIN; - - if (PG_ARGISNULL(2)) { - input.pm[0] = 0; - } else { - input.pm[0] = PG_GETARG_FLOAT8(2); - } - if (PG_ARGISNULL(3)) { + if (PG_ARGISNULL(2) || PG_ARGISNULL(3)) { + input.pm[0] = 0; input.pm[1] = 0; + output_null[3] = 1; + output_null[4] = 1; } else { + input.pm[0] = PG_GETARG_FLOAT8(2); input.pm[1] = PG_GETARG_FLOAT8(3); } if (PG_ARGISNULL(4)) { input.rv = 0; + output_null[5] = 1; } else { input.rv = PG_GETARG_FLOAT8(4); } @@ -172,6 +177,15 @@ epoch_prop(PG_FUNCTION_ARGS) { propagate_phasevec(&input, delta_t, &output); + /* If we have an invalid parallax but a good RV, preserve the original, + untransformed RV on output. See + https://github.com/ivoa-std/udf-catalogue/pull/20#issuecomment-2115053757 + for the rationale. */ + if (!PG_ARGISNULL(4) && !input.parallax_valid) { + output_null[5] = 0; + output.rv = input.rv; + } + /* change to internal units: rad, rad/yr, mas, and km/s */ retvals[0] = Float8GetDatum(output.pos.lng); retvals[1] = Float8GetDatum(output.pos.lat); @@ -181,7 +195,6 @@ epoch_prop(PG_FUNCTION_ARGS) { retvals[5] = Float8GetDatum(output.rv); { - bool isnull[6] = {0, 0, 0, 0, 0, 0}; int lower_bounds[1] = {1}; int dims[1] = {6}; #ifdef USE_FLOAT8_BYVAL @@ -190,13 +203,7 @@ epoch_prop(PG_FUNCTION_ARGS) { bool embyval = false; #endif - if (! output.parallax_valid) { - /* invalidate parallax and rv */ - isnull[2] = 1; - isnull[5] = 1; - } - - result = construct_md_array(retvals, isnull, 1, dims, lower_bounds, + result = construct_md_array(retvals, output_null, 1, dims, lower_bounds, FLOAT8OID, sizeof(float8), embyval, 'd'); } PG_RETURN_ARRAYTYPE_P(result); diff --git a/src/epochprop.h b/src/epochprop.h index 9e1b87e..3b61a02 100644 --- a/src/epochprop.h +++ b/src/epochprop.h @@ -3,24 +3,15 @@ #include -Datum epoch_prop(PG_FUNCTION_ARGS); +extern Datum epoch_prop(PG_FUNCTION_ARGS); -/* a cartesian point; this is like geo_decl's point, but you can't -have both geo_decls and pg_sphere right now (both define a type Point, -not to mention they have different ideas on EPSILON */ -typedef struct s_cpoint { - double x, y; -} CPoint; - -typedef struct s_phasevec { - SPoint pos; /* Position as an SPoint */ - double pm[2]; /* Proper motion long/lat in rad/year, - PM in longitude has cos(lat) applied */ - double parallax; /* in rad */ - double rv; /* radial velocity in km/s */ - int parallax_valid; /* 1 if the parallax really is a NULL */ +typedef struct s_phasevec +{ + SPoint pos; /* Position as an SPoint */ + double pm[2]; /* Proper motion long/lat in rad/year, PM in + * longitude has cos(lat) applied */ + double parallax; /* in rad */ + double rv; /* radial velocity in km/s */ + int parallax_valid; /* 1 if we accept the parallax as physical */ } phasevec; - - - diff --git a/src/euler.c b/src/euler.c index a45f7b3..f9d4190 100644 --- a/src/euler.c +++ b/src/euler.c @@ -109,8 +109,8 @@ spheretrans_from_float8_and_type(PG_FUNCTION_ARGS) d[1] = PG_GETARG_DATUM(1); d[2] = PG_GETARG_DATUM(2); se = (SEuler *) DatumGetPointer( - DirectFunctionCall3(spheretrans_from_float8, - d[0], d[1], d[2])); + DirectFunctionCall3(spheretrans_from_float8, + d[0], d[1], d[2])); for (i = 0; i < 3; i++) { @@ -165,7 +165,8 @@ seuler_set_zxz(SEuler *se) bool strans_eq(const SEuler *e1, const SEuler *e2) { - SPoint in[2], p[4]; + SPoint in[2], + p[4]; in[0].lng = 0.0; in[0].lat = 0.0; @@ -210,6 +211,7 @@ Datum spheretrans_theta(PG_FUNCTION_ARGS) { SEuler *se = (SEuler *) PG_GETARG_POINTER(0); + PG_RETURN_FLOAT8(se->theta); } @@ -267,8 +269,8 @@ spheretrans_type(PG_FUNCTION_ARGS) void spheretrans_inv(SEuler *se) { - float8 lng[3]; - const unsigned char c = se->phi_a; + float8 lng[3]; + const unsigned char c = se->phi_a; lng[2] = -se->phi; lng[1] = -se->theta; @@ -298,7 +300,7 @@ strans_zxz(SEuler *ret, const SEuler *se) } else { - SEuler tmp; + SEuler tmp; tmp.psi = 0.0; tmp.theta = 0.0; @@ -339,7 +341,7 @@ spheretrans_invert(PG_FUNCTION_ARGS) void seuler_trans_zxz(SEuler *out, const SEuler *in, const SEuler *se) { - SPoint sp[4]; + SPoint sp[4]; sp[0].lng = 0.0; sp[0].lat = 0.0; @@ -380,7 +382,8 @@ spheretrans_trans_inv(PG_FUNCTION_ARGS) void euler_spoint_trans(SPoint *out, const SPoint *in, const SEuler *se) { - Vector3D v, o; + Vector3D v, + o; spoint_vector3d(&v, in); euler_vector_trans(&o, &v, se); @@ -425,7 +428,9 @@ spherevector_to_euler_inv(SEuler *se, const SPoint *spb, const SPoint *spe) } else { - Vector3D vbeg, vend, vtmp; + Vector3D vbeg, + vend, + vtmp; SPoint spt[2]; SEuler set; @@ -448,7 +453,7 @@ spherevector_to_euler_inv(SEuler *se, const SPoint *spb, const SPoint *spe) bool spherevector_to_euler(SEuler *se, const SPoint *spb, const SPoint *spe) { - bool ret; + bool ret; ret = spherevector_to_euler_inv(se, spb, spe); if (ret) @@ -461,10 +466,13 @@ spherevector_to_euler(SEuler *se, const SPoint *spb, const SPoint *spe) void euler_vector_trans(Vector3D *out, const Vector3D *in, const SEuler *se) { - int i; - unsigned char t; - const double *a; - double u[3], vr[3], sa, ca; + int i; + unsigned char t; + const double *a; + double u[3], + vr[3], + sa, + ca; t = 0; a = NULL; diff --git a/src/euler.h b/src/euler.h index 35e3a2c..6baca28 100644 --- a/src/euler.h +++ b/src/euler.h @@ -12,12 +12,12 @@ */ typedef struct { - unsigned char phi_a:2, /* first axis */ - theta_a:2, /* second axis */ - psi_a:2; /* third axis */ - float8 phi, /* first rotation angle */ - theta, /* second rotation angle */ - psi; /* third rotation angle */ + unsigned char phi_a:2, /* first axis */ + theta_a:2, /* second axis */ + psi_a:2; /* third axis */ + float8 phi, /* first rotation angle */ + theta, /* second rotation angle */ + psi; /* third rotation angle */ } SEuler; @@ -25,137 +25,137 @@ typedef struct * Transforms a spherical point and returns the pointer to a transformed spherical * point. */ -void euler_spoint_trans(SPoint *out, const SPoint *in, const SEuler *se); +extern void euler_spoint_trans(SPoint *out, const SPoint *in, const SEuler *se); /* * Transforms a spherical vector from 'spb' to 'spe' into an Euler transformation. * Returns true if the transformation was successful. */ -bool spherevector_to_euler(SEuler *se, const SPoint *spb, const SPoint *spe); +extern bool spherevector_to_euler(SEuler *se, const SPoint *spb, const SPoint *spe); /* * Sets the axes of transformation to ZXZ. */ -void seuler_set_zxz(SEuler *se); +extern void seuler_set_zxz(SEuler *se); /* * Checks equality of two transformations. */ -bool strans_eq(const SEuler *e1, const SEuler *e2); +extern bool strans_eq(const SEuler *e1, const SEuler *e2); /* * Transforms a vector using an Euler transformation. Returns the pointer to * the result vector. */ -void euler_vector_trans(Vector3D *out, const Vector3D *in, const SEuler *se); +extern void euler_vector_trans(Vector3D *out, const Vector3D *in, const SEuler *se); /* * Inverts an Euler transformation. Returns the pointer to the * inverted transformation. */ -void spheretrans_inverse(SEuler *se_out, const SEuler *se_in); +extern void spheretrans_inverse(SEuler *se_out, const SEuler *se_in); /* * Inverts an Euler transformation replacing the original Euler transformation. * Returns the pointer to the inverted transformation. */ -void spheretrans_inv(SEuler *se); +extern void spheretrans_inv(SEuler *se); /* * Converts an Euler transformation to a ZXZ-axis transformation. Returns * the pointer to the converted transformation. */ -void strans_zxz(SEuler *ret, const SEuler *se); +extern void strans_zxz(SEuler *ret, const SEuler *se); /* * Transforms an Euler transformation 'in' into 'out' using 'se'. The result * is always a ZXZ-axis transformation. Returns the pointer to the transformed * transformation. */ -void seuler_trans_zxz(SEuler *out, const SEuler *in, const SEuler *se); +extern void seuler_trans_zxz(SEuler *out, const SEuler *in, const SEuler *se); /* * Input of an Euler transformation. */ -Datum spheretrans_in(PG_FUNCTION_ARGS); +extern Datum spheretrans_in(PG_FUNCTION_ARGS); /* * Input of an Euler transformation with axis Z,X,Z from three angles * (phi, theta, psi) in radians. */ -Datum spheretrans_from_float8(PG_FUNCTION_ARGS); +extern Datum spheretrans_from_float8(PG_FUNCTION_ARGS); /* * Returns the first angle of an Euler transformation in radians. */ -Datum spheretrans_phi(PG_FUNCTION_ARGS); +extern Datum spheretrans_phi(PG_FUNCTION_ARGS); /* * Returns the second angle of an Euler transformation in radians. */ -Datum spheretrans_theta(PG_FUNCTION_ARGS); +extern Datum spheretrans_theta(PG_FUNCTION_ARGS); /* * Returns the third angle of an Euler transformation in radians. */ -Datum spheretrans_psi(PG_FUNCTION_ARGS); +extern Datum spheretrans_psi(PG_FUNCTION_ARGS); /* * Returns the axis of an Euler transformation as three letter code. */ -Datum spheretrans_type(PG_FUNCTION_ARGS); +extern Datum spheretrans_type(PG_FUNCTION_ARGS); /* * Returns the Euler transformation (does nothing). This function is needed * for +strans operator. */ -Datum spheretrans(PG_FUNCTION_ARGS); +extern Datum spheretrans(PG_FUNCTION_ARGS); /* * Returns the inverse Euler transformation. */ -Datum spheretrans_invert(PG_FUNCTION_ARGS); +extern Datum spheretrans_invert(PG_FUNCTION_ARGS); /* * Convert an Euler transformation to a ZXZ-axis transformation. */ -Datum spheretrans_zxz(PG_FUNCTION_ARGS); +extern Datum spheretrans_zxz(PG_FUNCTION_ARGS); /* * This function creates an Euler transformation from 3 angle values in * radians and three letter code used for axes. A letter can be X, Y or Z * (case-insensitive). */ -Datum spheretrans_from_float8_and_type(PG_FUNCTION_ARGS); +extern Datum spheretrans_from_float8_and_type(PG_FUNCTION_ARGS); /* * Checks equality of two Euler transformations. */ -Datum spheretrans_equal(PG_FUNCTION_ARGS); +extern Datum spheretrans_equal(PG_FUNCTION_ARGS); /* * Checks inequality of two Euler transformations. */ -Datum spheretrans_not_equal(PG_FUNCTION_ARGS); +extern Datum spheretrans_not_equal(PG_FUNCTION_ARGS); /* * Transforms an Euler transformation. */ -Datum spheretrans_trans(PG_FUNCTION_ARGS); +extern Datum spheretrans_trans(PG_FUNCTION_ARGS); /* * Transforms inverse an Euler transformations. */ -Datum spheretrans_trans_inv(PG_FUNCTION_ARGS); +extern Datum spheretrans_trans_inv(PG_FUNCTION_ARGS); /* * Transforms a spherical point. */ -Datum spheretrans_point(PG_FUNCTION_ARGS); +extern Datum spheretrans_point(PG_FUNCTION_ARGS); /* * Perform inverse transformation of a spherical point. */ -Datum spheretrans_point_inverse(PG_FUNCTION_ARGS); +extern Datum spheretrans_point_inverse(PG_FUNCTION_ARGS); #endif diff --git a/src/gist.c b/src/gist.c index b3223a5..0fef2ac 100644 --- a/src/gist.c +++ b/src/gist.c @@ -36,6 +36,7 @@ PG_FUNCTION_INFO_V1(g_spherekey_penalty); PG_FUNCTION_INFO_V1(g_spherekey_picksplit); PG_FUNCTION_INFO_V1(g_spoint3_penalty); PG_FUNCTION_INFO_V1(g_spoint3_picksplit); +PG_FUNCTION_INFO_V1(g_spoint_distance); PG_FUNCTION_INFO_V1(g_spoint3_distance); PG_FUNCTION_INFO_V1(g_spoint3_fetch); @@ -510,7 +511,7 @@ g_spoint_consistent(PG_FUNCTION_ARGS) SCK_INTERLEAVE(SELLIPSE, sphereellipse_gen_key, 0); break; case 42: - SCK_INTERLEAVE(SBOX, spherebox_gen_key , 0); + SCK_INTERLEAVE(SBOX, spherebox_gen_key, 0); break; } @@ -681,6 +682,13 @@ g_spoint3_consistent(PG_FUNCTION_ARGS) PG_RETURN_BOOL(false); } +static double +distance_vector_point_3d(Vector3D *v, double x, double y, double z) +{ + /* as v has length = 1 by design */ + return acos((v->x * x + v->y * y + v->z * z) / sqrt(x * x + y * y + z * z)); +} + Datum g_spoint3_distance(PG_FUNCTION_ARGS) { @@ -1672,6 +1680,224 @@ fallbackSplit(Box3D *boxes, OffsetNumber maxoff, GIST_SPLITVEC *v) v->spl_ldatum_exists = v->spl_rdatum_exists = false; } + +Datum +g_spoint_distance(PG_FUNCTION_ARGS) +{ + GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0); + StrategyNumber strategy = (StrategyNumber) PG_GETARG_UINT16(2); + Box3D *box = (Box3D *) DatumGetPointer(entry->key); + double retval; + SPoint *point = (SPoint *) PG_GETARG_POINTER(1); + Vector3D v_point, + v_low, + v_high; + + switch (strategy) + { + case 17: + /* Prepare data for calculation */ + spoint_vector3d(&v_point, point); + v_low.x = (double) box->low.coord[0] / MAXCVALUE; + v_low.y = (double) box->low.coord[1] / MAXCVALUE; + v_low.z = (double) box->low.coord[2] / MAXCVALUE; + v_high.x = (double) box->high.coord[0] / MAXCVALUE; + v_high.y = (double) box->high.coord[1] / MAXCVALUE; + v_high.z = (double) box->high.coord[2] / MAXCVALUE; + + /* + * a box splits space into 27 subspaces (6+12+8+1) with different + * distance calculation + */ + if (v_point.x < v_low.x) + { + if (v_point.y < v_low.y) + { + if (v_point.z < v_low.z) + { + /* point2point distance */ + retval = distance_vector_point_3d(&v_point, v_low.x, v_low.y, v_low.z); + } + else if (v_point.z < v_high.z) + { + /* point2line distance */ + retval = distance_vector_point_3d(&v_point, v_low.x, v_low.y, v_point.z); + } + else + { + /* point2point distance */ + retval = distance_vector_point_3d(&v_point, v_low.x, v_low.y, v_high.z); + } + } + else if (v_point.y < v_high.y) + { + if (v_point.z < v_low.z) + { + /* point2line distance */ + retval = distance_vector_point_3d(&v_point, v_low.x, v_point.y, v_low.z); + } + else if (v_point.z < v_high.z) + { + /* point2plane distance */ + retval = distance_vector_point_3d(&v_point, v_low.x, v_point.y, v_point.z); + } + else + { + /* point2line distance */ + retval = distance_vector_point_3d(&v_point, v_low.x, v_point.y, v_high.z); + } + } + else + { + if (v_point.z < v_low.z) + { + /* point2point distance */ + retval = distance_vector_point_3d(&v_point, v_low.x, v_high.y, v_low.z); + } + else if (v_point.z < v_high.z) + { + /* point2line distance */ + retval = distance_vector_point_3d(&v_point, v_low.x, v_high.y, v_point.z); + } + else + { + /* point2point distance */ + retval = distance_vector_point_3d(&v_point, v_low.x, v_high.y, v_high.z); + } + } + } + else if (v_point.x < v_high.x) + { + if (v_point.y < v_low.y) + { + if (v_point.z < v_low.z) + { + /* p2line distance */ + retval = distance_vector_point_3d(&v_point, v_point.x, v_low.y, v_low.z); + } + else if (v_point.z < v_high.z) + { + /* point2plane distance */ + retval = distance_vector_point_3d(&v_point, v_point.x, v_low.y, v_point.z); + } + else + { + /* point2line distance */ + retval = distance_vector_point_3d(&v_point, v_point.x, v_low.y, v_high.z); + } + } + else if (v_point.y < v_high.y) + { + if (v_point.z < v_low.z) + { + /* point2plane distance */ + retval = distance_vector_point_3d(&v_point, v_point.x, v_point.y, v_low.z); + } + else if (v_point.z < v_high.z) + { + /* inside cube */ + retval = 0; + } + else + { + /* point2plane distance */ + retval = distance_vector_point_3d(&v_point, v_point.x, v_point.y, v_high.z); + } + } + else + { + if (v_point.z < v_low.z) + { + /* point2line distance */ + retval = distance_vector_point_3d(&v_point, v_point.x, v_high.y, v_low.z); + } + else if (v_point.z < v_high.z) + { + /* point2plane distance */ + retval = distance_vector_point_3d(&v_point, v_point.x, v_high.y, v_point.z); + } + else + { + /* point2line distance */ + retval = distance_vector_point_3d(&v_point, v_point.x, v_high.y, v_high.z); + } + } + } + else + { + if (v_point.y < v_low.y) + { + if (v_point.z < v_low.z) + { + /* p2p distance */ + retval = distance_vector_point_3d(&v_point, v_high.x, v_low.y, v_low.z); + } + else if (v_point.z < v_high.z) + { + /* point2line distance */ + retval = distance_vector_point_3d(&v_point, v_high.x, v_low.y, v_point.z); + } + else + { + /* point2point distance */ + retval = distance_vector_point_3d(&v_point, v_high.x, v_low.y, v_high.z); + } + } + else if (v_point.y < v_high.y) + { + if (v_point.z < v_low.z) + { + /* point2line distance */ + retval = distance_vector_point_3d(&v_point, v_high.x, v_point.y, v_low.z); + } + else if (v_point.z < v_high.z) + { + /* point2plane distance */ + retval = distance_vector_point_3d(&v_point, v_high.x, v_point.y, v_point.z); + } + else + { + /* point2line distance */ + retval = distance_vector_point_3d(&v_point, v_high.x, v_point.y, v_high.z); + } + } + else + { + if (v_point.z < v_low.z) + { + /* point2point distance */ + retval = distance_vector_point_3d(&v_point, v_high.x, v_high.y, v_low.z); + } + else if (v_point.z < v_high.z) + { + /* point2line distance */ + retval = distance_vector_point_3d(&v_point, v_high.x, v_high.y, v_point.z); + } + else + { + /* point2point distance */ + retval = distance_vector_point_3d(&v_point, v_high.x, v_high.y, v_high.z); + } + } + } + + elog(DEBUG1, "distance (%lg,%lg,%lg %lg,%lg,%lg) <-> (%lg,%lg) = %lg", + v_low.x, v_low.y, v_low.z, + v_high.x, v_high.y, v_high.z, + point->lng, point->lat, + retval + ); + break; + + default: + elog(ERROR, "unrecognized cube strategy number: %d", strategy); + retval = 0; /* keep compiler quiet */ + break; + } + + PG_RETURN_FLOAT8(retval); +} + /* * Represents information about an entry that can be placed to either group * without affecting overlap over selected axis ("common entry"). @@ -2203,7 +2429,7 @@ do_picksplit(Box3D *boxes, OffsetNumber maxoff, GIST_SPLITVEC *v) { box = &boxes[i]; commonEntries[i].delta = fabs((unionSizeBox3D(leftBox, box) - leftBoxSize) - - (unionSizeBox3D(rightBox, box) - rightBoxSize)); + (unionSizeBox3D(rightBox, box) - rightBoxSize)); } /* diff --git a/src/gist.h b/src/gist.h index 6dac2a4..58e32f1 100644 --- a/src/gist.h +++ b/src/gist.h @@ -11,150 +11,150 @@ typedef unsigned char uchar; /* PGS_KEY_REL Key relationships */ -#define SCKEY_DISJ 0 /* two keys are disjunct */ -#define SCKEY_OVERLAP 1 /* two keys are overlapping */ -#define SCKEY_IN 2 /* first key contains second key */ -#define SCKEY_SAME 3 /* keys are equal */ +#define SCKEY_DISJ 0 /* two keys are disjunct */ +#define SCKEY_OVERLAP 1 /* two keys are overlapping */ +#define SCKEY_IN 2 /* first key contains second key */ +#define SCKEY_SAME 3 /* keys are equal */ -uchar spherekey_interleave(const int32 *k1, const int32 *k2); +extern uchar spherekey_interleave(const int32 *k1, const int32 *k2); /* * For given "query" of "pgstype" of PGS_DATA_TYPES type, puts key of cached * query into "key" pointer. Returns true when given query is equal to * current query. */ -bool gq_cache_get_value(unsigned pgstype, const void *query, int32 **key); +extern bool gq_cache_get_value(unsigned pgstype, const void *query, int32 **key); /* * Copy current query, type and its key value to cache. */ -void gq_cache_set_value(unsigned pgstype, const void *query, const int32 *key); +extern void gq_cache_set_value(unsigned pgstype, const void *query, const int32 *key); /* * Input function of key value. Just a dummy. But PostgreSQL need this * function to create a data type. */ -Datum spherekey_in(PG_FUNCTION_ARGS); +extern Datum spherekey_in(PG_FUNCTION_ARGS); /* * Output function of key value. Just a dummy. But PostgreSQL need this * function to create a data type. */ -Datum spherekey_out(PG_FUNCTION_ARGS); +extern Datum spherekey_out(PG_FUNCTION_ARGS); /* * GIST's decompress method. This function does nothing. */ -Datum g_spherekey_decompress(PG_FUNCTION_ARGS); +extern Datum g_spherekey_decompress(PG_FUNCTION_ARGS); /* * GIST's compress method for circle. Creates the key value from a spherical * circle. */ -Datum g_scircle_compress(PG_FUNCTION_ARGS); +extern Datum g_scircle_compress(PG_FUNCTION_ARGS); /* * GIST's compress method for point. Creates the key value from a spherical point. */ -Datum g_spoint_compress(PG_FUNCTION_ARGS); +extern Datum g_spoint_compress(PG_FUNCTION_ARGS); /* * GIST's compress method for line. Creates the key value from a spherical line. */ -Datum g_sline_compress(PG_FUNCTION_ARGS); +extern Datum g_sline_compress(PG_FUNCTION_ARGS); /* * GIST's compress method for path. Creates the key value from a spherical path. */ -Datum g_spath_compress(PG_FUNCTION_ARGS); +extern Datum g_spath_compress(PG_FUNCTION_ARGS); /* * GIST's compress method for polygon. Creates the key value from a spherical * polygon. */ -Datum g_spoly_compress(PG_FUNCTION_ARGS); +extern Datum g_spoly_compress(PG_FUNCTION_ARGS); /* * GIST's compress method for ellipse. Creates the key value from a spherical * ellipse. */ -Datum g_sellipse_compress(PG_FUNCTION_ARGS); +extern Datum g_sellipse_compress(PG_FUNCTION_ARGS); /* * GIST's compress method for box. Creates the key value from a spherical box. */ -Datum g_sbox_compress(PG_FUNCTION_ARGS); +extern Datum g_sbox_compress(PG_FUNCTION_ARGS); /* * The GiST Union method for boxes. Returns the minimal bounding box that * encloses all the entries in entryvec. */ -Datum g_spherekey_union(PG_FUNCTION_ARGS); +extern Datum g_spherekey_union(PG_FUNCTION_ARGS); /* * GIST's equality method. */ -Datum g_spherekey_same(PG_FUNCTION_ARGS); +extern Datum g_spherekey_same(PG_FUNCTION_ARGS); /* * GIST's consistent method for a point. */ -Datum g_spoint_consistent(PG_FUNCTION_ARGS); +extern Datum g_spoint_consistent(PG_FUNCTION_ARGS); /* * GIST's consistent method for a circle. */ -Datum g_scircle_consistent(PG_FUNCTION_ARGS); +extern Datum g_scircle_consistent(PG_FUNCTION_ARGS); /* * GIST's consistent method for a line. */ -Datum g_sline_consistent(PG_FUNCTION_ARGS); +extern Datum g_sline_consistent(PG_FUNCTION_ARGS); /* * GIST's consistent method for a path. */ -Datum g_spath_consistent(PG_FUNCTION_ARGS); +extern Datum g_spath_consistent(PG_FUNCTION_ARGS); /* * GIST's consistent method for a polygon. */ -Datum g_spoly_consistent(PG_FUNCTION_ARGS); +extern Datum g_spoly_consistent(PG_FUNCTION_ARGS); /* * GIST's consistent method for an ellipse. */ -Datum g_sellipse_consistent(PG_FUNCTION_ARGS); +extern Datum g_sellipse_consistent(PG_FUNCTION_ARGS); /* * GIST's consistent method for a box. */ -Datum g_sbox_consistent(PG_FUNCTION_ARGS); +extern Datum g_sbox_consistent(PG_FUNCTION_ARGS); /* * GIST's penalty method. */ -Datum g_spherekey_penalty(PG_FUNCTION_ARGS); +extern Datum g_spherekey_penalty(PG_FUNCTION_ARGS); /* * GIST's picksplit method. This method is using the double sorting node * splitting algorithm for R-Trees. See "A new double sorting-based node * splitting algorithm for R-tree", A. Korotkov. */ -Datum g_spherekey_picksplit(PG_FUNCTION_ARGS); - -Datum pointkey_in(PG_FUNCTION_ARGS); -Datum pointkey_out(PG_FUNCTION_ARGS); -Datum pointkey_volume(PG_FUNCTION_ARGS); -Datum pointkey_area(PG_FUNCTION_ARGS); -Datum pointkey_perimeter(PG_FUNCTION_ARGS); -Datum g_spoint3_compress(PG_FUNCTION_ARGS); -Datum g_spoint3_union(PG_FUNCTION_ARGS); -Datum g_spoint3_same(PG_FUNCTION_ARGS); -Datum g_spoint3_consistent(PG_FUNCTION_ARGS); -Datum g_spoint3_penalty(PG_FUNCTION_ARGS); -Datum g_spoint3_picksplit(PG_FUNCTION_ARGS); -Datum g_spoint3_distance(PG_FUNCTION_ARGS); -Datum g_spoint3_fetch(PG_FUNCTION_ARGS); +extern Datum g_spherekey_picksplit(PG_FUNCTION_ARGS); + +extern Datum pointkey_in(PG_FUNCTION_ARGS); +extern Datum pointkey_out(PG_FUNCTION_ARGS); +extern Datum pointkey_volume(PG_FUNCTION_ARGS); +extern Datum pointkey_area(PG_FUNCTION_ARGS); +extern Datum pointkey_perimeter(PG_FUNCTION_ARGS); +extern Datum g_spoint3_compress(PG_FUNCTION_ARGS); +extern Datum g_spoint3_union(PG_FUNCTION_ARGS); +extern Datum g_spoint3_same(PG_FUNCTION_ARGS); +extern Datum g_spoint3_consistent(PG_FUNCTION_ARGS); +extern Datum g_spoint3_penalty(PG_FUNCTION_ARGS); +extern Datum g_spoint3_picksplit(PG_FUNCTION_ARGS); +extern Datum g_spoint3_distance(PG_FUNCTION_ARGS); +extern Datum g_spoint3_fetch(PG_FUNCTION_ARGS); #endif diff --git a/src/gnomo.h b/src/gnomo.h index bae1d11..c7a2777 100644 --- a/src/gnomo.h +++ b/src/gnomo.h @@ -3,7 +3,7 @@ /* function prototypes for the direct and inverse gnomonic projections */ -Datum gnomonic_proj(PG_FUNCTION_ARGS); -Datum gnomonic_inv(PG_FUNCTION_ARGS); +extern Datum gnomonic_proj(PG_FUNCTION_ARGS); +extern Datum gnomonic_inv(PG_FUNCTION_ARGS); #endif diff --git a/src/key.h b/src/key.h index aa77ca9..e4c39dc 100644 --- a/src/key.h +++ b/src/key.h @@ -20,30 +20,32 @@ typedef struct { - char vl_len_[4]; + char vl_len_[4]; union { - struct /* the compiler will probably insert 4 bytes of padding here */ + struct /* the compiler will probably insert 4 bytes + * of padding here */ { - float8 lat, - lng; + float8 lat, + lng; }; }; -} GiSTSPointKey_Leaf; +} GiSTSPointKey_Leaf; typedef struct { - char vl_len_[4]; + char vl_len_[4]; union { - struct /* the compiler will probably insert 4 bytes of padding here */ + struct /* the compiler will probably insert 4 bytes + * of padding here */ { - float8 lat, - lng; + float8 lat, + lng; }; struct { - int32 k[6]; + int32 k[6]; }; }; } GiSTSPointKey; @@ -51,10 +53,12 @@ typedef struct #define INTERNAL_KEY_SIZE sizeof(GiSTSPointKey) #define LEAF_KEY_SIZE sizeof(GiSTSPointKey_Leaf) #define IS_LEAF(key) (VARSIZE(key) == LEAF_KEY_SIZE) + #define ALLOC_LEAF_KEY(key) do { \ key = (GiSTSPointKey *)palloc0(LEAF_KEY_SIZE); \ SET_VARSIZE(key, LEAF_KEY_SIZE); \ } while (0) ; + #define ALLOC_INTERNAL_KEY(key) do { \ key = (GiSTSPointKey *)palloc0(INTERNAL_KEY_SIZE); \ SET_VARSIZE(key, INTERNAL_KEY_SIZE); \ @@ -63,128 +67,128 @@ typedef struct /* * Returns the union of two keys. Result is placed into 'kunion'. */ -void spherekey_union_two(int32 *kunion, const int32 *key); +extern void spherekey_union_two(int32 *kunion, const int32 *key); /* * Returns the intersection of two keys. Returns NULL if there is * no intersection. Result is placed into 'kinter'. */ -bool spherekey_inter_two(int32 *kinter, const int32 *key); +extern bool spherekey_inter_two(int32 *kinter, const int32 *key); /* * Generates the key of a spherical point and returns it. Result is placed * into 'k'. */ -void spherepoint_gen_key(int32 *k, const SPoint *sp); +extern void spherepoint_gen_key(int32 *k, const SPoint *sp); /* * Generates the circle's key and returns it. Result is placed into 'k'. */ -void spherecircle_gen_key(int32 *k, const SCIRCLE *c); +extern void spherecircle_gen_key(int32 *k, const SCIRCLE *c); /* * Generates the key of a spherical ellipse and returns it. Result is placed * into 'k'. */ -void sphereellipse_gen_key(int32 *k, const SELLIPSE *e); +extern void sphereellipse_gen_key(int32 *k, const SELLIPSE *e); /* * Generates the key of a spherical line and returns it. Result is placed * into 'k'. */ -void sphereline_gen_key(int32 *k, const SLine *sl); +extern void sphereline_gen_key(int32 *k, const SLine *sl); /* * Generates the key of a polygon and returns it. Result is placed into 'k'. */ -void spherepoly_gen_key(int32 *k, const SPOLY *sp); +extern void spherepoly_gen_key(int32 *k, const SPOLY *sp); /* * Generates the key of a path and returns it. Result is placed into 'k'. */ -void spherepath_gen_key(int32 *k, const SPATH *sp); +extern void spherepath_gen_key(int32 *k, const SPATH *sp); /* * Generates the key of a box and returns it. Result is placed into 'k'. */ -void spherebox_gen_key(int32 *key, const SBOX *box); +extern void spherebox_gen_key(int32 *key, const SBOX *box); /* * Returns true if the first key is less than the second key. */ -Datum spherekey_lt(PG_FUNCTION_ARGS); +extern Datum spherekey_lt(PG_FUNCTION_ARGS); /* * Returns true if the first key is less or equal than the second key. */ -Datum spherekey_le(PG_FUNCTION_ARGS); +extern Datum spherekey_le(PG_FUNCTION_ARGS); /* * Returns true if two keys are equal. */ -Datum spherekey_eq(PG_FUNCTION_ARGS); +extern Datum spherekey_eq(PG_FUNCTION_ARGS); /* * Returns true if two keys are not equal. */ -Datum spherekey_eq_neg(PG_FUNCTION_ARGS); +extern Datum spherekey_eq_neg(PG_FUNCTION_ARGS); /* * Returns true if the first key is greater or equal than the second key. */ -Datum spherekey_ge(PG_FUNCTION_ARGS); +extern Datum spherekey_ge(PG_FUNCTION_ARGS); /* * Returns true if the first key is greater than the second key. */ -Datum spherekey_gt(PG_FUNCTION_ARGS); +extern Datum spherekey_gt(PG_FUNCTION_ARGS); /* * Returns relationship between the two keys. * Calls skey_cmp(const int32 *, const int32 *) for two keys. */ -Datum spherekey_cmp(PG_FUNCTION_ARGS); +extern Datum spherekey_cmp(PG_FUNCTION_ARGS); /* * Returns relationship between the keys of two spherical points. * Calls skey_cmp(const int32 *, const int32 *) for two points. */ -Datum spherepoint_cmp(PG_FUNCTION_ARGS); +extern Datum spherepoint_cmp(PG_FUNCTION_ARGS); /* * Returns relationship between the keys of two spherical circles. * Calls skey_cmp(const int32 *, const int32 *) for two circles. */ -Datum spherecircle_cmp(PG_FUNCTION_ARGS); +extern Datum spherecircle_cmp(PG_FUNCTION_ARGS); /* * Returns relationship between the keys of two spherical ellipses. * Calls skey_cmp(const int32 *, const int32 *) for two ellipses. */ -Datum sphereellipse_cmp(PG_FUNCTION_ARGS); +extern Datum sphereellipse_cmp(PG_FUNCTION_ARGS); /* * Returns relationship between the keys of two spherical lines. * Calls skey_cmp(const int32 *, const int32 *) for two lines. */ -Datum sphereline_cmp(PG_FUNCTION_ARGS); +extern Datum sphereline_cmp(PG_FUNCTION_ARGS); /* * Returns relationship between the keys of two spherical paths. * Calls skey_cmp(const int32 *, const int32 *) for two paths. */ -Datum spherepath_cmp(PG_FUNCTION_ARGS); +extern Datum spherepath_cmp(PG_FUNCTION_ARGS); /* * Returns relationship between the keys of two spherical polygons. * Calls skey_cmp(const int32 *, const int32 *) for two polygons. */ -Datum spherepoly_cmp(PG_FUNCTION_ARGS); +extern Datum spherepoly_cmp(PG_FUNCTION_ARGS); /* * Returns relationship between the keys of two spherical boxes. * Calls skey_cmp(const int32 *, const int32 *) for two boxes. */ -Datum spherebox_cmp(PG_FUNCTION_ARGS); +extern Datum spherebox_cmp(PG_FUNCTION_ARGS); #endif diff --git a/src/line.h b/src/line.h index 002f371..deaa028 100644 --- a/src/line.h +++ b/src/line.h @@ -10,10 +10,10 @@ */ typedef struct { - float8 phi, /* the first rotation angle around z axis */ - theta, /* the second rotation angle around x axis */ - psi; /* the last rotation angle around z axis */ - float8 length; /* the length of the line */ + float8 phi, /* the first rotation angle around z axis */ + theta, /* the second rotation angle around x axis */ + psi; /* the last rotation angle around z axis */ + float8 length; /* the length of the line */ } SLine; /* PGS_RELATIONSHIPS Object relationships */ @@ -37,47 +37,47 @@ typedef struct * * Returns false if the distance between the 'pbeg' and the 'pend' is 180deg. */ -bool sline_from_points(SLine *sl, const SPoint *pbeg, const SPoint *pend); +extern bool sline_from_points(SLine *sl, const SPoint *pbeg, const SPoint *pend); /* * Returns a meridian line of a given longitude in radians. The result is placed * into 'sl'. */ -void sline_meridian(SLine *sl, float8 lng); +extern void sline_meridian(SLine *sl, float8 lng); /* * Returns the starting point of a line 'l'. Result is placed into 'p'. */ -void sline_begin(SPoint *p, const SLine *l); +extern void sline_begin(SPoint *p, const SLine *l); /* * Returns the ending point of a line 'l'. Result is placed into 'p'. */ -void sline_end(SPoint *p, const SLine *l); +extern void sline_end(SPoint *p, const SLine *l); /* * Puts the minimum and the maximum latitudes of a spherical line 's1' into 'minlat' * and 'maxlat'. */ -void sline_min_max_lat(const SLine *sl, float8 *minlat, float8 *maxlat); +extern void sline_min_max_lat(const SLine *sl, float8 *minlat, float8 *maxlat); /* * Calculates spherical points with a latitude 'lat' on a spherical line. * * Returns the number of found points or <0 if undefined. */ -int32 sphereline_latitude_points(const SLine *sl, float8 lat, SPoint *p1, SPoint *p2); +extern int32 sphereline_latitude_points(const SLine *sl, float8 lat, SPoint *p1, SPoint *p2); /* * Returns true if two lines are equal. */ -bool sline_eq(const SLine *l1, const SLine *l2); +extern bool sline_eq(const SLine *l1, const SLine *l2); /* * Returns the relationship between a line and a circle as PGS_CIRCLE_LINE_REL * int8 value. */ -int8 sphereline_circle_pos(const SLine *sl, const SCIRCLE *sc); +extern int8 sphereline_circle_pos(const SLine *sl, const SCIRCLE *sc); /* * Assuming that a line and a circle overlap, this function returns true @@ -87,31 +87,31 @@ int8 sphereline_circle_pos(const SLine *sl, const SCIRCLE *sc); * * See sphereline_circle_pos (const SLine *, const SCIRCLE *) */ -bool sline_circle_touch(const SLine *sl, const SCIRCLE *sc); +extern bool sline_circle_touch(const SLine *sl, const SCIRCLE *sc); /* * Returns the relationship between two lines as PGS_LINE_LINE_REL int8 value. */ -int8 sline_sline_pos(const SLine *l1, const SLine *l2); +extern int8 sline_sline_pos(const SLine *l1, const SLine *l2); /* * Checks whether a point is on a line. */ -bool spoint_at_sline(const SPoint *p, const SLine *sl); +extern bool spoint_at_sline(const SPoint *p, const SLine *sl); /* * Returns the Euler transformation of a line. * * See spheretrans_from_line(PG_FUNCTION_ARGS) */ -void sphereline_to_euler(SEuler *se, const SLine *sl); +extern void sphereline_to_euler(SEuler *se, const SLine *sl); /* * Returns the inverse Euler transformation of a line. * * See spheretrans_from_line(PG_FUNCTION_ARGS) */ -void sphereline_to_euler_inv(SEuler *se, const SLine *sl); +extern void sphereline_to_euler_inv(SEuler *se, const SLine *sl); /* * Transforms a line using an Euler transformation. @@ -122,187 +122,187 @@ void sphereline_to_euler_inv(SEuler *se, const SLine *sl); * * See spheretrans_line (PG_FUNCTION_ARGS) */ -void euler_sline_trans(SLine *out, const SLine *in, const SEuler *se); +extern void euler_sline_trans(SLine *out, const SLine *in, const SEuler *se); /* * Puts the center of a line 'sl' into point 'c'. */ -void sline_center(SPoint *c, const SLine *sl); +extern void sline_center(SPoint *c, const SLine *sl); /* * Calculates the distance between a line 'sl' and a point 'p' */ -float8 sline_point_dist(const SLine *sl, const SPoint *p); +float8 sline_point_dist(const SLine *sl, const SPoint *p); /* * The input function for spherical line. */ -Datum sphereline_in(PG_FUNCTION_ARGS); +extern Datum sphereline_in(PG_FUNCTION_ARGS); /* * Create a line from a spherical point. */ -Datum sphereline_from_point(PG_FUNCTION_ARGS); +extern Datum sphereline_from_point(PG_FUNCTION_ARGS); /* * This function creates a spherical line using a starting point * and an ending point. The distance between the points must not be * equal to 180deg. */ -Datum sphereline_from_points(PG_FUNCTION_ARGS); +extern Datum sphereline_from_points(PG_FUNCTION_ARGS); /* * This function creates a spherical line using a given Euler transformation * and the length of a line. If the length is less than zero, an error occurs. * If the length is larger than 360deg, it is set to 360deg. */ -Datum sphereline_from_trans(PG_FUNCTION_ARGS); +extern Datum sphereline_from_trans(PG_FUNCTION_ARGS); /* * This function creates a meridian running from south to north. * The float8 param provides the longitude in radians. */ -Datum sphereline_meridian(PG_FUNCTION_ARGS); +extern Datum sphereline_meridian(PG_FUNCTION_ARGS); /* * Swaps the starting point and the ending point of a line. */ -Datum sphereline_swap_beg_end(PG_FUNCTION_ARGS); +extern Datum sphereline_swap_beg_end(PG_FUNCTION_ARGS); /* * Turns the line while preserving the starting & ending points. */ -Datum sphereline_turn(PG_FUNCTION_ARGS); +extern Datum sphereline_turn(PG_FUNCTION_ARGS); /* * Returns the beginning of a line. */ -Datum sphereline_begin(PG_FUNCTION_ARGS); +extern Datum sphereline_begin(PG_FUNCTION_ARGS); /* * Returns the ending of a line. */ -Datum sphereline_end(PG_FUNCTION_ARGS); +extern Datum sphereline_end(PG_FUNCTION_ARGS); /* * Returns the length of a line in radians. */ -Datum sphereline_length(PG_FUNCTION_ARGS); +extern Datum sphereline_length(PG_FUNCTION_ARGS); /* * Checks whether a line contains a point. */ -Datum sphereline_cont_point(PG_FUNCTION_ARGS); +extern Datum sphereline_cont_point(PG_FUNCTION_ARGS); /* * Checks whether a line doesn't contain a point. */ -Datum sphereline_cont_point_neg(PG_FUNCTION_ARGS); +extern Datum sphereline_cont_point_neg(PG_FUNCTION_ARGS); /* * Checks whether a line contains a point. */ -Datum sphereline_cont_point_com(PG_FUNCTION_ARGS); +extern Datum sphereline_cont_point_com(PG_FUNCTION_ARGS); /* * Checks whether a line doesn't contain a point. */ -Datum sphereline_cont_point_com_neg(PG_FUNCTION_ARGS); +extern Datum sphereline_cont_point_com_neg(PG_FUNCTION_ARGS); /* * Checks whether a circle contains a line. */ -Datum spherecircle_cont_line(PG_FUNCTION_ARGS); +extern Datum spherecircle_cont_line(PG_FUNCTION_ARGS); /* * Checks whether a circle doesn't contain a line. */ -Datum spherecircle_cont_line_neg(PG_FUNCTION_ARGS); +extern Datum spherecircle_cont_line_neg(PG_FUNCTION_ARGS); /* * Checks whether a circle contains a line. */ -Datum spherecircle_cont_line_com(PG_FUNCTION_ARGS); +extern Datum spherecircle_cont_line_com(PG_FUNCTION_ARGS); /* * Checks whether a circle doesn't contain a line. */ -Datum spherecircle_cont_line_com_neg(PG_FUNCTION_ARGS); +extern Datum spherecircle_cont_line_com_neg(PG_FUNCTION_ARGS); /* * Checks whether a circle and a line overlap. */ -Datum sphereline_overlap_circle(PG_FUNCTION_ARGS); +extern Datum sphereline_overlap_circle(PG_FUNCTION_ARGS); /* * Checks whether circle and a line don't overlap. */ -Datum sphereline_overlap_circle_neg(PG_FUNCTION_ARGS); +extern Datum sphereline_overlap_circle_neg(PG_FUNCTION_ARGS); /* * Checks whether a circle and a line overlap. */ -Datum sphereline_overlap_circle_com(PG_FUNCTION_ARGS); +extern Datum sphereline_overlap_circle_com(PG_FUNCTION_ARGS); /* * Checks whether circle and a line don't overlap. */ -Datum sphereline_overlap_circle_com_neg(PG_FUNCTION_ARGS); +extern Datum sphereline_overlap_circle_com_neg(PG_FUNCTION_ARGS); /* * Checks whether two lines are equal. */ -Datum sphereline_equal(PG_FUNCTION_ARGS); +extern Datum sphereline_equal(PG_FUNCTION_ARGS); /* * Checks whether two lines are not equal. */ -Datum sphereline_equal_neg(PG_FUNCTION_ARGS); +extern Datum sphereline_equal_neg(PG_FUNCTION_ARGS); /* * Checks whether two lines cross each other. */ -Datum sphereline_crosses(PG_FUNCTION_ARGS); +extern Datum sphereline_crosses(PG_FUNCTION_ARGS); /* * Checks whether two lines don't cross each other. */ -Datum sphereline_crosses_neg(PG_FUNCTION_ARGS); +extern Datum sphereline_crosses_neg(PG_FUNCTION_ARGS); /* * Checks whether two lines overlap. */ -Datum sphereline_overlap(PG_FUNCTION_ARGS); +extern Datum sphereline_overlap(PG_FUNCTION_ARGS); /* * Checks whether two lines are overlap. */ -Datum sphereline_overlap_neg(PG_FUNCTION_ARGS); +extern Datum sphereline_overlap_neg(PG_FUNCTION_ARGS); /* * Returns an Euler transformation. An inverse transformation with it puts * the line into equator beginning at (0,0) and ending at (0,length). */ -Datum spheretrans_from_line(PG_FUNCTION_ARGS); +extern Datum spheretrans_from_line(PG_FUNCTION_ARGS); /* * Transforms a line with an Euler transformation. */ -Datum spheretrans_line(PG_FUNCTION_ARGS); +extern Datum spheretrans_line(PG_FUNCTION_ARGS); /* * Transforms a line with an inverse Euler transformation. */ -Datum spheretrans_line_inverse(PG_FUNCTION_ARGS); +extern Datum spheretrans_line_inverse(PG_FUNCTION_ARGS); /* * Returns the distance between a line and a point. */ -Datum sphereline_point_distance(PG_FUNCTION_ARGS); +extern Datum sphereline_point_distance(PG_FUNCTION_ARGS); /* * Returns the distance between a point and a line. */ -Datum sphereline_point_distance_com(PG_FUNCTION_ARGS); +extern Datum sphereline_point_distance_com(PG_FUNCTION_ARGS); #endif diff --git a/src/output.c b/src/output.c index 7598d46..7df5889 100644 --- a/src/output.c +++ b/src/output.c @@ -1,5 +1,12 @@ #include "types.h" +#if PG_VERSION_NUM >= 120000 +#include "utils/float.h" +#include "common/shortest_dec.h" +#endif + +#include + #if !defined(PGSPHERE_VERSION) #error "PGSPHERE_VERSION macro is not set" #endif @@ -9,7 +16,6 @@ /* Output functions */ - /* Output modes */ #define OUTPUT_RAD 1 /* output in radians */ #define OUTPUT_DEG 2 /* output in degrees */ @@ -25,7 +31,7 @@ static unsigned char sphere_output = OUTPUT_RAD; /* * Defines the precision of floating point values in output. */ -static int sphere_output_precision = DBL_DIG; +static int sphere_output_precision = INT_MAX; PG_FUNCTION_INFO_V1(set_sphere_output); PG_FUNCTION_INFO_V1(spherepoint_out); @@ -37,6 +43,7 @@ PG_FUNCTION_INFO_V1(spherepath_out); PG_FUNCTION_INFO_V1(sphereellipse_out); PG_FUNCTION_INFO_V1(spherebox_out); PG_FUNCTION_INFO_V1(set_sphere_output_precision); +PG_FUNCTION_INFO_V1(reset_sphere_output_precision); PG_FUNCTION_INFO_V1(pg_sphere_version); /* @@ -94,6 +101,8 @@ Datum spherebox_out(PG_FUNCTION_ARGS); */ Datum pg_sphere_version(PG_FUNCTION_ARGS); +static void +spheretrans_out_buffer(StringInfo si, const SEuler *se); /* * Converts radians to DEG ( degrees, minutes, seconds ) @@ -128,6 +137,116 @@ rad_to_dms(double rad, unsigned int *deg, unsigned int *min, double *sec) } } +static void +pgs_strinfo_put_chr(StringInfo si, char c) +{ + appendStringInfoChar(si, c); +} + +static void +pgs_strinfo_put_str(StringInfo si, char *s) +{ + appendStringInfoString(si, s); +} + +static void +pgs_strinfo_put_d64(StringInfo si, double value) +{ + int cw, + ndig; + char buf[128]; + +#if PG_VERSION_NUM >= 120000 + + if (extra_float_digits > 0) + { + cw = double_to_shortest_decimal_buf(value, buf); + } + else + { + ndig = DBL_DIG + extra_float_digits; + if (ndig < 1) + ndig = 1; + + cw = pg_strfromd(buf, 128, ndig, value); + } + +#else + + ndig = DBL_DIG + extra_float_digits; + if (ndig < 1) + ndig = 1; + + cw = snprintf(buf, 128, "%.*g", ndig, value); + +#endif + + if (cw < 0) + { + fflush(stderr); + abort(); + } + + pgs_strinfo_put_str(si, buf); +} + +static void +pgs_strinfo_put_lng_dms(StringInfo si, double lng) +{ + unsigned int lngdeg, + lngmin; + double lngsec; + + rad_to_dms(lng, &lngdeg, &lngmin, &lngsec); + + appendStringInfo(si, "%3ud %2um ", lngdeg, lngmin); + pgs_strinfo_put_d64(si, lngsec); + pgs_strinfo_put_chr(si, 's'); +} + +static void +pgs_strinfo_put_lng_hms(StringInfo si, double lng) +{ + unsigned int lnghour, + lngmin; + double lngsec; + + rad_to_dms(lng / 15.0, &lnghour, &lngmin, &lngsec); + + appendStringInfo(si, "%3uh %2um ", lnghour, lngmin); + pgs_strinfo_put_d64(si, lngsec); + pgs_strinfo_put_chr(si, 's'); +} + +static void +pgs_strinfo_put_lat_dms(StringInfo si, double lat) +{ + unsigned int latdeg, + latmin; + double latsec; + const char latsign = lat >= 0 ? '+' : '-'; + + rad_to_dms(lat, &latdeg, &latmin, &latsec); + + appendStringInfo(si, "%c%2ud %2um ", latsign, latdeg, latmin); + pgs_strinfo_put_d64(si, latsec); + pgs_strinfo_put_chr(si, 's'); +} + +static void +pgs_strinfo_put_radius_dms(StringInfo si, double radius) +{ + unsigned int rdeg, + rmin; + double rsec; + + rad_to_dms(radius, &rdeg, &rmin, &rsec); + + appendStringInfo(si, "%2ud %2um ", rdeg, rmin); + pgs_strinfo_put_d64(si, rsec); + pgs_strinfo_put_chr(si, 's'); +} + Datum set_sphere_output_precision(PG_FUNCTION_ARGS) { @@ -144,6 +263,18 @@ set_sphere_output_precision(PG_FUNCTION_ARGS) PG_RETURN_CSTRING(buf); } +Datum +reset_sphere_output_precision(PG_FUNCTION_ARGS) +{ + char *buf = (char *) palloc(20); + + sphere_output_precision = INT_MAX; + + sprintf(buf, "RESET"); + + PG_RETURN_CSTRING(buf); +} + Datum set_sphere_output(PG_FUNCTION_ARGS) { @@ -176,8 +307,8 @@ set_sphere_output(PG_FUNCTION_ARGS) PG_RETURN_CSTRING(buf); } -Datum -spherepoint_out(PG_FUNCTION_ARGS) +static Datum +spherepoint_out_compat(PG_FUNCTION_ARGS) { SPoint *sp = (SPoint *) PG_GETARG_POINTER(0); char *buffer = (char *) palloc(255); @@ -227,11 +358,89 @@ spherepoint_out(PG_FUNCTION_ARGS) } PG_RETURN_CSTRING(buffer); +} + +static void +spherepoint_out_deg(StringInfo si, const SPoint *sp) +{ + pgs_strinfo_put_chr(si, '('); + pgs_strinfo_put_d64(si, RADIANS * sp->lng); + pgs_strinfo_put_str(si, "d, "); + pgs_strinfo_put_d64(si, RADIANS * sp->lat); + pgs_strinfo_put_str(si, "d)"); +} +static void +spherepoint_out_rad(StringInfo si, const SPoint *sp) +{ + pgs_strinfo_put_chr(si, '('); + pgs_strinfo_put_d64(si, sp->lng); + pgs_strinfo_put_str(si, " , "); + pgs_strinfo_put_d64(si, sp->lat); + pgs_strinfo_put_str(si, ")"); +} + +static void +spherepoint_out_dms(StringInfo si, const SPoint *sp) +{ + pgs_strinfo_put_chr(si, '('); + pgs_strinfo_put_lng_dms(si, sp->lng); + pgs_strinfo_put_str(si, " , "); + pgs_strinfo_put_lat_dms(si, sp->lat); + pgs_strinfo_put_chr(si, ')'); +} + +static void +spherepoint_out_hms(StringInfo si, const SPoint *sp) +{ + pgs_strinfo_put_chr(si, '('); + pgs_strinfo_put_lng_hms(si, sp->lng); + pgs_strinfo_put_str(si, " , "); + pgs_strinfo_put_lat_dms(si, sp->lat); + pgs_strinfo_put_chr(si, ')'); +} + +static inline void +spherepoint_out_buffer(StringInfo si, const SPoint *sp) +{ + switch (sphere_output) + { + case OUTPUT_DEG: + spherepoint_out_deg(si, sp); + break; + case OUTPUT_DMS: + spherepoint_out_dms(si, sp); + break; + case OUTPUT_HMS: + spherepoint_out_hms(si, sp); + break; + default: + spherepoint_out_rad(si, sp); + break; + } } Datum -spherecircle_out(PG_FUNCTION_ARGS) +spherepoint_out(PG_FUNCTION_ARGS) +{ + StringInfoData si; + SPoint *sp; + + if (sphere_output_precision != INT_MAX) + return spherepoint_out_compat(fcinfo); + + sp = (SPoint *) PG_GETARG_POINTER(0); + if (!sp) + PG_RETURN_NULL(); + + initStringInfo(&si); + spherepoint_out_buffer(&si, sp); + + PG_RETURN_CSTRING(si.data); +} + +static Datum +spherecircle_out_compat(PG_FUNCTION_ARGS) { SCIRCLE *c = (SCIRCLE *) PG_GETARG_POINTER(0); char *buffer = (char *) palloc(255); @@ -272,12 +481,86 @@ spherecircle_out(PG_FUNCTION_ARGS) } pfree(pointstr); + PG_RETURN_CSTRING(buffer); +} + +static void +spherecircle_out_deg(StringInfo si, const SCIRCLE *sc) +{ + pgs_strinfo_put_chr(si, '<'); + spherepoint_out_deg(si, &sc->center); + pgs_strinfo_put_str(si, " , "); + pgs_strinfo_put_d64(si, RADIANS * sc->radius); + pgs_strinfo_put_chr(si, '>'); +} +static void +spherecircle_out_rad(StringInfo si, const SCIRCLE *sc) +{ + pgs_strinfo_put_chr(si, '<'); + spherepoint_out_rad(si, &sc->center); + pgs_strinfo_put_str(si, " , "); + pgs_strinfo_put_d64(si, sc->radius); + pgs_strinfo_put_chr(si, '>'); +} + +static void +spherecircle_out_dms(StringInfo si, const SCIRCLE *sc) +{ + pgs_strinfo_put_chr(si, '<'); + spherepoint_out_dms(si, &sc->center); + pgs_strinfo_put_str(si, " , "); + pgs_strinfo_put_radius_dms(si, sc->radius); + pgs_strinfo_put_chr(si, '>'); +} + +static void +spherecircle_out_hms(StringInfo si, const SCIRCLE *sc) +{ + pgs_strinfo_put_chr(si, '<'); + spherepoint_out_hms(si, &sc->center); + pgs_strinfo_put_str(si, " , "); + pgs_strinfo_put_radius_dms(si, sc->radius); + pgs_strinfo_put_chr(si, '>'); } Datum -sphereellipse_out(PG_FUNCTION_ARGS) +spherecircle_out(PG_FUNCTION_ARGS) +{ + StringInfoData si; + SCIRCLE *sc; + + if (sphere_output_precision != INT_MAX) + return spherecircle_out_compat(fcinfo); + + sc = (SCIRCLE *) PG_GETARG_POINTER(0); + if (!sc) + PG_RETURN_NULL(); + + initStringInfo(&si); + + switch (sphere_output) + { + case OUTPUT_DEG: + spherecircle_out_deg(&si, sc); + break; + case OUTPUT_DMS: + spherecircle_out_dms(&si, sc); + break; + case OUTPUT_HMS: + spherecircle_out_hms(&si, sc); + break; + default: + spherecircle_out_rad(&si, sc); + break; + } + + PG_RETURN_CSTRING(si.data); +} + +static Datum +sphereellipse_out_compat(PG_FUNCTION_ARGS) { SELLIPSE *e = (SELLIPSE *) PG_GETARG_POINTER(0); char *buffer = (char *) palloc(255); @@ -333,8 +616,88 @@ sphereellipse_out(PG_FUNCTION_ARGS) PG_RETURN_CSTRING(buffer); } +static void +sphereellipse_out_deg(StringInfo si, SELLIPSE *e) +{ + const SPoint sp = { e->psi, e->theta }; + + pgs_strinfo_put_str(si, "<{ "); + pgs_strinfo_put_d64(si, RADIANS * e->rad[0]); + pgs_strinfo_put_str(si, "d , "); + pgs_strinfo_put_d64(si, RADIANS * e->rad[1]); + pgs_strinfo_put_str(si, "d },"); + spherepoint_out_buffer(si, &sp); + pgs_strinfo_put_str(si, " , "); + pgs_strinfo_put_d64(si, RADIANS * e->phi); + pgs_strinfo_put_str(si, "d>"); +} + +static void +sphereellipse_out_rad(StringInfo si, SELLIPSE *e) +{ + const SPoint sp = { e->psi, e->theta }; + + pgs_strinfo_put_str(si, "<{ "); + pgs_strinfo_put_d64(si, e->rad[0]); + pgs_strinfo_put_str(si, " , "); + pgs_strinfo_put_d64(si, e->rad[1]); + pgs_strinfo_put_str(si, " },"); + spherepoint_out_buffer(si, &sp); + pgs_strinfo_put_str(si, " , "); + pgs_strinfo_put_d64(si, e->phi); + pgs_strinfo_put_str(si, ">"); +} + +static void +sphereellipse_out_dms(StringInfo si, SELLIPSE *e) +{ + const SPoint sp = { e->psi, e->theta }; + + pgs_strinfo_put_str(si, "<{ "); + pgs_strinfo_put_lng_dms(si, e->rad[0]); + pgs_strinfo_put_str(si, " , "); + pgs_strinfo_put_lng_dms(si, e->rad[1]); + pgs_strinfo_put_str(si, " },"); + spherepoint_out_buffer(si, &sp); + pgs_strinfo_put_str(si, " , "); + pgs_strinfo_put_lng_dms(si, e->phi); + pgs_strinfo_put_str(si, ">"); +} + Datum -sphereline_out(PG_FUNCTION_ARGS) +sphereellipse_out(PG_FUNCTION_ARGS) +{ + StringInfoData si; + SELLIPSE *e; + + if (sphere_output_precision != INT_MAX) + return sphereellipse_out_compat(fcinfo); + + e = (SELLIPSE *) PG_GETARG_POINTER(0); + if (!e) + PG_RETURN_NULL(); + + initStringInfo(&si); + + switch (sphere_output) + { + case OUTPUT_DEG: + sphereellipse_out_deg(&si, e); + break; + case OUTPUT_HMS: + case OUTPUT_DMS: + sphereellipse_out_dms(&si, e); + break; + default: + sphereellipse_out_rad(&si, e); + break; + } + + PG_RETURN_CSTRING(si.data); +} + +static Datum +sphereline_out_compat(PG_FUNCTION_ARGS) { SLine *sl = (SLine *) PG_GETARG_POINTER(0); char *out = (char *) palloc(255); @@ -384,7 +747,49 @@ sphereline_out(PG_FUNCTION_ARGS) } Datum -spheretrans_out(PG_FUNCTION_ARGS) +sphereline_out(PG_FUNCTION_ARGS) +{ + StringInfoData si; + SLine *sl; + SEuler se; + + if (sphere_output_precision != INT_MAX) + return sphereline_out_compat(fcinfo); + + sl = (SLine *) PG_GETARG_POINTER(0); + if (!sl) + PG_RETURN_NULL(); + + seuler_set_zxz(&se); + se.phi = sl->phi; + se.theta = sl->theta; + se.psi = sl->psi; + + initStringInfo(&si); + + pgs_strinfo_put_str(&si, "( "); + spheretrans_out_buffer(&si, &se); + pgs_strinfo_put_str(&si, " ), "); + + switch (sphere_output) + { + case OUTPUT_DEG: + pgs_strinfo_put_d64(&si, RADIANS * sl->length); + break; + case OUTPUT_HMS: + case OUTPUT_DMS: + pgs_strinfo_put_lng_dms(&si, sl->length); + break; + default: + pgs_strinfo_put_d64(&si, sl->length); + break; + } + + PG_RETURN_CSTRING(si.data); +} + +static Datum +spheretrans_out_compat(PG_FUNCTION_ARGS) { SEuler *se = (SEuler *) PG_GETARG_POINTER(0); char *buffer = (char *) palloc(255); @@ -469,8 +874,117 @@ spheretrans_out(PG_FUNCTION_ARGS) PG_RETURN_CSTRING(buffer); } +static void +spheretrans_out_deg(StringInfo si, SPoint sp[3]) +{ + int i; + + for (i = 0; i < 3; ++i) + { + pgs_strinfo_put_d64(si, RADIANS * sp[i].lng); + pgs_strinfo_put_str(si, ", "); + } +} + +static void +spheretrans_out_rad(StringInfo si, SPoint sp[3]) +{ + int i; + + for (i = 0; i < 3; ++i) + { + pgs_strinfo_put_d64(si, sp[i].lng); + pgs_strinfo_put_str(si, ", "); + } +} + +static void +spheretrans_out_dms(StringInfo si, SPoint sp[3]) +{ + int i; + + for (i = 0; i < 3; ++i) + { + pgs_strinfo_put_lng_dms(si, sp[i].lng); + pgs_strinfo_put_str(si, ", "); + } +} + +static void +spheretrans_out_buffer(StringInfo si, const SEuler *se) +{ + SPoint val[3]; + unsigned char t[3]; + int i; + + val[0].lat = val[1].lat = val[2].lat = 0.0; + val[0].lng = se->phi; + val[1].lng = se->theta; + val[2].lng = se->psi; + + t[0] = se->phi_a; + t[1] = se->theta_a; + t[2] = se->psi_a; + + spoint_check(&val[0]); + spoint_check(&val[1]); + spoint_check(&val[2]); + + switch (sphere_output) + { + case OUTPUT_DEG: + spheretrans_out_deg(si, val); + break; + case OUTPUT_HMS: + case OUTPUT_DMS: + spheretrans_out_dms(si, val); + break; + default: + spheretrans_out_rad(si, val); + break; + } + + for (i = 0; i < 3; i++) + { + switch (t[i]) + { + case EULER_AXIS_X: + pgs_strinfo_put_chr(si, 'X'); + break; + case EULER_AXIS_Y: + pgs_strinfo_put_chr(si, 'Y'); + break; + case EULER_AXIS_Z: + pgs_strinfo_put_chr(si, 'Z'); + break; + default: + Assert(false); + } + } +} + Datum -spherepath_out(PG_FUNCTION_ARGS) +spheretrans_out(PG_FUNCTION_ARGS) +{ + StringInfoData si; + SEuler *se; + + if (sphere_output_precision != INT_MAX) + return spheretrans_out_compat(fcinfo); + + se = (SEuler *) PG_GETARG_POINTER(0); + if (!se) + PG_RETURN_NULL(); + + initStringInfo(&si); + + spheretrans_out_buffer(&si, se); + + PG_RETURN_CSTRING(si.data); +} + +static Datum +spherepath_out_compat(PG_FUNCTION_ARGS) { SPATH *path = PG_GETARG_SPATH(0); int32 i; @@ -494,7 +1008,37 @@ spherepath_out(PG_FUNCTION_ARGS) } Datum -spherepoly_out(PG_FUNCTION_ARGS) +spherepath_out(PG_FUNCTION_ARGS) +{ + StringInfoData si; + SPATH *path; + int32 i; + + if (sphere_output_precision != INT_MAX) + return spherepath_out_compat(fcinfo); + + path = PG_GETARG_SPATH(0); + if (!path) + PG_RETURN_NULL(); + + initStringInfo(&si); + + pgs_strinfo_put_chr(&si, '{'); + + for (i = 0; i < path->npts; ++i) + { + if (i > 0) + pgs_strinfo_put_chr(&si, ','); + spherepoint_out_buffer(&si, &path->p[i]); + } + + pgs_strinfo_put_chr(&si, '}'); + + PG_RETURN_CSTRING(si.data); +} + +static Datum +spherepoly_out_compat(PG_FUNCTION_ARGS) { SPOLY *poly = PG_GETARG_SPOLY(0); int32 i; @@ -518,7 +1062,37 @@ spherepoly_out(PG_FUNCTION_ARGS) } Datum -spherebox_out(PG_FUNCTION_ARGS) +spherepoly_out(PG_FUNCTION_ARGS) +{ + StringInfoData si; + SPOLY *poly; + int32 i; + + if (sphere_output_precision != INT_MAX) + return spherepoly_out_compat(fcinfo); + + poly = PG_GETARG_SPOLY(0); + if (!poly) + PG_RETURN_NULL(); + + initStringInfo(&si); + + pgs_strinfo_put_chr(&si, '{'); + + for (i = 0; i < poly->npts; ++i) + { + if (i > 0) + pgs_strinfo_put_chr(&si, ','); + spherepoint_out_buffer(&si, &poly->p[i]); + } + + pgs_strinfo_put_chr(&si, '}'); + + PG_RETURN_CSTRING(si.data); +} + +static Datum +spherebox_out_compat(PG_FUNCTION_ARGS) { SBOX *box = (SBOX *) PG_GETARG_POINTER(0); char *buffer = (char *) palloc(255); @@ -535,6 +1109,30 @@ spherebox_out(PG_FUNCTION_ARGS) PG_RETURN_CSTRING(buffer); } +Datum +spherebox_out(PG_FUNCTION_ARGS) +{ + StringInfoData si; + SBOX *box; + + if (sphere_output_precision != INT_MAX) + return spherebox_out_compat(fcinfo); + + box = (SBOX *) PG_GETARG_POINTER(0); + if (!box) + PG_RETURN_NULL(); + + initStringInfo(&si); + + pgs_strinfo_put_chr(&si, '('); + spherepoint_out_buffer(&si, &box->sw); + pgs_strinfo_put_str(&si, ", "); + spherepoint_out_buffer(&si, &box->ne); + pgs_strinfo_put_chr(&si, ')'); + + PG_RETURN_CSTRING(si.data); +} + Datum pg_sphere_version(PG_FUNCTION_ARGS) { diff --git a/src/path.h b/src/path.h index 91e1662..8f98cee 100644 --- a/src/path.h +++ b/src/path.h @@ -12,22 +12,22 @@ */ typedef struct { - char vl_len_[4]; /* total size in bytes */ - int32 npts; /* count of points */ - SPoint p[1]; /* variable length array of SPoints */ + char vl_len_[4]; /* total size in bytes */ + int32 npts; /* count of points */ + SPoint p[1]; /* variable length array of SPoints */ } SPATH; /* Path and circle */ -#define PGS_CIRCLE_PATH_AVOID 0 /* circle avoids path */ -#define PGS_CIRCLE_CONT_PATH 1 /* circle contains path */ -#define PGS_CIRCLE_PATH_OVER 2 /* circle overlaps path */ +#define PGS_CIRCLE_PATH_AVOID 0 /* circle avoids path */ +#define PGS_CIRCLE_CONT_PATH 1 /* circle contains path */ +#define PGS_CIRCLE_PATH_OVER 2 /* circle overlaps path */ /* Path and polygon */ -#define PGS_POLY_PATH_AVOID 0 /* polygon avoids path */ -#define PGS_POLY_CONT_PATH 1 /* polygon contains path */ -#define PGS_POLY_PATH_OVER 2 /* polygon and path overlap */ +#define PGS_POLY_PATH_AVOID 0 /* polygon avoids path */ +#define PGS_POLY_CONT_PATH 1 /* polygon contains path */ +#define PGS_POLY_PATH_OVER 2 /* polygon and path overlap */ /* Path and ellipse */ #define PGS_ELLIPSE_PATH_AVOID 0 /* ellipse avoids path */ @@ -41,12 +41,12 @@ typedef struct /* * Checks whether two paths are equal. */ -bool spath_eq(const SPATH *p1, const SPATH *p2); +extern bool spath_eq(const SPATH *p1, const SPATH *p2); /* * Checks whether a path contains a point. */ -bool spath_cont_point(const SPATH *path, const SPoint *sp); +extern bool spath_cont_point(const SPATH *path, const SPoint *sp); /* * Returns the i-th line segment of a path. @@ -57,24 +57,24 @@ bool spath_cont_point(const SPATH *path, const SPoint *sp); * * Returns the pointer to the line segment or NULL if fails. */ -bool spath_segment(SLine *sl, const SPATH *path, int32 i); +extern bool spath_segment(SLine *sl, const SPATH *path, int32 i); /* * Input function of path. */ -Datum spherepath_in(PG_FUNCTION_ARGS); +extern Datum spherepath_in(PG_FUNCTION_ARGS); /* * Returns the n-th point of a path. * * See spherepath_get_point(PG_FUNCTION_ARGS) */ -Datum spherepath_get_point(PG_FUNCTION_ARGS); +extern Datum spherepath_get_point(PG_FUNCTION_ARGS); /* * Returns spath as array of points */ -Datum spherepath_get_array(PG_FUNCTION_ARGS); +extern Datum spherepath_get_array(PG_FUNCTION_ARGS); /* * This function interpolates between points of path. Returns the @@ -82,212 +82,212 @@ Datum spherepath_get_array(PG_FUNCTION_ARGS); * * See spherepath_point(PG_FUNCTION_ARGS) */ -Datum spherepath_point(PG_FUNCTION_ARGS); +extern Datum spherepath_point(PG_FUNCTION_ARGS); /* * Checks whether two paths are equal. */ -Datum spherepath_equal(PG_FUNCTION_ARGS); +extern Datum spherepath_equal(PG_FUNCTION_ARGS); /* * Checks whether two paths aren't equal. */ -Datum spherepath_equal_neg(PG_FUNCTION_ARGS); +extern Datum spherepath_equal_neg(PG_FUNCTION_ARGS); /* * Returns the length of a path. */ -Datum spherepath_length(PG_FUNCTION_ARGS); +extern Datum spherepath_length(PG_FUNCTION_ARGS); /* * Returns the number of points in a path. */ -Datum spherepath_npts(PG_FUNCTION_ARGS); +extern Datum spherepath_npts(PG_FUNCTION_ARGS); /* * Changes the direction of a path. */ -Datum spherepath_swap(PG_FUNCTION_ARGS); +extern Datum spherepath_swap(PG_FUNCTION_ARGS); /* * Checks whether a path contains a point. */ -Datum spherepath_cont_point(PG_FUNCTION_ARGS); +extern Datum spherepath_cont_point(PG_FUNCTION_ARGS); /* * Checks whether a path doesn't contain a point. */ -Datum spherepath_cont_point_neg(PG_FUNCTION_ARGS); +extern Datum spherepath_cont_point_neg(PG_FUNCTION_ARGS); /* * Checks whether a path contains a point. */ -Datum spherepath_cont_point_com(PG_FUNCTION_ARGS); +extern Datum spherepath_cont_point_com(PG_FUNCTION_ARGS); /* * Checks whether a path doesn't contain a point. */ -Datum spherepath_cont_point_com_neg(PG_FUNCTION_ARGS); +extern Datum spherepath_cont_point_com_neg(PG_FUNCTION_ARGS); /* * Checks whether a path and a line overlap. */ -Datum spherepath_overlap_line(PG_FUNCTION_ARGS); +extern Datum spherepath_overlap_line(PG_FUNCTION_ARGS); /* * Checks whether a path and a line don't overlap. */ -Datum spherepath_overlap_line_neg(PG_FUNCTION_ARGS); +extern Datum spherepath_overlap_line_neg(PG_FUNCTION_ARGS); /* * Checks whether path and line overlap. */ -Datum spherepath_overlap_line_com(PG_FUNCTION_ARGS); +extern Datum spherepath_overlap_line_com(PG_FUNCTION_ARGS); /* * Checks whether a path and a line don't overlap. */ -Datum spherepath_overlap_line_com_neg(PG_FUNCTION_ARGS); +extern Datum spherepath_overlap_line_com_neg(PG_FUNCTION_ARGS); /* * Checks whether a circle contains a path. */ -Datum spherecircle_cont_path(PG_FUNCTION_ARGS); +extern Datum spherecircle_cont_path(PG_FUNCTION_ARGS); /* * Checks whether a circle doesn't contain a path. */ -Datum spherecircle_cont_path_neg(PG_FUNCTION_ARGS); +extern Datum spherecircle_cont_path_neg(PG_FUNCTION_ARGS); /* * Checks whether a circle contains a path. */ -Datum spherecircle_cont_path_com(PG_FUNCTION_ARGS); +extern Datum spherecircle_cont_path_com(PG_FUNCTION_ARGS); /* * Checks whether a circle doesn't contain a path. */ -Datum spherecircle_cont_path_com_neg(PG_FUNCTION_ARGS); +extern Datum spherecircle_cont_path_com_neg(PG_FUNCTION_ARGS); /* * Checks whether a circle and a path overlap. */ -Datum spherecircle_overlap_path(PG_FUNCTION_ARGS); +extern Datum spherecircle_overlap_path(PG_FUNCTION_ARGS); /* * Checks whether a circle and a path don't overlap. */ -Datum spherecircle_overlap_path_neg(PG_FUNCTION_ARGS); +extern Datum spherecircle_overlap_path_neg(PG_FUNCTION_ARGS); /* * Checks whether a circle and a path overlap. */ -Datum spherecircle_overlap_path_com(PG_FUNCTION_ARGS); +extern Datum spherecircle_overlap_path_com(PG_FUNCTION_ARGS); /* * Checks whether a circle and a path don't overlap. */ -Datum spherecircle_overlap_path_com_neg(PG_FUNCTION_ARGS); +extern Datum spherecircle_overlap_path_com_neg(PG_FUNCTION_ARGS); /* * Checks whether a polygon contains a path. */ -Datum spherepoly_cont_path(PG_FUNCTION_ARGS); +extern Datum spherepoly_cont_path(PG_FUNCTION_ARGS); /* * Checks whether a polygon doesn't contain a path. */ -Datum spherepoly_cont_path_neg(PG_FUNCTION_ARGS); +extern Datum spherepoly_cont_path_neg(PG_FUNCTION_ARGS); /* * Checks whether a polygon contains path. */ -Datum spherepoly_cont_path_com(PG_FUNCTION_ARGS); +extern Datum spherepoly_cont_path_com(PG_FUNCTION_ARGS); /* * Checks whether a polygon doesn't contain a path. */ -Datum spherepoly_cont_path_com_neg(PG_FUNCTION_ARGS); +extern Datum spherepoly_cont_path_com_neg(PG_FUNCTION_ARGS); /* * Checks whether a polygon and a path overlap. */ -Datum spherepoly_overlap_path(PG_FUNCTION_ARGS); +extern Datum spherepoly_overlap_path(PG_FUNCTION_ARGS); /* * Checks whether a polygon and a path don't overlap. */ -Datum spherepoly_overlap_path_neg(PG_FUNCTION_ARGS); +extern Datum spherepoly_overlap_path_neg(PG_FUNCTION_ARGS); /* * Checks whether a polygon and a path overlap. */ -Datum spherepoly_overlap_path_com(PG_FUNCTION_ARGS); +extern Datum spherepoly_overlap_path_com(PG_FUNCTION_ARGS); /* * Checks whether a polygon and a path don't overlap. */ -Datum spherepoly_overlap_path_com_neg(PG_FUNCTION_ARGS); +extern Datum spherepoly_overlap_path_com_neg(PG_FUNCTION_ARGS); /* * Checks whether two paths overlap. */ -Datum spherepath_overlap_path(PG_FUNCTION_ARGS); +extern Datum spherepath_overlap_path(PG_FUNCTION_ARGS); /* * Checks whether two paths don't overlap. */ -Datum spherepath_overlap_path_neg(PG_FUNCTION_ARGS); +extern Datum spherepath_overlap_path_neg(PG_FUNCTION_ARGS); /* * Checks whether an ellipse contains path. */ -Datum sphereellipse_cont_path(PG_FUNCTION_ARGS); +extern Datum sphereellipse_cont_path(PG_FUNCTION_ARGS); /* * Checks whether an ellipse doesn't contain a path. */ -Datum sphereellipse_cont_path_neg(PG_FUNCTION_ARGS); +extern Datum sphereellipse_cont_path_neg(PG_FUNCTION_ARGS); /* * Checks whether an ellipse contains a path. */ -Datum sphereellipse_cont_path_com(PG_FUNCTION_ARGS); +extern Datum sphereellipse_cont_path_com(PG_FUNCTION_ARGS); /* * Checks whether an ellipse doesn't contain a path. */ -Datum sphereellipse_cont_path_com_neg(PG_FUNCTION_ARGS); +extern Datum sphereellipse_cont_path_com_neg(PG_FUNCTION_ARGS); /* * Checks whether an ellipse and a path overlap. */ -Datum sphereellipse_overlap_path(PG_FUNCTION_ARGS); +extern Datum sphereellipse_overlap_path(PG_FUNCTION_ARGS); /* * Checks whether an ellipse and a path don't overlap. */ -Datum sphereellipse_overlap_path_neg(PG_FUNCTION_ARGS); +extern Datum sphereellipse_overlap_path_neg(PG_FUNCTION_ARGS); /* * Checks whether an ellipse and a path overlap. */ -Datum sphereellipse_overlap_path_com(PG_FUNCTION_ARGS); +extern Datum sphereellipse_overlap_path_com(PG_FUNCTION_ARGS); /* * Checks whether an ellipse and a path don't overlap. */ -Datum sphereellipse_overlap_path_com_neg(PG_FUNCTION_ARGS); +extern Datum sphereellipse_overlap_path_com_neg(PG_FUNCTION_ARGS); /* * Performs an Euler transformation on a path. */ -Datum spheretrans_path(PG_FUNCTION_ARGS); +extern Datum spheretrans_path(PG_FUNCTION_ARGS); /* * Performs an inverse Euler transformation on a path. */ -Datum spheretrans_path_inverse(PG_FUNCTION_ARGS); +extern Datum spheretrans_path_inverse(PG_FUNCTION_ARGS); /* * State transition function for aggregate function spath(spoint). Never @@ -295,11 +295,11 @@ Datum spheretrans_path_inverse(PG_FUNCTION_ARGS); * * Adds a point to a path. */ -Datum spherepath_add_point(PG_FUNCTION_ARGS); +extern Datum spherepath_add_point(PG_FUNCTION_ARGS); /* * Finalize function for adding spoints to a path. */ -Datum spherepath_add_points_finalize(PG_FUNCTION_ARGS); +extern Datum spherepath_add_points_finalize(PG_FUNCTION_ARGS); #endif diff --git a/src/pg_sphere.h b/src/pg_sphere.h index 24d950a..9cfc5f2 100644 --- a/src/pg_sphere.h +++ b/src/pg_sphere.h @@ -72,7 +72,7 @@ #else #define PGSPHERE_FLOAT_STORE 0 #endif -#endif // PGSPHERE_FLOAT_STORE +#endif /* PGSPHERE_FLOAT_STORE */ #define EPSILON 1.0E-09 @@ -84,6 +84,7 @@ static inline bool FPeq(double A, double B) { const volatile double AB = A - B; + return A == B || fabs(AB) <= EPSILON; } @@ -91,6 +92,7 @@ static inline bool FPne(double A, double B) { const volatile double AB = A - B; + return A != B && fabs(AB) > EPSILON; } @@ -98,6 +100,7 @@ static inline bool FPlt(double A, double B) { const volatile double AE = A + EPSILON; + return AE < B; } @@ -105,6 +108,7 @@ static inline bool FPle(double A, double B) { const volatile double BE = B + EPSILON; + return A <= BE; } @@ -112,6 +116,7 @@ static inline bool FPgt(double A, double B) { const volatile double BE = B + EPSILON; + return A > BE; } @@ -119,6 +124,7 @@ static inline bool FPge(double A, double B) { const volatile double AE = A + EPSILON; + return AE >= B; } @@ -160,7 +166,7 @@ FPge(double A, double B) return A + EPSILON >= B; } -#endif // PGSPHERE_FLOAT_STORE +#endif /* PGSPHERE_FLOAT_STORE */ /*--------------------------------------------------------------------- * Point - (x,y) @@ -171,7 +177,6 @@ typedef struct y; } Point; -void sphere_yyparse(void); +extern void sphere_yyparse(void); #endif - diff --git a/src/pgs_chealpix.h b/src/pgs_chealpix.h index c3233d1..f15b4fe 100644 --- a/src/pgs_chealpix.h +++ b/src/pgs_chealpix.h @@ -2,7 +2,7 @@ #define __PGS_CHEALPIX_H__ #include -#include /* PostgreSQL type definitions */ +#include /* PostgreSQL type definitions */ /* * Actually, chealpix changed its API: thus, this file must be included first, * directly or indirectly. diff --git a/src/pgs_util.h b/src/pgs_util.h index 1b3ad76..f04d5be 100644 --- a/src/pgs_util.h +++ b/src/pgs_util.h @@ -1,18 +1,18 @@ #ifndef __PGS_UTIL_H__ #define __PGS_UTIL_H__ -#define PI 3.14159265358979323846 /* pi */ -#define PIH 1.57079632679489661923 /* pi/2 */ -#define PID 6.2831853071795864769 /* 2*pi */ -#define RADIANS 57.295779513082320877 /* 180/pi */ +#define PI 3.14159265358979323846 /* pi */ +#define PIH 1.57079632679489661923 /* pi/2 */ +#define PID 6.2831853071795864769 /* 2*pi */ +#define RADIANS 57.295779513082320877 /* 180/pi */ #define PI_EPS 4.4408920985006261617e-16 /* 2 ** -51 */ -#define Sqr(a) ( (a) * (a) ) /* square function as macro */ +#define Sqr(a) ( (a) * (a) ) /* square function as macro */ #ifdef EPSILON #undef EPSILON #endif -#define EPSILON 1.0E-09 /* precision of floating point values */ +#define EPSILON 1.0E-09 /* precision of floating point values */ /* spherical circle constants */ #define SPHERE_SURFACE (4 * PI) @@ -22,7 +22,8 @@ static inline double conv_theta(double x) { - double y = PIH - x; + double y = PIH - x; + if (fabs(x) < PI_EPS / 2) return PIH; if (fabs(y) < PI_EPS / 2) @@ -30,7 +31,8 @@ conv_theta(double x) return y; } -static inline double deg_to_rad(double in) +static inline double +deg_to_rad(double in) { return in * PI / 180; } diff --git a/src/point.h b/src/point.h index d7af228..b9d85d1 100644 --- a/src/point.h +++ b/src/point.h @@ -11,100 +11,109 @@ */ typedef struct { - float8 lng; /* longitude value in radians */ - float8 lat; /* latitude value in radians */ + float8 lng; /* longitude value in radians */ + float8 lat; /* latitude value in radians */ } SPoint; -Oid get_spoint_type_oid(void); +extern Oid get_spoint_type_oid(void); /* * Calculate the distance between two spherical points in radians. */ -float8 spoint_dist(const SPoint *p1, const SPoint *p2); + +extern float8 spoint_dist(const SPoint *p1, const SPoint *p2); /* * Check whether two points are equal. */ -bool spoint_eq(const SPoint *p1, const SPoint *p2); + +extern bool spoint_eq(const SPoint *p1, const SPoint *p2); /* * Check the longitude and latitude values of a spherical point. */ -void spoint_check(SPoint *spoint); + +extern void spoint_check(SPoint *spoint); /* * Transforms a 3d vector into a spherical point. */ -void vector3d_spoint(SPoint *p, const Vector3D *v); + +extern void vector3d_spoint(SPoint *p, const Vector3D *v); /* * Transforms a spherical point into a 3d vector. */ -void spoint_vector3d(Vector3D *v, const SPoint *p); + +extern void spoint_vector3d(Vector3D *v, const SPoint *p); /* * Take the input and store it as a spherical point. */ -Datum spherepoint_in(PG_FUNCTION_ARGS); + +extern Datum spherepoint_in(PG_FUNCTION_ARGS); /* * Create spherical point from lat, lng and store to first argument(pointer) */ -void create_spherepoint_from_long_lat(SPoint *p, float8 lng, float8 lat); + +extern void create_spherepoint_from_long_lat(SPoint *p, float8 lng, float8 lat); /* * Create a spherical point from longitude and latitude both in radians. */ -Datum spherepoint_from_long_lat(PG_FUNCTION_ARGS); + +extern Datum spherepoint_from_long_lat(PG_FUNCTION_ARGS); /* * Create a spherical point from longitude and latitude both in degrees. */ -Datum spherepoint_from_long_lat_deg(PG_FUNCTION_ARGS); + +extern Datum spherepoint_from_long_lat_deg(PG_FUNCTION_ARGS); /* * Calculate the distance between two spherical points. */ -Datum spherepoint_distance(PG_FUNCTION_ARGS); +extern Datum spherepoint_distance(PG_FUNCTION_ARGS); /* * Longitude of a spherical point. */ -Datum spherepoint_long(PG_FUNCTION_ARGS); +extern Datum spherepoint_long(PG_FUNCTION_ARGS); /* * Latitude of a spherical point. */ -Datum spherepoint_lat(PG_FUNCTION_ARGS); +extern Datum spherepoint_lat(PG_FUNCTION_ARGS); /* * Cartesian x-value of a spherical point. */ -Datum spherepoint_x(PG_FUNCTION_ARGS); +extern Datum spherepoint_x(PG_FUNCTION_ARGS); /* * Cartesian y-value of a spherical point. */ -Datum spherepoint_y(PG_FUNCTION_ARGS); +extern Datum spherepoint_y(PG_FUNCTION_ARGS); /* * Cartesian z-value of a spherical point. */ -Datum spherepoint_z(PG_FUNCTION_ARGS); +extern Datum spherepoint_z(PG_FUNCTION_ARGS); /* * Cartesian values of a spherical point as an array. */ -Datum spherepoint_xyz(PG_FUNCTION_ARGS); +extern Datum spherepoint_xyz(PG_FUNCTION_ARGS); /* * Check whether two points are equal. */ -Datum spherepoint_equal(PG_FUNCTION_ARGS); +extern Datum spherepoint_equal(PG_FUNCTION_ARGS); /* * Compute a 32-bit hash value of a point. */ -Datum spherepoint_hash32(PG_FUNCTION_ARGS); +extern Datum spherepoint_hash32(PG_FUNCTION_ARGS); #endif diff --git a/src/polygon.h b/src/polygon.h index b8c754d..0233c41 100644 --- a/src/polygon.h +++ b/src/polygon.h @@ -12,9 +12,9 @@ */ typedef struct { - char vl_len_[4]; /* total size in bytes */ - int32 npts; /* count of points */ - SPoint p[1]; /* variable length array of SPoints */ + char vl_len_[4]; /* total size in bytes */ + int32 npts; /* count of points */ + SPoint p[1]; /* variable length array of SPoints */ } SPOLY; #define MAX_POINTS 1024 @@ -26,20 +26,20 @@ typedef struct #define PGS_ELLIPSE_POLY_OVER 3 /* ellipse overlaps polygon */ /* Polygon and circle */ -#define PGS_CIRCLE_POLY_AVOID 0 /* circle avoids polygon */ -#define PGS_POLY_CONT_CIRCLE 1 /* polygon contains circle */ -#define PGS_CIRCLE_CONT_POLY 2 /* circle contains polygon */ -#define PGS_CIRCLE_POLY_OVER 3 /* circle overlap polygon */ +#define PGS_CIRCLE_POLY_AVOID 0 /* circle avoids polygon */ +#define PGS_POLY_CONT_CIRCLE 1 /* polygon contains circle */ +#define PGS_CIRCLE_CONT_POLY 2 /* circle contains polygon */ +#define PGS_CIRCLE_POLY_OVER 3 /* circle overlap polygon */ /* Polygon and line */ -#define PGS_LINE_POLY_AVOID 0 /* line avoids polygon */ -#define PGS_POLY_CONT_LINE 1 /* polygon contains line */ -#define PGS_LINE_POLY_OVER 2 /* line overlap polygon */ +#define PGS_LINE_POLY_AVOID 0 /* line avoids polygon */ +#define PGS_POLY_CONT_LINE 1 /* polygon contains line */ +#define PGS_LINE_POLY_OVER 2 /* line overlap polygon */ /* Polygon and polygon */ -#define PGS_POLY_AVOID 0 /* polygon avoids other polygon */ -#define PGS_POLY_CONT 1 /* polygon contains other polygon */ -#define PGS_POLY_OVER 2 /* polygons overlap */ +#define PGS_POLY_AVOID 0 /* polygon avoids other polygon */ +#define PGS_POLY_CONT 1 /* polygon contains other polygon */ +#define PGS_POLY_OVER 2 /* polygons overlap */ #define PG_GETARG_SPOLY( arg ) \ @@ -53,7 +53,7 @@ typedef struct * * If 'dir' is true, check with reverse polygon of 'p2'. */ -bool spoly_eq(const SPOLY *p1, const SPOLY *p2, bool dir); +extern bool spoly_eq(const SPOLY *p1, const SPOLY *p2, bool dir); /* * Returns the i-th line segment of a polygon. @@ -62,7 +62,7 @@ bool spoly_eq(const SPOLY *p1, const SPOLY *p2, bool dir); * poly - pointer to the polygon * i - number of the segment */ -bool spoly_segment(SLine *sl, const SPOLY *poly, int32 i); +extern bool spoly_segment(SLine *sl, const SPOLY *poly, int32 i); /* * Checks whether a polygon contains a point. @@ -70,12 +70,12 @@ bool spoly_segment(SLine *sl, const SPOLY *poly, int32 i); * pg - pointer to the polygon * sp - pointer to the point */ -bool spoly_contains_point(const SPOLY *pg, const SPoint *sp); +extern bool spoly_contains_point(const SPOLY *pg, const SPoint *sp); /* * Returns the n-th point of a spoly. */ -Datum spherepoly_get_point(PG_FUNCTION_ARGS); +extern Datum spherepoly_get_point(PG_FUNCTION_ARGS); /* * Returns the relationship between a polygon and a line as @@ -84,295 +84,295 @@ Datum spherepoly_get_point(PG_FUNCTION_ARGS); * poly - pointer to the polygon * line - pointer to the line */ -int8 poly_line_pos(const SPOLY *poly, const SLine *line); +extern int8 poly_line_pos(const SPOLY *poly, const SLine *line); /* * Creates a spherical polygon (spoly) from an array of pair-consecutive * numbers (lng, lat), in radians. */ -Datum spherepoly_rad(PG_FUNCTION_ARGS); +extern Datum spherepoly_rad(PG_FUNCTION_ARGS); /* * Creates a spherical polygon (spoly) from an array of pair-consecutive * numbers (lng, lat), in degrees. */ -Datum spherepoly_deg(PG_FUNCTION_ARGS); +extern Datum spherepoly_deg(PG_FUNCTION_ARGS); /* * Creates a spherical polygon (spoly) from an array of spoint elements. */ -Datum spherepoly_from_point_array(PG_FUNCTION_ARGS); +extern Datum spherepoly_from_point_array(PG_FUNCTION_ARGS); /* * Input of a spherical polygon. */ -Datum spherepoly_in(PG_FUNCTION_ARGS); +extern Datum spherepoly_in(PG_FUNCTION_ARGS); /* * Checks whether two polygons are equal. */ -Datum spherepoly_equal(PG_FUNCTION_ARGS); +extern Datum spherepoly_equal(PG_FUNCTION_ARGS); /* * Checks whether two polygons are not equal. */ -Datum spherepoly_equal_neg(PG_FUNCTION_ARGS); +extern Datum spherepoly_equal_neg(PG_FUNCTION_ARGS); /* * Circumstance of a polygon. Returns circumference in radians * (float8 datum). */ -Datum spherepoly_circ(PG_FUNCTION_ARGS); +extern Datum spherepoly_circ(PG_FUNCTION_ARGS); /* * Count points (edges) of a polygon. */ -Datum spherepoly_npts(PG_FUNCTION_ARGS); +extern Datum spherepoly_npts(PG_FUNCTION_ARGS); /* * Returns area of a polygon. */ -Datum spherepoly_area(PG_FUNCTION_ARGS); +extern Datum spherepoly_area(PG_FUNCTION_ARGS); /* * Checks whether a polygon contains a point. */ -Datum spherepoly_cont_point(PG_FUNCTION_ARGS); +extern Datum spherepoly_cont_point(PG_FUNCTION_ARGS); /* * Checks whether a polygon doesn't contain a point. */ -Datum spherepoly_cont_point_neg(PG_FUNCTION_ARGS); +extern Datum spherepoly_cont_point_neg(PG_FUNCTION_ARGS); /* * Checks whether a polygon contains a point. */ -Datum spherepoly_cont_point_com(PG_FUNCTION_ARGS); +extern Datum spherepoly_cont_point_com(PG_FUNCTION_ARGS); /* * Checks whether a polygon doesn't contain a point. */ -Datum spherepoly_cont_point_com_neg(PG_FUNCTION_ARGS); +extern Datum spherepoly_cont_point_com_neg(PG_FUNCTION_ARGS); /* * Checks whether a polygon contains a circle. */ -Datum spherepoly_cont_circle(PG_FUNCTION_ARGS); +extern Datum spherepoly_cont_circle(PG_FUNCTION_ARGS); /* * Checks whether a polygon doesn't contain a circle. */ -Datum spherepoly_cont_circle_neg(PG_FUNCTION_ARGS); +extern Datum spherepoly_cont_circle_neg(PG_FUNCTION_ARGS); /* * Checks whether a polygon contains a circle. */ -Datum spherepoly_cont_circle_com(PG_FUNCTION_ARGS); +extern Datum spherepoly_cont_circle_com(PG_FUNCTION_ARGS); /* * Checks whether a polygon doesn't contain a circle. */ -Datum spherepoly_cont_circle_com_neg(PG_FUNCTION_ARGS); +extern Datum spherepoly_cont_circle_com_neg(PG_FUNCTION_ARGS); /* * Checks whether a circle contains a polygon. */ -Datum spherecircle_cont_poly(PG_FUNCTION_ARGS); +extern Datum spherecircle_cont_poly(PG_FUNCTION_ARGS); /* * Checks whether a circle doesn't contain a polygon. */ -Datum spherecircle_cont_poly_neg(PG_FUNCTION_ARGS); +extern Datum spherecircle_cont_poly_neg(PG_FUNCTION_ARGS); /* * Checks whether a circle contains a polygon. */ -Datum spherecircle_cont_poly_com(PG_FUNCTION_ARGS); +extern Datum spherecircle_cont_poly_com(PG_FUNCTION_ARGS); /* * Checks whether a circle doesn't contain a polygon. */ -Datum spherecircle_cont_poly_com_neg(PG_FUNCTION_ARGS); +extern Datum spherecircle_cont_poly_com_neg(PG_FUNCTION_ARGS); /* * Checks whether a polygon and a circle overlap. */ -Datum spherepoly_overlap_circle(PG_FUNCTION_ARGS); +extern Datum spherepoly_overlap_circle(PG_FUNCTION_ARGS); /* * Checks whether a polygon and a circle don't overlap. */ -Datum spherepoly_overlap_circle_neg(PG_FUNCTION_ARGS); +extern Datum spherepoly_overlap_circle_neg(PG_FUNCTION_ARGS); /* * Checks whether a polygon and a circle overlap. */ -Datum spherepoly_overlap_circle_com(PG_FUNCTION_ARGS); +extern Datum spherepoly_overlap_circle_com(PG_FUNCTION_ARGS); /* * Checks whether a polygon and a circle don't overlap. */ -Datum spherepoly_overlap_circle_com_neg(PG_FUNCTION_ARGS); +extern Datum spherepoly_overlap_circle_com_neg(PG_FUNCTION_ARGS); /* * Checks whether a polygon contains a line. */ -Datum spherepoly_cont_line(PG_FUNCTION_ARGS); +extern Datum spherepoly_cont_line(PG_FUNCTION_ARGS); /* * Checks whether a polygon doesn't contain a line. */ -Datum spherepoly_cont_line_neg(PG_FUNCTION_ARGS); +extern Datum spherepoly_cont_line_neg(PG_FUNCTION_ARGS); /* * Checks whether a polygon contains a line. */ -Datum spherepoly_cont_line_com(PG_FUNCTION_ARGS); +extern Datum spherepoly_cont_line_com(PG_FUNCTION_ARGS); /* * Checks whether a polygon doesn't contain a line. */ -Datum spherepoly_cont_line_com_neg(PG_FUNCTION_ARGS); +extern Datum spherepoly_cont_line_com_neg(PG_FUNCTION_ARGS); /* * Checks whether a polygon and a line overlap. */ -Datum spherepoly_overlap_line(PG_FUNCTION_ARGS); +extern Datum spherepoly_overlap_line(PG_FUNCTION_ARGS); /* * Checks whether a polygon and a line don't overlap. */ -Datum spherepoly_overlap_line_neg(PG_FUNCTION_ARGS); +extern Datum spherepoly_overlap_line_neg(PG_FUNCTION_ARGS); /* * Checks whether a polygon and a line overlap. */ -Datum spherepoly_overlap_line_com(PG_FUNCTION_ARGS); +extern Datum spherepoly_overlap_line_com(PG_FUNCTION_ARGS); /* * Checks whether a polygon and a line don't overlap. */ -Datum spherepoly_overlap_line_com_neg(PG_FUNCTION_ARGS); +extern Datum spherepoly_overlap_line_com_neg(PG_FUNCTION_ARGS); /* * Checks whether a polygon contains other polygon. */ -Datum spherepoly_cont_poly(PG_FUNCTION_ARGS); +extern Datum spherepoly_cont_poly(PG_FUNCTION_ARGS); /* * Checks whether a polygon doesn't contain other polygon. */ -Datum spherepoly_cont_poly_neg(PG_FUNCTION_ARGS); +extern Datum spherepoly_cont_poly_neg(PG_FUNCTION_ARGS); /* * Checks whether a polygon contains other polygon. */ -Datum spherepoly_cont_poly_com(PG_FUNCTION_ARGS); +extern Datum spherepoly_cont_poly_com(PG_FUNCTION_ARGS); /* * Checks whether a polygon doesn't contain other polygon. */ -Datum spherepoly_cont_poly_com_neg(PG_FUNCTION_ARGS); +extern Datum spherepoly_cont_poly_com_neg(PG_FUNCTION_ARGS); /* * Checks whether two polygons overlap. */ -Datum spherepoly_overlap_poly(PG_FUNCTION_ARGS); +extern Datum spherepoly_overlap_poly(PG_FUNCTION_ARGS); /* * Checks whether two polygons don't overlap. */ -Datum spherepoly_overlap_poly_neg(PG_FUNCTION_ARGS); +extern Datum spherepoly_overlap_poly_neg(PG_FUNCTION_ARGS); /* * Checks whether a polygon contains an ellipse. */ -Datum spherepoly_cont_ellipse(PG_FUNCTION_ARGS); +extern Datum spherepoly_cont_ellipse(PG_FUNCTION_ARGS); /* * Checks whether a polygon doesn't contain an ellipse. */ -Datum spherepoly_cont_ellipse_neg(PG_FUNCTION_ARGS); +extern Datum spherepoly_cont_ellipse_neg(PG_FUNCTION_ARGS); /* * Checks whether a polygon contains an ellipse. */ -Datum spherepoly_cont_ellipse_com(PG_FUNCTION_ARGS); +extern Datum spherepoly_cont_ellipse_com(PG_FUNCTION_ARGS); /* * Checks whether a polygon doesn't contain an ellipse. */ -Datum spherepoly_cont_ellipse_com_neg(PG_FUNCTION_ARGS); +extern Datum spherepoly_cont_ellipse_com_neg(PG_FUNCTION_ARGS); /* * Checks whether an ellipse contains a polygon. */ -Datum sphereellipse_cont_poly(PG_FUNCTION_ARGS); +extern Datum sphereellipse_cont_poly(PG_FUNCTION_ARGS); /* * Checks whether an ellipse doesn't contain a polygon. */ -Datum sphereellipse_cont_poly_neg(PG_FUNCTION_ARGS); +extern Datum sphereellipse_cont_poly_neg(PG_FUNCTION_ARGS); /* * Checks whether an ellipse contains a polygon. */ -Datum sphereellipse_cont_poly_com(PG_FUNCTION_ARGS); +extern Datum sphereellipse_cont_poly_com(PG_FUNCTION_ARGS); /* * Checks whether an ellipse doesn't contain a polygon. */ -Datum sphereellipse_cont_poly_com_neg(PG_FUNCTION_ARGS); +extern Datum sphereellipse_cont_poly_com_neg(PG_FUNCTION_ARGS); /* * Checks whether a polygon and an ellipse overlap. */ -Datum spherepoly_overlap_ellipse(PG_FUNCTION_ARGS); +extern Datum spherepoly_overlap_ellipse(PG_FUNCTION_ARGS); /* * Checks whether a polygon and an ellipse don't overlap. */ -Datum spherepoly_overlap_ellipse_neg(PG_FUNCTION_ARGS); +extern Datum spherepoly_overlap_ellipse_neg(PG_FUNCTION_ARGS); /* * Checks whether a polygon and an ellipse overlap. */ -Datum spherepoly_overlap_ellipse_com(PG_FUNCTION_ARGS); +extern Datum spherepoly_overlap_ellipse_com(PG_FUNCTION_ARGS); /* * Checks whether a polygon and an ellipse don't overlap. */ -Datum spherepoly_overlap_ellipse_com_neg(PG_FUNCTION_ARGS); +extern Datum spherepoly_overlap_ellipse_com_neg(PG_FUNCTION_ARGS); /* * Performs inverse transform on a polygon using an Euler transformation. */ -Datum spheretrans_poly(PG_FUNCTION_ARGS); +extern Datum spheretrans_poly(PG_FUNCTION_ARGS); /* * Performs inverse transform on a polygon using an Euler transformation. */ -Datum spheretrans_poly_inverse(PG_FUNCTION_ARGS); +extern Datum spheretrans_poly_inverse(PG_FUNCTION_ARGS); /* * State transition function for the aggregate function spoly(spoint). Never * call this function outside an aggregate function! Adds a point to a polygon. */ -Datum spherepoly_add_point(PG_FUNCTION_ARGS); +extern Datum spherepoly_add_point(PG_FUNCTION_ARGS); /* * Finalize function for adding spoints to a polygon. */ -Datum spherepoly_add_points_finalize(PG_FUNCTION_ARGS); +extern Datum spherepoly_add_points_finalize(PG_FUNCTION_ARGS); /* * Returns spoly as array of points */ -Datum spherepoly_get_array(PG_FUNCTION_ARGS); +extern Datum spherepoly_get_array(PG_FUNCTION_ARGS); /* * Checks whether a polygon is convex */ -Datum spherepoly_is_convex(PG_FUNCTION_ARGS); +extern Datum spherepoly_is_convex(PG_FUNCTION_ARGS); #endif diff --git a/src/sbuffer.h b/src/sbuffer.h index 57599ee..b16f152 100644 --- a/src/sbuffer.h +++ b/src/sbuffer.h @@ -3,89 +3,89 @@ /* Parser buffer declarations */ -#define STYPE_UNKNOWN 0 /* unknown type */ -#define STYPE_POINT 1 /* input is spherical type */ -#define STYPE_CIRCLE 2 /* input is spherical circle */ -#define STYPE_LINE 3 /* input is spherical line */ -#define STYPE_EULER 4 /* input is Euler transformation */ -#define STYPE_PATH 5 /* input is spherical path or polygon */ -#define STYPE_ELLIPSE 6 /* input is spherical ellipse */ -#define STYPE_BOX 7 /* input is spherical box */ +#define STYPE_UNKNOWN 0 /* unknown type */ +#define STYPE_POINT 1 /* input is spherical type */ +#define STYPE_CIRCLE 2 /* input is spherical circle */ +#define STYPE_LINE 3 /* input is spherical line */ +#define STYPE_EULER 4 /* input is Euler transformation */ +#define STYPE_PATH 5 /* input is spherical path or polygon */ +#define STYPE_ELLIPSE 6 /* input is spherical ellipse */ +#define STYPE_BOX 7 /* input is spherical box */ /* PGS_EULER_AXIS Euler axis */ -#define EULER_AXIS_X 1 /* x - axis for Euler transformation */ -#define EULER_AXIS_Y 2 /* y - axis for Euler transformation */ -#define EULER_AXIS_Z 3 /* z - axis for Euler transformation */ +#define EULER_AXIS_X 1 /* x - axis for Euler transformation */ +#define EULER_AXIS_Y 2 /* y - axis for Euler transformation */ +#define EULER_AXIS_Z 3 /* z - axis for Euler transformation */ -int sphere_yylex(); -void sphere_yyerror(const char *str); -void sphere_flush_scanner_buffer(void); +extern int sphere_yylex(); +extern void sphere_yyerror(const char *str); +extern void sphere_flush_scanner_buffer(void); /* Sets the data type */ -void set_spheretype(unsigned char st); +extern void set_spheretype(unsigned char st); /* Initialize the input buffer */ -void init_buffer(char *buffer); +extern void init_buffer(char *buffer); /* Resets the input buffer */ -void reset_buffer(void); +extern void reset_buffer(void); /* * Read the "offset" number of bytes from "buf" buffer. * Returns the number of read bytes. */ -int get_buffer(char *buf, int offset); +extern int get_buffer(char *buf, int offset); /* * Input of an angle. When is_deg > 0 then "a" is in degrees, * otherwise it's in radians. Returns the unique ID (position) of the angle. */ -int set_angle(unsigned char is_deg, double a); +extern int set_angle(unsigned char is_deg, double a); /* * Set the sign of an angle. "apos" is the angle. "s" is a sign of the angle * ( < 0 .. - , > 0 .. + ). Returns the unique ID (position) of the angle. */ -int set_angle_sign(int apos, int s); +extern int set_angle_sign(int apos, int s); /* * Creates a spherical point. "lngpos" is the ID of a longitude angle, "latpos" * is the ID of a latitude angle. Returns the unique ID (position) of the spherical * point. */ -int set_point(int lngpos, int latpos); +extern int set_point(int lngpos, int latpos); /* * Creates a spherical circle. "spos" is the ID of a spherical point, "rpos" * is the ID of a radius angle. */ -void set_circle(int spos, int rpos); +extern void set_circle(int spos, int rpos); /* * Sets the length of a spherical line. "length" is the ID of a length angle. */ -void set_line(int length); +extern void set_line(int length); /* * Creates an Euler transformation. "phi" is the ID of a first angle, * "theta" is the ID of a second angle, "psi" is the ID of a third angle, * "etype" is the three letter code of Euler transformation axes. */ -void set_euler(int phi, int theta, int psi, char *etype); +extern void set_euler(int phi, int theta, int psi, char *etype); /* * Creates a spherical ellipse. "r1" is the ID of a first radius angle, * "r2" is the ID of a second radius angle, "sp" is the ID of a spherical * point ( center ), "inc" is the ID of an inclination angle. */ -void set_ellipse(int r1, int r2, int sp, int inc); +extern void set_ellipse(int r1, int r2, int sp, int inc); /* * Returns the point parameters. "lng" is the pointer to a longitude * value, "lat" is the pointer to a latitude value. Returns 0 if user * input is a spherical point. */ -int get_point(double *lng, double *lat); +extern int get_point(double *lng, double *lat); /* * Returns the circle parameters. "lng" is pointer to a longitude @@ -93,7 +93,7 @@ int get_point(double *lng, double *lat); * "radius" is the pointer to the radius value. Returns 0 if user input * is a spherical circle. */ -int get_circle(double *lng, double *lat, double *radius); +extern int get_circle(double *lng, double *lat, double *radius); /* * Returns the ellipse parameters. "lng" is the pointer to a longitude value @@ -102,8 +102,8 @@ int get_circle(double *lng, double *lat, double *radius); * radius value, "inc" is the pointer to an inclination angle. Returns 0 if user * input is a spherical ellipse. */ -int get_ellipse(double *lng, double *lat, double *r1, - double *r2, double *inc); +extern int get_ellipse(double *lng, double *lat, double *r1, + double *r2, double *inc); /* * Returns the line parameters. "phi" is the pointer to the first angle @@ -112,8 +112,8 @@ int get_ellipse(double *lng, double *lat, double *r1, * "etype" is the pointer to the axes value of Euler transformation, "length" is * the pointer to the length value. Returns 0 if user input is a spherical line. */ -int get_line(double *phi, double *theta, double *psi, - unsigned char *etype, double *length); +extern int get_line(double *phi, double *theta, double *psi, + unsigned char *etype, double *length); /* * Returns the Euler transformation parameters. "phi" is the pointer to the @@ -122,20 +122,20 @@ int get_line(double *phi, double *theta, double *psi, * transformation, "etype" is the pointer to the axes value of Euler transformation. * Returns 0 if user input is an Euler transformation. */ -int get_euler(double *phi, double *theta, - double *psi, unsigned char *etype); +extern int get_euler(double *phi, double *theta, + double *psi, unsigned char *etype); /* * Returns the number of path elements. */ -int get_path_count(void); +extern int get_path_count(void); /* * Returns the elements of a path. "spos" is the number of element, "lng" is * the ID of longitude angle, "lat" is the ID of a latitude angle. Returns 0 * if user input is a path or a polygon and "spos" is valid. */ -int get_path_elem(int spos, double *lng, double *lat); +extern int get_path_elem(int spos, double *lng, double *lat); /* * Returns the elements of a box. "lng1" is the ID of the first longitude @@ -143,6 +143,6 @@ int get_path_elem(int spos, double *lng, double *lat); * the second longitude angle, "lat2" is the ID of the second latitude angle. * Returns 0 if user input is a box. */ -int get_box(double *lng1, double *lat1, double *lng2, double *lat2); +extern int get_box(double *lng1, double *lat1, double *lng2, double *lat2); #endif diff --git a/src/sparse.c b/src/sparse.c index f220086..16a65d1 100644 --- a/src/sparse.c +++ b/src/sparse.c @@ -74,7 +74,7 @@ #define yychar sphere_yychar /* First part of user prologue. */ -#line 1 "sparse.y" +#line 1 "src/sparse.y" #include #include @@ -110,7 +110,7 @@ static double human2dec(double d, double m, double s) } -#line 114 "sparse.c" +#line 114 "src/sparse.c" # ifndef YY_NULLPTR # if defined __cplusplus @@ -134,8 +134,8 @@ static double human2dec(double d, double m, double s) /* Use api.header.include to #include this header instead of duplicating it here. */ -#ifndef YY_SPHERE_YY_SPARSE_H_INCLUDED -# define YY_SPHERE_YY_SPARSE_H_INCLUDED +#ifndef YY_SPHERE_YY_SRC_SPARSE_H_INCLUDED +# define YY_SPHERE_YY_SRC_SPARSE_H_INCLUDED /* Debug traces. */ #ifndef YYDEBUG # define YYDEBUG 0 @@ -160,9 +160,9 @@ extern int sphere_yydebug; CLOSEPOINT = 266, OPENARR = 267, CLOSEARR = 268, - SIGN = 269, - INT = 270, - FLOAT = 271, + TOK_SIGN = 269, + TOK_INT = 270, + TOK_FLOAT = 271, EULERAXIS = 272 }; #endif @@ -178,22 +178,22 @@ extern int sphere_yydebug; #define CLOSEPOINT 266 #define OPENARR 267 #define CLOSEARR 268 -#define SIGN 269 -#define INT 270 -#define FLOAT 271 +#define TOK_SIGN 269 +#define TOK_INT 270 +#define TOK_FLOAT 271 #define EULERAXIS 272 /* Value type. */ #if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED union YYSTYPE { -#line 41 "sparse.y" +#line 41 "src/sparse.y" int i; double d; char c[3]; -#line 197 "sparse.c" +#line 197 "src/sparse.c" }; typedef union YYSTYPE YYSTYPE; @@ -206,7 +206,7 @@ extern YYSTYPE sphere_yylval; int sphere_yyparse (void); -#endif /* !YY_SPHERE_YY_SPARSE_H_INCLUDED */ +#endif /* !YY_SPHERE_YY_SRC_SPARSE_H_INCLUDED */ @@ -515,10 +515,11 @@ static const char *const yytname[] = { "$end", "error", "$undefined", "HOUR", "DEG", "MIN", "SEC", "COMMA", "OPENCIRC", "CLOSECIRC", "OPENPOINT", "CLOSEPOINT", "OPENARR", - "CLOSEARR", "SIGN", "INT", "FLOAT", "EULERAXIS", "$accept", "commands", - "command", "number", "angle_lat_us", "angle_long_us", "angle_long", - "angle_lat", "spherepoint", "spherecircle", "eulertrans", "sphereline", - "spherepointlist", "spherepath", "sphereellipse", "spherebox", YY_NULLPTR + "CLOSEARR", "TOK_SIGN", "TOK_INT", "TOK_FLOAT", "EULERAXIS", "$accept", + "commands", "command", "number", "angle_lat_us", "angle_long_us", + "angle_long", "angle_lat", "spherepoint", "spherecircle", "eulertrans", + "sphereline", "spherepointlist", "spherepath", "sphereellipse", + "spherebox", YY_NULLPTR }; #endif @@ -1349,265 +1350,265 @@ yyparse (void) switch (yyn) { case 4: -#line 70 "sparse.y" +#line 70 "src/sparse.y" { set_spheretype( STYPE_POINT ); } -#line 1355 "sparse.c" +#line 1356 "src/sparse.c" break; case 5: -#line 71 "sparse.y" +#line 71 "src/sparse.y" { set_spheretype( STYPE_CIRCLE ); } -#line 1361 "sparse.c" +#line 1362 "src/sparse.c" break; case 6: -#line 72 "sparse.y" +#line 72 "src/sparse.y" { set_spheretype( STYPE_LINE ); } -#line 1367 "sparse.c" +#line 1368 "src/sparse.c" break; case 7: -#line 73 "sparse.y" +#line 73 "src/sparse.y" { set_spheretype( STYPE_EULER ); } -#line 1373 "sparse.c" +#line 1374 "src/sparse.c" break; case 8: -#line 74 "sparse.y" +#line 74 "src/sparse.y" { set_spheretype( STYPE_PATH ); } -#line 1379 "sparse.c" +#line 1380 "src/sparse.c" break; case 9: -#line 75 "sparse.y" +#line 75 "src/sparse.y" { set_spheretype( STYPE_ELLIPSE ); } -#line 1385 "sparse.c" +#line 1386 "src/sparse.c" break; case 10: -#line 76 "sparse.y" +#line 76 "src/sparse.y" { set_spheretype( STYPE_BOX ); } -#line 1391 "sparse.c" +#line 1392 "src/sparse.c" break; case 11: -#line 81 "sparse.y" +#line 81 "src/sparse.y" { (yyval.d) = (yyvsp[0].d); } -#line 1397 "sparse.c" +#line 1398 "src/sparse.c" break; case 12: -#line 82 "sparse.y" +#line 82 "src/sparse.y" { (yyval.d) = (yyvsp[0].i); } -#line 1403 "sparse.c" +#line 1404 "src/sparse.c" break; case 13: -#line 87 "sparse.y" +#line 87 "src/sparse.y" { (yyval.i) = set_angle(0, (yyvsp[0].d) ); } -#line 1409 "sparse.c" +#line 1410 "src/sparse.c" break; case 14: -#line 88 "sparse.y" +#line 88 "src/sparse.y" { (yyval.i) = set_angle(1, human2dec((yyvsp[-1].d), 0, 0) ); } -#line 1415 "sparse.c" +#line 1416 "src/sparse.c" break; case 15: -#line 89 "sparse.y" +#line 89 "src/sparse.y" { (yyval.i) = set_angle(1, human2dec((yyvsp[-1].i), 0, 0) ); } -#line 1421 "sparse.c" +#line 1422 "src/sparse.c" break; case 16: -#line 90 "sparse.y" +#line 90 "src/sparse.y" { (yyval.i) = set_angle(1, human2dec((yyvsp[-2].i), (yyvsp[0].d), 0) ); } -#line 1427 "sparse.c" +#line 1428 "src/sparse.c" break; case 17: -#line 91 "sparse.y" +#line 91 "src/sparse.y" { (yyval.i) = set_angle(1, human2dec((yyvsp[-3].i), (yyvsp[-1].d), 0) ); } -#line 1433 "sparse.c" +#line 1434 "src/sparse.c" break; case 18: -#line 92 "sparse.y" +#line 92 "src/sparse.y" { (yyval.i) = set_angle(1, human2dec((yyvsp[-3].i), (yyvsp[-1].i), 0) ); } -#line 1439 "sparse.c" +#line 1440 "src/sparse.c" break; case 19: -#line 93 "sparse.y" +#line 93 "src/sparse.y" { (yyval.i) = set_angle(1, human2dec((yyvsp[-4].i), (yyvsp[-2].i), (yyvsp[0].d)) ); } -#line 1445 "sparse.c" +#line 1446 "src/sparse.c" break; case 20: -#line 94 "sparse.y" +#line 94 "src/sparse.y" { (yyval.i) = set_angle(1, human2dec((yyvsp[-5].i), (yyvsp[-3].i), (yyvsp[-1].d)) ); } -#line 1451 "sparse.c" +#line 1452 "src/sparse.c" break; case 21: -#line 99 "sparse.y" +#line 99 "src/sparse.y" { (yyval.i) = set_angle(0, (yyvsp[0].d)); } -#line 1457 "sparse.c" +#line 1458 "src/sparse.c" break; case 22: -#line 100 "sparse.y" +#line 100 "src/sparse.y" { (yyval.i) = set_angle(1, human2dec((yyvsp[-1].d), 0, 0)); } -#line 1463 "sparse.c" +#line 1464 "src/sparse.c" break; case 23: -#line 101 "sparse.y" +#line 101 "src/sparse.y" { (yyval.i) = set_angle(1, human2dec((yyvsp[-1].i), 0, 0)); } -#line 1469 "sparse.c" +#line 1470 "src/sparse.c" break; case 24: -#line 102 "sparse.y" +#line 102 "src/sparse.y" { (yyval.i) = set_angle(1, human2dec((yyvsp[-2].i), (yyvsp[0].d), 0)); } -#line 1475 "sparse.c" +#line 1476 "src/sparse.c" break; case 25: -#line 103 "sparse.y" +#line 103 "src/sparse.y" { (yyval.i) = set_angle(1, human2dec((yyvsp[-3].i), (yyvsp[-1].d), 0)); } -#line 1481 "sparse.c" +#line 1482 "src/sparse.c" break; case 26: -#line 104 "sparse.y" +#line 104 "src/sparse.y" { (yyval.i) = set_angle(1, human2dec((yyvsp[-3].i), (yyvsp[-1].i), 0)); } -#line 1487 "sparse.c" +#line 1488 "src/sparse.c" break; case 27: -#line 105 "sparse.y" +#line 105 "src/sparse.y" { (yyval.i) = set_angle(1, human2dec((yyvsp[-4].i), (yyvsp[-2].i), (yyvsp[0].d))); } -#line 1493 "sparse.c" +#line 1494 "src/sparse.c" break; case 28: -#line 106 "sparse.y" +#line 106 "src/sparse.y" { (yyval.i) = set_angle(1, human2dec((yyvsp[-5].i), (yyvsp[-3].i), (yyvsp[-1].d))); } -#line 1499 "sparse.c" +#line 1500 "src/sparse.c" break; case 29: -#line 107 "sparse.y" +#line 107 "src/sparse.y" { (yyval.i) = set_angle(1, 15 * human2dec((yyvsp[-2].i), (yyvsp[0].d), 0)); } -#line 1505 "sparse.c" +#line 1506 "src/sparse.c" break; case 30: -#line 108 "sparse.y" +#line 108 "src/sparse.y" { (yyval.i) = set_angle(1, 15 * human2dec((yyvsp[-4].i), (yyvsp[-2].i), (yyvsp[0].d))); } -#line 1511 "sparse.c" +#line 1512 "src/sparse.c" break; case 31: -#line 109 "sparse.y" +#line 109 "src/sparse.y" { (yyval.i) = set_angle(1, 15 * human2dec((yyvsp[-5].i), (yyvsp[-3].i), (yyvsp[-1].d))); } -#line 1517 "sparse.c" +#line 1518 "src/sparse.c" break; case 32: -#line 114 "sparse.y" +#line 114 "src/sparse.y" { (yyval.i) = set_angle_sign((yyvsp[0].i), 1); } -#line 1523 "sparse.c" +#line 1524 "src/sparse.c" break; case 33: -#line 115 "sparse.y" +#line 115 "src/sparse.y" { (yyval.i) = set_angle_sign((yyvsp[0].i), (yyvsp[-1].i)); } -#line 1529 "sparse.c" +#line 1530 "src/sparse.c" break; case 34: -#line 120 "sparse.y" +#line 120 "src/sparse.y" { (yyval.i) = set_angle_sign((yyvsp[0].i), 1); } -#line 1535 "sparse.c" +#line 1536 "src/sparse.c" break; case 35: -#line 121 "sparse.y" +#line 121 "src/sparse.y" { (yyval.i) = set_angle_sign((yyvsp[0].i), (yyvsp[-1].i)); } -#line 1541 "sparse.c" +#line 1542 "src/sparse.c" break; case 36: -#line 128 "sparse.y" +#line 128 "src/sparse.y" { (yyval.i) = set_point((yyvsp[-3].i), (yyvsp[-1].i)); } -#line 1549 "sparse.c" +#line 1550 "src/sparse.c" break; case 37: -#line 136 "sparse.y" +#line 136 "src/sparse.y" { set_circle((yyvsp[-3].i), (yyvsp[-1].i)); } -#line 1557 "sparse.c" +#line 1558 "src/sparse.c" break; case 38: -#line 144 "sparse.y" +#line 144 "src/sparse.y" { set_euler((yyvsp[-4].i), (yyvsp[-2].i), (yyvsp[0].i), "ZXZ"); } -#line 1565 "sparse.c" +#line 1566 "src/sparse.c" break; case 39: -#line 148 "sparse.y" +#line 148 "src/sparse.y" { set_euler((yyvsp[-6].i), (yyvsp[-4].i), (yyvsp[-2].i), (yyvsp[0].c)); } -#line 1573 "sparse.c" +#line 1574 "src/sparse.c" break; case 40: -#line 156 "sparse.y" +#line 156 "src/sparse.y" { set_line ((yyvsp[0].i)); } -#line 1581 "sparse.c" +#line 1582 "src/sparse.c" break; case 43: -#line 168 "sparse.y" +#line 168 "src/sparse.y" { } -#line 1587 "sparse.c" +#line 1588 "src/sparse.c" break; case 44: -#line 174 "sparse.y" +#line 174 "src/sparse.y" { set_ellipse((yyvsp[-8].i), (yyvsp[-6].i), (yyvsp[-3].i), (yyvsp[-1].i)); } -#line 1595 "sparse.c" +#line 1596 "src/sparse.c" break; case 45: -#line 181 "sparse.y" +#line 181 "src/sparse.y" { } -#line 1601 "sparse.c" +#line 1602 "src/sparse.c" break; case 46: -#line 182 "sparse.y" +#line 182 "src/sparse.y" { } -#line 1607 "sparse.c" +#line 1608 "src/sparse.c" break; -#line 1611 "sparse.c" +#line 1612 "src/sparse.c" default: break; } diff --git a/src/sparse.h b/src/sparse.h index 032b5fd..c6607ba 100644 --- a/src/sparse.h +++ b/src/sparse.h @@ -34,8 +34,8 @@ /* Undocumented macros, especially those whose name start with YY_, are private implementation details. Do not rely on them. */ -#ifndef YY_SPHERE_YY_SPARSE_H_INCLUDED -# define YY_SPHERE_YY_SPARSE_H_INCLUDED +#ifndef YY_SPHERE_YY_SRC_SPARSE_H_INCLUDED +# define YY_SPHERE_YY_SRC_SPARSE_H_INCLUDED /* Debug traces. */ #ifndef YYDEBUG # define YYDEBUG 0 @@ -60,9 +60,9 @@ extern int sphere_yydebug; CLOSEPOINT = 266, OPENARR = 267, CLOSEARR = 268, - SIGN = 269, - INT = 270, - FLOAT = 271, + TOK_SIGN = 269, + TOK_INT = 270, + TOK_FLOAT = 271, EULERAXIS = 272 }; #endif @@ -78,22 +78,22 @@ extern int sphere_yydebug; #define CLOSEPOINT 266 #define OPENARR 267 #define CLOSEARR 268 -#define SIGN 269 -#define INT 270 -#define FLOAT 271 +#define TOK_SIGN 269 +#define TOK_INT 270 +#define TOK_FLOAT 271 #define EULERAXIS 272 /* Value type. */ #if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED union YYSTYPE { -#line 41 "sparse.y" +#line 41 "src/sparse.y" int i; double d; char c[3]; -#line 97 "sparse.h" +#line 97 "src/sparse.h" }; typedef union YYSTYPE YYSTYPE; @@ -106,4 +106,4 @@ extern YYSTYPE sphere_yylval; int sphere_yyparse (void); -#endif /* !YY_SPHERE_YY_SPARSE_H_INCLUDED */ +#endif /* !YY_SPHERE_YY_SRC_SPARSE_H_INCLUDED */ diff --git a/src/sparse.y b/src/sparse.y index 22e8778..0b65d9f 100644 --- a/src/sparse.y +++ b/src/sparse.y @@ -44,9 +44,9 @@ static double human2dec(double d, double m, double s) char c[3]; } -%token SIGN -%token INT -%token FLOAT +%token TOK_SIGN +%token TOK_INT +%token TOK_FLOAT %token EULERAXIS %left COMMA @@ -78,47 +78,47 @@ command: /* unsigned number */ number : - FLOAT { $$ = $1; } - | INT { $$ = $1; } + TOK_FLOAT { $$ = $1; } + | TOK_INT { $$ = $1; } ; /* unsigned longitude */ angle_lat_us : number { $$ = set_angle(0, $1 ); } - | FLOAT DEG { $$ = set_angle(1, human2dec($1, 0, 0) ); } - | INT DEG { $$ = set_angle(1, human2dec($1, 0, 0) ); } - | INT DEG number { $$ = set_angle(1, human2dec($1, $3, 0) ); } - | INT DEG FLOAT MIN { $$ = set_angle(1, human2dec($1, $3, 0) ); } - | INT DEG INT MIN { $$ = set_angle(1, human2dec($1, $3, 0) ); } - | INT DEG INT MIN number { $$ = set_angle(1, human2dec($1, $3, $5) ); } - | INT DEG INT MIN number SEC { $$ = set_angle(1, human2dec($1, $3, $5) ); } + | TOK_FLOAT DEG { $$ = set_angle(1, human2dec($1, 0, 0) ); } + | TOK_INT DEG { $$ = set_angle(1, human2dec($1, 0, 0) ); } + | TOK_INT DEG number { $$ = set_angle(1, human2dec($1, $3, 0) ); } + | TOK_INT DEG TOK_FLOAT MIN { $$ = set_angle(1, human2dec($1, $3, 0) ); } + | TOK_INT DEG TOK_INT MIN { $$ = set_angle(1, human2dec($1, $3, 0) ); } + | TOK_INT DEG TOK_INT MIN number { $$ = set_angle(1, human2dec($1, $3, $5) ); } + | TOK_INT DEG TOK_INT MIN number SEC { $$ = set_angle(1, human2dec($1, $3, $5) ); } ; /* unsigned latitude */ angle_long_us : number { $$ = set_angle(0, $1); } - | FLOAT DEG { $$ = set_angle(1, human2dec($1, 0, 0)); } - | INT DEG { $$ = set_angle(1, human2dec($1, 0, 0)); } - | INT DEG number { $$ = set_angle(1, human2dec($1, $3, 0)); } - | INT DEG FLOAT MIN { $$ = set_angle(1, human2dec($1, $3, 0)); } - | INT DEG INT MIN { $$ = set_angle(1, human2dec($1, $3, 0)); } - | INT DEG INT MIN number { $$ = set_angle(1, human2dec($1, $3, $5)); } - | INT DEG INT MIN number SEC { $$ = set_angle(1, human2dec($1, $3, $5)); } - | INT HOUR number { $$ = set_angle(1, 15 * human2dec($1, $3, 0)); } - | INT HOUR INT MIN number { $$ = set_angle(1, 15 * human2dec($1, $3, $5)); } - | INT HOUR INT MIN number SEC { $$ = set_angle(1, 15 * human2dec($1, $3, $5)); } + | TOK_FLOAT DEG { $$ = set_angle(1, human2dec($1, 0, 0)); } + | TOK_INT DEG { $$ = set_angle(1, human2dec($1, 0, 0)); } + | TOK_INT DEG number { $$ = set_angle(1, human2dec($1, $3, 0)); } + | TOK_INT DEG TOK_FLOAT MIN { $$ = set_angle(1, human2dec($1, $3, 0)); } + | TOK_INT DEG TOK_INT MIN { $$ = set_angle(1, human2dec($1, $3, 0)); } + | TOK_INT DEG TOK_INT MIN number { $$ = set_angle(1, human2dec($1, $3, $5)); } + | TOK_INT DEG TOK_INT MIN number SEC { $$ = set_angle(1, human2dec($1, $3, $5)); } + | TOK_INT HOUR number { $$ = set_angle(1, 15 * human2dec($1, $3, 0)); } + | TOK_INT HOUR TOK_INT MIN number { $$ = set_angle(1, 15 * human2dec($1, $3, $5)); } + | TOK_INT HOUR TOK_INT MIN number SEC { $$ = set_angle(1, 15 * human2dec($1, $3, $5)); } ; /* longitude */ angle_long : angle_long_us { $$ = set_angle_sign($1, 1); } - | SIGN angle_long_us { $$ = set_angle_sign($2, $1); } + | TOK_SIGN angle_long_us { $$ = set_angle_sign($2, $1); } ; /* latitude */ angle_lat : angle_lat_us { $$ = set_angle_sign($1, 1); } - | SIGN angle_lat_us { $$ = set_angle_sign($2, $1); } + | TOK_SIGN angle_lat_us { $$ = set_angle_sign($2, $1); } ; diff --git a/src/sscan.c b/src/sscan.c index 3d904c6..50e0e70 100644 --- a/src/sscan.c +++ b/src/sscan.c @@ -1,6 +1,6 @@ -#line 2 "sscan.c" +#line 2 "src/sscan.c" -#line 4 "sscan.c" +#line 4 "src/sscan.c" #define YY_INT_ALIGNED short int @@ -722,8 +722,8 @@ int yy_flex_debug = 0; #define YY_MORE_ADJ 0 #define YY_RESTORE_YY_MORE_OFFSET char *yytext; -#line 1 "sscan.l" -#line 2 "sscan.l" +#line 1 "src/sscan.l" +#line 2 "src/sscan.l" #include #include "string.h" #include "sparse.h" @@ -745,8 +745,8 @@ void sphere_flush_scanner_buffer(void) { YY_FLUSH_BUFFER; } -#line 749 "sscan.c" -#line 750 "sscan.c" +#line 749 "src/sscan.c" +#line 750 "src/sscan.c" #define INITIAL 0 @@ -961,9 +961,9 @@ YY_DECL } { -#line 35 "sscan.l" +#line 35 "src/sscan.l" -#line 967 "sscan.c" +#line 967 "src/sscan.c" while ( /*CONSTCOND*/1 ) /* loops until end-of-file is reached */ { @@ -1018,106 +1018,106 @@ YY_DECL case 1: YY_RULE_SETUP -#line 36 "sscan.l" -sphere_yylval.i = (strcmp("-", yytext)) ? (1) : (-1); return SIGN; +#line 36 "src/sscan.l" +sphere_yylval.i = (strcmp("-", yytext)) ? (1) : (-1); return TOK_SIGN; YY_BREAK case 2: YY_RULE_SETUP -#line 37 "sscan.l" -sphere_yylval.i = atoi(yytext); return INT; +#line 37 "src/sscan.l" +sphere_yylval.i = atoi(yytext); return TOK_INT; YY_BREAK case 3: YY_RULE_SETUP -#line 38 "sscan.l" -sphere_yylval.d = atof(yytext); return FLOAT; +#line 38 "src/sscan.l" +sphere_yylval.d = atof(yytext); return TOK_FLOAT; YY_BREAK case 4: YY_RULE_SETUP -#line 39 "sscan.l" +#line 39 "src/sscan.l" memcpy(&sphere_yylval.c[0], yytext, 3); return EULERAXIS; YY_BREAK case 5: YY_RULE_SETUP -#line 40 "sscan.l" +#line 40 "src/sscan.l" return HOUR; YY_BREAK case 6: YY_RULE_SETUP -#line 41 "sscan.l" +#line 41 "src/sscan.l" return DEG; YY_BREAK case 7: YY_RULE_SETUP -#line 42 "sscan.l" +#line 42 "src/sscan.l" return MIN; YY_BREAK case 8: YY_RULE_SETUP -#line 43 "sscan.l" +#line 43 "src/sscan.l" return MIN; YY_BREAK case 9: YY_RULE_SETUP -#line 44 "sscan.l" +#line 44 "src/sscan.l" return SEC; YY_BREAK case 10: YY_RULE_SETUP -#line 45 "sscan.l" +#line 45 "src/sscan.l" return SEC; YY_BREAK case 11: YY_RULE_SETUP -#line 46 "sscan.l" +#line 46 "src/sscan.l" return COMMA; YY_BREAK case 12: YY_RULE_SETUP -#line 47 "sscan.l" +#line 47 "src/sscan.l" return OPENCIRC; YY_BREAK case 13: YY_RULE_SETUP -#line 48 "sscan.l" +#line 48 "src/sscan.l" return CLOSECIRC; YY_BREAK case 14: YY_RULE_SETUP -#line 49 "sscan.l" +#line 49 "src/sscan.l" return OPENPOINT; YY_BREAK case 15: YY_RULE_SETUP -#line 50 "sscan.l" +#line 50 "src/sscan.l" return CLOSEPOINT; YY_BREAK case 16: YY_RULE_SETUP -#line 51 "sscan.l" +#line 51 "src/sscan.l" return OPENARR; YY_BREAK case 17: YY_RULE_SETUP -#line 52 "sscan.l" +#line 52 "src/sscan.l" return CLOSEARR; YY_BREAK case 18: /* rule 18 can match eol */ YY_RULE_SETUP -#line 53 "sscan.l" +#line 53 "src/sscan.l" /* discard spaces */ YY_BREAK case 19: YY_RULE_SETUP -#line 54 "sscan.l" +#line 54 "src/sscan.l" /* alert parser of the garbage */ YY_BREAK case 20: YY_RULE_SETUP -#line 55 "sscan.l" +#line 55 "src/sscan.l" ECHO; YY_BREAK -#line 1121 "sscan.c" +#line 1121 "src/sscan.c" case YY_STATE_EOF(INITIAL): yyterminate(); @@ -2086,6 +2086,6 @@ void yyfree (void * ptr ) #define YYTABLES_NAME "yytables" -#line 55 "sscan.l" +#line 55 "src/sscan.l" diff --git a/src/sscan.l b/src/sscan.l index 99bd8ac..d3103b6 100644 --- a/src/sscan.l +++ b/src/sscan.l @@ -33,9 +33,9 @@ real ({int})?\.({int}) float ({int}|{real})([eE]{sign}{int})? %% -{sign} sphere_yylval.i = (strcmp("-", yytext)) ? (1) : (-1); return SIGN; -{int} sphere_yylval.i = atoi(yytext); return INT; -{float} sphere_yylval.d = atof(yytext); return FLOAT; +{sign} sphere_yylval.i = (strcmp("-", yytext)) ? (1) : (-1); return TOK_SIGN; +{int} sphere_yylval.i = atoi(yytext); return TOK_INT; +{float} sphere_yylval.d = atof(yytext); return TOK_FLOAT; [x-zX-Z]{3} memcpy(&sphere_yylval.c[0], yytext, 3); return EULERAXIS; h return HOUR; d return DEG; diff --git a/src/vector3d.h b/src/vector3d.h index 23ba9b9..47a5a82 100644 --- a/src/vector3d.h +++ b/src/vector3d.h @@ -10,9 +10,9 @@ */ typedef struct { - float8 x; /* x (-1.0 .. 1.0) */ - float8 y; /* y (-1.0 .. 1.0) */ - float8 z; /* z (-1.0 .. 1.0) */ + float8 x; /* x (-1.0 .. 1.0) */ + float8 y; /* y (-1.0 .. 1.0) */ + float8 z; /* z (-1.0 .. 1.0) */ } Vector3D; @@ -20,27 +20,28 @@ typedef struct * Calculate the cross product of two vectors. Puts * cross product of v1 and v2 into out and returns it. */ -void vector3d_cross(Vector3D *out, const Vector3D *v1, const Vector3D *v2); +extern void vector3d_cross(Vector3D *out, const Vector3D *v1, + const Vector3D *v2); /* * Checks equality of two vectors. */ -bool vector3d_eq(const Vector3D *a, const Vector3D *b); +extern bool vector3d_eq(const Vector3D *a, const Vector3D *b); /* * Calculate the scalar product of two vectors. */ -float8 vector3d_scalar(Vector3D *v1, Vector3D *v2); +extern float8 vector3d_scalar(Vector3D *v1, Vector3D *v2); /* * Calculate the length of a vector. */ -float8 vector3d_length(const Vector3D *v); +extern float8 vector3d_length(const Vector3D *v); -/* - * Calculate result + scalar*delta +/* + * Calculate result + scalar*delta */ -void vector3d_addwithscalar( - Vector3D *result, double scalar, const Vector3D *delta); +extern void vector3d_addwithscalar(Vector3D *result, double scalar, + const Vector3D *delta); #endif diff --git a/upgrade_scripts/pg_sphere--1.4.2--1.5.0.sql.in b/upgrade_scripts/pg_sphere--1.4.2--1.5.0.sql.in new file mode 100644 index 0000000..8b2ce2b --- /dev/null +++ b/upgrade_scripts/pg_sphere--1.4.2--1.5.0.sql.in @@ -0,0 +1,21 @@ +-- Upgrade: 1.4.2 -> 1.5.0 + +CREATE OR REPLACE FUNCTION g_spoint_distance(internal, spoint, smallint, oid, internal) + RETURNS internal + AS 'MODULE_PATHNAME', 'g_spoint_distance' + LANGUAGE 'c'; + +DO $$ +BEGIN + ALTER OPERATOR FAMILY spoint USING gist ADD + FUNCTION 8 (spoint, spoint) g_spoint_distance (internal, spoint, smallint, oid, internal); +EXCEPTION + WHEN duplicate_object THEN NULL; + WHEN OTHERS THEN RAISE; +END; +$$; + +CREATE FUNCTION reset_sphere_output_precision() + RETURNS CSTRING + AS 'MODULE_PATHNAME', 'reset_sphere_output_precision' + LANGUAGE 'c'; diff --git a/upgrade_scripts/pg_sphere--1.5.0--1.5.1.sql.in b/upgrade_scripts/pg_sphere--1.5.0--1.5.1.sql.in new file mode 100644 index 0000000..20c7cf6 --- /dev/null +++ b/upgrade_scripts/pg_sphere--1.5.0--1.5.1.sql.in @@ -0,0 +1,11 @@ +-- Upgrade: 1.5.0 -> 1.5.1 + +DO $$ +BEGIN + ALTER OPERATOR FAMILY spoint USING gist ADD + OPERATOR 17 <-> (spoint, spoint) FOR ORDER BY float_ops; +EXCEPTION + WHEN duplicate_object THEN NULL; + WHEN OTHERS THEN RAISE; +END; +$$; diff --git a/upgrade_scripts/pg_sphere--1.5.1--1.5.2.sql.in b/upgrade_scripts/pg_sphere--1.5.1--1.5.2.sql.in new file mode 100644 index 0000000..3ff6a66 --- /dev/null +++ b/upgrade_scripts/pg_sphere--1.5.1--1.5.2.sql.in @@ -0,0 +1,2 @@ +-- Upgrade: 1.5.1 -> 1.5.2 +-- Nothing to do yet