-- Do cached and uncached distance agree?
SELECT c, abs(ST_Distance(ply::geography, pt::geography) - _ST_DistanceUnCached(ply::geography, pt::geography)) < 0.01 FROM
( VALUES
('geog_distance_cached_1a', 'POLYGON((0 0, 0 10, 10 10, 10 0, 0 0))', 'POINT(5 5)'),
('geog_distance_cached_1b', 'POLYGON((0 0, 0 10, 10 10, 10 0, 0 0))', 'POINT(5 5)'),
('geog_distance_cached_1c', 'POLYGON((0 0, 0 10, 10 10, 10 0, 0 0))', 'POINT(5 5)'),
('geog_distance_cached_1e', 'POLYGON((0 0, 0 10, 10 10, 10 0, 0 0))', 'POINT(5 5)'),
('geog_distance_cached_1f', 'POLYGON((0 0, 0 10, 10 10, 10 0, 0 0))', 'POINT(5 5)'),
('geog_distance_cached_1g', 'POLYGON((0 0, 0 10, 10 10, 10 0, 0 0))', 'POINT(5 5)'),
('geog_distance_cached_1h', 'POLYGON((0 0, 0 10, 10 10, 10 0, 0 0))', 'POINT(5 5)')
) AS u(c,ply,pt);

-- Does tolerance based distance work cached? Inside tolerance
SELECT c, ST_DWithin(ply::geography, pt::geography, 3000) from
( VALUES
('geog_dithin_cached_1a', 'POLYGON((0 0, 0 10, 10 10, 10 0, 0 0))', 'POINT(10.01 5)'),
('geog_dithin_cached_1b', 'POLYGON((0 0, 0 10, 10 10, 10 0, 0 0))', 'POINT(10.01 5)'),
('geog_dithin_cached_1c', 'POLYGON((0 0, 0 10, 10 10, 10 0, 0 0))', 'POINT(10.01 5)')
) as p(c, ply, pt);

-- Does tolerance based distance work cached? Outside tolerance
SELECT c, ST_DWithin(ply::geography, pt::geography, 1000) from
( VALUES
('geog_dithin_cached_2a', 'POLYGON((0 0, 0 10, 10 10, 10 0, 0 0))', 'POINT(10.01 5)'),
('geog_dithin_cached_2b', 'POLYGON((0 0, 0 10, 10 10, 10 0, 0 0))', 'POINT(10.01 5)'),
('geog_dithin_cached_2c', 'POLYGON((0 0, 0 10, 10 10, 10 0, 0 0))', 'POINT(10.01 5)')
) as p(c, ply, pt);

-- Do things work when there's cache coherence on the point side but not the poly side?
SELECT c, ST_DWithin(ply::geography, pt::geography, 3000) from
( VALUES
('geog_dithin_cached_3a', 'POLYGON((0 0, 0 10, 10 10, 10 0, 0 0))', 'POINT(5 5)'),
('geog_dithin_cached_3b', 'POLYGON((1 1, 1 10, 10 10, 10 1, 1 1))', 'POINT(5 5)'),
('geog_dithin_cached_3c', 'POLYGON((2 2, 2 10, 10 10, 10 2, 2 2))', 'POINT(5 5)')
) as p(c, ply, pt);

-- Test a precision case near the south pole that came up during development.
WITH pt AS (
    SELECT point::geography FROM ( VALUES
    ('0101000020E61000006C5B94D920EB4CC0A0FD481119B24FC0'),
    ('0101000020E610000097A8DE1AD8524CC09C8A54185B1050C0'),
    ('0101000020E61000008FC2F5285C4F4CC0E5ED08A7050F50C0'),
    ('0101000020E61000008FC2F5285C4F4CC0E5ED08A7050F50C0') ) AS p(point)
),
ply AS (
    SELECT polygon::geography FROM ( VALUES
    ('[encoded data, 13396 characters]')
    ) as q(polygon)
)
SELECT 'geog_precision_savffir', _ST_DistanceUnCached(pt.point, ply.polygon), ST_Distance(pt.point, ply.polygon) FROM pt, ply;

-- Test another precision case near the north poly and over the dateline
WITH pt AS (
    SELECT point::geography FROM ( VALUES
    ('0101000020E610000000000000004065400000000000804840'),
    ('0101000020E610000075C8CD70033965C02176A6D079315040') ) AS p(point)
),
ply AS (
    SELECT polygon::geography FROM ( VALUES
    ('[encoded data, 10306 characters]')
    ) as q(polygon)
)
SELECT 'geog_precision_pazafir', _ST_DistanceUnCached(pt.point, ply.polygon), ST_Distance(pt.point, ply.polygon) FROM pt, ply;

-- #2941
CREATE TABLE test(id integer, geog geography(multilinestring,4269));
INSERT INTO test VALUES (1, 'SRID=4269;MULTILINESTRING((0 0, 1 1))');
SELECT id,ST_AsText(geog) FROM test;
DROP TABLE test;

-- #2422
CREATE TABLE dwithgeogbug (
    gid integer,
    geog geography
);
INSERT INTO dwithgeogbug (gid, geog) VALUES (1, '0103000020E6100000010000000B0000000AA2F068F47651C0F7893DEB70B8454007ABD4C6D57651C000FB650799B84540C21AA2645A7651C011C24BA84AB8454089A9A325E87751C03314EB5453B74540AF9ED96BF57751C0BF9818F889B74540E936A498B47751C0690C87D1C5B74540F5386204DC7751C02FCA658F1AB8454077B65F7B657751C012C586EE37B845408C1862C5977751C00F17E41674B84540D4012F57357751C0AD3BC67E99B845400AA2F068F47651C0F7893DEB70B84540');
INSERT INTO dwithgeogbug (gid, geog) VALUES (2, '[encoded data, 6354 characters]');
SELECT
'#2422' as ticket, gid, radius,
_ST_DWithin(geog, tgeog, radius, true) AS dwithin_t,
_ST_DWithin(geog, tgeog, radius, false) AS dwithin_f,
round(ST_Distance(geog, tgeog, true)::numeric,3) AS distance_t,
round(ST_Distance(geog, tgeog, false)::numeric,3) AS distance_f,
round(_ST_DistanceUnCached(geog, tgeog)::numeric,3) AS distance_uncached,
round(_ST_DistanceTree(geog, tgeog)::numeric,3) AS distance_tree
FROM dwithgeogbug
CROSS JOIN ST_GeogFromText('POINT(-69.83262 43.43636)') AS tgeog
CROSS JOIN (VALUES (1609),(1600),(1068)) AS t (radius)
ORDER BY distance_t;
DROP TABLE dwithgeogbug;

-- Test segmentize on geography
-- Check that the maximum sphere distance over all the segments is lesser than the max distance used for segmentize
WITH
seg as (select ST_Segmentize('LINESTRING(0 0 10,0 90 20)'::geography, 50000)::geometry as geom),
dumped as (SELECT (st_dumppoints(geom)).path[1] as id, (st_dumppoints(geom)).geom from seg)
SELECT 'segmentize_geography', max(st_distance(d1.geom::geography, d2.geom::geography, false))::int FROM dumped as d1, dumped as d2 where d2.id = d1.id + 1;

-- Check that st_segmentize creates segments on the geodesic path
SELECT 'segmentize_geography2', st_dwithin(st_pointn(st_segmentize('linestring(1 47,-64 47)'::geography, 3000000)::geometry, 2), 'SRID=4326;POINT(-31.5 51.81)'::geometry, 0.01);

-- #bug 3667
SELECT 'segmentize_geography_3667', abs(ST_Length(geog) - ST_Length(ST_Segmentize(geog, 30000))) < 0.00001
  FROM (SELECT ST_GeographyFromText('LINESTRING(38.769917 10.780694, 38.769917 9.106194)') As geog) AS f;

-- typmod checks
select 'typmod_point_4326', geography_typmod_out(geography_typmod_in('{Point,4326}'));
select 'typmod_point_0', geography_typmod_out(geography_typmod_in('{Point,0}'));
select 'typmod_point_-1', geography_typmod_out(geography_typmod_in('{Point,-1}'));
select 'typmod_pointzm_0', geography_typmod_out(geography_typmod_in('{PointZM,0}'));
select 'typmod_geometry_0', geography_typmod_out(geography_typmod_in('{Geometry,0}'));
select 'typmod_geometry_4326', geography_typmod_out(geography_typmod_in('{Geometry,4326}'));
select 'typmod_geography_0', geography_typmod_out(geography_typmod_in('{Geogrpahy,0}'));

-- ST_DWithin
select 'dwithin_pt_pt_1', ST_DWithin('POINT(0 0)'::geography, 'POINT(1 1)'::geography, 300000);
select 'dwithin_pt_pt_2', ST_DWithin('POINT(0 0)'::geography, 'POINT(1 1)'::geography, 10);
select 'dwithin_pt_line_1', ST_DWithin('POINT(0 0)'::geography, 'LINESTRING(1 1, 2 2)'::geography, 300000);
select 'dwithin_line_pt_1', ST_DWithin('LINESTRING(1 1, 2 2)'::geography, 'POINT(0 0)'::geography, 300000);
select 'dwithin_pt_poly_1', ST_DWithin('POINT(0 0)'::geography, 'POLYGON((1 1, 2 2, 3 0, 1 1))'::geography, 300000);
select 'dwithin_poly_pt_1', ST_DWithin('POLYGON((1 1, 2 2, 3 0, 1 1))'::geography, 'POINT(0 0)'::geography, 300000);
select 'dwithin_line_poly_1', ST_DWithin('LINESTRING(-1 -1, 0 0)'::geography, 'POLYGON((1 1, 2 2, 3 0, 1 1))'::geography, 300000);
select 'dwithin_poly_line_1', ST_DWithin('POLYGON((1 1, 2 2, 3 0, 1 1))'::geography, 'LINESTRING(-1 -1, 0 0)'::geography, 300000);
select 'dwithin_poly_poly_1', ST_DWithin('POLYGON((0 0, -2 -2, -3 0, 0 0))'::geography, 'POLYGON((1 1, 2 2, 3 0, 1 1))'::geography, 10);
select 'dwithin_poly_poly_2', ST_DWithin('POLYGON((0 0, -2 -2, -3 0, 0 0))'::geography, 'POLYGON((1 1, 2 2, 3 0, 1 1))'::geography, 300000);
select 'dwithin_poly_poly_3', ST_DWithin('POLYGON((1 1, -2 -2, -3 0, 1 1))'::geography, 'POLYGON((1 1, 2 2, 3 0, 1 1))'::geography, 300000);


-- Linear Referencing functions
-- #5456 garden crash
SELECT '#5456' As ticket, ST_LineLocatePoint('0102000020E610000001000000000000000000F03F0000000000000040'::geography, 'POINT(-11.1111111 40)'::geography, false);
SELECT 'lrs_empty_1', ST_LineInterpolatePoint(geography 'Linestring empty', 0.1);
SELECT 'lrs_empty_2', ST_LineInterpolatePoints(geography 'Linestring empty', 0.1, true);
SELECT 'lrs_empty_3', ST_LineLocatePoint(geography 'Linestring empty', 'Point(45 45)', true);
SELECT 'lrs_empty_4', ST_LineSubstring(geography 'Linestring empty', 0.1, 0.2);
SELECT 'lrs_empty_5', ST_ClosestPoint(geography 'Linestring empty', 'Point(45 45)', true);
SELECT 'lrs_empty_6', ST_ShortestLine(geography 'Linestring empty', 'Point(45 45)', true);

SELECT 'lrs_lip_1', ST_AsText(ST_LineInterpolatePoint(geography 'Linestring(4.35 50.85, 37.617222 55.755833)', 0.0), 2);
SELECT 'lrs_lip_2', ST_AsText(ST_LineInterpolatePoints(geography 'Linestring(4.35 50.85, 37.617222 55.755833)', 0.0, true), 2);
SELECT 'lrs_lip_3', ST_AsText(ST_LineInterpolatePoints(geography 'Linestring(4.35 50.85, 37.617222 55.755833)', 1.0, false), 2);
SELECT 'lrs_lip_4', ST_AsText(ST_LineInterpolatePoints(geography 'Linestring(4.35 50.85, 37.617222 55.755833)', 0.1, true), 2);
SELECT 'lrs_lip_5', ST_AsText(ST_LineInterpolatePoints(geography 'Linestring(4.35 50.85, 37.617222 55.755833)', 0.1, false), 2);

SELECT 'lrs_llp_1', round(ST_LineLocatePoint(geography 'linestring(0 1, 50 1)', geography 'Point(25 0)')::numeric, 2);
SELECT 'lrs_llp_2', round(ST_LineLocatePoint(geography 'linestring(0 1, 50 1)', geography 'Point(-5 0)')::numeric, 2);
SELECT 'lrs_llp_3', round(ST_LineLocatePoint(geography 'linestring(0 1, 50 1)', geography 'Point(55 0)')::numeric, 2);
SELECT 'lrs_llp_4', round(ST_LineLocatePoint(geography 'linestring(0 1, 50 1)', geography 'Linestring(25 0,26 1)')::numeric, 2);

SELECT 'lrs_substr_1', ST_AsText(ST_LineSubstring(geography 'linestring(0 20, 100 20)', 0.1, 0.2),2);

--SELECT 'lrs_cp_1', ST_AsText(ST_ClosestPoint(geography 'Linestring(0 20, 50 20)', 'Point(25 20)'), 3);
--SELECT 'lrs_cp_2', ST_AsText(ST_ClosestPoint(geography 'Point(25 20)', geography 'Linestring(0 20, 50 20)'), 3);

SELECT 'lrs_sl_1', ST_AsText(ST_ShortestLine(geography 'linestring(0 40, 50 40)', 'Point(25 40)', true), 2);

