]> git.openstreetmap.org Git - nominatim.git/blob - lib/SearchContext.php
1b48fd84985a0a6c39342ff06a0d381725e63b7d
[nominatim.git] / lib / SearchContext.php
1 <?php
2
3 namespace Nominatim;
4
5 require_once(CONST_BasePath.'/lib/lib.php');
6
7
8 /**
9  * Collects search constraints that are independent of the
10  * actual interpretation of the search query.
11  *
12  * The search context is shared between all SearchDescriptions. This
13  * object mainly serves as context provider for the database queries.
14  * Therefore most data is directly cached as SQL statements.
15  */
16 class SearchContext
17 {
18     private $fNearRadius = false;
19     public $bViewboxBounded = false;
20
21     public $sqlNear = '';
22     public $sqlViewboxSmall = '';
23     public $sqlViewboxLarge = '';
24     public $sqlViewboxCentre = '';
25     private $sqlExcludeList = '';
26
27     public function hasNearPoint()
28     {
29         return $this->fNearRadius !== false;
30     }
31
32     public function nearRadius()
33     {
34         return $this->fNearRadius;
35     }
36
37     public function setNearPoint($fLat, $fLon, $fRadius = 0.1)
38     {
39         $this->fNearRadius = $fRadius;
40         $this->sqlNear = 'ST_SetSRID(ST_Point('.$fLon.','.$fLat.'),4326)';
41     }
42
43     public function isBoundedSearch()
44     {
45         return $this->hasNearPoint() || ($this->sqlViewboxSmall && $this->bViewboxBounded);
46
47     }
48
49     public function setViewboxFromBox(&$aViewBox, $bBounded)
50     {
51         $this->bViewboxBounded = $bBounded;
52         $this->sqlViewboxCentre = '';
53
54         $this->sqlViewboxSmall = sprintf(
55             'ST_SetSRID(ST_MakeBox2D(ST_Point(%F,%F),ST_Point(%F,%F)),4326)',
56             $aViewBox[0],
57             $aViewBox[1],
58             $aViewBox[2],
59             $aViewBox[3]
60         );
61
62         $fHeight = $aViewBox[0] - $aViewBox[2];
63         $fWidth = $aViewBox[1] - $aViewBox[3];
64
65         $this->sqlViewboxLarge = sprintf(
66             'ST_SetSRID(ST_MakeBox2D(ST_Point(%F,%F),ST_Point(%F,%F)),4326)',
67             max($aViewBox[0], $aViewBox[2]) + $fHeight,
68             max($aViewBox[1], $aViewBox[3]) + $fWidth,
69             min($aViewBox[0], $aViewBox[2]) - $fHeight,
70             min($aViewBox[1], $aViewBox[3]) - $fWidth
71         );
72     }
73
74     public function setViewboxFromRoute(&$oDB, $aRoutePoints, $fRouteWidth, $bBounded)
75     {
76         $this->bViewboxBounded = $bBounded;
77         $this->sqlViewboxCentre = "ST_SetSRID('LINESTRING(";
78         $sSep = '';
79         foreach ($aRoutePoints as $aPoint) {
80             $fPoint = (float)$aPoint;
81             $this->sqlViewboxCentre .= $sSep.$fPoint;
82             $sSep = ($sSep == ' ') ? ',' : ' ';
83         }
84         $this->sqlViewboxCentre .= ")'::geometry,4326)";
85
86         $sSQL = 'ST_BUFFER('.$this->sqlViewboxCentre.','.($fRouteWidth/69).')';
87         $sGeom = chksql($oDB->getOne("select ".$sSQL), "Could not get small viewbox");
88         $this->sqlViewboxSmall = "'".$sGeom."'::geometry";
89
90         $sSQL = 'ST_BUFFER('.$this->sqlViewboxCentre.','.($fRouteWidth/30).')';
91         $sGeom = chksql($oDB->getOne("select ".$sSQL), "Could not get large viewbox");
92         $this->sqlViewboxLarge = "'".$sGeom."'::geometry";
93     }
94
95     public function setExcludeList($aExcluded)
96     {
97         $this->sqlExcludeList = ' not in ('.join(',', $aExcluded).')';
98     }
99
100     /**
101      * Extract a coordinate point from a query string.
102      *
103      * @param string $sQuery Query to scan.
104      *
105      * @return The remaining query string.
106      */
107     public function setNearPointFromQuery($sQuery)
108     {
109         $aResult = parseLatLon($sQuery);
110
111         if ($aResult !== false
112             && $aResult[1] <= 90.1
113             && $aResult[1] >= -90.1
114             && $aResult[2] <= 180.1
115             && $aResult[2] >= -180.1
116         ) {
117             $this->setNearPoint($aResult[1], $aResult[2]);
118             $sQuery = trim(str_replace($aResult[0], ' ', $sQuery));
119         }
120
121         return $sQuery;
122     }
123
124     public function distanceSQL($sObj)
125     {
126         return 'ST_Distance('.$this->sqlNear.", $sObj)";
127     }
128
129     public function withinSQL($sObj)
130     {
131         return sprintf('ST_DWithin(%s, %s, %F)', $sObj, $this->sqlNear, $this->fNearRadius);
132     }
133
134     public function viewboxImportanceSQL($sObj)
135     {
136         $sSQL = '';
137
138         if ($this->sqlViewboxSmall) {
139             $sSQL = " * CASE WHEN ST_Contains($this->sqlViewboxSmall, $sObj) THEN 1 ELSE 0.5 END";
140         }
141         if ($this->sqlViewboxLarge) {
142             $sSQL = " * CASE WHEN ST_Contains($this->sqlViewboxLarge, $sObj) THEN 1 ELSE 0.5 END";
143         }
144
145         return $sSQL;
146     }
147
148     public function excludeSQL($sVariable)
149     {
150         if ($this->sqlExcludeList) {
151             return $sVariable.$this->sqlExcludeList;
152         }
153
154         return '';
155     }
156 }