Filterung in Overpass nach der Zahl der Objekten

Hallo zusammen!

Erst, entschuldiget ihr mir bitte, wenn solches Thema schon existiert.

Also, ich brauche, im bestimmten Gebiet Polygonen mit dem Tag place=village, in deren es jeweils weniger als 20 Häuser gibt, zu finden. Mithilfe von dem Overpass. Wie kann ich das machen?

Vielleicht gibt es jetzt keine Weise, das zu tun. Wenn ja, könnet ihr vorschlägen, wie diese Option aussiehen kann und wie man sie in Overpass implementieren kann?

Ich siehe es so:


{{geocodeArea:Thüringen}}->.a;    //zum Beispiel

relation
  (area.a)
  [place=village]
->.b;

map_to_area -> .c;

foreach.c -> .d (
  way
    (area.d)
    [building]
    (count<20)(    // if count of objects in this input set is smaller than 20, then print .d
      .d out meta;
    );
);

P. S. Ich suche Dörfer, wo es in OSM keine oder zu wenig Häuser gibt, um dort Häuser zu mappen.

P. P. S. Entschuldigung, wenn ich Verben mit “ihr” falsch schreibe :slight_smile:

Viele Grüße
Eduard

So wäre es besser:


{{geocodeArea:Thüringen}}->.a;    //zum Beispiel

relation
  (area.a)
  [place=village]
->.b;

map_to_area -> .c;

foreach.c -> .d (
  way
    (area.d)
    [building]
  ->.e;

  // Sintaxis is similar to "(user:*)" and "foreach":
  // if condition in first parentheses is satisfied,
  // Overpass must run code in second parentheses.
  // This repeats for each object in input set.

  (count_less:20).e(    // if count of objects in input set ".e" is smaller than 20, then print an input set ".d"
    .d out meta;
  );
);

Hallo Eduard,

mal ganz abgesehen von der Formuliering der Abfrage im teschnischen:

Bist du dir denn bewusst, ob in deinem Testgebiet die ganzen Objecte mit place=village wirklich auch als **Relation **erfasst sind, und nicht “nur” als eine einzige geschlossene **Linie *mit z.B. landuse= oder als einzelner Node?

Und inwieweit bist du dir sicher, dass bei allen Dörfern mit place=village auch wirklich schon alle Häuser in den OSM-Daten enthalten sind? Denn was machst du mit Orten, die in der realen Welt dreißig Häuder haben, davon sind aber bisher nur 5 in OSM drin?

Hallo Stephan,

vielen Dank für die Antwort.

Relation und Linie - das kann man später korrigieren und ergänzen. Die oben genannte Abfrage ist nur Beispiel.

Ich suche genau diese Orten, um dort alle Häuser zu malen.

Hallo,

Hier ein Beispiel, das im Umkreis von 1000m die Zahl der Buildings für alle place=village Nodes im Saarland ermittelt:


[out:csv(::id, name, ::count)];
{{geocodeArea:Saarland}};

node(area)[place=village];

foreach (
  out;
  way(around:1000)[building];
  out count;
);
  

http://overpass-turbo.eu/s/aXr (bzw. http://overpass-turbo.eu/s/aXt)

Alles andere funktioniert leider nicht. Eine Diskussion dazu ist am besten auf Github oder auf der Overpass Dev-List aufgehoben. Hier im Forum geht das schlicht und einfach unter.

Gruß,
mmd

Hallo mmd,

danke, aber über “out count;” weiß ich schon. Man kann natürlich deine Abfrage nutzen und dann selbstständig die Orte, wo es wäniger als 20 Häuser gibt, aussuchen. Ich möchte diesen Prozeß ein bisschen automatisieren.

Über GitHub und Mailing-List - danke, vestanden. Werde dort schreiben.

Grüße,
Eduard

Du könntest die Daten, die du als CSV bekommst, z.B. mit einem Python- oder AWK-Skript einlesen und nur die Orte Filtern, die weniger als 20 in der Spalte “count” stehen haben.

Danke, das ist ja klar. Das sieht aber unschön :slight_smile: wegen der größer Anzahl der Schritten.

Nebenbei gesagt:
Wenn ich diese Abfrage (http://overpass-turbo.eu/s/aXr) starte, bekomme ich die Ergebnis in Form:


@id	name	@count
<id>	<name>
		<count>

Das bedeutet, dass nicht an der Zeile mit und steht, sondern an nächster Zeile. Wie kann man in richtige Zeile setzen?

Das geht heute nur über Post-Processing. Über die Query selbst lässt sich das nicht beeinflussen.

Gruß,
mmd

Shade.
Na, danke für die Information!

Grüße
Eduard

Post-Processing ist nicht soo schwierig:


tail -n +2 result.csv | paste - - -d"\t"

…und die beiden Extra-Tabs lassen sich bestimmt auch gut rauswerfen:


tail -n +2 result.csv | sed 's/\t\t//g' | paste - - -d"\t" | sort -t$'\t' -k3 -n