2 9.11. Geometric Functions and Operators #
4 The geometric types point, box, lseg, line, path, polygon, and circle
5 have a large set of native support functions and operators, shown in
6 Table 9.36, Table 9.37, and Table 9.38.
8 Table 9.36. Geometric Operators
16 geometric_type + point → geometric_type
18 Adds the coordinates of the second point to those of each point of the
19 first argument, thus performing translation. Available for point, box,
22 box '(1,1),(0,0)' + point '(2,0)' → (3,1),(2,0)
26 Concatenates two open paths (returns NULL if either path is closed).
28 path '[(0,0),(1,1)]' + path '[(2,2),(3,3),(4,4)]' →
29 [(0,0),(1,1),(2,2),(3,3),(4,4)]
31 geometric_type - point → geometric_type
33 Subtracts the coordinates of the second point from those of each point
34 of the first argument, thus performing translation. Available for
35 point, box, path, circle.
37 box '(1,1),(0,0)' - point '(2,0)' → (-1,1),(-2,0)
39 geometric_type * point → geometric_type
41 Multiplies each point of the first argument by the second point
42 (treating a point as being a complex number represented by real and
43 imaginary parts, and performing standard complex multiplication). If
44 one interprets the second point as a vector, this is equivalent to
45 scaling the object's size and distance from the origin by the length of
46 the vector, and rotating it counterclockwise around the origin by the
47 vector's angle from the x axis. Available for point, box,^[a] path,
50 path '((0,0),(1,0),(1,1))' * point '(3.0,0)' → ((0,0),(3,0),(3,3))
52 path '((0,0),(1,0),(1,1))' * point(cosd(45), sind(45)) →
53 ((0,0),(0.7071067811865475,0.7071067811865475),(0,1.414213562373095))
55 geometric_type / point → geometric_type
57 Divides each point of the first argument by the second point (treating
58 a point as being a complex number represented by real and imaginary
59 parts, and performing standard complex division). If one interprets the
60 second point as a vector, this is equivalent to scaling the object's
61 size and distance from the origin down by the length of the vector, and
62 rotating it clockwise around the origin by the vector's angle from the
63 x axis. Available for point, box,^[a] path, circle.
65 path '((0,0),(1,0),(1,1))' / point '(2.0,0)' →
66 ((0,0),(0.5,0),(0.5,0.5))
68 path '((0,0),(1,0),(1,1))' / point(cosd(45), sind(45)) →
69 ((0,0),(0.7071067811865476,-0.7071067811865476),(1.4142135623730951,0
72 @-@ geometric_type → double precision
74 Computes the total length. Available for lseg, path.
76 @-@ path '[(0,0),(1,0),(1,1)]' → 2
78 @@ geometric_type → point
80 Computes the center point. Available for box, lseg, polygon, circle.
82 @@ box '(2,2),(0,0)' → (1,1)
84 # geometric_type → integer
86 Returns the number of points. Available for path, polygon.
88 # path '((1,0),(0,1),(-1,0))' → 3
90 geometric_type # geometric_type → point
92 Computes the point of intersection, or NULL if there is none. Available
95 lseg '[(0,0),(1,1)]' # lseg '[(1,0),(0,1)]' → (0.5,0.5)
99 Computes the intersection of two boxes, or NULL if there is none.
101 box '(2,2),(-1,-1)' # box '(1,1),(-2,-2)' → (1,1),(-1,-1)
103 geometric_type ## geometric_type → point
105 Computes the closest point to the first object on the second object.
106 Available for these pairs of types: (point, box), (point, lseg),
107 (point, line), (lseg, box), (lseg, lseg), (line, lseg).
109 point '(0,0)' ## lseg '[(2,0),(0,2)]' → (1,1)
111 geometric_type <-> geometric_type → double precision
113 Computes the distance between the objects. Available for all seven
114 geometric types, for all combinations of point with another geometric
115 type, and for these additional pairs of types: (box, lseg), (lseg,
116 line), (polygon, circle) (and the commutator cases).
118 circle '<(0,0),1>' <-> circle '<(5,0),1>' → 3
120 geometric_type @> geometric_type → boolean
122 Does first object contain second? Available for these pairs of types:
123 (box, point), (box, box), (path, point), (polygon, point), (polygon,
124 polygon), (circle, point), (circle, circle).
126 circle '<(0,0),2>' @> point '(1,1)' → t
128 geometric_type <@ geometric_type → boolean
130 Is first object contained in or on second? Available for these pairs of
131 types: (point, box), (point, lseg), (point, line), (point, path),
132 (point, polygon), (point, circle), (box, box), (lseg, box), (lseg,
133 line), (polygon, polygon), (circle, circle).
135 point '(1,1)' <@ circle '<(0,0),2>' → t
137 geometric_type && geometric_type → boolean
139 Do these objects overlap? (One point in common makes this true.)
140 Available for box, polygon, circle.
142 box '(1,1),(0,0)' && box '(2,2),(0,0)' → t
144 geometric_type << geometric_type → boolean
146 Is first object strictly left of second? Available for point, box,
149 circle '<(0,0),1>' << circle '<(5,0),1>' → t
151 geometric_type >> geometric_type → boolean
153 Is first object strictly right of second? Available for point, box,
156 circle '<(5,0),1>' >> circle '<(0,0),1>' → t
158 geometric_type &< geometric_type → boolean
160 Does first object not extend to the right of second? Available for box,
163 box '(1,1),(0,0)' &< box '(2,2),(0,0)' → t
165 geometric_type &> geometric_type → boolean
167 Does first object not extend to the left of second? Available for box,
170 box '(3,3),(0,0)' &> box '(2,2),(0,0)' → t
172 geometric_type <<| geometric_type → boolean
174 Is first object strictly below second? Available for point, box,
177 box '(3,3),(0,0)' <<| box '(5,5),(3,4)' → t
179 geometric_type |>> geometric_type → boolean
181 Is first object strictly above second? Available for point, box,
184 box '(5,5),(3,4)' |>> box '(3,3),(0,0)' → t
186 geometric_type &<| geometric_type → boolean
188 Does first object not extend above second? Available for box, polygon,
191 box '(1,1),(0,0)' &<| box '(2,2),(0,0)' → t
193 geometric_type |&> geometric_type → boolean
195 Does first object not extend below second? Available for box, polygon,
198 box '(3,3),(0,0)' |&> box '(2,2),(0,0)' → t
202 Is first object below second (allows edges to touch)?
204 box '((1,1),(0,0))' <^ box '((2,2),(1,1))' → t
208 Is first object above second (allows edges to touch)?
210 box '((2,2),(1,1))' >^ box '((1,1),(0,0))' → t
212 geometric_type ?# geometric_type → boolean
214 Do these objects intersect? Available for these pairs of types: (box,
215 box), (lseg, box), (lseg, lseg), (lseg, line), (line, box), (line,
218 lseg '[(-1,0),(1,0)]' ?# box '(2,2),(-2,-2)' → t
226 ?- lseg '[(-1,0),(1,0)]' → t
228 point ?- point → boolean
230 Are points horizontally aligned (that is, have same y coordinate)?
232 point '(1,0)' ?- point '(0,0)' → t
240 ?| lseg '[(-1,0),(1,0)]' → f
242 point ?| point → boolean
244 Are points vertically aligned (that is, have same x coordinate)?
246 point '(0,1)' ?| point '(0,0)' → t
248 line ?-| line → boolean
250 lseg ?-| lseg → boolean
252 Are lines perpendicular?
254 lseg '[(0,0),(0,1)]' ?-| lseg '[(0,0),(1,0)]' → t
256 line ?|| line → boolean
258 lseg ?|| lseg → boolean
262 lseg '[(-1,0),(1,0)]' ?|| lseg '[(-1,2),(1,2)]' → t
264 geometric_type ~= geometric_type → boolean
266 Are these objects the same? Available for point, box, polygon, circle.
268 polygon '((0,0),(1,1))' ~= polygon '((1,1),(0,0))' → t
270 ^[a] “Rotating” a box with these operators only moves its corner
271 points: the box is still considered to have sides parallel to the axes.
272 Hence the box's size is not preserved, as a true rotation would do.
276 Note that the “same as” operator, ~=, represents the usual notion of
277 equality for the point, box, polygon, and circle types. Some of the
278 geometric types also have an = operator, but = compares for equal areas
279 only. The other scalar comparison operators (<= and so on), where
280 available for these types, likewise compare areas.
284 Before PostgreSQL 14, the point is strictly below/above comparison
285 operators point <<| point and point |>> point were respectively called
286 <^ and >^. These names are still available, but are deprecated and will
287 eventually be removed.
289 Table 9.37. Geometric Functions
297 area ( geometric_type ) → double precision
299 Computes area. Available for box, path, circle. A path input must be
300 closed, else NULL is returned. Also, if the path is self-intersecting,
301 the result may be meaningless.
303 area(box '(2,2),(0,0)') → 4
305 center ( geometric_type ) → point
307 Computes center point. Available for box, circle.
309 center(box '(1,2),(0,0)') → (0.5,1)
311 diagonal ( box ) → lseg
313 Extracts box's diagonal as a line segment (same as lseg(box)).
315 diagonal(box '(1,2),(0,0)') → [(1,2),(0,0)]
317 diameter ( circle ) → double precision
319 Computes diameter of circle.
321 diameter(circle '<(0,0),2>') → 4
323 height ( box ) → double precision
325 Computes vertical size of box.
327 height(box '(1,2),(0,0)') → 2
329 isclosed ( path ) → boolean
333 isclosed(path '((0,0),(1,1),(2,0))') → t
335 isopen ( path ) → boolean
339 isopen(path '[(0,0),(1,1),(2,0)]') → t
341 length ( geometric_type ) → double precision
343 Computes the total length. Available for lseg, path.
345 length(path '((-1,0),(1,0))') → 4
347 npoints ( geometric_type ) → integer
349 Returns the number of points. Available for path, polygon.
351 npoints(path '[(0,0),(1,1),(2,0)]') → 3
353 pclose ( path ) → path
355 Converts path to closed form.
357 pclose(path '[(0,0),(1,1),(2,0)]') → ((0,0),(1,1),(2,0))
359 popen ( path ) → path
361 Converts path to open form.
363 popen(path '((0,0),(1,1),(2,0))') → [(0,0),(1,1),(2,0)]
365 radius ( circle ) → double precision
367 Computes radius of circle.
369 radius(circle '<(0,0),2>') → 2
371 slope ( point, point ) → double precision
373 Computes slope of a line drawn through the two points.
375 slope(point '(0,0)', point '(2,1)') → 0.5
377 width ( box ) → double precision
379 Computes horizontal size of box.
381 width(box '(1,2),(0,0)') → 1
383 Table 9.38. Geometric Type Conversion Functions
393 Computes box inscribed within the circle.
395 box(circle '<(0,0),2>') →
396 (1.414213562373095,1.414213562373095),(-1.414213562373095,-1.414213562
401 Converts point to empty box.
403 box(point '(1,0)') → (1,0),(1,0)
405 box ( point, point ) → box
407 Converts any two corner points to box.
409 box(point '(0,1)', point '(1,0)') → (1,1),(0,0)
411 box ( polygon ) → box
413 Computes bounding box of polygon.
415 box(polygon '((0,0),(1,1),(2,0))') → (2,1),(0,0)
417 bound_box ( box, box ) → box
419 Computes bounding box of two boxes.
421 bound_box(box '(1,1),(0,0)', box '(4,4),(3,3)') → (4,4),(0,0)
423 circle ( box ) → circle
425 Computes smallest circle enclosing box.
427 circle(box '(1,1),(0,0)') → <(0.5,0.5),0.7071067811865476>
429 circle ( point, double precision ) → circle
431 Constructs circle from center and radius.
433 circle(point '(0,0)', 2.0) → <(0,0),2>
435 circle ( polygon ) → circle
437 Converts polygon to circle. The circle's center is the mean of the
438 positions of the polygon's points, and the radius is the average
439 distance of the polygon's points from that center.
441 circle(polygon '((0,0),(1,3),(2,0))') → <(1,1),1.6094757082487299>
443 line ( point, point ) → line
445 Converts two points to the line through them.
447 line(point '(-1,0)', point '(1,0)') → {0,-1,0}
451 Extracts box's diagonal as a line segment.
453 lseg(box '(1,0),(-1,0)') → [(1,0),(-1,0)]
455 lseg ( point, point ) → lseg
457 Constructs line segment from two endpoints.
459 lseg(point '(-1,0)', point '(1,0)') → [(-1,0),(1,0)]
461 path ( polygon ) → path
463 Converts polygon to a closed path with the same list of points.
465 path(polygon '((0,0),(1,1),(2,0))') → ((0,0),(1,1),(2,0))
467 point ( double precision, double precision ) → point
469 Constructs point from its coordinates.
471 point(23.4, -44.5) → (23.4,-44.5)
473 point ( box ) → point
475 Computes center of box.
477 point(box '(1,0),(-1,0)') → (0,0)
479 point ( circle ) → point
481 Computes center of circle.
483 point(circle '<(0,0),2>') → (0,0)
485 point ( lseg ) → point
487 Computes center of line segment.
489 point(lseg '[(-1,0),(1,0)]') → (0,0)
491 point ( polygon ) → point
493 Computes center of polygon (the mean of the positions of the polygon's
496 point(polygon '((0,0),(1,1),(2,0))') → (1,0.3333333333333333)
498 polygon ( box ) → polygon
500 Converts box to a 4-point polygon.
502 polygon(box '(1,1),(0,0)') → ((0,0),(0,1),(1,1),(1,0))
504 polygon ( circle ) → polygon
506 Converts circle to a 12-point polygon.
508 polygon(circle '<(0,0),2>') →
509 ((-2,0),(-1.7320508075688774,0.9999999999999999),(-1.0000000000000002
510 ,1.7320508075688772),(-1.2246063538223773e-16,2),(0.9999999999999996,
511 1.7320508075688774),(1.732050807568877,1.0000000000000007),(2,2.44921
512 27076447545e-16),(1.7320508075688776,-0.9999999999999994),(1.00000000
513 00000009,-1.7320508075688767),(3.673819061467132e-16,-2),(-0.99999999
514 99999987,-1.732050807568878),(-1.7320508075688767,-1.0000000000000009)
517 polygon ( integer, circle ) → polygon
519 Converts circle to an n-point polygon.
521 polygon(4, circle '<(3,0),1>') →
522 ((2,0),(3,1),(4,1.2246063538223773e-16),(3,-1))
524 polygon ( path ) → polygon
526 Converts closed path to a polygon with the same list of points.
528 polygon(path '((0,0),(1,1),(2,0))') → ((0,0),(1,1),(2,0))
530 It is possible to access the two component numbers of a point as though
531 the point were an array with indexes 0 and 1. For example, if t.p is a
532 point column then SELECT p[0] FROM t retrieves the X coordinate and
533 UPDATE t SET p[1] = ... changes the Y coordinate. In the same way, a
534 value of type box or lseg can be treated as an array of two point