PLZ nach Entfernung sortieren

Gast #1303578
Lesenswert?

Gut: ich hätte noch schreiben sollen, das es auch Funktionieren soll.
Die ich bis jetzt gefunden habe waren bis zur Unbrauchbarkeit in Ihrer 
Funktion eingeschränkt. Da ich das nur einmal und nicht kommerziell
brauche ist ein Kauf für ein paar 100 Euro auch nicht die Lösung.
Gast #1304085
Lesenswert?

Wie man das macht : Ein Karte nehmen, dort die Postleitzahlgebiete mit 
Farbe anmalen. Dann vom gewuenschten Ort in einer Spirale nach aussen 
wandern und die besuchten Zonen einschwaerzen. So schwierig ist das 
nicht.
#1304407
Lesenswert?

Bei
http://fa-technik.adfc.de/code/opengeodb/PLZ.tab
gibt es eine Datei der Form

#loc_id  plz  lon  lat  Ort
5078  01067  13.7210676148814  51.0600336463379  Dresden
5079  01069  13.7389066401609  51.039558876083  Dresden
5080  01097  13.7439674110642  51.0667452412037  Dresden
5081  01099  13.8289798683304  51.0926193047084  Dresden

D.h. bei allen PLZ sind die Geo-(GPS)-Koordinaten angegeben.
PS: Die Entfernung zwischen Gps-Koordinaten berechnet sich mit

arccos(sin(B_lat)*sin(A_lat)+cos(B_lat)*cos(A_lat)*cos(B_lon - A_lon)) * 
Erdradius Mit dem Erdradius von etwa 6380 km.
Gast #1304520
Lesenswert?

>Dabei hat Maik doch ausdrücklich geschrieben,
>dass er was Fertiges haben will

nö.. so ausdrücklich habe ich das nun nicht gesagt.

Das mit der Liste ist zwar etwas anders als ich mir das vorgestellt
habe, aber es ist auch eine Lösung.
überlege nur gerade mit was sich das am besten (einfachsten) berechnet.
(Kandidat Nummer 1 ist Matlab gerade...)
#1304556
Lesenswert?

Habe gerade ein C-Prograemmchen geschrieben, was mir von einen 
beliebigen Ort benachbarte Orte ausgibt, z.B. im Umkreis von 20km.
Als Beispiel-Ort  Simmern/Hunsrück.
Das ging recht schnell mit der Formel
1
dist=acos(sin(nlat)*sin(lat)+cos(nlat)*cos(lat)*cos(nlon-lon)) * 6380;
Wenn Du willst, kann ich dir die Sourcen z.Verfuegung stellen.


55413 Weiler bei Bingen, dist=18.949
55422 Bacharach, dist=15.261
55430 Oberwesel, dist=15.102
55432 Niederburg, dist=14.940
55442 Stromberg, dist=16.336
55444 Seibersbach, dist=15.885
55469 Simmern / Hunsrück, dist=0.000
55471 Tiefenbach, dist=4.406
55481 Kirchberg (Hunsrück), dist=11.232
55483 Dickenschied, dist=15.261
55487 Sohren, dist=17.484
55490 Gemünden, dist=13.032
55494 Rheinböllen, dist=8.242
55496 Argenthal, dist=7.631
55497 Ellern (Hunsrück), dist=7.631
55499 Riesweiler, dist=7.631
55595 Hargesheim, dist=19.204
55618 Simmertal, dist=19.825
55619 Hennweiler, dist=19.947
55629 Seesbach, dist=16.037
56281 Emmelshausen, dist=17.760
56288 Kastellaun, dist=9.346
56290 Beltheim, dist=16.484
56291 Leiningen, dist=12.065
56329 Sankt Goar, dist=19.702
56858 Peterswald-Löffelscheid, dist=19.579
56865 Blankenrath, dist=18.298
56869 Mastershausen, dist=14.777
#1306177
Lesenswert?

Absolut quick and dirty.
Habe ich nur zum Spass so schnell mal programmiert, da mir die Aufgabe 
(benachbarte Orte finden) interessant erschien.
90% des Codes handelt das Einlesen der Datei
http://fa-technik.adfc.de/code/opengeodb/PLZ.tab
in ein int-Array.
Haette man viel besser loesen koennen mit struct ...
Aber ich wollte keinen Preis in 'sauber programmieren' gewinnen, sondern 
ganz schnell etwas loesen.

Die Datei PLZ.tab muss man als erstes Argument mitgeben.
Compiliert wird es mit dem Befehl
1
gcc -Wall -lm  -o /usr/local/bin/gps_plz gps_plz.c
Es besteht nur aus dieser Datei.
1
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
2
//sudo gcc -Wall -lm -o /usr/local/bin/gps_plz gps_plz.c
3
//
4
//This file needed:
5
//http://fa-technik.adfc.de/code/opengeodb/PLZ.tab
6
//5078  01067  13.7210676148814  51.0600336463379  Dresden
7

8
#include <stdlib.h>
9
#include <stdio.h>
10
#include <string.h>
11
#include <math.h>
12
#include <tgmath.h>
13
#ifndef max
14
#define min(a1,a2) ((a1)<(a2)?(a1):(a2))
15
#define max(a1,a2) ((a1)>(a2)?(a1):(a2))
16
#endif
17

18

19
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
20
/*--------------------------*/
21
//Searches in the char array s[] for a character in array
22
//  'charr'. When the first match is found, string position
23
//  in *is will be updated, the index of the found character
24
//  (charr[]) will be returned.
25
//  If no match, -1 is returned
26
char str_searchch2(const char *s, int *is,
27
 const char *charr) {
28
int i,j,lcharr;
29
char ret;
30

31
i= is==NULL? 0:*is;
32
lcharr=strlen(charr);
33
ret=-1;
34
while (s[i]!=0) {
35
  char ch=s[i];
36
  for (j=0;j<lcharr;j++) {
37
    if (charr[j]==ch) break;
38
  }  
39
  if (j!=lcharr) {ret=j; break;} //found
40
  i++;
41
}
42
if (is!=NULL) *is=i;
43
return ret;
44
}
45

46
// - - - - - - - - - - - - - -
47
//Database constants
48

49
//angles (lat,lon) will be stored as ints.
50
//they will be multiplied by 100000, i.e.
51
// 90Degree = 9000000
52

53
//LENGTH of each entry (int's)
54
#define DBLEN1 (3+8)
55

56
//Maximum number of entries
57
#define DBLEN2 8300
58

59
// - - - - - - - - - - - - - -
60
// this loads the geo-DB into a int-array
61
void load_db(int *plzdb, FILE *fh) {
62
char s[0x100]; int is,is2;
63
int ientr, idb;
64
double hdbl;
65
int i,h1;
66
char s2[0x40];
67

68
is=0; h1=0; ientr=0; idb=0;
69
while (fgets(s,sizeof(s), fh)!=NULL) {
70
  //printf("%s\n",s);
71
  if (s[0]=='#') continue;
72
  is=0;
73
  if (str_searchch2(s,&is,"\t\n")==1) continue;
74
    // search for \t or \n.
75
    // if a \n is found, proceed next line
76
  is++;
77
  for (i=0;i<4;i++) {
78
    is2=is;
79
    if (str_searchch2(s,&is2,"\t\n")==1) {
80
      if (i<3) break;
81
    }
82
    strncpy(s2,s+is,is2-is); s2[is2-is]=0;
83
    //printf("%s,",s2);
84
    if (i==1 || i==2) {
85
      hdbl=atof(s2); //printf("%d,",(int)(hdbl*100000));
86
      plzdb[idb+i]=(int)(hdbl*100000);
87
    }
88
    else if (i==0) {
89
      plzdb[idb+0]=atoi(s2);
90
      //printf("%d,",plzdb[idb+0]);
91
    }
92
    else if (i==3) {
93
      h1=max(h1,is2-is);
94
      strcpy((char*)&plzdb[idb+3],s2);
95
      //printf("%s",s2);
96
    }
97
    is=is2+1;
98
  }
99
  //printf("\n");
100
  if (i<3) {
101
    printf("#%s\n",s); 
102
    continue;
103
  }
104
  ientr++; idb+=DBLEN1;
105
}
106
plzdb[idb+0]=0;
107
printf("maxlen=%d, num_plz=%d\n",h1,ientr);
108
}
109

110
// - - - - - - - - - - - - - -
111
int main(int argc, char *argv[] ) {
112
FILE *fh;
113
int *plzdb;
114

115
plzdb=malloc(DBLEN2*DBLEN1*sizeof(int));
116
if ((fh=fopen(argv[1],"r"))==NULL) {
117
  fprintf(stderr,"file not found.\n");
118
  exit(1);
119
}
120
load_db(plzdb,fh);
121

122

123
{
124
float lat=4999716*M_PI/18000000;
125
float lon=753259*M_PI/18000000;
126
float nlat,nlon, dist;
127
int idb;
128

129
idb=0;
130
while (plzdb[idb+0]!=0) {
131
  nlat=plzdb[idb+2]*M_PI/18000000;
132
  nlon=plzdb[idb+1]*M_PI/18000000;
133
  dist=acos(sin(nlat)*sin(lat)+cos(nlat)*cos(lat)*cos(nlon-lon)) * 6380;
134
  if (dist<20) printf("%05d %s, dist=%.3f\n",
135
    plzdb[idb+0],(char*)&plzdb[idb+3],dist);
136
  idb+=DBLEN1;
137
}
138

139

140
}
141
return 0;
142
}
#1306184
Lesenswert?

Gast schrieb:
> Nachtrag: Was ich gebrauchen könnte, wäre eine sortierte Liste, die aber
> nicht nach Luftdistanz geoeordnet ist, sondern nach Anfahrzeit.

Kein Problem.
Obiger Code darf erweitert werden.
Die Ordnung nach Anfahrzeit erscheint mir unmoeglich, da die Datei keine 
Information darueber enthaelt.

Aber ich weiss wie man das machen kann:
Bei openstreetmap.org gibt es freie Daten, wo nicht nur Ort mit PLZ und 
Geo-Koordinaten abgespeichert sind, sondern auch Strassen.
Mit den Strassen-Infos laesst sich die Fahrtzeit muehelos berechnen.
#1306198
Lesenswert?

> "Mühelos" ist gut. Und wenn du damit fertig bist will er bestimmt auch

Ne, ne, ich werde mich da nicht an die Arbeit machen.
1. Openstreetmap ist noch nicht flaechendeckend. Noch nicht alle Orte 
sind eingetragen.
2. Vermutlich sind Hoechstgeschwindigkeiten bei den Strassen nicht 
eingetragen, dann wird die Fahrtzeit sehr ungenau.
3. Man muesste einen Router selbst programmieren (ein riesen Aufwand) 
oder den bestehenden vom OSM-Projekt ins Programm einbinden. Dazu habe 
ich einfach keine Lust. Das Programmieren soll ja zunaechst Spass 
machen.
#1306231
Lesenswert?

Erste verbesserte Version.
Durch Verwendung von 'sscanf' verkuerzte sich der Code von 142 auf 87 
Zeilen.

Der Bezugs-Ort ist noch hart-kodiert (z.B. Simmern). (Er sollte durch 
eine Eingabefunktion beliebig sein, aber was kann man bei 87 Zeilen 
erwarten)
1
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
2
//sudo gcc -Wall -lm -o /usr/local/bin/gps_plz gps_plz.c
3
//
4
//This file needed:
5
//http://fa-technik.adfc.de/code/opengeodb/PLZ.tab
6
//5078  01067  13.7210676148814  51.0600336463379  Dresden
7

8
#include <stdlib.h>
9
#include <stdio.h>
10
#include <string.h>
11
#include <math.h>
12
#include <tgmath.h>
13
#ifndef max
14
#define min(a1,a2) ((a1)<(a2)?(a1):(a2))
15
#define max(a1,a2) ((a1)>(a2)?(a1):(a2))
16
#endif
17

18

19
// - - - - - - - - - - - - - -
20
//Database constants
21

22
//angles (lat,lon) will be stored as ints.
23
//they will be multiplied by 100000, i.e.
24
// 90Degree = 9000000
25

26
//LENGTH of each entry (int's)
27
#define DBLEN1 (3+8)
28

29
//Maximum number of entries
30
#define DBLEN2 8300
31

32
// - - - - - - - - - - - - - -
33
// this loads the geo-DB into a int-array
34
void load_db(int *plzdb, FILE *fh) {
35
char s[0x100]; int is;
36
int ientr, idb;
37
double f1, f2;
38
int h1,h2;
39
char s2[0x40];
40

41
is=0; h1=0; ientr=0; idb=0;
42
while (fgets(s,sizeof(s), fh)!=NULL) {
43
  if (s[0]=='#') continue;
44
  if (sscanf(s,"%d %d %lf %lf %[^\n\r]s",
45
     &h2,&h1,&f1,&f2,s2)!=5) {
46
    printf("**%s\n",s);
47
    continue;
48
  }
49
  plzdb[idb+0]=h1;
50
  plzdb[idb+1]=(int)(f1*100000);
51
  plzdb[idb+2]=(int)(f2*100000);
52
  strcpy((char*)&plzdb[idb+3],s2);
53
  ientr++; idb+=DBLEN1;
54
}
55
plzdb[idb+0]=0;
56
}
57

58
// - - - - - - - - - - - - - -
59
int main(int argc, char *argv[] ) {
60
FILE *fh;
61
int *plzdb;
62

63
plzdb=malloc(DBLEN2*DBLEN1*sizeof(int));
64
if ((fh=fopen(argv[1],"r"))==NULL) {
65
  fprintf(stderr,"file not found.\n");
66
  exit(1);
67
}
68
load_db(plzdb,fh);
69

70
{
71
float lat=4999716*M_PI/18000000;
72
float lon=753259*M_PI/18000000;
73
float nlat,nlon, dist;
74
int idb;
75

76
idb=0;
77
while (plzdb[idb+0]!=0) {
78
  nlat=plzdb[idb+2]*M_PI/18000000;
79
  nlon=plzdb[idb+1]*M_PI/18000000;
80
  dist=acos(sin(nlat)*sin(lat)+cos(nlat)*cos(lat)*cos(nlon-lon)) * 6380;
81
  if (dist<20) printf("%05d %s, dist=%.3f\n",
82
    plzdb[idb+0],(char*)&plzdb[idb+3],dist);
83
  idb+=DBLEN1;
84
}
85
}
86
return 0;
87
}
Gast #1306770
Lesenswert?

>Nachtrag: Was ich gebrauchen könnte, wäre eine sortierte Liste, die aber
>nicht nach Luftdistanz geoeordnet ist, sondern nach Anfahrzeit.

Sowas taugt aber hoechstens fuer Flachlaender. Bei uns hat's hin und 
wieder ein Huegel, oder ein See dazwischen

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren