From f2c48625023bebcc3959333b8fd6c48fa8264f38 Mon Sep 17 00:00:00 2001 From: spertl Date: Mon, 26 Aug 2024 04:48:32 +0000 Subject: [PATCH] Upload zwischenstand --- upload/__entwurf_Versickerung.py | 176 ++++++++++++ upload/__init__.py | 36 +++ upload/config.toml | 14 + upload/gdeMessdatenImport.py.bak | 294 +++++++++++++++++++ upload/ibpTools.py | 475 +++++++++++++++++++++++++++++++ 5 files changed, 995 insertions(+) create mode 100644 upload/__entwurf_Versickerung.py create mode 100644 upload/__init__.py create mode 100644 upload/config.toml create mode 100644 upload/gdeMessdatenImport.py.bak create mode 100644 upload/ibpTools.py diff --git a/upload/__entwurf_Versickerung.py b/upload/__entwurf_Versickerung.py new file mode 100644 index 0000000..6599570 --- /dev/null +++ b/upload/__entwurf_Versickerung.py @@ -0,0 +1,176 @@ + + +import toml +import numpy as np +import matplotlib.pyplot as plt + +toml_string = """ + +[kanalplanung] + +inp_file = "C:/Daten/nc/Ingenieurbüro/20 Projekte/Kanalplanung/kanalplanung.gpkg" +""" + +prj = '0122' # Projektnummer als Filter + + + +#toml.load("config.toml") +cfg = toml.loads(toml_string) + +md = QgsProviderRegistry.instance().providerMetadata("ogr") +gpkg_con = md.createConnection( cfg['kanalplanung']['inp_file'], {}) +#gpkg_con.fields('public','schacht') + +query = "SELECT * FROM schacht_versickerung" + +col = ['s.ezg_total_Aum','sv.fz','sv.di','sv.wandst','sv.da','sv.n','sv.r_5','sv.tiefe','sv.r_mas','sv.D_mas','sv.z_v','sv.Q_s','sv.D'] +## col_dict = {j:i for i,j in enumerate(col)} + +#Ermittle Index von Objekt +#col.index('sv.di') + +col_str = '' + + +query = "UPDATE schacht_versickerung SET d_a = d_i+2*wandst" +res = gpkg_con.execSql(query) + +query = """UPDATE schacht_versickerung SET + k_f = (SELECT + pr.kf + FROM schacht s JOIN projekt pr ON pr.nr = s.ibpprj + WHERE s.fid = schacht_versickerung.schacht_fid) WHERE k_f is NULL + + + + """ +res = gpkg_con.execSql(query) + +query = """SELECT + s.fid as fid, + sv.schacht_fid, + s.ezg_total_Aum, + sv.f_z, + sv.d_i, + sv.wandst, + sv.d_a, + sv.n, + sv.r_5, + sv.tiefe, + sv.r_mas, + sv.D_mas, + sv.z_v, + sv.Q_s, + sv.D, + sv.k_f + FROM schacht s + JOIN schacht_versickerung sv ON s.fid = sv.schacht_fid + JOIN projekt pr ON pr.nr = s.ibpprj + """ + +# Spaltennamen in das Ergebnis-Array integrieren +dat = [] + +res = gpkg_con.execSql(query) +for row in res.rows(): + d = {} + for i,j in enumerate(res.columns()): + d[j] = row[i] + dat.append(d) + +#res = gpkg_con.executeSql(query) +#res = res[0] +#res_dict = {j:res[i] for i,j in enumerate(col)} +# +#i = res[0] +# +#D = i[13] +#r = i[7].replace("[","").replace("]","").replace("\n","").split(";") +#z = [] +# +# +# +#def z_v(r, D): +# (A_u * r - math.pi * d_a**2/4 * k_f/2) / (d_i**2 * math.pi / 4 * D * f_z + d_a * math.pi * k_f/4) * n + + +for d in dat: + #via Numpy: + r = np.fromstring(d['r_5'].replace(',','.'), sep=';') + D = np.fromstring(d['D'].replace(',','.'), sep=';') + + z = (d['ezg_total_Aum']*10**-7 * r - math.pi * d['d_a']**2/4 * d['k_f']/2) / (d['d_i']**2 * math.pi / (4 * D * 60 * d['f_z']) + d['d_a'] * math.pi * d['k_f']/4) * d['n'] + + z_max = z.max() + idx = z.argmax() + D_z_max = D[idx] + r_z_max = r[idx] + Q_s = (math.pi*d['d_i']**2/4+math.pi*d['d_i']*z_max/2)*d['n'] * d['k_f']/2 + + #r = d['r_5'].replace("[","").replace("]","").replace(",",".").replace("\n","").split(";") + #r = [float(i) for i in r] + #D = d['D'].replace("[","").replace("]","").replace("\n","").split(";") + #D = [float(i) for i in D] + + #z = [] + # + #for i, j in enumerate(D): + # #z.append(z_v(r[i], j)) + # z.append( + # (d['ezg_total_Aum']*10**-7 * r[i] - math.pi * d['da']**2/4 * d['kf']/2) / (d['di']**2 * math.pi / (4 * D[i] * 60 * d['fz']) + d['da'] * math.pi * d['kf']/4) * d['n']) + + #z_max = max(z) + #idx = z.index(z_max) + #D_z_max = D[idx] + #r_z_max = r[idx] + + #z_str = np.array2string(r) + + query = """UPDATE schacht_versickerung SET + z = '{}', + z_v = {}, + r_mas = {}, + D_mas = {}, + Q_s = {} + WHERE schacht_fid = {}""".format(np.array2string(z).replace("[","").replace("]","").replace(" ",";"), z_max, r_z_max, D_z_max, Q_s, d['schacht_fid']) + print(query) + gpkg_con.execSql(query) + +#https://github.com/geopandas/geopandas/issues/2794 +#https://gist.github.com/MaxDragonheart/46445a150aac9d528dadd2ec877203a5 +#https://github.com/geopandas/geopandas/issues/1035 + + + # + # PLOT-DIAGRAMM + # + + + plt.style.use('_mpl-gallery') + + # make data + x = D + x = np.append(0, x) + y = z + y = np.append(0, y) + + # plot + fig, ax = plt.subplots(facecolor='white', figsize=[8/2.54*1.4, 8/2.54*1.4], dpi=100) + #fig.subplots_adjust(top=0.15,bottom=0.15,left=0.15,right=0.15) + + ax.plot(x, y, linewidth=2.0) + + ax.set_xlim(0, D_z_max+120) + ax.set_xlabel('Dauerstufe [min]') + ax.set_ylim(0, z_max+1) + ax.set_ylabel('Wasserstand [m]') + ax.set_title('Schachtversickerung') + + ax + + #plt.show() + plt.savefig('C:\\Daten\\nc\\Ingenieurbüro\\20 Projekte\\Kanalplanung\\Grafiken\\berechnet\\a138-schachtversickerung_{}.png'.format(d['schacht_fid']), bbox_inches="tight", transparent=True) + + + diff --git a/upload/__init__.py b/upload/__init__.py new file mode 100644 index 0000000..8fdb186 --- /dev/null +++ b/upload/__init__.py @@ -0,0 +1,36 @@ +# -*- coding: utf-8 -*- +""" +/*************************************************************************** + GemeindeMessdatenImport + A QGIS plugin + Importiert Messdaten + Generated by Plugin Builder: http://g-sherman.github.io/Qgis-Plugin-Builder/ + ------------------- + begin : 2024-02-01 + copyright : (C) 2024 by Sebastian Pertl + email : sebastian.pertl@fridolfing.bayern.de + git sha : $Format:%H$ + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + This script initializes the plugin, making it known to QGIS. +""" + + +# noinspection PyPep8Naming +def classFactory(iface): # pylint: disable=invalid-name + """Load GemeindeMessdatenImport class from file GemeindeMessdatenImport. + + :param iface: A QGIS interface instance. + :type iface: QgsInterface + """ + # + from .ibpTools import ibpTools + return ibpTools(iface) diff --git a/upload/config.toml b/upload/config.toml new file mode 100644 index 0000000..b87600b --- /dev/null +++ b/upload/config.toml @@ -0,0 +1,14 @@ + + +[qgs_cad] +import_layer_prefix = "_IBP_QIN_" + + + +[iface] +host = "localhost" +port = 8080 +debug = false + + + diff --git a/upload/gdeMessdatenImport.py.bak b/upload/gdeMessdatenImport.py.bak new file mode 100644 index 0000000..80c67aa --- /dev/null +++ b/upload/gdeMessdatenImport.py.bak @@ -0,0 +1,294 @@ +# -*- coding: utf-8 -*- +""" +/*************************************************************************** + GemeindeMessdatenImport + A QGIS plugin + Importiert Messdaten im TXT-Format in die Gemeindeeigene Messdaten-Datenbank. + + + ------------------- + begin : 2024-02-01 + git sha : $Format:%H$ + copyright : (C) 2024 by Sebastian Pertl + email : sebastian.pertl@fridolfing.bayern.de + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ +""" +from qgis.PyQt.QtCore import QSettings, QTranslator, QCoreApplication +from qgis.PyQt.QtGui import QIcon +from qgis.PyQt.QtWidgets import QAction, QComboBox + +from qgis.PyQt import uic +from qgis.PyQt import QtWidgets +from qgis.PyQt.QtWidgets import QFileDialog + +from qgis.core import QgsVectorLayer, QgsVectorFileWriter, QgsProviderRegistry +from qgis.utils import iface + +# Initialize Qt resources from file resources.py +from .resources import * +# Import the code for the dialog +#from .gdeMessdatenImport_dialog import GemeindeMessdatenImportDialog + +import os +import os.path + + +class GemeindeMessdatenImport: + """QGIS Plugin Implementation.""" + + def __init__(self, iface): + """Constructor. + + :param iface: An interface instance that will be passed to this class + which provides the hook by which you can manipulate the QGIS + application at run time. + :type iface: QgsInterface + """ + # Save reference to the QGIS interface + self.iface = iface + # initialize plugin directory + self.plugin_dir = os.path.dirname(__file__) + + # Declare instance attributes + # Eintrag Menüband Oben + self.actions = [] + self.menu = u'&Gemeinde Messdaten Import' + + # Check if plugin was started the first time in current QGIS session + # Must be set in initGui() to survive plugin reloads + self.first_start = None + + def initGui(self): + """Create the menu entries and toolbar icons inside the QGIS GUI.""" + + # + self.toolBar = self.iface.addToolBar("Gemeinde Pertl tools") + + icon_path = os.path.join(self.plugin_dir, 'icon_txt.png') + self.act1 = QAction(QIcon(icon_path), u'Import Messdaten', self.iface.mainWindow()) + self.act1.triggered.connect(self.run1) + self.toolBar.addAction(self.act1) + self.iface.addPluginToMenu(self.menu, self.act1) + + icon_path = os.path.join(self.plugin_dir, 'icon_dupl.png') + self.act2 = QAction(QIcon(icon_path), u'Lösche Vorhandene', self.iface.mainWindow()) + self.act2.triggered.connect(self.run2) + self.toolBar.addAction(self.act2) + self.iface.addPluginToMenu(self.menu, self.act2) + + icon_path = os.path.join(self.plugin_dir, 'icon_db.png') + self.act3 = QAction(QIcon(icon_path), u'Gemeinde Übertrag', self.iface.mainWindow()) + self.act3.triggered.connect(self.run3) + self.toolBar.addAction(self.act3) + self.iface.addPluginToMenu(self.menu, self.act3) + + icon_path = os.path.join(self.plugin_dir, 'icon_db.png') + self.act4 = QComboBox(self.iface.mainWindow()) + self.act4.addItem('KG') + self.act4.addItem('EG') + self.act4.addItem('1.OG') + self.act4.addItem('2.OG') + self.act4.addItem('3.OG') + self.act4.currentTextChanged.connect(self.run4) + self.toolBar.addWidget(self.act4) + #self.toolBar.addAction(self.act4) + #self.iface.addPluginToMenu(self.menu, self.act4) + + self.first_start = True + + + def unload(self): + """Removes the plugin menu item and icon from QGIS GUI.""" + for action in self.actions: + self.iface.removePluginMenu(u'&Gemeinde Messdaten Import', action) + self.iface.removeToolBarIcon(action) + + def run_init(self): + # Create the dialog with elements (after translation) and keep reference + # Only create GUI ONCE in callback, so that it will only load when the plugin is started + if self.first_start == True: + self.first_start = False + self.dlg = GemeindeMessdatenImportDialog() + + + def run1(self): + """Run method that performs all the real work""" + + self.run_init() + self.dlg.run() + + result = True + if result: + # Do something useful here - delete the line containing pass and + # substitute with your code. + pass + + def run2(self): + """Run method that performs all the real work""" + + self.run_init() + self.dlg.run_del_dup() + + result = True + if result: + # Do something useful here - delete the line containing pass and + # substitute with your code. + pass + + def run3(self): + """Run method that performs all the real work""" + + self.run_init() + self.dlg.run_save() + + result = True + if result: + # Do something useful here - delete the line containing pass and + # substitute with your code. + pass + + def run4(self): + print(self.act4.currentIndex()) + print(self.act4.currentText()) + + +class GemeindeMessdatenImportDialog(): + def __init__(self, parent=None): + """Constructor.""" + + self.inp_file = 'T:/RIWA-GIS/Layer/fridolfing.gpkg' + + self.md = QgsProviderRegistry.instance().providerMetadata("ogr") + self.con = self.md.createConnection( self.inp_file, {}) + + + def run(self): + + qfd = QFileDialog() + filename = QFileDialog.getOpenFileName(qfd, "Wähle Vermessungsdaten","::{645ff040-5081-101b-9f08-00aa002f954e}", '*.txt') + + csv = filename[0] + rutacsv = 'file:///' + csv + '?delimiter=,&xField=field3&yField=field2' + tabla = QgsVectorLayer(rutacsv, os.path.basename(csv), 'delimitedtext') + + opt = QgsVectorFileWriter.SaveVectorOptions() + opt.EditionCapability = QgsVectorFileWriter.CanAddNewLayer + opt.layerName = "messdaten_imp" + opt.actionOnExistingFile = QgsVectorFileWriter.CreateOrOverwriteLayer + QgsVectorFileWriter.writeAsVectorFormat(tabla, self.inp_file, opt) + + # Datensätze bereinigen + query = """UPDATE messdaten_imp SET + field6 = replace(field6 ,"HSDV:",""), + field7 = replace(field7 ,"VSDV:",""), + field8 = replace(field8 ,"STATUS:",""), + field9 = replace(field9 ,"SATS:",""), + field10 = replace(field10,"AGE:",""), + field11 = replace(field11,"PDOP:",""), + field12 = replace(field12,"HDOP:",""), + field13 = replace(field13,"VDOP:",""), + field14 = replace(field14,"TDOP:",""), + field15 = replace(field15,"GDOP:",""), + field16 = replace(field16,"NSDV:",""), + field17 = replace(field17,"ESDV:",""), + field18 = replace(field18,"DATE:",""), + field19 = replace(field19,"TIME:","");""" + self.con.executeSql(query) + + ## Erzeuge Geometrie für Vorschau + #query = """UPDATE messdaten_imp SET geom = AsGPB(setsrid(makepoint(field3, field2), 25832));""" + #con.executeSql(query) + + # Datum formatieren + query = """UPDATE messdaten_imp SET field18 = substr(field18,7,4)||'-'||substr(field18,1,2)||'-'||substr(field18,4,2);""" + self.con.executeSql(query) + + iface.mapCanvas().refreshAllLayers() + + def run_del_dup(self): + # Duplikate löschen + query = """DELETE FROM messdaten_imp WHERE field3 || field2 || field4 in (SELECT rw || hw || höhe FROM messdaten);""" + self.con.executeSql(query) + query = """DELETE FROM messdaten_imp WHERE field1 in (SELECT Nummer FROM messdaten);""" + self.con.executeSql(query) + + iface.mapCanvas().refreshAllLayers() + + + def run_save(self): + + # Daten übertragen + query = """INSERT INTO + messdaten + ( + "fid", + "geom", + "Nummer", + "RW", + "HW", + "Höhe", + "Beschreibung", + "HSDV", + "VSDV", + "STATUS", + "SATS", + "AGE", + "PDOP", + "HDOP", + "VDOP", + "TDOP", + "GDOP", + "NSDV", + "ESDV", + "aufnahme_dat", + "aufnahme_uhr", + "import_dat", + "Anmerkung", + "Quelle" + ) + SELECT + NULL, + AsGPB(setsrid(makepoint(field3, field2), 25832)), + field1, + field3, + field2, + field4, + field5, + field6 , + field7 , + field8 , + field9 , + field10, + field11, + field12, + field13, + field14, + field15, + field16, + field17, --ESDV + field18, + field19, + DATE('now'), + '', + 'Vermessung Bauhof' + FROM messdaten_imp;""" + self.con.executeSql(query) + + # Anzahl der Objekte aktuallisieren + query = """DELETE FROM messdaten_imp WHERE field1 in (SELECT Nummer FROM messdaten);""" + self.con.executeSql(query) + + # Import-Tabelle leeren + query = """DELETE FROM messdaten_imp;""" + self.con.executeSql(query) + + iface.mapCanvas().refreshAllLayers() \ No newline at end of file diff --git a/upload/ibpTools.py b/upload/ibpTools.py new file mode 100644 index 0000000..f12f1f4 --- /dev/null +++ b/upload/ibpTools.py @@ -0,0 +1,475 @@ +# -*- coding: utf-8 -*- +""" +/*************************************************************************** + GemeindeMessdatenImport + A QGIS plugin + Importiert Messdaten im TXT-Format in die Gemeindeeigene Messdaten-Datenbank. + + + ------------------- + begin : 2024-02-01 + git sha : $Format:%H$ + copyright : (C) 2024 by Sebastian Pertl + email : sebastian.pertl@fridolfing.bayern.de + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ +""" +from qgis.PyQt.QtCore import QSettings, QTranslator, QCoreApplication +from qgis.PyQt.QtGui import QIcon +from qgis.PyQt.QtWidgets import QAction, QComboBox + +from qgis.PyQt import uic +from qgis.PyQt import QtWidgets +from qgis.PyQt.QtWidgets import QFileDialog, QMessageBox, QInputDialog, QLineEdit + +#from qgis.core import QgsVectorLayer, QgsVectorFileWriter, QgsProviderRegistry +#from qgis.core import QgsProject, QgsFeature +from qgis.core import * +from qgis.utils import iface +import qgis.core + +import toml + +# Initialize Qt resources from file resources.py +# from .resources import * +# Import the code for the dialog +#from .gdeMessdatenImport_dialog import GemeindeMessdatenImportDialog + +import os +import os.path + +import ezdxf +import pandas as pd +import numpy as np +import networkx as nx +import math +import scipy +import sqlite3 +import subprocess +import win32com.client + +from http.server import BaseHTTPRequestHandler, HTTPServer +import time + +hostName = "localhost" +serverPort = 8080 + + +file_path = "D:/Daten/nc/Ingenieurbüro/98-CAD-Daten/Tools-QGIS/ibpTools/" +with open(file_path + 'config.toml', 'r') as f: + CFG = toml.load(f) + + +class MyServer(BaseHTTPRequestHandler): + def do_GET(self): + self.send_response(200) + self.send_header("Content-type", "text/html") + self.end_headers() + self.wfile.write(bytes("https://pythonbasics.org", "utf-8")) + self.wfile.write(bytes("

Request: %s

" % self.path, "utf-8")) + self.wfile.write(bytes("", "utf-8")) + self.wfile.write(bytes("

This is an example web server.

", "utf-8")) + self.wfile.write(bytes("", "utf-8")) + +basepath = os.path.dirname(os.path.realpath(__file__)) +TEIGHA_PATH = basepath.replace("\\","/") + "/Teigha File Converter 4.3.2/TeighaFileConverter.exe" + + +tmp_folder = r"C:/tmp" + + +class ibpTools: + """QGIS Plugin Implementation.""" + + def __init__(self, iface): + """Constructor. + + :param iface: An interface instance that will be passed to this class + which provides the hook by which you can manipulate the QGIS + application at run time. + :type iface: QgsInterface + """ + # Save reference to the QGIS interface + self.iface = iface + # initialize plugin directory + self.plugin_dir = os.path.dirname(__file__) + + # Declare instance attributes + # Eintrag Menüband Oben + self.actions = [] + self.menu = u'&IBP: Kanalplanung-Tools' + + # Check if plugin was started the first time in current QGIS session + # Must be set in initGui() to survive plugin reloads + self.first_start = None + + inp_file = 'D:/Daten/nc/Ingenieurbüro/20 Projekte/Kanalplanung/kanalplanung.gpkg' + self.md = QgsProviderRegistry.instance().providerMetadata("ogr") + self.gpkg_con = self.md.createConnection( inp_file, {}) + + self.doc = False + + def initGui(self): + """Create the menu entries and toolbar icons inside the QGIS GUI.""" + + # + self.toolBar = self.iface.addToolBar("IBP: Kanalplanung-Tools") + + self.actList = [] + + icon_path = os.path.join(self.plugin_dir, 'icon_filter.png') + act = QAction(QIcon(icon_path), u'Setze Projektfilter', self.iface.mainWindow()) + act.triggered.connect(self.run_projectFilter) + self.actList.append(act) + + icon_path = os.path.join(self.plugin_dir, 'icon_setup.png') + act = QAction(QIcon(icon_path), u'Initialisiere BricsCAD', self.iface.mainWindow()) + act.triggered.connect(self.run_setup) + self.actList.append(act) + + icon_path = os.path.join(self.plugin_dir, 'icon_import.png') + act = QAction(QIcon(icon_path), u'Importiere von BricsCAD', self.iface.mainWindow()) + act.triggered.connect(self.run_import_from_bricscad) + self.actList.append(act) + + icon_path = os.path.join(self.plugin_dir, 'icon_export.png') + act = QAction(QIcon(icon_path), u'Übertrag in BricsCAD', self.iface.mainWindow()) + act.triggered.connect(self.run_export_to_bricscad) + self.actList.append(act) + + + for i in self.actList: + self.toolBar.addAction(i) + self.iface.addPluginToMenu(self.menu, i) + + + + self.first_start = True + + + def unload(self): + """Removes the plugin menu item and icon from QGIS GUI.""" + for action in self.actions: + self.iface.removePluginMenu(u'&IBP: Kanalplanung-Tools', action) + self.iface.removeToolBarIcon(action) + + def run_projectFilter(self): + qid = QInputDialog() + filter, ok = QInputDialog.getText( qid, "Projektfilter", "Projektnummmer", QLineEdit.Normal, "") + + self.gpkg_con.executeSql("UPDATE projekt SET aktiv = 0;") + + if filter != "": + self.gpkg_con.executeSql("UPDATE projekt SET aktiv = 1 WHERE nr='{}';".format(filter)) + + #for i in self.iface.mapCanvas().layers(): + for i in QgsProject.instance().mapLayers().values(): + if type(i) == type(QgsVectorLayer()): + idx = i.fields().indexFromName('ibpprj') + if idx >= 0: + i.setSubsetString("ibpprj LIKE '%"+filter+"%'") + + else: + row.setSubsetString("") + + def run_setup(self): + self.acad = win32com.client.Dispatch("BricscadApp.AcadApplication") + self.doc = self.acad.ActiveDocument + self.model = self.doc.ModelSpace + + QMessageBox.information(None, "Information", "BricsCAD gestartet und Datei gewählt: "+self.doc.name) + + def run_import_from_bricscad(self): + """ + Lädt alle Layer von BricsCAD in QGIS die mit "_IBP_QIN_" beginnen. + """ + + if self.doc == False: + QMessageBox.warning(None, "Warnung", "Verbindung noch nicht initialisiert!") + else: + self.doc.save() + + ibp_dwg_to_dxf(self.doc.name, self.doc.path.replace("\\","/")) + + file_path = self.doc.path.replace("\\","/")+self.doc.name.replace(".dwg",".dxf") + print(file_path) + s_doc = ezdxf.readfile(file_path) + s_msp = s_doc.modelspace() + + # QGIS-Daten + laylist = {} + laylist['cad_punkt'] = {"qgis_handle":[], "add_new":[], "qgis_lay": None} + laylist['cad_linie'] = {"qgis_handle":[], "add_new":[], "qgis_lay": None} + + #@todo: Wenn Layer nicht existiert soll er neu angelegt werden + for key, val in laylist.items(): + val['qgis_lay'] = QgsProject.instance().mapLayersByName(key)[0] + val['qgis_lay'].startEditing() + for i in val['qgis_lay'].getFeatures(): + if i['doc'] == self.doc.name: + val['qgis_handle'].append(i['handle']) + + # Übertrage alle Elemente des Bricscad Layer "_IBP_QIN_..." in QGIS + cad_qgis_obj = [] + for i in s_msp.query('*[layer?"{}.*"]'.format(CFG['qgs_cad']['import_layer_prefix'])): + cad_qgis_obj.append(i) + + #print(cad_qgis_obj) + + for i in cad_qgis_obj: + layer = "" + if i.dxftype() in ["INSERT","POINT","CIRCLE"]: + layer = "cad_punkt" + elif i.dxftype() in ["LINE","LWPOLYLINE"]: + layer = "cad_linie" + else: + continue + new_feat = False + + if i.dxf.handle not in laylist[layer]['qgis_handle']: + new_feat = True + feature = QgsFeature(laylist[layer]['qgis_lay'].fields()) + feature['layer'] = i.dxf.layer + feature['handle'] = i.dxf.handle + feature['doc'] = self.doc.name + feature['type'] = i.dxftype() + else: + for j in laylist[layer]['qgis_lay'].getFeatures(): + if j['handle'] == i.dxf.handle and j['doc'] == self.doc.name: + feature = j + + if i.dxftype() == "LINE": + geom = QgsGeometry.fromPolylineXY([QgsPointXY(i.dxf.start[0],i.dxf.start[1]), + QgsPointXY(i.dxf.end[0],i.dxf.end[1])]) + elif i.dxftype() == "INSERT": + geom = QgsGeometry.fromPointXY(QgsPointXY(i.dxf.insert[0],i.dxf.insert[1])) + feature['block_name'] = i.dxf.name + elif i.dxftype() == "LWPOLYLINE": + pts = [] + for j in i.vertices(): + pts.append(QgsPointXY(j[0],j[1])) + ##Kontrolle ob geschlossen + if i.dxf.flags == 1: + geom = QgsGeometry.fromPolygonXY([pts]) + else: + geom = QgsGeometry.fromPolylineXY(pts) + elif i.dxftype() == "POINT": + geom = QgsGeometry.fromPointXY(QgsPointXY(i.dxf.location[0],i.dxf.location[1])) + elif i.dxftype() == "CIRCLE": + geom = QgsGeometry.fromPointXY(QgsPointXY(i.dxf.center[0],i.dxf.center[1])) + + if new_feat: + feature.setGeometry(geom) + laylist[layer]['add_new'].append(feature) + else: + laylist[layer]['qgis_lay'].updateFeature(feature) + laylist[layer]['qgis_lay'].changeGeometry(feature.id(), geom) + + for key, val in laylist.items(): + val['qgis_lay'].commitChanges() + val['qgis_lay'].dataProvider().addFeatures(val['add_new']) + + self.iface.mapCanvas().refreshAllLayers() + + def run_export_to_bricscad(self): + + if self.doc == False: + QMessageBox.warning(None, "Warnung", "Verbindung noch nicht initialisiert!") + else: + lgp_file = self.doc.path.replace("\\","/")+self.doc.name.replace(".dwg","_Lageplan.dxf") + + try: + ibp_dwg_to_dxf(lgp_file.split("/")[-1].replace(".dxf",".dwg"),lgp_file.replace(lgp_file.split("/")[-1],"")) + lgp_doc = ezdxf.readfile(lgp_file) + except: + lgp_doc = ezdxf.readfile('C:/Daten/nc/Ingenieurbüro/99-Vorlagen/ezdxf_vorl.dxf') + + lgp_msp = lgp_doc.modelspace() + + lay = QgsProject.instance().mapLayersByName('schacht')[0] + lay.startEditing() + + for i in lay.getFeatures(): + if i['schacht_dn'] > 0: + rad = i['schacht_dn']/1000/2 + else: + if i['fallrohr'] > 0: + rad = i['fallrohr']/1000/2 + else: + rad = 0.05 + + if len(lgp_msp.query().filter(lambda e: "QGIS:schacht:symb:{}".format(i['fid']) in e.get_hyperlink())) == 1: + # Element vorhanden + #ent_symb = lgp_msp.query('*[handle=="'+i['cad_out_handle_symb']+'"]')[0] + ent_symb = lgp_msp.query().filter(lambda e: "QGIS:schacht:symb:{}".format(i['fid']) in e.get_hyperlink())[0] + else: + # Element anlegen + ent_symb = lgp_msp.add_circle((0,0), 1) + ent_symb.dxf.layer = '_IBP_QO_EW_{}_SCH'.format(i['art']) + + ent_symb.dxf.center = (i.geometry().asPoint().x(), i.geometry().asPoint().y()) + ent_symb.dxf.radius = rad + + if len(lgp_msp.query().filter(lambda e: "QGIS:schacht:txt1:{}".format(i['fid']) in e.get_hyperlink())) == 1: + # Element vorhanden + # ent_txt = lgp_msp.query('*[handle=="{}"]'.format(i['cad_out_handle_txt']))[0] + ent_txt = lgp_msp.query().filter(lambda e: "QGIS:schacht:txt1:{}".format(i['fid']) in e.get_hyperlink())[0] + else: + # Element anlegen + ent_txt = lgp_msp.add_mtext("abc") + ent_txt.dxf.insert = ent_symb.dxf.center + ent_txt.dxf.layer = '_IBP_QO_EW_{}_SCH_Txt'.format(i['art']) + ent_txt.dxf.char_height = 0.25 + ent_txt.dxf.style = 'IBP_Norm' + + ent_txt.text = "{}".format(i['name']) + if i['schacht_dn'] != NULL: + ent_txt.text+="\nDN{:.0f}".format(i['schacht_dn']) + if i['dh'] != NULL: + ent_txt.text+="\nDH: {:.2f}".format(i['dh']) + if i['sh'] != NULL: + ent_txt.text+="\nSH: {:.2f}".format(i['sh']) + + #i['cad_out_handle_symb'] = ent_symb.dxf.handle + #i['cad_out_handle_txt'] = ent_txt.dxf.handle + + ent_symb.set_hyperlink("QGIS:schacht:symb:{}".format(i['fid'])) + ent_txt.set_hyperlink("QGIS:schacht:txt1:{}".format(i['fid'])) + + + #lay.commitChanges() + + lay = QgsProject.instance().mapLayersByName('haltung')[0] + lay.startEditing() + + for i in lay.getFeatures(): + points = [] + for j in i.geometry().vertices(): + points.append((j.x(),j.y())) + + qry = lgp_msp.query().filter(lambda e: "QGIS:haltung:symb:{}".format(i['fid']) in e.get_hyperlink()) + if len(qry) == 1: + # Element vorhanden + #ent_symb = lgp_msp.query('*[handle=="{}"]'.format(i['cad_out_handle_symb']))[0] + ent_symb = qry[0] + else: + # Element anlegen + ent_symb = lgp_msp.add_lwpolyline(points) + ent_symb.dxf.layer = '_IBP_QO_EW_{}_Lei'.format(i['art']) + + #i['cad_out_handle_symb'] = ent_symb.dxf.handle + ent_symb.set_hyperlink("QGIS:haltung:symb:{}".format(i['fid'])) + + mid_point = i.geometry().interpolate(i.geometry().length()/2) + mid_point_c = [mid_point.asPoint().x(), mid_point.asPoint().y()] + mid_angle = i.geometry().interpolateAngle(i.geometry().length()/2) + mid_angle_deg = 90-mid_angle/math.pi*180 + if mid_angle_deg < 0: + mid_angle_deg+= 360 + if mid_angle_deg > 90 and mid_angle_deg < 270: + mid_angle_deg-= 180 + + qry = lgp_msp.query().filter(lambda e: "QGIS:haltung:txt1:{}".format(i['fid']) in e.get_hyperlink()) + if len(qry) == 1: + # Element vorhanden + #ent_txt = lgp_msp.query('*[handle=="{}"]'.format(i['cad_out_handle_txt']))[0] + ent_txt = qry[0] + else: + # Element anlegen + ent_txt = lgp_msp.add_mtext("abc") + ent_txt.dxf.insert = [mid_point_c[0]+math.cos((mid_angle_deg+90)/180*math.pi)*.1, + mid_point_c[1]+math.sin((mid_angle_deg+90)/180*math.pi)*.1] + ent_txt.dxf.layer = '_IBP_QO_EW_{}_Lei_Txt'.format(i['art']) + ent_txt.dxf.rotation = mid_angle_deg + ent_txt.dxf.attachment_point = ezdxf.lldxf.const.MTEXT_BOTTOM_CENTER + ent_txt.dxf.char_height = 0.25 + ent_txt.dxf.style = 'IBP_Norm' + ent_txt.text = "{}".format(i['mat']) + #i['cad_out_handle_txt'] = ent_txt.dxf.handle + ent_txt.set_hyperlink("QGIS:haltung:txt1:{}".format(i['fid'])) + + qry = lgp_msp.query().filter(lambda e: "QGIS:haltung:txt2:{}".format(i['fid']) in e.get_hyperlink()) + if len(qry) == 1: + # Element vorhanden + #ent_txt = lgp_msp.query('*[handle=="{}"]'.format(i['cad_out_handle_txt2']))[0] + ent_txt = qry[0] + else: + # Element anlegen + ent_txt = lgp_msp.add_mtext("abc") + ent_txt.dxf.insert = [mid_point_c[0]-math.cos((mid_angle_deg+90)/180*math.pi)*.1, + mid_point_c[1]-math.sin((mid_angle_deg+90)/180*math.pi)*.1] + ent_txt.dxf.layer = '_IBP_QO_EW_{}_Lei_Txt'.format(i['art']) + ent_txt.dxf.rotation = mid_angle_deg + ent_txt.dxf.attachment_point = ezdxf.lldxf.const.MTEXT_TOP_CENTER + ent_txt.dxf.char_height = 0.25 + ent_txt.dxf.style = 'IBP_Norm' + if i['gefaelle'] == qgis.core.NULL: + ent_txt.text = '{:.2f}m'.format(i['c_laenge']) + else: + ent_txt.text = '{:.2f}‰; {:.2f}m'.format(i['gefaelle'], i['c_laenge']) + #i['cad_out_handle_txt2'] = ent_txt.dxf.handle + ent_txt.set_hyperlink("QGIS:haltung:txt2:{}".format(i['fid'])) + + + #lay.updateFeature(i) #Update-QGIS-Layer + + + + lay.commitChanges() + + lgp_doc.saveas(lgp_file) + ibp_dxf_to_dwg(lgp_file.split("/")[-1],lgp_file.replace(lgp_file.split("/")[-1],"")) + + def run_init(self): + # Create the dialog with elements (after translation) and keep reference + # Only create GUI ONCE in callback, so that it will only load when the plugin is started + if self.first_start == True: + self.first_start = False + self.dlg = ibpToolsDialog() + + + + + + + +# PARAMS: +# Input folder +# Output folder +# Output version: ACAD9, ACAD10, ACAD12, ACAD14, ACAD2000, ACAD2004, ACAD2007, ACAD20010, ACAD2013, ACAD2018 +# Output file type: DWG, DXF, DXB +# Recurse Input Folder: 0, 1 +# Audit each file: 0, 1 +# (Optional) Input files filter: *.DWG, *.DXF + +def ibp_dwg_to_dxf(file, INPUT_FOLDER = tmp_folder, OUTPUT_FOLDER = tmp_folder, RECURSIVE = "0", AUDIT = "1"): + if INPUT_FOLDER != tmp_folder and OUTPUT_FOLDER == tmp_folder: + OUTPUT_FOLDER = INPUT_FOLDER + OUTVER = "ACAD2018" + OUTFORMAT = "DXF" + # Command to run + cmd = [TEIGHA_PATH, INPUT_FOLDER, OUTPUT_FOLDER, OUTVER, OUTFORMAT, RECURSIVE, AUDIT, file] + + # Run + subprocess.run(cmd, shell=True) + + +def ibp_dxf_to_dwg(file, INPUT_FOLDER = tmp_folder, OUTPUT_FOLDER = tmp_folder, RECURSIVE = "0", AUDIT = "1"): + if INPUT_FOLDER != tmp_folder and OUTPUT_FOLDER == tmp_folder: + OUTPUT_FOLDER = INPUT_FOLDER + OUTVER = "ACAD2018" + OUTFORMAT = "DWG" + # Command to run + cmd = [TEIGHA_PATH, INPUT_FOLDER, OUTPUT_FOLDER, OUTVER, OUTFORMAT, RECURSIVE, AUDIT, file] + + # Run + subprocess.run(cmd, shell=True) + \ No newline at end of file