source: trunk/mapbender/http/nav/alkisnav_adr.php @ 431

Revision 425, 15.3 KB checked in by frank.jaeger, 2 years ago (diff)

Web-GIS-Auskunft und Mapbender2-Navigation: neue Konfigurations-Parameter und verbessertes Grundbuch-Modul

Line 
1<?php
2/*      Navigation mit ALKIS-Daten im Mapbender 2 - Teil Adressen-Suche
3        Datenbank-Struktur aus dem norGIS-ALKIS-Importer.
4Version vom
5        2016-02-11 Version fÃŒr norGIS-ALKIS-Import aus Version Classic abgeleitet.
6        2016-03-02 $gemeinde auf feste LÀnge korrigieren
7        2016-11-28 Gemeinsam genutzte Datenbanken ermöglichen
8        2018-02-15 Strikte Input-Validation der Parameter
9        2018-11-12 Full-Schema
10        2021-11-24 Neue Var. $katamtmix  (Kataster-Amt-Mix).
11                   SchlÃŒsseltabellen sind mehrfach belegt. Dadurch doppelte Treffer bei der Suche.
12
13ToDo:
14        -       Gruppierung (mit Zeile) der Straßenliste nach Gemeinde
15        -       Eingabe aus "Balken" von Buchauskunft "Lage" zulassen: Numerisch: Gem-Str-Haus-lfd
16                -- lfd (NebengebÀude) als Untergliederung der geklickten Haus-Nr anzeigen
17                Analog zur Zerlegung des FS-Kennz in _fls
18        -       Mouse-Over in Straßenliste soll Position zeigen.
19                Dazu in der DB eine Tabelle mit Koordinate zum StraßenschlÃŒssel aufbauen.
20*/
21
22$cntget = extract($_GET);
23
24// Input-Validation
25// Parameter aus Konfiguration oder Links sollten keine "Eingabefehler" enthalten.
26// Entweder falsche Konfiguration oder Hack. Programm sofort abbrechen.
27if (!isset($gkz) or !preg_match('#^[0-9]{3}$#', $gkz)) {die("Eingabefehler gkz");} // Mandant, muss!
28
29if(isset($epsg)) { // SRS, kann. Wenn als Parameter ...
30        if (preg_match('#^EPSG:[0-9]{4,5}$#', $epsg)) { // Prefix aus MB-Mapframe
31                $epsg = str_replace("EPSG:", "" , $epsg);
32        } elseif (!preg_match('#^[0-9]{4,5}$#', $epsg)) { // nur die Nummer
33                die("Eingabefehler epsg");
34        }
35} else { // Nichts ÃŒbergeben
36        $epsg=$gui_epsg; // dann default aus Conf
37}
38
39// Filter-Parameter fÃŒr Gemeindenummer in Kreis-Datenbank aus der Mapbender GUI-Konfiguration
40if (isset($gemeinde) AND trim($gemeinde, '0') != "") {
41        if (!preg_match('#^[0-9]{1,3}$#', $gemeinde)) {die("Eingabefehler Gemeinde");}
42        $gemeinde=str_pad($gemeinde, 3, "0", STR_PAD_LEFT);
43        if(strpos($gemeinde, ",") === false) {
44                $gfilter = 1; // Einzelwert
45        } else {
46                $gfilter = 2; // Liste
47        }
48} else { // Kein Filter
49        $gemeinde = "";
50        $gfilter = 0;
51}
52if (isset($str_schl) ) {
53        if (!preg_match('#^[0-9]{4,13}$#', $str_schl)) {die("Eingabefehler Stra&zlig;enschl&uuml;ssel");}
54} else {
55        $str_schl="";
56}
57
58include("../../conf/alkisnav_conf.php");
59include("alkisnav_fkt.php"); // Funktionen
60$con = pg_connect ($dbconn) or die ("Fehler bei der Verbindung zur Datenbank ".$dbpre.$dbgkz);
61
62echo <<<END
63<!doctype html>
64<html lang="de">
65<head>
66        <meta http-equiv="cache-control" content="no-cache">
67        <meta http-equiv="pragma" content="no-cache">
68        <meta http-equiv="expires" content="0">
69        <meta charset="utf-8">
70        <title>ALKIS-Suche Adressen</title>
71        <link rel="stylesheet" type="text/css" href="alkisnav.css">
72        <script type='text/javascript'>
73                function transtitle (trans) { // Titel der letzten Transaktion anzeigen
74                        document.getElementById('transaktiontitle').innerHTML = trans;
75                }
76                function imFenster(dieURL) {
77                        var link = encodeURI(dieURL);
78                        window.open(link,'','left=10,top=10,width=620,height=800,resizable=yes,menubar=no,toolbar=no,location=no,status=no,scrollbars=yes');
79                }
80        </script>
81</head>
82<body>
83<a href='javascript:history.back()'>
84        <img src="ico/zurueck.png" width="16" height="16" alt="&lt;&lt;" title="zur&uuml;ck">
85</a>&nbsp;
86<span title='zuletzt ausgef&uuml;hrte Aktion'>
87        <dfn class='title' id='transaktiontitle'></dfn>
88</span>
89
90END;
91
92function suchStrName() {
93        // Strassen nach Name(-nsanfang)
94        global $street, $scalestr, $str_schl, $gkz, $gemeinde, $epsg, $gfilter, $debug, $auskpath, $katamtmix;
95        //if ($debug > 1) {echo "<p class='dbg'>function suchStrName()<p>";} // Ablauf-Verfolgung
96
97        $linelimit=120;  // -> in Conf?
98        $str_schl=""; // Löschen vorh. Ergebnis
99        preg_match("/^(\D+)(\d*)(\D*)/",$street,$matches); # 4 matches name/nr/zusatz
100        //echo "match: 1='".$matches[1]."', 2='".$matches[2]."', 3='".$matches[3]."'";
101        $matches[1] = preg_replace("/strasse/i","str", $matches[1]);
102        $matches[1] = preg_replace("/str\./i","str", $matches[1]);
103
104        if(preg_match("/\*/",$matches[1])){
105                $match=trim(preg_replace("/\*/i","%", strtoupper($matches[1])));
106        } else {
107                $match=trim($matches[1])."%";
108        }
109
110        $sql ="SELECT g.gemeinde, g.bezeichnung AS gemname, k.gml_id, k.bezeichnung, k.schluesselgesamt, k.lage "
111        ."FROM ax_lagebezeichnungkatalogeintrag k "
112        ."JOIN ax_gemeinde g ON k.land=g.land AND k.regierungsbezirk=g.regierungsbezirk AND k.kreis=g.kreis AND k.gemeinde=g.gemeinde ";
113        if ($katamtmix){$sql.="AND substr(k.gml_id,1,6) = substr(g.gml_id,1,6) ";}
114        $sql.="WHERE k.bezeichnung ILIKE $1 AND k.endet IS NULL AND g.endet IS NULL ";
115
116        switch ($gfilter) {
117                case 1: // Einzelwert
118                        $sql.="AND k.gemeinde='".$gemeinde."' ";
119                        break;
120                case 2: // Liste
121                        $sql.="AND k.gemeinde in (".str_replace(",", "','", $gemeinde).") ";
122                        break;
123                default: // kein Filter
124                        break;
125        }
126        $sql.="ORDER BY g.bezeichnung, k.bezeichnung, k.lage LIMIT $2 ;";
127        $v=array($match,$linelimit);
128        $res=pg_prepare("", $sql);
129        $res=pg_execute("", $v);
130
131        if (!$res) {
132                echo "\n<p class='err'>Fehler bei Name</p>";
133                if ($debug > 2) {echo "<p class='dbg'>SQL = '".$sql."'<p>";}
134                return;
135        }
136
137        $cnt = 0;
138        $gwgem="";
139        while($row = pg_fetch_array($res)) {
140                $gemname=$row["gemname"];
141                $gemnr=$row["gemeinde"] ;
142                if ($gwgem != $gemname) {
143                        if ($gfilter != 1) {
144                                zeile_gemeinde($gemnr, $gemname, false); // ToDo: aber ohne Link oder Link verarbeiten können
145                        }
146                        $gwgem=$gemname;
147                }
148                $gkey=$row["schluesselgesamt"]; // Land-RegBez-Kreis-Gem-Straße - fÃŒr weitere Suche
149                $skey=$row["lage"]; // Nur Str.-schl. daraus
150                $kgml=$row["gml_id"]; // ID von Katalog
151                $sname=htmlentities($row["bezeichnung"], ENT_QUOTES, "UTF-8");
152                zeile_strasse ($gkey, $skey, $sname, $kgml, $gemname);
153                $cnt++;
154        }
155
156        if($cnt == 0) {
157                echo "\n<p class='anz'>Keine Stra&szlig;e</p>";
158                //if ($debug > 2) {echo "<p class='err'>SQL = '".$sql."'<br>$1 = '".$match."'<p>";}
159        } elseif($cnt == 1) { // Eindeutig
160                $str_schl=$gkey; // dann gleich weiter
161        } elseif($cnt >= $linelimit) {
162                echo "\n<p class='anz'>".$cnt." Stra&szlig;en ... und weitere</p>";                     
163        } elseif ($cnt > 1) {
164                echo "\n<p class='anz'>".$cnt." Stra&szlig;en</p>";     
165        }
166        return;
167}
168
169function suchStrKey() { // Straßen nach num. SchlÃŒssel
170        global $street, $scalestr, $str_schl, $gkz, $gemeinde, $epsg, $gfilter, $debug, $auskpath, $katamtmix;
171        //if ($debug > 1) {echo "<p class='dbg'>function suchStrKey()<p>";} // Ablauf-Verfolgung
172        $linelimit=60;
173        if(preg_match("/\*/",$street)) {
174                $match=trim(preg_replace("/\*/i","%",$street));
175                // fuehrende Nullen eingeben oder fuehrende Wildcard
176        } else {
177                $match=str_pad($street, 5, "0", STR_PAD_LEFT); // "Wie eine Zahl" verarbeiten
178        }
179
180        $sql ="SELECT g.bezeichnung AS gemname, k.gml_id, k.bezeichnung, k.schluesselgesamt, k.lage "
181        ."FROM ax_lagebezeichnungkatalogeintrag as k "
182        ."JOIN ax_gemeinde g ON k.land=g.land AND k.regierungsbezirk=g.regierungsbezirk AND k.kreis=g.kreis AND k.gemeinde=g.gemeinde ";
183        if ($katamtmix){$sql.="AND substr(k.gml_id,1,6) = substr(g.gml_id,1,6) ";}
184        $sql.="WHERE k.lage LIKE $1 AND k.endet IS NULL AND g.endet IS NULL ";
185        switch ($gfilter) {
186                case 1: // Einzelwert
187                        $sql.="AND k.gemeinde='".$gemeinde."' ";
188                        break;
189                case 2: // Liste
190                        $sql.="AND k.gemeinde in ('".str_replace(",", "','", $gemeinde)."') ";
191                        break;
192        }
193        $sql.="ORDER BY k.lage, k.bezeichnung LIMIT $2 ;";
194
195        $v=array($match,$linelimit);
196        $res=pg_prepare("", $sql);
197        $res=pg_execute("", $v);
198        if (!$res) {
199                echo "\n<p class='err'>Fehler bei Schl&uuml;ssel</p>";
200                return;
201        }
202        $cnt = 0;
203        while($row = pg_fetch_array($res)) {
204                $sname=htmlentities($row["bezeichnung"], ENT_QUOTES, "UTF-8");         
205                $gkey=$row["schluesselgesamt"];
206                $gemname=htmlentities($row["gemname"], ENT_QUOTES, "UTF-8");
207                $skey=$row["lage"];
208                $kgml=$row["gml_id"]; // ID von Katalog
209                zeile_strasse ($gkey, $skey, $sname, $kgml, $gemname);
210                $cnt++;
211        }
212        if($cnt == 0) {
213                echo "\n<p class='anz'>Keine Stra&szlig;e mit Schl&uuml;ssel ".$match."</p>";
214        } elseif($cnt == 1) { // Eindeutig
215                $str_schl=$gkey; // dann gleich weiter
216        } elseif ($cnt >= $linelimit) {
217                echo "\n<p>".$cnt." Stra&szlig;en ... und weitere</p>";                 
218        } elseif ($cnt > 1) {
219                echo "\n<p class='anz'>".$cnt." Stra&szlig;en</p>";     
220        }       
221        return;
222}
223
224function suchHausZurStr($showParent) { // HÀuser zu einer Straße
225        global $str_schl, $gkz, $scalestr, $scalehs, $epsg, $gemeinde, $epsg, $gfilter, $debug, $auskpath, $katamtmix;
226        //if ($debug > 1) {echo "<p class='dbg'>function suchHausZurStr()<p>";} // Ablauf-Verfolgung
227
228        // Head
229        // Straße zum StrassenschlÃŒssel
230        $sql ="SELECT g.bezeichnung AS gemname, k.gml_id AS kgml, k.bezeichnung, k.land, k.regierungsbezirk, k.kreis, k.gemeinde, k.lage "
231        ."FROM ax_lagebezeichnungkatalogeintrag as k "
232        ."JOIN ax_gemeinde g ON k.land=g.land AND k.regierungsbezirk=g.regierungsbezirk AND k.kreis=g.kreis AND k.gemeinde=g.gemeinde ";
233        if ($katamtmix){$sql.="AND substr(k.gml_id,1,6) = substr(g.gml_id,1,6) ";}
234        $sql.="WHERE k.schluesselgesamt = $1 AND k.endet IS NULL AND g.endet IS NULL LIMIT 1";
235
236        $v=array($str_schl);    // SchlÃŒssel-Gesamt ..
237        $res=pg_prepare("", $sql);
238        $res=pg_execute("", $v);
239        if (!$res) {
240                echo "\n<p class='err'>Fehler bei Name zum Stra&szlig;enschl&uuml;ssel</p>";
241                if ($debug > 2) {echo "<p class='dbg'>SQL = '".$sql."'<p>";}
242                return;
243        }
244
245        if($row = pg_fetch_array($res)) { // .. gefunden
246                $kgml=$row["kgml"];     // ID aus Katalog
247                $sname=$row["bezeichnung"];
248                $land =$row["land"];    // Einzel-Felder fÃŒr JOIN _lagebezeichnung_
249                $regb =$row["regierungsbezirk"];
250                $kreis=$row["kreis"];
251                $gemnd=$row["gemeinde"];
252                $nr=$row["lage"];
253                $gemname=htmlentities($row["gemname"], ENT_QUOTES, "UTF-8");
254                if ($showParent) {
255                        // EINE Koordinate zur Straße besorgen
256                        // ax_Flurstueck >zeigtAuf> ax_LagebezeichnungOhneHausnummer
257                        $sqlko ="SELECT ";
258                        if($epsg == "25832") { // Transform nicht notwendig
259                                $sqlko.="st_x(st_Centroid(f.wkb_geometry)) AS x, st_y(st_Centroid(f.wkb_geometry)) AS y ";
260                        } else {
261                                $sqlko.="st_x(st_transform(st_Centroid(f.wkb_geometry), ".$epsg.")) AS x, "
262                                ."st_y(st_transform(st_Centroid(f.wkb_geometry), ".$epsg.")) AS y ";
263                        }
264                        $sqlko.="FROM ax_lagebezeichnungohnehausnummer o JOIN ax_flurstueck f ON o.gml_id=ANY(f.zeigtauf) "
265                        ."WHERE o.land= $1 AND o.regierungsbezirk= $2 AND o.kreis= $3 AND o.gemeinde= $4 AND o.lage= $5 LIMIT 1;"; // die erstbeste Koordinate
266
267                        $v=array($land,$regb,$kreis,$gemnd,$nr);
268                        $resko=pg_prepare("", $sqlko);
269                        $resko=pg_execute("", $v);
270                        if ($resko) {
271                                $rowko=pg_fetch_array($resko);
272                                $x=$rowko["x"];
273                                $y=$rowko["y"];
274                        } else {               
275                                echo "\n<p class='err'>Fehler bei Koordinate zur Stra&szlig;e</p>";
276                        }
277
278                        // "function zeile_strasse()" hier nicht verwendbar. ZusÀtzlicher Map-Link mit Koordinate
279                        // Icon -> Buchnachweis
280                        echo "\n\t<br><a href='javascript:imFenster(\"".$auskpath."alkisstrasse.php?gkz=".$gkz."&amp;gmlid=".$kgml."\")'>";
281                                echo "\n\t\t<img class='nwlink' src='ico/Lage_mit_Haus.png' width='16' height='16' alt='STR' title='Buchauskunft zur Stra&szlig;e'>";
282                        echo "\n\t</a>";
283
284                        if ($x > 0) { // Koord. bekommen?
285                                echo "\n\t<a title='Positionieren 1:".$scalestr."' href='javascript:" // mit Link
286                                                ."transtitle(\"auf Stra&szlig;e positioniert\"); "
287                                                ."parent.parent.parent.mb_repaintScale(\"mapframe1\",".$x.",".$y.",".$scalestr."); "
288                                                ."parent.parent.showHighlight(".$x.",".$y."); "
289                                                ."' " // end href
290                                        ."\n\t\tonmouseover='parent.parent.showHighlight(" .$x. "," .$y. ")' "
291                                        ."\n\t\tonmouseout='parent.parent.hideHighlight()'"
292                                .">\n\t\t".$sname." (".$nr.")\n\t</a>";
293                        } else { // keine Koord. gefunden
294                                echo $sname." (".$nr.")"; // nur Anzeige, ohne Link
295                        }
296                        switch ($gfilter) {
297                                case 0: // Kein Filter
298                                        echo " in ".$gemname;
299                                        break;
300                                case 2: // Liste
301                                        echo " in ".$gemname;
302                                        break;
303                        }                       
304                }
305                echo "\n<hr>";
306
307                // Body
308                // HÀuser zum StraßenschlÃŒssel
309                $sql="SELECT min(replace(h.hausnummer,' ','')) AS hsnr, ";
310                if($epsg == "25832") { // Transform nicht notwendig
311                        $sql.="avg (st_x(p.wkb_geometry)) AS x, avg (st_y(p.wkb_geometry)) AS y ";             
312                } else { 
313                        $sql.="avg (st_x(st_transform(p.wkb_geometry,".$epsg."))) AS x, "
314                        ."avg (st_y(st_transform(p.wkb_geometry,".$epsg."))) AS y ";           
315                }
316                $sql.="FROM ap_pto p JOIN ax_lagebezeichnungmithausnummer h ON h.gml_id=ANY(p.dientzurdarstellungvon) "
317                ."WHERE p.art='HNR' AND h.land= $1 AND h.regierungsbezirk= $2 AND h.kreis= $3 AND h.gemeinde= $4 AND h.lage= $5 "
318                ."AND p.endet IS NULL AND h.endet IS NULL "
319                ."GROUP BY lpad(split_part(hausnummer,' ',1), 4, '0'), split_part(hausnummer,' ',2) "
320                ."ORDER BY lpad(split_part(hausnummer,' ',1), 4, '0'), split_part(hausnummer,' ',2);";
321                // Problem: In der Datenbank gibt es mehrere hausnummern-Koordinaten fÃŒr verschiedene
322                // MaßstÀbe der Kartendarstellung
323                // Diese sollten nicht mehrfach gelistet werden. FÃŒr die Positionierung "irgendeine" nehmen.
324                // Lösung: ÃŒber GROUP BY in SQL. Alternative Lösungen wÀren:
325                //  1. Gruppenwechsel bei Abarbeitung des Result
326                //  2. Subquery mit LIMIT 1 statt JOIN
327                //  3. Koordinate aus dem Mittelpunkt der GebÀude-Geometrie verwenden statt aus dem PrÀsentationsobjekt der Hausnummer
328
329                $v=array($land,$regb,$kreis,$gemnd,$nr);
330                $resh=pg_prepare("", $sql);
331                $resh=pg_execute("", $v);
332                if (!$resh) {
333                        echo "\n<p class='err'>Fehler bei H&auml;user zum Stra&szlig;enschl&uuml;ssel</p>";
334                        if ($debug > 2) {echo "<p class='dbg'>SQL='".$sql."'<br>Array=".$v."</p>";}
335                        return;
336                }
337
338                $cnt=0;
339                $count=0;
340                echo "\n<table>";
341                while($rowh = pg_fetch_array($resh)) { // mehrere HsNr je Zeile
342                        if($count == 0) {echo "\n<tr>";}       
343                        $hsnr=$rowh["hsnr"];
344                        $x=$rowh["x"];
345                        $y=$rowh["y"];
346                        echo "\n\t<td class='hsnr'>"
347                                ."<a href='javascript:transtitle(\"auf Haus ".$hsnr." positioniert\"); "
348                                        ."parent.parent.parent.mb_repaintScale(\"mapframe1\",".$x.",".$y.",".$scalehs."); "
349                                        ."parent.parent.showHighlight(".$x.",".$y.");' "
350                                        ."onmouseover='parent.parent.showHighlight(".$x.",".$y.")' "
351                                        ."onmouseout='parent.parent.hideHighlight()"
352                                ."'>".$hsnr."</a>"
353                        ."</td>";
354                        $cnt++;
355                        $count++;
356                        if($count == 7) { // Max. HausNr je Zeile (Test: 3stellige HsNr mit Zusatz)
357                                echo "\n</tr>";
358                                $count = 0;
359                        }
360                }
361                if($count > 0) {echo "\n</tr>";}
362                echo "\n</table>";
363                if ($cnt > 1) {
364                        echo "\n<p class='anz'>".$cnt." Hausnummern</p>";
365                }
366        } else {
367                echo "\n<p class='anz'>Keine Stra&szlig;e</p>";
368        }
369        return;
370}
371
372// Start hier!
373
374// Validation: Eingabefeld aus Formular.
375// Suchbegriff Straßenname oder StraßenschlÃŒssel.
376// Hier formatierte Meldung und html-Foot.
377if (isset($street) and $street != "" ) {
378        if (!preg_match('#^[0-9a-zA-ZÀöÌÄÖÜß* -.]{1,25}$#', $street)) {
379                echo "<p class='err'>Eingabe unzul&auml;ssig!</p>";
380                $street="";
381        }
382} else {
383        $street="";
384}
385
386if ($str_schl != "") { // aus Link
387        $trans="Hausnummern zur Stra&szlig;e";
388        suchHausZurStr(true);
389} elseif($street != "") { // Eingabe in Formular
390        if (trim($street, "*,0..9, ") == "") { // Zahl, ggf. mit Wildcard
391                $trans="Suche Stra&szlig;enschl&uuml;ssel \"".$street."\"";
392                suchStrKey();
393        } else { // Name suchen
394                $trans="Suche Stra&szlig;enname \"".$street."*\"";
395                suchStrName();
396        }
397        if($str_schl != "") { // EINdeutiges Ergebnis
398                $trans="1 Stra&szlig;e gefunden, Hausnummern";
399                suchHausZurStr(false);
400        }
401} else {
402        $trans="keine Eingabe";
403}
404
405// Nach Durchlaufen des PHP-Scriptes die zuletzt ausgefÃŒhrte Transaktion im Kopf des Ergebnisrahmens anzeigen.
406// Dazu die im HTML-Header definierte Javascript-Function benutzen.
407// Alternativ wird auch aus dem Javascript "positionieren Karte" dieser Titel gesetzt.
408echo "
409<script type='text/javascript'>
410        transtitle ('".$trans."') ;
411</script>";
412
413?>
414
415</body>
416</html>
Note: See TracBrowser for help on using the repository browser.