Punktliste filtern

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
Xelfern
User
Beiträge: 3
Registriert: Montag 29. Januar 2018, 10:29

Montag 29. Januar 2018, 10:58

ich habe eine Punktlioste mit dreidimensionalen Punkten und will die Punkte herausfiltern, welche im X-Wert und Y-Wert in einem bestimmten Bereich liegen. will zum Beispiel alle Punkte, die im ersten Wert zwischen 4984.300 und 4984.800 und im zweiten zwischen 1047.500 und 1047.700 liegen. Einlesen und aufsplitten ist gemacht, also es sind schon Punkte mit X Y und Z, aber die Filterung ist mir ein Rätsel, vielen dank im Voraus

4984.407630 1047.532970 100.270170
4984.554300 1047.526320 99.915140
4984.672510 1047.561360 100.274070
4984.700930 1047.515300 100.573110
4984.495890 1047.505500 99.914170
4984.731800 1047.579040 99.977040
4984.735920 1047.572990 99.918050
4984.225030 1047.485850 100.147260
4983.969380 1047.436130 99.961370
4983.879480 1047.461770 100.079370
4984.321760 1047.447180 100.569280
4984.556990 1047.522430 100.452140
4984.293070 1047.491200 100.448240
4984.732170 1047.578270 100.156040
4984.638980 1047.504840 100.513140
4984.545400 1047.540250 99.974130
4984.042560 1047.436050 100.506360
4984.229240 1047.480160 100.448270
4984.227210 1047.482200 99.967260
4984.037680 1047.443520 100.084350
4983.900520 1047.431000 100.202400
4984.730930 1047.579020 100.275040
4984.312190 1047.462880 100.509260
4984.749610 1047.551180 99.860070
4984.029130 1047.456620 100.264340
4984.683360 1047.545080 100.394090
4984.099340 1047.458270 100.326320
4984.096480 1047.463690 100.386310
4984.168540 1047.462570 100.207300
4984.510070 1047.483440 100.571190
nezzcarth
User
Beiträge: 555
Registriert: Samstag 16. April 2011, 12:47

Montag 29. Januar 2018, 11:04

Xelfern hat geschrieben: Einlesen und aufsplitten ist gemacht, also es sind schon Punkte mit X Y und Z, aber die Filterung ist mir ein Rätsel
Na ja, schreib dir eine Funktion, die überprüft, ob ein konkreter Punkt deinen Kriterien entspricht und einen Wahrheitswert zurück liefert. Diese kannst du dann z.B. als Prädikat für die eingebaute 'filter'-Funktion nehmen, in einer List-Comprehension verwenden, oder auch ganz klassisch in einer Schleife.
Sirius3
User
Beiträge: 8420
Registriert: Sonntag 21. Oktober 2012, 17:20

Montag 29. Januar 2018, 11:55

@Xelfern: für solche Aufgaben ist numpy ideal geeignet. Lies mal das Tutorial und insbesondere den Abschnitt über Indexing durch.
Benutzeravatar
DeaD_EyE
User
Beiträge: 218
Registriert: Sonntag 19. September 2010, 13:45
Wohnort: Hagen
Kontaktdaten:

Montag 29. Januar 2018, 14:43

Ich hoffe mal, dass ich deine Hausaufgaben gelöst habe...

Da es sich hier um Punkte (Koordinaten) handelt, würde ich zuerst eine namedtuple dafür anlegen:

Code: Alles auswählen

from collections import namedtuple
Point = namedtuple('Point', 'x y z')
Hier deine Liste mit Punkten in eine Variable liste gepackt:

Code: Alles auswählen

points_text = """4984.407630 1047.532970 100.270170
4984.554300 1047.526320 99.915140
4984.672510 1047.561360 100.274070
4984.700930 1047.515300 100.573110
4984.495890 1047.505500 99.914170
4984.731800 1047.579040 99.977040
4984.735920 1047.572990 99.918050
4984.225030 1047.485850 100.147260
4983.969380 1047.436130 99.961370
4983.879480 1047.461770 100.079370
4984.321760 1047.447180 100.569280
4984.556990 1047.522430 100.452140
4984.293070 1047.491200 100.448240
4984.732170 1047.578270 100.156040
4984.638980 1047.504840 100.513140
4984.545400 1047.540250 99.974130
4984.042560 1047.436050 100.506360
4984.229240 1047.480160 100.448270
4984.227210 1047.482200 99.967260
4984.037680 1047.443520 100.084350
4983.900520 1047.431000 100.202400
4984.730930 1047.579020 100.275040
4984.312190 1047.462880 100.509260
4984.749610 1047.551180 99.860070
4984.029130 1047.456620 100.264340
4984.683360 1047.545080 100.394090
4984.099340 1047.458270 100.326320
4984.096480 1047.463690 100.386310
4984.168540 1047.462570 100.207300
4984.510070 1047.483440 100.571190"""

points = [Point(*map(float, p.split())) for p in points_text.splitlines()]
Das sieht dann so aus:

Code: Alles auswählen

>>> points[:4]
[Point(x=4984.40763, y=1047.53297, z=100.27017),
 Point(x=4984.5543, y=1047.52632, z=99.91514),
 Point(x=4984.67251, y=1047.56136, z=100.27407),
 Point(x=4984.70093, y=1047.5153, z=100.57311)]
Ich denke mal, dass du das in irgendeiner anderen Form vorliegen hast.
Nutze z.B. das Modul csv um z.B. mit csv-Dateien umzugehen.


Hier der eigentliche Teil, der dich interessieren wird:

Code: Alles auswählen

def in_range(value, minr, maxr):
    return minr < value < maxr
Die Funktion sollte selbsterklärend sein.
Würde man so lesen: minr ist kleiner als value und value ist kleiner als maxr
So kannst du Prüfen, ob sich etwas in einem Bereich befindet (True) oder außerhalb des Bereichs ist (False).


Eine Funktion, die es ermöglicht verschiedene Bereiche anzugeben, aber nicht alle sind notwendig.

Code: Alles auswählen

def filter_points(points, ranges):
    for point in points:
        if all(in_range(getattr(point, axis), *min_max) for (axis, min_max) in ranges.items()):
            yield point

ranges = {
    'x': [4984.0, 4985.0],
    'y': [1047.48,1047.49],
    'z': [100.44, 100.45],
    }

result = list(filter_points(points, ranges))
Als Listcomprehension lässt sich das ganze kompakter schreiben.

Code: Alles auswählen

# nur für x
[point for point in points if 4984.5 < point.x < 4985.0]

# für x und y
[point for point in points if 4984.5 < point.x < 4985.0 and 1047.52 < point.y < 1047.53]

# für x, y und z
[point for point in points if 4984.5 < point.x < 4985.0 and 1047.52 < point.y < 1047.53 and 100.0 < point.z < 105]
Die List-Comprehension für x würde man so als For-Schleife schreiben:

Code: Alles auswählen

result = []
for point in points:
    if 4984.5 < point.x < 4985.0:
        result.append(point)
für x, y und z:

Code: Alles auswählen

result = []
for point in points:
    if 4984.5 < point.x < 4985.0 and 1047.52 < point.y < 1047.53 and 100.0 < point.z < 105:
        result.append(point)
Die Module numpy und pandas haben für so etwas auch Funktionen/Methoden. Man lernt aber besser zuerst, wie man das mit der Standardlib macht und später kann man sich auf Module konzentrieren, die die Aufgabe besser und schneller erledigen.
sourceserver.info - sourceserver.info/wiki/ - Support für HL2-Server
Sirius3
User
Beiträge: 8420
Registriert: Sonntag 21. Oktober 2012, 17:20

Montag 29. Januar 2018, 15:22

@DeaD_EyE: für filter_points könnte man auch direkt die Standardfunktion `filter` verwenden und statt all(...) eine der direkten Bedingungen aus Deinen ListComprehensions.
Xelfern
User
Beiträge: 3
Registriert: Montag 29. Januar 2018, 10:29

Montag 29. Januar 2018, 15:31

Vielen Dank für die schnellen und ausführlichen Antworten. Normalerweise hätte ich soetwas mit Excel gemacht, allerdings hat mein Datensatz mehr als 1 050 000 Zeilen, deshlab will ich es mit python versuchen...
Xelfern
User
Beiträge: 3
Registriert: Montag 29. Januar 2018, 10:29

Montag 29. Januar 2018, 18:24

also ich benutze phyton in der Dynamo for Revit- Umgebung, daran finde ich nicht den Anschluss, also ich habe eine Liste mit den Punkten:
List
Point(X = 4984.407630, Y = 1047.532970, Z = 100.272170))
Point(X = 4984.468530, Y = 1047.529740, Z = 100.305550))
Point(X = 4984.389546, Y = 1047.531970, Z = 100.257820))
Point(X = 4984.416930, Y = 1047.530970, Z = 100.246140))

der Phytonknoten beginnt immer mit:

import clr
clr.AddReference('ProtoGeometry')
from Autodesk.DesignScript.Geometry import *
# Import RevitNodes
clr.AddReference("RevitNodes")
import Revit
# Import Revit elements
from Revit.Elements import *
# Import DocumentManager
clr.AddReference("RevitServices")
import RevitServices
from RevitServices.Persistence import DocumentManager
import System
#define inputs
punktliste = IN[0]
minx = IN[1]
miny = IN[2]
minz = IN[3]
maxx = IN[4]
maxy = IN[5]
maxz = IN[6]

die vorher gezeigte Punktliste ist als Input 0 deklariert und die die min und max punkte zeigen jeweils die Grenzwerte. Wie greif ich nun richtig auf die Punktliste zu, ich hab die Vorschlägevon DeaD_EyE alle ohne Erfolg probiert. Problem ist scheinbar die Anbindung. Weiß da jemand wie das geht?
Benutzeravatar
DeaD_EyE
User
Beiträge: 218
Registriert: Sonntag 19. September 2010, 13:45
Wohnort: Hagen
Kontaktdaten:

Freitag 2. Februar 2018, 10:51

Sirius3 hat geschrieben:@DeaD_EyE: für filter_points könnte man auch direkt die Standardfunktion `filter` verwenden und statt all(...) eine der direkten Bedingungen aus Deinen ListComprehensions.
Ohne jetzt feste nachzudenken, behaupte ich mal, dass man das mit filter kürzer schreiben kann ^^
sourceserver.info - sourceserver.info/wiki/ - Support für HL2-Server
Antworten