zusammenfügen 02.2.
This commit is contained in:
465
Import.py
465
Import.py
@@ -1,37 +1,95 @@
|
||||
import csv
|
||||
import sqlite3
|
||||
from decimal import Decimal
|
||||
from typing import Any
|
||||
import re
|
||||
import xml.etree.ElementTree as ET
|
||||
from decimal import Decimal, getcontext, ROUND_HALF_UP
|
||||
import sqlite3
|
||||
from typing import Any
|
||||
import xml.etree.ElementTree as ET
|
||||
|
||||
from Berechnungen import Berechnungen
|
||||
|
||||
|
||||
import Berechnungen
|
||||
|
||||
|
||||
class Import:
|
||||
def __init__(self, pfad_datenbank: str) -> None:
|
||||
"""Importfunktionen für Messdaten und Näherungswerte in die SQLite-Datenbank.
|
||||
|
||||
Die Klasse stellt Methoden zur Verfügung für:
|
||||
|
||||
- Import von Näherungskoordinaten (LH-Tachymeter, GNSS/ECEF) in die Tabelle Netzpunkte,
|
||||
- Import und Vorverarbeitung von Tachymeterbeobachtungen (CSV-Datei) inkl. optionaler Korrektur durch nicht gerundete Leica-JXL,
|
||||
- Import von GNSS-Basislinien inkl. Kovarianzanteilen in die Tabelle Beobachtungen,
|
||||
- Import von Nivellementdaten (Normalhöhen als Näherungen sowie RVVR-Züge als dh-Beobachtungen),
|
||||
- einfache Plausibilitätsprüfungen (Duplikate, InstrumentenID, Dateiname bereits importiert).
|
||||
"""
|
||||
def __init__(self, pfad_datenbank: str, a : float, b : float) -> None:
|
||||
"""Initialisiert die Importklasse.
|
||||
|
||||
Speichert den Pfad zur SQLite-Datenbank und initialisiert die Hilfsklasse Berechnungen.
|
||||
|
||||
:param a: Große Halbachse a des Referenzellipsoids in Meter.
|
||||
:type a: float
|
||||
:param b: Kleine Halbachse b des Referenzellipsoids in Meter.
|
||||
:type b: float
|
||||
:param pfad_datenbank: Pfad zur SQLite-Datenbank.
|
||||
:type pfad_datenbank: str
|
||||
:return: None
|
||||
:rtype: None
|
||||
"""
|
||||
self.a = a
|
||||
self.b = b
|
||||
self.pfad_datenbank = pfad_datenbank
|
||||
pass
|
||||
self.berechnungen = Berechnungen.Berechnungen(self.a, self.b)
|
||||
|
||||
def string_to_float(self, zahl: str) -> float:
|
||||
"""Konvertiert einen Zahlenstring in float.
|
||||
|
||||
Ersetzt das Dezimaltrennzeichen "," durch "." und führt anschließend float() aus.
|
||||
|
||||
:param zahl: Zahlenstring (z. B. "12,345" oder "12.345").
|
||||
:type zahl: str
|
||||
:return: Zahlenwert als float.
|
||||
:rtype: float
|
||||
"""
|
||||
zahl = zahl.replace(',', '.')
|
||||
return float(zahl)
|
||||
|
||||
def string_to_decimal(self, zahl: str) -> Decimal:
|
||||
"""Konvertiert einen Zahlenstring in Decimal.
|
||||
|
||||
Ersetzt das Dezimaltrennzeichen "," durch "." und erzeugt anschließend ein Decimal.
|
||||
|
||||
:param zahl: Zahlenstring (z. B. "12,345" oder "12.345").
|
||||
:type zahl: str
|
||||
:return: Konvertierter Decimal-Wert.
|
||||
:rtype: Decimal
|
||||
"""
|
||||
zahl = zahl.replace(',', '.')
|
||||
return Decimal(zahl)
|
||||
|
||||
def import_koordinaten_lh_tachymeter(self, pfad_datei: str) -> None:
|
||||
"""Importiert Näherungskoordinaten im lokalen Horizontsystem des Tachymeters in die Tabelle Netzpunkte.
|
||||
|
||||
Die Datei wird semikolon-separiert erwartet. Pro Zeile werden Punktnummer sowie X/Y/Z-Näherung
|
||||
ausgelesen und in Netzpunkte (naeherungx_lh, naeherungy_lh, naeherungz_lh) geschrieben.
|
||||
|
||||
Vor dem Import werden zwei zentrale Prüfungen durchgeführt:
|
||||
|
||||
- Punktnummern dürfen in der Importdatei nicht doppelt vorkommen,
|
||||
- Punktnummern aus der Importdatei dürfen noch nicht in der Tabelle Netzpunkte vorhanden sein.
|
||||
|
||||
:param pfad_datei: Pfad zur CSV-Datei mit Punktnummer und Koordinaten.
|
||||
:type pfad_datei: str
|
||||
:return: None
|
||||
:rtype: None
|
||||
"""
|
||||
liste_punktnummern = []
|
||||
liste_punktnummern_vorher = []
|
||||
liste_punktnummern_vorher_db = []
|
||||
|
||||
# Import_abbrechen wird True, sobald eine Fehler festgestellt wird. Als Folge wird der Import abgebrochen und eine Fehlermeldung mit Handlungshinweisen für den Benutzer ausgegeben.
|
||||
Import_abbrechen = False
|
||||
|
||||
|
||||
with open (pfad_datei, newline='', encoding='utf-8') as csvfile:
|
||||
# Abfragen aller in der Tabelle Netzpunkte enthaltenen Punktnummern
|
||||
con = sqlite3.connect(self.pfad_datenbank)
|
||||
cursor = con.cursor()
|
||||
liste_punktnummern_db = [r[0] for r in cursor.execute("SELECT DISTINCT punktnummer FROM Netzpunkte").fetchall()]
|
||||
@@ -41,6 +99,7 @@ class Import:
|
||||
r = csv.reader(csvfile, delimiter=';')
|
||||
for row in r:
|
||||
liste_punktnummern.append(row[0])
|
||||
# Abbruch des Imports und Ausgabe einer Fehlermeldung, wenn ein Punkt doppelt in der Importdatei vorhanden ist.
|
||||
if row[0] in liste_punktnummern_vorher:
|
||||
Import_abbrechen = True
|
||||
print(f"Der Import wurde abgebrochen, weil in der Datei {pfad_datei} Punktnummern doppelt vorhanden sind. Bitte in der Datei ändern und Import wiederholen.")
|
||||
@@ -48,12 +107,14 @@ class Import:
|
||||
|
||||
liste_punktnummern_vorher.append(row[0])
|
||||
|
||||
# Abbruch des Imports und Ausgabe einer Fehlermeldung, wenn mindestens eine Punktnummer aus der Importdatei bereits in der Tabelle Netzpunkte vorhanden ist.
|
||||
if row[0] in liste_punktnummern_db:
|
||||
Import_abbrechen = True
|
||||
print(f"Der Import wurde abgebrochen, weil mindestens ein Teil der Punktnummern aus der Datei {pfad_datei} bereits in der Datenbank vorhanden ist. Bitte in der Datei ändern und Import wiederholen.")
|
||||
break
|
||||
liste_punktnummern_vorher_db.append(row[0])
|
||||
|
||||
# Import durchführen, wenn keine Fehler festgestellt wurden
|
||||
if Import_abbrechen == False:
|
||||
con = sqlite3.connect(self.pfad_datenbank)
|
||||
cursor = con.cursor()
|
||||
@@ -70,15 +131,30 @@ class Import:
|
||||
con.close()
|
||||
print("Der Import der Näherungskoordinaten wurde erfolgreich abgeschlossen")
|
||||
|
||||
def ist_rundung_von_jxl(self, wert_csv: str, wert_jxl_voll: str) -> bool:
|
||||
def ist_rundung_von_jxl(self, wert_csv: str, wert_jxl: str) -> bool:
|
||||
"""Prüft, ob ein CSV-Wert eine Rundung eines JXL-Wertes (mit mehr Nachkommastellen) ist.
|
||||
|
||||
Es wird geprüft, ob:
|
||||
|
||||
- beide Werte echte Zahlen sind,
|
||||
- der CSV-Wert weniger Nachkommastellen als der JXL-Wert besitzt,
|
||||
- der JXL-Wert auf die Nachkommastellenanzahl des CSV-Wertes gerundet exakt dem CSV-Wert entspricht.
|
||||
|
||||
:param wert_csv: Wert aus der CSV-Datei.
|
||||
:type wert_csv: str
|
||||
:param wert_jxl: Wert aus der JXL-Datei.
|
||||
:type wert_jxl: str
|
||||
:return: True, wenn wert_csv eine Rundung von wert_jxl auf weniger Nachkommastellen darstellt, sonst False.
|
||||
:rtype: bool
|
||||
"""
|
||||
wert_csv = str(wert_csv).strip()
|
||||
wert_jxl_voll = str(wert_jxl_voll).strip()
|
||||
wert_jxl = str(wert_jxl).strip()
|
||||
|
||||
if ":ZH:" in wert_csv:
|
||||
wert_csv = wert_csv.split(":ZH:", 1)[0].strip()
|
||||
|
||||
if ":ZH:" in wert_jxl_voll:
|
||||
wert_jxl_voll = wert_jxl_voll.split(":ZH:", 1)[0].strip()
|
||||
if ":ZH:" in wert_jxl:
|
||||
wert_jxl = wert_jxl.split(":ZH:", 1)[0].strip()
|
||||
|
||||
def ist_zahl(text: str) -> bool:
|
||||
text = str(text).strip()
|
||||
@@ -115,9 +191,10 @@ class Import:
|
||||
if ist_zahl(wert_csv) == False:
|
||||
return False
|
||||
|
||||
if ist_zahl(wert_jxl_voll) == False:
|
||||
if ist_zahl(wert_jxl) == False:
|
||||
return False
|
||||
|
||||
# Ermittlung der Anzahl Nachkommastellen in CSV-Datei und JXL-Datei
|
||||
anzahl_nachkommastellen_csv = 0
|
||||
if "," in wert_csv:
|
||||
anzahl_nachkommastellen_csv = len(wert_csv.split(",", 1)[1])
|
||||
@@ -125,16 +202,16 @@ class Import:
|
||||
anzahl_nachkommastellen_csv = len(wert_csv.split(".", 1)[1])
|
||||
|
||||
anzahl_nachkommastellen_jxl = 0
|
||||
if "," in wert_jxl_voll:
|
||||
anzahl_nachkommastellen_jxl = len(wert_jxl_voll.split(",", 1)[1])
|
||||
elif "." in wert_jxl_voll:
|
||||
anzahl_nachkommastellen_jxl = len(wert_jxl_voll.split(".", 1)[1])
|
||||
if "," in wert_jxl:
|
||||
anzahl_nachkommastellen_jxl = len(wert_jxl.split(",", 1)[1])
|
||||
elif "." in wert_jxl:
|
||||
anzahl_nachkommastellen_jxl = len(wert_jxl.split(".", 1)[1])
|
||||
|
||||
if anzahl_nachkommastellen_csv >= anzahl_nachkommastellen_jxl:
|
||||
return False
|
||||
|
||||
wert_csv_decimal = self.string_to_decimal(wert_csv.replace(".", ","))
|
||||
wert_jxl_decimal = self.string_to_decimal(wert_jxl_voll.replace(".", ","))
|
||||
wert_jxl_decimal = self.string_to_decimal(wert_jxl.replace(".", ","))
|
||||
|
||||
q = Decimal("1") if anzahl_nachkommastellen_csv == 0 else Decimal("1." + ("0" * anzahl_nachkommastellen_csv))
|
||||
wert_jxl_gerundet = wert_jxl_decimal.quantize(q, rounding=ROUND_HALF_UP)
|
||||
@@ -143,6 +220,13 @@ class Import:
|
||||
return wert_jxl_gerundet == wert_csv_gerundet
|
||||
|
||||
def ist_zahl_csv(self, text: str) -> bool:
|
||||
"""Prüft, ob ein String in der CSV als Zahl interpretiert werden kann.
|
||||
|
||||
:param text: Zu prüfender Text.
|
||||
:type text: str
|
||||
:return: True, wenn der Text eine Zahl ist, sonst False.
|
||||
:rtype: bool
|
||||
"""
|
||||
text = str(text).strip()
|
||||
if text == "":
|
||||
return False
|
||||
@@ -172,58 +256,92 @@ class Import:
|
||||
pfad_datei_csv: str,
|
||||
pfad_datei_jxl: str,
|
||||
pfad_datei_csv_out: str) -> dict:
|
||||
Import_fortsetzen = True
|
||||
getcontext().prec = 70
|
||||
"""Korrigiert Tachymeterbeobachtungen in einer CSV-Datei über eine JXL-Datei (Leica XML).
|
||||
|
||||
Die JXL-Datei wird eingelesen und je StationID eine Sequenz an Beobachtungen (Zielpunktname,
|
||||
Horizontal-/Vertikalkreisablesung, Schrägdistanz sowie Prismenhöhe) aufgebaut. Die Winkel werden
|
||||
von Grad nach gon umgerechnet und in der Nachkommastellenauflösung der JXL gerundet.
|
||||
|
||||
Anschließend wird die CSV zeilenweise verarbeitet:
|
||||
|
||||
- Standpunktzeilen werden der zugehörigen StationID/IH aus der JXL zugeordnet,
|
||||
- Beobachtungszeilen werden falls der CSV-Wert eine Rundung des JXL-Werts ist durch den JXL-Wert mit voller Nachkommastellenzahl ersetzt,
|
||||
- Prismenhöhen (ZH) werden aus der JXL übernommen und in der letzten Spalte als ":ZH:" angehängt.
|
||||
|
||||
Zusätzlich werden Fehler-Listen erstellt (fehlende IH, fehlende ZH, Standpunkte in CSV aber nicht in JXL). Diese werden dem Benutzer übergeben.
|
||||
|
||||
:param pfad_datei_csv: Pfad zur Eingabe-CSV (Tachymeterbeobachtungen).
|
||||
:type pfad_datei_csv: str
|
||||
:param pfad_datei_jxl: Pfad zur JXL-Datei.
|
||||
:type pfad_datei_jxl: str
|
||||
:param pfad_datei_csv_out: Pfad zur Ausgabe-CSV (korrigierte Datei).
|
||||
:type pfad_datei_csv_out: str
|
||||
:return: Ergebnisdictionary mit Status und Diagnosen, u. a.:
|
||||
- "Import_fortsetzen" (bool),
|
||||
- "dict_ersetzungen" (dict mit Zählungen für "Hz", "Z", "SD"),
|
||||
- "liste_zeilen_ohne_IH" (list),
|
||||
- "liste_zeilen_ohne_ZH" (list),
|
||||
- "liste_zeilen_standpunkt_nicht_in_jxl" (list),
|
||||
- "pfad_datei_csv_out" (str).
|
||||
:rtype: dict
|
||||
"""
|
||||
# Import_fortsetzen wird False, sobald eine Fehler festgestellt wird. Als Folge wird der Import abgebrochen und eine Fehlermeldung mit Handlungshinweisen für den Benutzer ausgegeben.
|
||||
Import_fortsetzen = True
|
||||
|
||||
getcontext().prec = 70
|
||||
dict_ersetzungen = {"Hz": 0, "Z": 0, "SD": 0}
|
||||
|
||||
# IH = Instrumentenhöhe | ZH = Zielhöhe, bzw. Prismenhöhe
|
||||
liste_zeilen_ohne_IH = []
|
||||
liste_zeilen_ohne_ZH = []
|
||||
liste_zeilen_standpunkt_nicht_in_jxl = []
|
||||
|
||||
liste_stationrecords = []
|
||||
liste_tachymeterstandpunkte = []
|
||||
|
||||
dict_stationname_stationrecords = {}
|
||||
dict_stationname_zaehler = {}
|
||||
dict_stationname_tachymeterstandpunkte = {}
|
||||
dict_standpunkte_anzahl = {}
|
||||
|
||||
dict_targetID_zu_ZH = {}
|
||||
dict_stationID_zu_seq = {}
|
||||
|
||||
dict_stationnamen = {}
|
||||
|
||||
# Vorbereitung jxl-Datei lesen
|
||||
tree = ET.parse(pfad_datei_jxl)
|
||||
root = tree.getroot()
|
||||
|
||||
|
||||
# JXL-Datei auslesen
|
||||
if Import_fortsetzen:
|
||||
# StationRecords einlesen (Standpunkt, StationID, Instrumentenhöhe)
|
||||
# Standpunkt, StationID, Instrumentenhöhe aus der JXL-Datei auslesen
|
||||
for sr in root.iter("StationRecord"):
|
||||
stationname = (sr.findtext("StationName") or "").strip()
|
||||
station_id = (sr.attrib.get("ID") or "").strip()
|
||||
ih = (sr.findtext("TheodoliteHeight") or "").strip()
|
||||
|
||||
if stationname != "" and station_id != "":
|
||||
liste_stationrecords.append((stationname, station_id, ih))
|
||||
liste_tachymeterstandpunkte.append((stationname, station_id, ih))
|
||||
dict_stationnamen[stationname] = 1
|
||||
|
||||
if stationname not in dict_stationname_stationrecords:
|
||||
dict_stationname_stationrecords[stationname] = []
|
||||
dict_stationname_stationrecords[stationname].append((station_id, ih))
|
||||
if stationname not in dict_stationname_tachymeterstandpunkte:
|
||||
dict_stationname_tachymeterstandpunkte[stationname] = []
|
||||
dict_stationname_tachymeterstandpunkte[stationname].append((station_id, ih))
|
||||
|
||||
for stationname in dict_stationname_stationrecords.keys():
|
||||
dict_stationname_zaehler[stationname] = 0
|
||||
for stationname in dict_stationname_tachymeterstandpunkte.keys():
|
||||
dict_standpunkte_anzahl[stationname] = 0
|
||||
|
||||
# Prismenhöhe auslesen und in Dict speichern
|
||||
for tr in root.iter("TargetRecord"):
|
||||
target_id = (tr.attrib.get("ID") or "").strip()
|
||||
zh = (tr.findtext("TargetHeight") or "").strip()
|
||||
if target_id != "":
|
||||
dict_targetID_zu_ZH[target_id] = zh
|
||||
|
||||
for tupel in liste_stationrecords:
|
||||
for tupel in liste_tachymeterstandpunkte:
|
||||
station_id = tupel[1]
|
||||
if station_id not in dict_stationID_zu_seq:
|
||||
dict_stationID_zu_seq[station_id] = []
|
||||
|
||||
# Horizontal- und Vertikalkreisablesungen, sowie Schrägdistanzablesungen aus JXL-Datei auslesen
|
||||
for pr in root.iter("PointRecord"):
|
||||
station_id = (pr.findtext("StationID") or "").strip()
|
||||
if station_id == "" or station_id not in dict_stationID_zu_seq:
|
||||
@@ -267,13 +385,14 @@ class Import:
|
||||
z_gon_decimal = z_gon_decimal.quantize(q_z, rounding=ROUND_HALF_UP)
|
||||
sd_decimal = Decimal(sd_m).quantize(q_sd, rounding=ROUND_HALF_UP)
|
||||
|
||||
# Ausgabe mit Komma
|
||||
# Ausgabe mit Kommatrennung
|
||||
hz_gon_text = format(hz_gon_decimal, "f").replace(".", ",")
|
||||
z_gon_text = format(z_gon_decimal, "f").replace(".", ",")
|
||||
sd_text = format(sd_decimal, "f").replace(".", ",")
|
||||
|
||||
zh = dict_targetID_zu_ZH.get(target_id, "")
|
||||
|
||||
# Dictionary mit den Abfragen für die Weiterverarbeitung füllen.
|
||||
dict_stationID_zu_seq[station_id].append({
|
||||
"target": zielpunkt_name,
|
||||
"hz_gon": hz_gon_text,
|
||||
@@ -283,7 +402,7 @@ class Import:
|
||||
})
|
||||
|
||||
station_id_aktuell = None
|
||||
index_seq_aktuell = 0
|
||||
index_csv_jxl_aktuell = 0
|
||||
standpunkt_aktuell = None
|
||||
|
||||
# CSV-Datei zeilenweise durchgehen und ggf. Werte ersetzen
|
||||
@@ -304,9 +423,10 @@ class Import:
|
||||
standpunkt = row[0].strip()
|
||||
|
||||
if standpunkt in dict_stationnamen:
|
||||
zaehler = dict_stationname_zaehler.get(standpunkt, 0)
|
||||
liste_records = dict_stationname_stationrecords[standpunkt]
|
||||
zaehler = dict_standpunkte_anzahl.get(standpunkt, 0)
|
||||
liste_records = dict_stationname_tachymeterstandpunkte[standpunkt]
|
||||
|
||||
# Überprüfung, ob in beiden Dateien die selben Tachymeterstandpunkte vorhanden sind
|
||||
if zaehler >= len(liste_records):
|
||||
Import_fortsetzen = False
|
||||
print(
|
||||
@@ -314,18 +434,20 @@ class Import:
|
||||
break
|
||||
|
||||
station_id, ih = liste_records[zaehler]
|
||||
dict_stationname_zaehler[standpunkt] = zaehler + 1
|
||||
dict_standpunkte_anzahl[standpunkt] = zaehler + 1
|
||||
|
||||
station_id_aktuell = station_id
|
||||
index_seq_aktuell = 0
|
||||
index_csv_jxl_aktuell = 0
|
||||
standpunkt_aktuell = standpunkt
|
||||
|
||||
# Erstellen einer Liste mit allen Zeilennummern aus der JXL, für die keine Instrumentenhöhe vorliegt, damit dies als Fehlermeldung mit Bearbeitungshinweisen ausgegeben werden kann.
|
||||
if ih is None or str(ih).strip() == "":
|
||||
liste_zeilen_ohne_IH.append((nummer_zeile, standpunkt))
|
||||
|
||||
writer.writerow([standpunkt, f"IH:{ih}", "", "", ""])
|
||||
continue
|
||||
|
||||
# Erstellen einer Liste mit allen Zeilennummern aus der JXL, für die keine Prismenhöhe vorliegt, damit dies als Fehlermeldung mit Bearbeitungshinweisen ausgegeben werden kann.
|
||||
if standpunkt.isdigit():
|
||||
liste_zeilen_standpunkt_nicht_in_jxl.append((nummer_zeile, standpunkt))
|
||||
|
||||
@@ -338,8 +460,6 @@ class Import:
|
||||
wert_z = row[2].split(":ZH:", 1)[0].strip()
|
||||
wert_sd = row[3].split(":ZH:", 1)[0].strip()
|
||||
|
||||
|
||||
|
||||
if self.ist_zahl_csv(wert_hz) and self.ist_zahl_csv(wert_z) and self.ist_zahl_csv(wert_sd):
|
||||
ist_beobachtung = True
|
||||
|
||||
@@ -355,21 +475,23 @@ class Import:
|
||||
writer.writerow(row)
|
||||
continue
|
||||
|
||||
if index_seq_aktuell >= len(liste_seq):
|
||||
if index_csv_jxl_aktuell >= len(liste_seq):
|
||||
writer.writerow(row)
|
||||
continue
|
||||
|
||||
jxl_eintrag = liste_seq[index_seq_aktuell]
|
||||
index_neu = index_seq_aktuell + 1
|
||||
# Abfragen der selben Daten aus der JXL-Datei über den index
|
||||
jxl_eintrag = liste_seq[index_csv_jxl_aktuell]
|
||||
index_neu = index_csv_jxl_aktuell + 1
|
||||
|
||||
if jxl_eintrag["target"] != zielpunkt:
|
||||
index_ende = min(len(liste_seq), index_seq_aktuell + 200)
|
||||
index_ende = min(len(liste_seq), index_csv_jxl_aktuell + 200)
|
||||
liste_kandidaten = []
|
||||
|
||||
for index_kandidat in range(index_seq_aktuell, index_ende):
|
||||
for index_kandidat in range(index_csv_jxl_aktuell, index_ende):
|
||||
if liste_seq[index_kandidat]["target"] == zielpunkt:
|
||||
liste_kandidaten.append((index_kandidat, liste_seq[index_kandidat]))
|
||||
|
||||
# Überprüfung, ob die Ablesungen in der CSV-Datei wirklich Rundungen der selben Daten mit mehr Nachkommastellen aus der JXL-Datei sind und abspeichern der Prüfergebnisse.
|
||||
if liste_kandidaten != []:
|
||||
if len(liste_kandidaten) == 1:
|
||||
index_kandidat, kandidat = liste_kandidaten[0]
|
||||
@@ -392,9 +514,9 @@ class Import:
|
||||
jxl_eintrag = kandidat_best
|
||||
index_neu = index_best + 1
|
||||
|
||||
index_seq_aktuell = index_neu
|
||||
index_csv_jxl_aktuell = index_neu
|
||||
|
||||
# Nur ersetzen, wenn die CSV-Werte tatsächlich eine Rundung der JXL-Werte sind
|
||||
# Nur in der CSV-Datei ersetzen, wenn die CSV-Werte tatsächlich eine Rundung der JXL-Werte sind
|
||||
hz_out = hz_csv
|
||||
z_out = z_csv
|
||||
sd_out = sd_csv
|
||||
@@ -423,24 +545,27 @@ class Import:
|
||||
|
||||
if Import_fortsetzen:
|
||||
print(f"Korrektur erfolgreich abgeschlossen. Ausgabe: {pfad_datei_csv_out}")
|
||||
print(f"Ersetzungen (Rundung -> JXL volle Nachkommastellen): {dict_ersetzungen}")
|
||||
print(f"Ersetzungen in der CSV-Datei (Rundung -> JXL volle Nachkommastellen): {dict_ersetzungen}")
|
||||
|
||||
print("\n--- Fehlende IH ---")
|
||||
print(f"Anzahl: {len(liste_zeilen_ohne_IH)}")
|
||||
# Ausgabe der Zeilennummern in der JXL-Datei ohne Instrumentenhöhe
|
||||
if len(liste_zeilen_ohne_IH) > 0:
|
||||
print("\n--- Fehlende IH in JXL-Datei ---")
|
||||
print(f"Anzahl: {len(liste_zeilen_ohne_IH)}")
|
||||
print(liste_zeilen_ohne_IH)
|
||||
|
||||
print("\n--- Fehlende ZH ---")
|
||||
print(f"Anzahl: {len(liste_zeilen_ohne_ZH)}")
|
||||
# Ausgabe der Zeilennummern in der JXL-Datei ohne Prismenhöhe
|
||||
if len(liste_zeilen_ohne_ZH) > 0:
|
||||
print("\n--- Fehlende ZH ---")
|
||||
print(f"Anzahl: {len(liste_zeilen_ohne_ZH)}")
|
||||
print(liste_zeilen_ohne_ZH)
|
||||
|
||||
print("\n--- Standpunkt in CSV, aber kein StationRecord in JXL ---")
|
||||
print(f"Anzahl: {len(liste_zeilen_standpunkt_nicht_in_jxl)}")
|
||||
# Ausgabe der Zeilennummern in der JXL-Datei mit unterschiedlichen Tachymeterstandpunkten im Vergleich zur CSV-Datei
|
||||
if len(liste_zeilen_standpunkt_nicht_in_jxl) > 0:
|
||||
print("\n--- Standpunkt in CSV-Datei, aber nicht in JXL-Datei---")
|
||||
print(f"Anzahl: {len(liste_zeilen_standpunkt_nicht_in_jxl)}")
|
||||
print(liste_zeilen_standpunkt_nicht_in_jxl)
|
||||
else:
|
||||
print("Die Korrektur wurde abgebrochen.")
|
||||
print("Die Korrektur der CSV-Datei wurde abgebrochen.")
|
||||
|
||||
return {
|
||||
"Import_fortsetzen": Import_fortsetzen,
|
||||
@@ -451,8 +576,32 @@ class Import:
|
||||
"pfad_datei_csv_out": pfad_datei_csv_out
|
||||
}
|
||||
|
||||
def import_beobachtungen_tachymeter(self, pfad_datei: str, instrumentenID: int, a: float, b: float) -> None:
|
||||
berechnungen = Berechnungen.Berechnungen(a, b)
|
||||
def import_beobachtungen_tachymeter(self, pfad_datei: str, instrumentenID: int) -> None:
|
||||
"""Importiert Tachymeterbeobachtungen aus einer CSV-Datei in die Tabelle Beobachtungen.
|
||||
|
||||
Die Datei wird blockweise verarbeitet (Standpunktzeile + Beobachtungszeilen). Aus je zwei Halbsätzen
|
||||
wird ein Vollsatz abgeleitet:
|
||||
|
||||
- Richtung: Mittel aus Hz(HS1) und Hz(HS2-200 gon), normiert in [0, 400),
|
||||
- Zenitwinkel: (ZW1 - ZW2 + 400) / 2,
|
||||
- Schrägdistanz: Mittel der beiden SD.
|
||||
|
||||
Zusätzlich werden aus Instrumenten- und Prismenhöhe bodenbezogene Werte berechnet
|
||||
(schraegdistanz_bodenbezogen, zenitwinkel_bodenbezogen) über berechne_zenitwinkel_distanz_bodenbezogen().
|
||||
|
||||
Vorabprüfungen:
|
||||
|
||||
- Abbruch, wenn der Dateiname bereits in Beobachtungen vorkommt,
|
||||
- Abbruch, wenn instrumentenID nicht in Tabelle Instrumente existiert,
|
||||
- Plausibilitätsprüfung auf Vollsatz-Struktur (6 Zeilen pro Zielpunkt: 3 Vollsätze * 2 Halbsätze).
|
||||
|
||||
:param pfad_datei: Pfad zur CSV-Datei.
|
||||
:type pfad_datei: str
|
||||
:param instrumentenID: ID des verwendeten Instruments aus Tabelle Instrumente.
|
||||
:type instrumentenID: int
|
||||
:return: None
|
||||
:rtype: None
|
||||
"""
|
||||
|
||||
# Prüfen, ob Bereits Daten aus der Datei in der Datenbank vorhanden sind
|
||||
con = sqlite3.connect(self.pfad_datenbank)
|
||||
@@ -464,16 +613,19 @@ class Import:
|
||||
FROM Beobachtungen""").fetchall()]
|
||||
liste_instrumentenid = [r[0] for r in cursor.execute("SELECT instrumenteID FROM Instrumente").fetchall()]
|
||||
|
||||
cursor.close()
|
||||
con.close()
|
||||
cursor.close
|
||||
|
||||
# Import_fortsetzen wird False, sobald eine Fehler festgestellt wird. Als Folge wird der Import abgebrochen und eine Fehlermeldung mit Handlungshinweisen für den Benutzer ausgegeben.
|
||||
Import_fortsetzen = True
|
||||
|
||||
# Abbrechen des Imports, wenn bereits Daten aus der selben Datei importiert wurden.
|
||||
if pfad_datei in liste_dateinamen_in_db:
|
||||
Import_fortsetzen = False
|
||||
|
||||
if Import_fortsetzen:
|
||||
nummer_zielpunkt = 0
|
||||
# Abfragen der aktuell höschten Nummer im Attribut beobachtungsgruppeID der Tabelle Beobachtungen
|
||||
try:
|
||||
nummer_beobachtungsgruppeID = max(liste_beobachtungsgruppeID)
|
||||
except:
|
||||
@@ -487,20 +639,22 @@ class Import:
|
||||
liste_beobachtungen_vorbereitung = []
|
||||
|
||||
for i, zeile in enumerate(f):
|
||||
# Die ersten drei Zeilen der Importdatei müssen überprungen werden
|
||||
if i < 3:
|
||||
continue
|
||||
zeile = zeile.strip().split(";")
|
||||
if len(zeile) < 5:
|
||||
zeile = zeile + [""] * (5 - len(zeile))
|
||||
|
||||
# Tachymeterstandpunkt speichern und beobachtungsgruppeID als ID für das einmalige Aufbauen eines Tachymeters auf einem Punkt festlegen
|
||||
if zeile[2] == "" and zeile[3] == "" and zeile[4] == "":
|
||||
nummer_beobachtungsgruppeID += 1
|
||||
# print("Standpunkt: ",nummer_beobachtungsgruppeID ,zeile[0])
|
||||
standpunkt = zeile[0]
|
||||
instrumentenhoehe = zeile[1]
|
||||
if instrumentenhoehe.startswith("IH:"):
|
||||
instrumentenhoehe = instrumentenhoehe.split("IH:", 1)[1].strip()
|
||||
|
||||
# Überprüfung, ob für jeden Beobachteten Zielpunkt 6 Zeilen vorhanden sind (3 Vollszätze mit je 2 Halbsätzen)
|
||||
if nummer_zielpunkt % 6 != 0:
|
||||
liste_fehlerhafte_zeile.append(i)
|
||||
|
||||
@@ -509,6 +663,8 @@ class Import:
|
||||
liste_zielpunkte_vs2 = []
|
||||
liste_zielpunkte_vs3 = []
|
||||
else:
|
||||
# ZH = Prismenhöhe | VS = Vollsatz | HS = Halbsatz
|
||||
# Erstellen einer Liste mit Standpunkt, Vollsatz und Halbsatzzuordnung für die Beobachtungen für die Weiterverarbeitung
|
||||
nummer_zielpunkt += 1
|
||||
|
||||
if ":ZH:" in zeile[3]:
|
||||
@@ -519,17 +675,14 @@ class Import:
|
||||
if zeile[0] not in liste_zielpunkte_hs:
|
||||
liste_zielpunkte_hs.append(zeile[0])
|
||||
if zeile[0] in liste_zielpunkte_vs3:
|
||||
# print(f"{nummer_zielpunkt} VS3 HS1 {zeile}")
|
||||
liste_beobachtungen_vorbereitung.append(
|
||||
[nummer_beobachtungsgruppeID, "VS3", "HS1", standpunkt, zeile[0], zeile[1],
|
||||
zeile[2], zeile[3], zeile[4], instrumentenhoehe])
|
||||
elif zeile[0] in liste_zielpunkte_vs2:
|
||||
# print(f"{nummer_zielpunkt} VS2 HS1 {zeile}")
|
||||
liste_beobachtungen_vorbereitung.append(
|
||||
[nummer_beobachtungsgruppeID, "VS2", "HS1", standpunkt, zeile[0], zeile[1],
|
||||
zeile[2], zeile[3], zeile[4], instrumentenhoehe])
|
||||
else:
|
||||
# print(f"{nummer_zielpunkt} VS1 HS1 {zeile}")
|
||||
liste_beobachtungen_vorbereitung.append(
|
||||
[nummer_beobachtungsgruppeID, "VS1", "HS1", standpunkt, zeile[0], zeile[1],
|
||||
zeile[2],
|
||||
@@ -538,7 +691,6 @@ class Import:
|
||||
else:
|
||||
liste_zielpunkte_hs.remove(zeile[0])
|
||||
if zeile[0] in liste_zielpunkte_vs3:
|
||||
# print(f"{nummer_zielpunkt} VS3 HS2 {zeile}")
|
||||
liste_beobachtungen_vorbereitung.append(
|
||||
[nummer_beobachtungsgruppeID, "VS3", "HS2", standpunkt, zeile[0], zeile[1],
|
||||
zeile[2],
|
||||
@@ -547,7 +699,6 @@ class Import:
|
||||
elif zeile[0] in liste_zielpunkte_vs2:
|
||||
if zeile[0] not in liste_zielpunkte_vs3:
|
||||
liste_zielpunkte_vs3.append(zeile[0])
|
||||
# print(f"{nummer_zielpunkt} VS2 HS2 {zeile}")
|
||||
liste_beobachtungen_vorbereitung.append(
|
||||
[nummer_beobachtungsgruppeID, "VS2", "HS2", standpunkt, zeile[0], zeile[1],
|
||||
zeile[2],
|
||||
@@ -555,18 +706,19 @@ class Import:
|
||||
else:
|
||||
if zeile[0] not in liste_zielpunkte_vs2:
|
||||
liste_zielpunkte_vs2.append(zeile[0])
|
||||
# print(f"{nummer_zielpunkt} VS1 HS2 {zeile}")
|
||||
liste_beobachtungen_vorbereitung.append(
|
||||
[nummer_beobachtungsgruppeID, "VS1", "HS2", standpunkt, zeile[0], zeile[1],
|
||||
zeile[2],
|
||||
zeile[3], zeile[4], instrumentenhoehe])
|
||||
|
||||
if liste_fehlerhafte_zeile == []:
|
||||
# print(f"Einlesen der Datei {pfad_datei} erfolgreich beendet.")
|
||||
pass
|
||||
else:
|
||||
# Ausgabe, welche Zeilen in der Importdatei bearbeitet werden müssen.
|
||||
if liste_fehlerhafte_zeile != []:
|
||||
fehler_zeilen = ", ".join(map(str, liste_fehlerhafte_zeile))
|
||||
print(
|
||||
f"Das Einlesen der Datei {pfad_datei} wurde abgebrochen.\nBitte bearbeiten Sie die Zeilen rund um: {", ".join(map(str, liste_fehlerhafte_zeile))} in der csv-Datei und wiederholen Sie den Import.")
|
||||
f"Das Einlesen der Datei {pfad_datei} wurde abgebrochen.\n"
|
||||
f"Bitte bearbeiten Sie die Zeilen rund um: {fehler_zeilen} in der csv-Datei "
|
||||
f"und wiederholen Sie den Import."
|
||||
)
|
||||
Import_fortsetzen = False
|
||||
|
||||
else:
|
||||
@@ -579,13 +731,12 @@ class Import:
|
||||
while len(liste_beobachtungen_vorbereitung) > 0:
|
||||
liste_aktueller_zielpunkt = liste_beobachtungen_vorbereitung[0]
|
||||
aktueller_zielpunkt = liste_aktueller_zielpunkt[4]
|
||||
# print(liste_beobachtungen_vorbereitung[0])
|
||||
|
||||
for index in range(1, len(liste_beobachtungen_vorbereitung)):
|
||||
liste = liste_beobachtungen_vorbereitung[index]
|
||||
|
||||
# Berechnen der zu importierenden Beobachtungen. (Jeweils reduziert auf den Vollsatz)
|
||||
if liste[4] == aktueller_zielpunkt:
|
||||
# print(liste)
|
||||
richtung1 = self.string_to_decimal(liste_aktueller_zielpunkt[5])
|
||||
richtung2 = self.string_to_decimal(liste[5]) - Decimal(200)
|
||||
zenitwinkel_vollsatz_gon = (self.string_to_decimal(liste_aktueller_zielpunkt[6]) - self.string_to_decimal(
|
||||
@@ -612,12 +763,8 @@ class Import:
|
||||
Import_fortsetzen = False
|
||||
print(f"Der Import wurde abgebrochen, weil für zwei Halbsätze vom Standpunkt {liste_aktueller_zielpunkt[3]} zum Zielpunkt {aktueller_zielpunkt} unterschiedliche Instrumentenhöhen vorliegen. Bitte in der Datei {pfad_datei} korrigieren und Import neustarten.")
|
||||
|
||||
|
||||
|
||||
# print(richtung_vollsatz)
|
||||
# print(zenitwinkel_vollsatz)
|
||||
# print(distanz_vollsatz)
|
||||
schraegdistanz_bodenbezogen, zenitwinkel_bodenbezogen = berechnungen.berechne_zenitwinkel_distanz_bodenbezogen(
|
||||
# Umrechnen der Zenitwinkel und Schrägdistanzen auf den Boden unter Verwendung der Instrumenten- und Prismenhöhen
|
||||
schraegdistanz_bodenbezogen, zenitwinkel_bodenbezogen = self.berechnungen.berechne_zenitwinkel_distanz_bodenbezogen(
|
||||
float(zenitwinkel_vollsatz_rad), float(distanz_vollsatz), float(instrumentenhoehe_import), float(prismenhoehe))
|
||||
|
||||
liste_beobachtungen_import.append(
|
||||
@@ -627,12 +774,13 @@ class Import:
|
||||
del liste_beobachtungen_vorbereitung[0]
|
||||
break
|
||||
|
||||
# Überprüfung, ob das Instrument bereits vom Benutzer angelegt wurde.
|
||||
if instrumentenID not in liste_instrumentenid:
|
||||
Import_fortsetzen = False
|
||||
print(
|
||||
"Der Import wurde abgebrochen. Bitte eine gültige InstrumentenID eingeben. Bei Bedarf ist das Instrument neu anzulegen.")
|
||||
|
||||
|
||||
# Berechnete bodenbezogene Beobachtungen, welche jeweils auf den Vollsatz reduziert sind, in die Tabelle Beobachtungen importieren.
|
||||
if Import_fortsetzen:
|
||||
con = sqlite3.connect(self.pfad_datenbank)
|
||||
cursor = con.cursor()
|
||||
@@ -649,28 +797,47 @@ class Import:
|
||||
|
||||
def vorbereitung_import_beobachtungen_nivellement_naeherung_punkthoehen(self, pfad_datei: str,
|
||||
instrumentenID: int) -> None | tuple[None, None] | tuple[dict[Any, Any], list[Any]]:
|
||||
# Prüfen, ob Bereits Daten aus der Datei in der Datenbank vorhanden sind
|
||||
"""Bereitet den Import von Nivellementdaten zur Ableitung von Näherungs-Normalhöhen vor.
|
||||
|
||||
Aus einer semikolon-separierten Datei werden Zeilen erkannt, die berechnete Zielweiten/Punkthöhen enthalten,
|
||||
und daraus pro Punktnummer alle gefundenen Z-Werte gesammelt. Anschließend wird je Punktnummer
|
||||
der Mittelwert berechnet (Rundung auf 6 Nachkommastellen).
|
||||
Danach wird geprüft, welche dieser Punktnummern bereits in der Tabelle Netzpunkte existieren.
|
||||
|
||||
Abbruchbedingungen:
|
||||
|
||||
- Dateiname bereits in Beobachtungen vorhanden,
|
||||
- instrumentenID nicht in Instrumente vorhanden.
|
||||
|
||||
:param pfad_datei: Pfad zur Importdatei.
|
||||
:type pfad_datei: str
|
||||
:param instrumentenID: ID des verwendeten Niv-Instruments aus der Tabelle Instrumente.
|
||||
:type instrumentenID: int
|
||||
:return: (dict_punkt_mittelwert_punkthoehen, liste_punktnummern_in_db) oder (None, None) bei Abbruch.
|
||||
:rtype: None | tuple[None, None] | tuple[dict[Any, Any], list[Any]]
|
||||
"""
|
||||
# Prüfen, ob bereits Daten aus der Datei in der Datenbank vorhanden sind
|
||||
con = sqlite3.connect(self.pfad_datenbank)
|
||||
cursor = con.cursor()
|
||||
liste_dateinamen_in_db = [r[0] for r in cursor.execute(
|
||||
"SELECT DISTINCT dateiname FROM Beobachtungen"
|
||||
).fetchall()]
|
||||
liste_beobachtungsgruppeID = [r[0] for r in cursor.execute("""SELECT DISTINCT beobachtungsgruppeID
|
||||
FROM Beobachtungen""").fetchall()]
|
||||
liste_instrumentenid = [r[0] for r in cursor.execute("SELECT instrumenteID FROM Instrumente").fetchall()]
|
||||
liste_netzpunkte = [r[0] for r in cursor.execute("SELECT punktnummer FROM Netzpunkte").fetchall()]
|
||||
|
||||
cursor.close()
|
||||
con.close()
|
||||
|
||||
|
||||
# Import_fortsetzen wird False, sobald eine Fehler festgestellt wird. Als Folge wird der Import abgebrochen und eine Fehlermeldung mit Handlungshinweisen für den Benutzer ausgegeben.
|
||||
Import_fortsetzen = True
|
||||
|
||||
# Abbruch des Imports, wenn bereits Daten aus der Datei importiert wurden.
|
||||
if pfad_datei in liste_dateinamen_in_db:
|
||||
Import_fortsetzen = False
|
||||
print(f"Der Import wurde abgebrochen, weil die Beobachtungen aus der Datei {pfad_datei} bereits in der Datenbank vorhanden sind.")
|
||||
return None, None
|
||||
|
||||
# Abbruch, wenn das Instrument noch nicht vom Benutzer angelegt wurde.
|
||||
if instrumentenID not in liste_instrumentenid:
|
||||
Import_fortsetzen = False
|
||||
print(
|
||||
@@ -678,7 +845,7 @@ class Import:
|
||||
return None, None
|
||||
|
||||
if Import_fortsetzen:
|
||||
# Berechnete Punkthöhe Importieren
|
||||
# Messwerte aus der Importdatei abfragen
|
||||
muster_berechnete_zielweiten = "| | |Z "
|
||||
dict_punkt_alle_punkthoehen = {}
|
||||
dict_punkt_mittelwert_punkthoehen = {}
|
||||
@@ -702,7 +869,6 @@ class Import:
|
||||
wert_z = self.string_to_float(teil.split()[0])
|
||||
|
||||
if punktnummer is not None and wert_z is not None:
|
||||
#print(f"{punktnummer}, {float(wert_z)}")
|
||||
if punktnummer not in dict_punkt_alle_punkthoehen:
|
||||
dict_punkt_alle_punkthoehen[punktnummer] = []
|
||||
|
||||
@@ -711,6 +877,7 @@ class Import:
|
||||
# Hier wird auf 6 Nachkommastellen gerundet!
|
||||
dict_punkt_mittelwert_punkthoehen[punktnummer] = round(sum(liste_z) / len(liste_z),6)
|
||||
|
||||
# Erstellen einer Liste mit allen Punktnummern, die in der Datenbank vorliegen und für die Nivellementbeobachtungen vorliegen.
|
||||
if Import_fortsetzen:
|
||||
# Ausgabe, welche Niv-Punkte bereits in der Tabelle Netzpunkte enthalten sind
|
||||
liste_punktnummern_nivellement = dict_punkt_mittelwert_punkthoehen.keys()
|
||||
@@ -722,6 +889,7 @@ class Import:
|
||||
else:
|
||||
liste_punktnummern_nicht_in_db.append(punktnummer)
|
||||
|
||||
# Es werden nur Höhendifferenzen für Punkte berechnet, für die Näherungskoordinaten in der Datenbank vorliegen.
|
||||
if Import_fortsetzen:
|
||||
print(f"Für folgende Nivellementpunkte werden die Höhen in der Ausgleichung berechnet: {liste_punktnummern_in_db}\nFür folgende Punkte wird aktuell keine Höhe in der Ausgleichung berechnet: {liste_punktnummern_nicht_in_db}. Bei Bedarf im folgenden Schritt ändern!")
|
||||
return dict_punkt_mittelwert_punkthoehen, liste_punktnummern_in_db
|
||||
@@ -729,6 +897,21 @@ class Import:
|
||||
def import_beobachtungen_nivellement_naeherung_punkthoehen(self, dict_punkt_mittelwert_punkthoehen: dict,
|
||||
liste_punktnummern_in_db: list,
|
||||
liste_punktnummern_hinzufuegen: list) -> str | None:
|
||||
"""Importiert Näherungsnormalhöhen in die Tabelle Netzpunkte.
|
||||
|
||||
Es werden Listen geführt für neu hinzugefügte, bereits vorhandene und geänderte Punkte und
|
||||
abschließend als Konsolen-Ausgabe ausgegeben.
|
||||
|
||||
:param dict_punkt_mittelwert_punkthoehen: Dictionary {punktnummer: normalhoehe} als Mittelwerte.
|
||||
:type dict_punkt_mittelwert_punkthoehen: dict
|
||||
:param liste_punktnummern_in_db: Punktnummern, die bereits in Netzpunkte existieren.
|
||||
:type liste_punktnummern_in_db: list
|
||||
:param liste_punktnummern_hinzufuegen: Zusätzliche Punktnummern, die ebenfalls übernommen werden sollen.
|
||||
:type liste_punktnummern_hinzufuegen: list
|
||||
:return: Status-String mit der Liste der Punkte, für die Normalhöhen in der Ausgleichung verfügbar sind, oder None bei Abbruch.
|
||||
:rtype: str | None
|
||||
"""
|
||||
# Import_fortsetzen wird False, sobald eine Fehler festgestellt wird. Als Folge wird der Import abgebrochen und eine Fehlermeldung mit Handlungshinweisen für den Benutzer ausgegeben.
|
||||
Import_fortsetzen = True
|
||||
|
||||
if dict_punkt_mittelwert_punkthoehen == None or liste_punktnummern_in_db == None or liste_punktnummern_hinzufuegen == None:
|
||||
@@ -744,6 +927,7 @@ class Import:
|
||||
liste_punkte_geaendert = []
|
||||
|
||||
for punktnummer in liste_punktnummern_hinzufuegen:
|
||||
# Neu anlegen oder aktualisieren der Normalhöhen in der Tabelle Netzpunkte
|
||||
try:
|
||||
cursor.execute(f"INSERT INTO Netzpunkte (punktnummer, normalhoehe_hfp) VALUES (?, ?)", (punktnummer, dict_punkt_mittelwert_punkthoehen[punktnummer]))
|
||||
liste_punkte_neu_hinzugefuegt.append(punktnummer)
|
||||
@@ -765,10 +949,31 @@ class Import:
|
||||
print(f"Bereits vorhanden ({len(liste_punkte_bereits_vorhanden)}): {liste_punkte_bereits_vorhanden}")
|
||||
print(f"Geändert ({len(liste_punkte_geaendert)}): {liste_punkte_geaendert}\n")
|
||||
|
||||
return f"Für folgende Punkte werden die Höhen Ausgeglichen: {liste_punktnummern_hinzufuegen + liste_punktnummern_in_db}"
|
||||
return f"Für folgende Punkte werden die Höhen Ausgeglichen: {liste_punktnummern_in_db}"
|
||||
|
||||
|
||||
def import_beobachtungen_nivellement_RVVR(self, pfad_datei: str, instrumentenID: int) -> str | None:
|
||||
"""Importiert geometrische Nivellementbeobachtungen nach dem RVVR Prinzip die Tabelle Beobachtungen.
|
||||
|
||||
Es werden Zeilen mit Rück-/Vormessungen erkannt (rvvr: Rück, Vor, Vor, Rück). Pro Block werden
|
||||
dh und Entfernung berechnet (Rundung jeweils auf 8 Nachkommastellen). Anschließend werden Züge reduziert, indem
|
||||
Wechselpunkte, die nicht in Netzpunkte vorhanden sind, durch Summation herausgekürzt werden.
|
||||
Damit werden nur Beobachtungen zwischen Punkten in Netzpunkte (bzw. reduzierten Start-/Zielpunkten)
|
||||
in Beobachtungen gespeichert.
|
||||
|
||||
Abbruchbedingungen:
|
||||
|
||||
- Dateiname bereits in Beobachtungen vorhanden,
|
||||
- instrumentenID nicht in Instrumente vorhanden,
|
||||
- Anzahl RVVR-Zeilen nicht durch 4 teilbar.
|
||||
|
||||
:param pfad_datei: Pfad zur Textdatei.
|
||||
:type pfad_datei: str
|
||||
:param instrumentenID: ID des verwendeten Niv-Instruments aus der Tabelle Instrumente.
|
||||
:type instrumentenID: int
|
||||
:return: Status-String bei Erfolg oder None bei Abbruch.
|
||||
:rtype: str | None
|
||||
"""
|
||||
# Prüfen, ob Bereits Daten aus der Datei in der Datenbank vorhanden sind
|
||||
con = sqlite3.connect(self.pfad_datenbank)
|
||||
cursor = con.cursor()
|
||||
@@ -781,36 +986,36 @@ class Import:
|
||||
cursor.close()
|
||||
con.close()
|
||||
|
||||
|
||||
# Import_fortsetzen wird False, sobald eine Fehler festgestellt wird. Als Folge wird der Import abgebrochen und eine Fehlermeldung mit Handlungshinweisen für den Benutzer ausgegeben.
|
||||
Import_fortsetzen = True
|
||||
|
||||
# Import abbrechen, wenn bereits Daten aus der selben Datei importiert wurden
|
||||
if pfad_datei in liste_dateinamen_in_db:
|
||||
Import_fortsetzen = False
|
||||
print(f"Der Import wurde abgebrochen, weil die Beobachtungen aus der Datei {pfad_datei} bereits in der Datenbank vorhanden sind.")
|
||||
|
||||
# Import abbrechen, wenn das Instrument noch nicht vom Benutzer angelegt wurde.
|
||||
if instrumentenID not in liste_instrumentenid:
|
||||
Import_fortsetzen = False
|
||||
print(
|
||||
"Der Import wurde abgebrochen. Bitte eine gültige InstrumentenID eingeben. Bei Bedarf ist das Instrument neu anzulegen.")
|
||||
|
||||
if Import_fortsetzen:
|
||||
# rvvr = Rück, Vor, Vor, Rück
|
||||
# Berechnen der Höhenunterschiede delta H und Schrägstrecken zwischen Zwei Punkten gemäß der Importdatei aus rvvr.
|
||||
anzahl_zeilen_rvvr = 0
|
||||
liste_zeilen_rvvr = []
|
||||
liste_punktpaare = []
|
||||
with open(pfad_datei, "r", encoding="utf-8") as f:
|
||||
for i, zeile in enumerate(f):
|
||||
if ("Lr" in zeile) or ("Lv" in zeile):
|
||||
#print(zeile.rstrip())
|
||||
|
||||
liste_zeilen_rvvr.append(zeile)
|
||||
anzahl_zeilen_rvvr += 1
|
||||
|
||||
|
||||
if anzahl_zeilen_rvvr % 4 == 0:
|
||||
index = 0
|
||||
while index < len(liste_zeilen_rvvr):
|
||||
block_4 = liste_zeilen_rvvr[index:index + 4]
|
||||
|
||||
liste_punktnummern_block = []
|
||||
|
||||
for zeile_block in block_4:
|
||||
@@ -885,7 +1090,9 @@ class Import:
|
||||
|
||||
index += 4
|
||||
|
||||
|
||||
# Berechnen der Höhendifferenzen und schrägstrecken zwischen Punkten in der Tabelle Netzpunkte.
|
||||
# Somit werden alle Wechselpunkte nicht in der Ausgleichung berücksichtigt.
|
||||
# Die Berechnung erfolgt durch addition.
|
||||
liste_beobachtungen_reduziert = []
|
||||
liste_beobachtungen_bearbeitung = []
|
||||
zugnummer_vorher = liste_punktpaare[0][0]
|
||||
@@ -893,15 +1100,12 @@ class Import:
|
||||
zugnummer = einzelbeobachtung[0]
|
||||
if zugnummer == zugnummer_vorher:
|
||||
if einzelbeobachtung[1] in liste_netzpunkte and einzelbeobachtung[2] in liste_netzpunkte:
|
||||
#print(einzelbeobachtung)
|
||||
liste_beobachtungen_reduziert.append(einzelbeobachtung + (1,))
|
||||
|
||||
elif einzelbeobachtung[1] in liste_netzpunkte and einzelbeobachtung[2] not in liste_netzpunkte:
|
||||
#print(f"Zielpunkt nicht enthalten {einzelbeobachtung}")
|
||||
liste_beobachtungen_bearbeitung.append(einzelbeobachtung)
|
||||
|
||||
elif einzelbeobachtung[1] not in liste_netzpunkte and einzelbeobachtung[2] in liste_netzpunkte:
|
||||
#print(f"Startpunkt nicht enthalten {einzelbeobachtung}")
|
||||
liste_beobachtungen_bearbeitung.append(einzelbeobachtung)
|
||||
startpunkt = None
|
||||
zielpunkt = None
|
||||
@@ -919,24 +1123,20 @@ class Import:
|
||||
summe_dh += beobachtung_bearbeiten[3]
|
||||
summe_entfernung += beobachtung_bearbeiten[4]
|
||||
anzahl_standpunkte += 1
|
||||
|
||||
# Achtung:Hier Rundung auf 8 Nachkommastellen!
|
||||
liste_beobachtungen_reduziert.append(
|
||||
(zugnummer, startpunkt, zielpunkt, round(summe_dh, 8),
|
||||
round(summe_entfernung, 8), anzahl_standpunkte))
|
||||
liste_beobachtungen_bearbeitung = []
|
||||
else:
|
||||
#print(f"Startpunkt und Zielpunkt nicht enthalten {einzelbeobachtung}")
|
||||
liste_beobachtungen_bearbeitung.append(einzelbeobachtung)
|
||||
else:
|
||||
#print(f"-----------------------------")
|
||||
if einzelbeobachtung[1] in liste_netzpunkte and einzelbeobachtung[2] in liste_netzpunkte:
|
||||
#print(einzelbeobachtung)
|
||||
liste_beobachtungen_reduziert.append(einzelbeobachtung + (1,))
|
||||
elif einzelbeobachtung[1] in liste_netzpunkte and einzelbeobachtung[2] not in liste_netzpunkte:
|
||||
#print(f"Zielpunkt nicht enthalten {einzelbeobachtung}")
|
||||
liste_beobachtungen_bearbeitung.append(einzelbeobachtung)
|
||||
elif einzelbeobachtung[1] not in liste_netzpunkte and einzelbeobachtung[2] in liste_netzpunkte:
|
||||
#print(f"Startpunkt nicht enthalten {einzelbeobachtung}")
|
||||
liste_beobachtungen_bearbeitung.append(einzelbeobachtung)
|
||||
startpunkt = None
|
||||
zielpunkt = None
|
||||
@@ -954,12 +1154,12 @@ class Import:
|
||||
summe_dh += beobachtung_bearbeiten[3]
|
||||
summe_entfernung += beobachtung_bearbeiten[4]
|
||||
anzahl_standpunkte += 1
|
||||
|
||||
#Achtung:Hier Rundung auf 8 Nachkommastellen!
|
||||
liste_beobachtungen_reduziert.append(
|
||||
(zugnummer, startpunkt, zielpunkt, round(summe_dh,8), round(summe_entfernung,8), anzahl_standpunkte))
|
||||
liste_beobachtungen_bearbeitung = []
|
||||
else:
|
||||
# print(f"Startpunkt und Zielpunkt nicht enthalten {einzelbeobachtung}")
|
||||
liste_beobachtungen_bearbeitung.append(einzelbeobachtung)
|
||||
zugnummer_vorher = zugnummer
|
||||
|
||||
@@ -970,22 +1170,28 @@ class Import:
|
||||
con.commit()
|
||||
cursor.close()
|
||||
con.close()
|
||||
|
||||
return f"Die Beobachtungen aus der Datei {pfad_datei} wurden erfolgreich importiert."
|
||||
|
||||
|
||||
|
||||
|
||||
else:
|
||||
print(f"Anzahl nicht RVVR durch 4 teilbar. Bitte die Datei {pfad_datei} überprüfen! Der Import wurde abgebrochen.")
|
||||
Import_fortsetzen = False
|
||||
|
||||
|
||||
|
||||
def import_koordinaten_gnss(self, pfad_datei: str, liste_sapos_stationen_genauigkeiten: list) -> str:
|
||||
liste_zeilen = []
|
||||
dict_koordinaten = {}
|
||||
"""Importiert GNSS-Koordinaten (ECEF) in die Tabelle Netzpunkte.
|
||||
|
||||
Die Datei wird semikolon-separiert gelesen und zusätzlich aufgesplittet (Leerzeichen und Kommas).
|
||||
Für Referenzstationen (Kennzeichnung "Referenz" und Standardabweichungen 0.0000/0.0000/0.0000)
|
||||
werden die übergebenen Genauigkeiten (X/Y/Z) eingesetzt.
|
||||
|
||||
Die Koordinaten und Standardabweichungen werden in Netzpunkte geschrieben.
|
||||
|
||||
:param pfad_datei: Pfad zur Koordinatendatei.
|
||||
:type pfad_datei: str
|
||||
:param liste_sapos_stationen_genauigkeiten: Liste mit drei Werten [σX, σY, σZ] für Referenzstationen.
|
||||
:type liste_sapos_stationen_genauigkeiten: list
|
||||
:return: Statusmeldung zum erfolgreichen Import.
|
||||
:rtype: str
|
||||
"""
|
||||
con = sqlite3.connect(self.pfad_datenbank)
|
||||
cursor = con.cursor()
|
||||
|
||||
@@ -995,7 +1201,6 @@ class Import:
|
||||
row_neu = []
|
||||
for eintrag in row:
|
||||
eintrag = str(eintrag).strip()
|
||||
|
||||
eintrag = eintrag.replace("'", "")
|
||||
aufgeteilt = eintrag.split()
|
||||
for teil in aufgeteilt:
|
||||
@@ -1012,14 +1217,33 @@ class Import:
|
||||
stabw_vorinfo_y = excluded.stabw_vorinfo_y,
|
||||
stabw_vorinfo_z = excluded.stabw_vorinfo_z""", (row_neu[0], row_neu[4], row_neu[5], row_neu[6], row_neu[7], row_neu[8], row_neu[9])
|
||||
)
|
||||
#liste_zeilen.append(row_neu)
|
||||
|
||||
|
||||
con.commit()
|
||||
con.close()
|
||||
return "Import der Koordinaten aus stationärem GNSS abgeschlossen."
|
||||
|
||||
def import_basislinien_gnss(self, pfad_datei: str, instrumentenID: int) -> None:
|
||||
"""Importiert GNSS-Basislinien inkl. Kovarianzen in die Tabelle Beobachtungen.
|
||||
|
||||
Die Datei wird zeilenweise gelesen und Basislinien werden über Präfixe erkannt:
|
||||
|
||||
- @+ : Ziel-/Punktkennung (ID),
|
||||
- @- : Gegenpunktkennung und Komponenten (bx/by/bz),
|
||||
- @= : s0 und Kovarianzterme (cxx, cxy, cxz, cyy, cyz, czz).
|
||||
|
||||
Vorabprüfungen:
|
||||
|
||||
- Abbruch, wenn der Dateiname bereits in Beobachtungen vorkommt,
|
||||
- Abbruch, wenn instrumentenID nicht in Instrumente existiert.
|
||||
|
||||
:param pfad_datei: Pfad zur Basisliniendatei (Text).
|
||||
:type pfad_datei: str
|
||||
:param instrumentenID: ID des verwendeten GNSS-Instruments (FK auf Instrumente).
|
||||
:type instrumentenID: int
|
||||
:return: None
|
||||
:rtype: None
|
||||
"""
|
||||
# Import_fortsetzen wird False, sobald eine Fehler festgestellt wird. Als Folge wird der Import abgebrochen und eine Fehlermeldung mit Handlungshinweisen für den Benutzer ausgegeben.
|
||||
Import_fortsetzen = True
|
||||
|
||||
# Prüfen, ob Bereits Daten aus der Datei in der Datenbank vorhanden sind
|
||||
@@ -1033,18 +1257,16 @@ class Import:
|
||||
if pfad_datei in liste_dateinamen_in_db:
|
||||
Import_fortsetzen = False
|
||||
|
||||
# Import abbrechen, wenn das Instrument noch nicht vom Benutzer angelegt wurde.
|
||||
liste_instrumentenid = [r[0] for r in cursor.execute("SELECT instrumenteID FROM Instrumente").fetchall()]
|
||||
cursor.close()
|
||||
con.close()
|
||||
cursor.close
|
||||
if instrumentenID not in liste_instrumentenid:
|
||||
Import_fortsetzen = False
|
||||
print(
|
||||
"Der Import wurde abgebrochen. Bitte eine gültige InstrumentenID eingeben. Bei Bedarf ist das Instrument neu anzulegen.")
|
||||
|
||||
|
||||
|
||||
if Import_fortsetzen:
|
||||
|
||||
liste_basilinien = []
|
||||
tupel_basislinie = ()
|
||||
with (open(pfad_datei, "r", encoding="utf-8") as txt):
|
||||
@@ -1052,17 +1274,13 @@ class Import:
|
||||
zeile = str(zeile).rstrip("\n").rstrip("\r")
|
||||
aufgeteilt = zeile.split()
|
||||
if aufgeteilt[0][:2] == "@+":
|
||||
#print(aufgeteilt[0][2:])
|
||||
tupel_basislinie += (aufgeteilt[0][2:],)
|
||||
if aufgeteilt[0][:2] == "@-":
|
||||
#print(aufgeteilt[0][2:], aufgeteilt[1], aufgeteilt[2], aufgeteilt[3])
|
||||
tupel_basislinie += (aufgeteilt[0][2:], aufgeteilt[1], aufgeteilt[2], aufgeteilt[3],)
|
||||
if aufgeteilt[0][:2] == "@=":
|
||||
#print(aufgeteilt[1], aufgeteilt[2], aufgeteilt[3], aufgeteilt[4], aufgeteilt[5], aufgeteilt[6], aufgeteilt[7])
|
||||
tupel_basislinie += (aufgeteilt[1], aufgeteilt[2], aufgeteilt[3], aufgeteilt[4], aufgeteilt[5], aufgeteilt[6], aufgeteilt[7], )
|
||||
liste_basilinien.append(tupel_basislinie)
|
||||
tupel_basislinie = ()
|
||||
#print(liste_basilinien)
|
||||
|
||||
else:
|
||||
print(
|
||||
@@ -1078,7 +1296,4 @@ class Import:
|
||||
con.commit()
|
||||
cursor.close()
|
||||
con.close()
|
||||
print(f"Der Import der Datei {pfad_datei} wurde erfolgreich abgeschlossen.")
|
||||
|
||||
|
||||
|
||||
print(f"Der Import der Datei {pfad_datei} wurde erfolgreich abgeschlossen.")
|
||||
Reference in New Issue
Block a user