line_perp() (?-|) is broken.

From: Kyotaro HORIGUCHI <horiguchi(dot)kyotaro(at)lab(dot)ntt(dot)co(dot)jp>
To: pgsql-hackers(at)postgresql(dot)org
Subject: line_perp() (?-|) is broken.
Date: 2018-02-01 11:51:38
Message-ID: 20180201.205138.34583581.horiguchi.kyotaro@lab.ntt.co.jp
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-hackers

I happend to see a strange geometric calcualtion on master/HEAD.

CREATE TABLE t (l1 line, l2 line);
INSERT INTO t
(SELECT line(point(0, 0), point(x, y)), line(point(0,0), point(-y, x))
FROM (SELECT random() x, random() y FROM generate_series(0, 1000)) AS a);
SELECT l1?-|l2 AS is_perp, l1, l2 FROM t;
is_perp | l1 | l2
---------+----------------------------+-----------------------------
f | {0.215980373614968,-1,0} | {-4.63005032940037,-1,0}
f | {1.51653638154567,-1,0} | {-0.659397303070824,-1,0}
f | {0.596861744826871,-1,0} | {-1.67542987746696,-1,0}
...
SELECT l1?-|l2 AS is_perp, l1, l2 FROM t WHERE l1?-|l2;
is_perp | l1 | l2
---------+----+----
(0 rows)

The two lines in a row are always perpendicular, but ?-| doesn't
agree.

line_perp() is working with the following arithmetic.

(l1->A * l2->B) / (l1->B * l2->A) == -1.0

or

(l1->A * l2->B) + (l1->B * l2->A) == 0

If the plus were a minus, it would calculate the cross product of
the two vectors and tell if the two lines are "parallel" or
not... Anyway it doesn't work as expected. At least back to 9.0
has the same expression in the function.

Instead, calculating inner product of the two direction vectors
works as expected.

(l1->A * l2->A) + (l1->B * l2->B) == 0

FPzero checks at the beggining of the function for the purpose of
avoiding div0 is useless with this form of expression.

With the attached patch, we will have the correct result.

is_perp | l1 | l2
---------+----------------------------+-----------------------------
t | {0.215980373614968,-1,0} | {-4.63005032940037,-1,0}
t | {1.51653638154567,-1,0} | {-0.659397303070824,-1,0}
t | {0.596861744826871,-1,0} | {-1.67542987746696,-1,0}
t | {2.14739225724798,-1,0} | {-0.465681105361517,-1,0}
...
SELECT l1?-|l2 AS is_perp, l1, l2 FROM t WHERE NOT l1?-|l2;
is_perp | l1 | l2
---------+----+----
(0 rows)

regards.

Attachment Content-Type Size
fix_line_perp.patch text/x-patch 565 bytes

Responses

Browse pgsql-hackers by date

  From Date Subject
Next Message Kyotaro HORIGUCHI 2018-02-01 11:52:10 Re: [HACKERS] [PATCH] Improve geometric types
Previous Message Simon Riggs 2018-02-01 11:07:49 Re: [HACKERS] MERGE SQL Statement for PG11