From 52c41e5998c56d27fab46b7363d5aee43f1a26d5 Mon Sep 17 00:00:00 2001 From: Vincent Mora Date: Mon, 20 May 2019 17:12:40 +0200 Subject: [PATCH 01/42] applies qgis2to3 --- axis_layer.py | 3 ++- doc/__main__.py | 1 + elementary_volume/__init__.py | 35 ++++++++++++++++++++++------------- export_elementary_volume.py | 7 ++++--- import_test.py | 4 +++- log_strati.py | 13 ++++++++----- metadata.txt | 4 ++-- mineralization.py | 6 +++--- package.py | 4 +++- plugin.py | 33 ++++++++++----------------------- project.py | 2 ++ test.py | 4 +++- viewer_3d/__main__.py | 4 ++-- viewer_3d/camera.py | 5 +++-- viewer_3d/scene.py | 6 ++++-- viewer_3d/utility.py | 1 + viewer_3d/viewer_3d.py | 8 ++++---- viewer_3d/viewer_controls.py | 6 +++--- 18 files changed, 80 insertions(+), 66 deletions(-) diff --git a/axis_layer.py b/axis_layer.py index af09dc5..07e1c48 100644 --- a/axis_layer.py +++ b/axis_layer.py @@ -1,9 +1,10 @@ # coding: utf-8 +from builtins import range from qgis.core import (QgsPluginLayerType, QgsPluginLayer, QgsRectangle) -from PyQt4.QtCore import pyqtSignal +from qgis.PyQt.QtCore import pyqtSignal import traceback import logging diff --git a/doc/__main__.py b/doc/__main__.py index c8988ed..72d7164 100644 --- a/doc/__main__.py +++ b/doc/__main__.py @@ -10,6 +10,7 @@ """ +from builtins import str import sys import getopt from . import build diff --git a/elementary_volume/__init__.py b/elementary_volume/__init__.py index bd014d2..8de0fbe 100644 --- a/elementary_volume/__init__.py +++ b/elementary_volume/__init__.py @@ -1,4 +1,10 @@ +from __future__ import print_function # coding = utf-8 +from builtins import next +from builtins import str +from builtins import zip +from builtins import range +from builtins import object import os import random from itertools import combinations @@ -240,8 +246,8 @@ def elementary_volumes(holes_, starts_, ends_, hole_ids_, node_ids_, nodes_, end # and that have at leat 2 incident edges that are not in the same # face (i.e. different holes) unused_nodes = set(nodes.keys()).difference(triangle_nodes) - offsets = {nodes[n].coords[0]: ends[n][0].coords[0] for n, l in ends.items() if len(l)==1} - offsets.update({nodes[n].coords[-1]: ends[n][0].coords[-1] for n, l in ends.items() if len(l)==1}) + offsets = {nodes[n].coords[0]: ends[n][0].coords[0] for n, l in list(ends.items()) if len(l)==1} + offsets.update({nodes[n].coords[-1]: ends[n][0].coords[-1] for n, l in list(ends.items()) if len(l)==1}) for n in unused_nodes: p = pair_of_non_coplanar_neighbors(n, graph, holes) if p: @@ -254,7 +260,7 @@ def elementary_volumes(holes_, starts_, ends_, hole_ids_, node_ids_, nodes_, end if DEBUG: open('/tmp/offsets.vtk', 'w').write( - to_vtk(MultiLineString([n for l in ends.values() for n in l]).wkb_hex)) + to_vtk(MultiLineString([n for l in list(ends.values()) for n in l]).wkb_hex)) sorted_holes = sorted(holes_) # face origin is the lowest bottom of the node in the first hole @@ -269,7 +275,7 @@ def elementary_volumes(holes_, starts_, ends_, hole_ids_, node_ids_, nodes_, end direct_orientation = (hl, hr) == (holes_[0], holes_[1]) or (hl, hr) == (holes_[1], holes_[2]) or (hl, hr) == (holes_[2], holes_[0]) face_edges = list(set([(s, e) if holes[s] == hl else (e, s) - for s in graph.keys() for e in graph[s] if holes[s] in (hl, hr) and holes[e] in (hl, hr)])) + for s in list(graph.keys()) for e in graph[s] if holes[s] in (hl, hr) and holes[e] in (hl, hr)])) if not len(face_edges): continue @@ -280,7 +286,7 @@ def elementary_volumes(holes_, starts_, ends_, hole_ids_, node_ids_, nodes_, end face_lines.append(Line([nodes[e[0]].coords[1], nodes[e[1]].coords[1]], Line.BOTTOM)) # split lines - for i, j in combinations(range(len(face_lines)), 2): + for i, j in combinations(list(range(len(face_lines))), 2): assert(face_lines[i].side != Line.VERTICAL and face_lines[j].side != Line.VERTICAL) p = sym_split(face_lines[i].points, face_lines[j].points) if p and p not in offsets: @@ -302,7 +308,7 @@ def elementary_volumes(holes_, starts_, ends_, hole_ids_, node_ids_, nodes_, end else: offsets[p] = p - for k, n in nodes.items(): + for k, n in list(nodes.items()): if holes[k] in (hl, hr): face_lines.append(Line([n.coords[0], n.coords[1]], Line.VERTICAL)) @@ -340,7 +346,8 @@ def elementary_volumes(holes_, starts_, ends_, hole_ids_, node_ids_, nodes_, end bug = 0 for i, li in enumerate(linework): if li.length <= 0: - print('zero length line', i, li.wkt) + # fix_print_with_import + print(('zero length line', i, li.wkt)) bug = True break found = False @@ -348,7 +355,8 @@ def elementary_volumes(holes_, starts_, ends_, hole_ids_, node_ids_, nodes_, end if i!=j and (not (lj.coords[0] != li.coords[0] or lj.coords[1] != li.coords[1]) \ or not (lj.coords[0] != li.coords[1] or lj.coords[1] != li.coords[0])): open("/tmp/dup_line_{}_face_{}.vtk".format(bug, face_idx), 'w').write(to_vtk(MultiLineString([LineString(linework_sav[j])]).wkb_hex)) - print('duplicate line', li.wkt, lj.wkt) + # fix_print_with_import + print(('duplicate line', li.wkt, lj.wkt)) bug += 1 if i!=j and li.coords[1] == lj.coords[0] or li.coords[1] == lj.coords[1]: found = True @@ -356,7 +364,8 @@ def elementary_volumes(holes_, starts_, ends_, hole_ids_, node_ids_, nodes_, end print(MultiLineString(linework).wkt) bug += 1 if bug: - print('open', MultiLineString(linework).wkt) + # fix_print_with_import + print(('open', MultiLineString(linework).wkt)) assert(False) @@ -386,12 +395,12 @@ def elementary_volumes(holes_, starts_, ends_, hole_ids_, node_ids_, nodes_, end top_lines = [l for l in face_lines if l.side==Line.TOP] bottom_lines = [l for l in face_lines if l.side==Line.BOTTOM] - end_lines = [tuple(nodes[n].coords) for n in ends.keys()] + end_lines = [tuple(nodes[n].coords) for n in list(ends.keys())] if DEBUG: open('/tmp/top_lines_face_{}.vtk'.format(face_idx), 'w').write(to_vtk(MultiLineString([l.points for l in top_lines]).wkb_hex)) open('/tmp/bottom_lines_face_{}.vtk'.format(face_idx), 'w').write(to_vtk(MultiLineString([l.points for l in bottom_lines]).wkb_hex)) open('/tmp/offsets_bis.vtk', 'w').write( - to_vtk(MultiLineString([LineString([k, v]) for k, v in offsets.items()]).wkb_hex)) + to_vtk(MultiLineString([LineString([k, v]) for k, v in list(offsets.items())]).wkb_hex)) # create terminations edges = set() @@ -470,7 +479,7 @@ def elementary_volumes(holes_, starts_, ends_, hole_ids_, node_ids_, nodes_, end result.append(q) # adds isolated nodes terminations - for n, l in ends.items(): + for n, l in list(ends.items()): if len(l) == 2: node = nodes[n] A, B, C = array(node.coords[0]), array(l[0].coords[0]), array(l[1].coords[0]) @@ -510,7 +519,7 @@ def pop_connected(n, graph): connected = [] while len(graph): - n = next(iter(graph.keys())) + n = next(iter(list(graph.keys()))) connected.append(pop_connected(n, graph)) for c in connected: diff --git a/export_elementary_volume.py b/export_elementary_volume.py index 8d26407..ff9c8eb 100644 --- a/export_elementary_volume.py +++ b/export_elementary_volume.py @@ -1,8 +1,9 @@ import os -from PyQt4 import uic -from PyQt4.QtCore import Qt -from PyQt4.QtGui import QDialog, QFileDialog, QApplication, QCursor +from qgis.PyQt import uic +from qgis.PyQt.QtCore import Qt +from qgis.PyQt.QtWidgets import QDialog, QFileDialog, QApplication +from qgis.PyQt.QtGui import QCursor from qgis.core import QgsFeatureRequest diff --git a/import_test.py b/import_test.py index 184d4ff..d455ba0 100644 --- a/import_test.py +++ b/import_test.py @@ -1,3 +1,4 @@ +from __future__ import print_function # coding = utf-8 if __name__ == "__main__": @@ -14,7 +15,8 @@ project = Project.create(project_name, 32632) start = time.time() project.import_data(sys.argv[1]) - print "time for import", time.time() - start, 'sec' + # fix_print_with_import + print("time for import", time.time() - start, 'sec') #project = Project(project_name) # #project.triangulate() diff --git a/log_strati.py b/log_strati.py index dc0d40f..851dea1 100644 --- a/log_strati.py +++ b/log_strati.py @@ -1,10 +1,13 @@ # coding=utf-8 +from builtins import str +from builtins import range from qgis.core import QgsDataSourceURI -from PyQt4 import uic -from PyQt4.QtGui import QGraphicsScene, QImage, QPixmap, QMainWindow, QBrush, QColor, QWheelEvent, QPen -from PyQt4.QtCore import Qt, QObject +from qgis.PyQt import uic +from qgis.PyQt.QtWidgets import QGraphicsScene, QMainWindow +from qgis.PyQt.QtGui import QImage, QPixmap, QBrush, QColor, QPen +from qgis.PyQt.QtCore import Qt, QObject from shapely import wkb import os @@ -227,8 +230,8 @@ def __init__(self, conn_info, parent=None): if __name__=='__main__': import sys - from PyQt4.QtCore import QSettings - from PyQt4.QtGui import QApplication + from qgis.PyQt.QtCore import QSettings + from qgis.PyQt.QtWidgets import QApplication QApplication.setOrganizationName("QGIS") QApplication.setOrganizationDomain("qgis.org") diff --git a/metadata.txt b/metadata.txt index e4ac93f..ccf4c9c 100644 --- a/metadata.txt +++ b/metadata.txt @@ -1,8 +1,8 @@ [general] name=Albion -qgisMinimumVersion=2.14 +qgisMinimumVersion=3.2 description=Build 3D geological model from wells information -version=3.0.0 +version=2.2.0 author=Oslandia email=infos@oslandia.com experimental=False diff --git a/mineralization.py b/mineralization.py index 8c7854d..fac5786 100644 --- a/mineralization.py +++ b/mineralization.py @@ -1,7 +1,7 @@ # coding = utf-8 import qgis.core -from PyQt4.QtGui import QDialog -from PyQt4 import uic +from qgis.PyQt.QtWidgets import QDialog +from qgis.PyQt import uic import os class MineralizationDialog(QDialog): @@ -15,7 +15,7 @@ def accept(self): self.close() if __name__=="__main__": - from PyQt4.QtGui import QApplication + from qgis.PyQt.QtWidgets import QApplication import sys from albion.project import Project diff --git a/package.py b/package.py index 0650b67..725d114 100644 --- a/package.py +++ b/package.py @@ -19,7 +19,9 @@ -t launch the tests before installing/uninstalling """ +from __future__ import print_function +from builtins import str import os import zipfile import re @@ -30,7 +32,7 @@ # @todo make that work on windows -qgis_plugin_dir = os.path.join(os.path.expanduser("~"), ".qgis2", "python", "plugins") +qgis_plugin_dir = os.path.join(os.path.expanduser("~"), ".local", "share", "QGIS", "QGIS3", "profiles", "default", "python", "plugins") zipname = "albion" zipext = ".zip" diff --git a/plugin.py b/plugin.py index a0458f2..7389a92 100644 --- a/plugin.py +++ b/plugin.py @@ -1,25 +1,12 @@ # coding: utf-8 +from builtins import str from qgis.core import * from qgis.gui import * -from PyQt4.QtCore import QObject, Qt, QFileInfo, QUrl -from PyQt4.QtGui import ( - QComboBox, - QShortcut, - QKeySequence, - QToolBar, - QIcon, - QMenu, - QFileDialog, - QInputDialog, - QLineEdit, - QMessageBox, - QProgressBar, - QApplication, - QDockWidget, - QDesktopServices, -) +from qgis.PyQt.QtCore import QObject, Qt, QFileInfo, QUrl +from qgis.PyQt.QtWidgets import QComboBox, QShortcut, QToolBar, QMenu, QFileDialog, QInputDialog, QLineEdit, QMessageBox, QProgressBar, QApplication, QDockWidget +from qgis.PyQt.QtGui import QKeySequence, QIcon, QDesktopServices import psycopg2 import os @@ -101,12 +88,12 @@ def initGui(self): ).triggered.connect(self.__log_strati_clicked) self.__toolbar.addWidget(self.__current_graph) - self.__current_graph.currentIndexChanged[unicode].connect( + self.__current_graph.currentIndexChanged[str].connect( self.__current_graph_changed ) self.__toolbar.addWidget(self.__current_section) - self.__current_section.currentIndexChanged[unicode].connect( + self.__current_section.currentIndexChanged[str].connect( self.__current_section_changed ) @@ -416,7 +403,7 @@ def __upgrade_project(self): def __new_project(self): # @todo open dialog to configure project name and srid - fil = QFileDialog.getSaveFileName( + fil, __ = QFileDialog.getSaveFileName( None, u"New project name (no space, plain ascii)", QgsProject.instance().readEntry("albion", "last_dir", "")[0], @@ -602,7 +589,7 @@ def __export_volume(self): if self.project is None: return - fil = QFileDialog.getSaveFileName( + fil, __ = QFileDialog.getSaveFileName( None, u"Export volume for current graph", QgsProject.instance().readEntry("albion", "last_dir", "")[0], @@ -636,7 +623,7 @@ def __export_elementary_volume(self): export_widget.exec_() def __import_project(self): - fil = QFileDialog.getOpenFileName( + fil, __ = QFileDialog.getOpenFileName( None, u"Import project from file", QgsProject.instance().readEntry("albion", "last_dir", "")[0], @@ -689,7 +676,7 @@ def __export_project(self): if self.project is None: return - fil = QFileDialog.getSaveFileName( + fil, __ = QFileDialog.getSaveFileName( None, u"Export project", QgsProject.instance().readEntry("albion", "last_dir", "")[0], diff --git a/project.py b/project.py index fefc065..c502afd 100644 --- a/project.py +++ b/project.py @@ -1,5 +1,7 @@ # coding = utf-8 +from builtins import str +from builtins import object from pglite import cluster_params import psycopg2 import os diff --git a/test.py b/test.py index b6b7dec..a41dee1 100644 --- a/test.py +++ b/test.py @@ -1,3 +1,4 @@ +from __future__ import print_function # coding = utf-8 if __name__ == "__main__": @@ -42,7 +43,8 @@ ) as t """) for rec in cur.fetchall(): - print rec + # fix_print_with_import + print(rec) #con = project.connect() #cur = con.cursor() diff --git a/viewer_3d/__main__.py b/viewer_3d/__main__.py index d89b260..28c4d1f 100644 --- a/viewer_3d/__main__.py +++ b/viewer_3d/__main__.py @@ -1,6 +1,6 @@ -from PyQt4.QtGui import * -from PyQt4.QtCore import * +from qgis.PyQt.QtGui import * +from qgis.PyQt.QtCore import * import sys from ..project import Project from .viewer_3d import ViewerWindow diff --git a/viewer_3d/camera.py b/viewer_3d/camera.py index 0292da8..b9b1320 100644 --- a/viewer_3d/camera.py +++ b/viewer_3d/camera.py @@ -1,7 +1,8 @@ # -*- coding: UTF-8 -*- -from PyQt4.QtCore import Qt -from PyQt4.QtGui import QVector3D +from builtins import object +from qgis.PyQt.QtCore import Qt +from qgis.PyQt.QtGui import QVector3D class Camera(object): "a simple camera" diff --git a/viewer_3d/scene.py b/viewer_3d/scene.py index aa167d1..b5184ec 100644 --- a/viewer_3d/scene.py +++ b/viewer_3d/scene.py @@ -1,11 +1,13 @@ # -*- coding: UTF-8 -*- +from builtins import zip +from builtins import range import numpy from OpenGL.GL import * from OpenGL.GL import shaders -from PyQt4.QtGui import * -from PyQt4.QtCore import * +from qgis.PyQt.QtGui import * +from qgis.PyQt.QtCore import * from .utility import computeNormals from shapely import wkb diff --git a/viewer_3d/utility.py b/viewer_3d/utility.py index afca416..22826a5 100644 --- a/viewer_3d/utility.py +++ b/viewer_3d/utility.py @@ -1,5 +1,6 @@ # -*- coding: UTF-8 -*- +from builtins import str import sys import re import numpy diff --git a/viewer_3d/viewer_3d.py b/viewer_3d/viewer_3d.py index b43430a..75fc6fe 100644 --- a/viewer_3d/viewer_3d.py +++ b/viewer_3d/viewer_3d.py @@ -8,10 +8,10 @@ from OpenGL import GLU -from PyQt4.QtOpenGL import QGLWidget, QGLPixelBuffer, QGLFormat -from PyQt4.QtCore import * -from PyQt4.QtGui import * -from PyQt4 import uic +from PyQt5.QtOpenGL import QGLWidget, QGLPixelBuffer, QGLFormat +from qgis.PyQt.QtCore import * +from qgis.PyQt.QtGui import * +from qgis.PyQt import uic import os import re diff --git a/viewer_3d/viewer_controls.py b/viewer_3d/viewer_controls.py index f144baf..fb9cc2c 100644 --- a/viewer_3d/viewer_controls.py +++ b/viewer_3d/viewer_controls.py @@ -2,9 +2,9 @@ import os #from qgis.core import * #from qgis.gui import * -from PyQt4.QtCore import * -from PyQt4.QtGui import * -from PyQt4 import uic +from qgis.PyQt.QtCore import * +from qgis.PyQt.QtGui import * +from qgis.PyQt import uic from functools import partial class ViewerControls(QWidget): From 32b8aa4d60562b18a6069491ee78a3c7cf47c573 Mon Sep 17 00:00:00 2001 From: Vincent Mora Date: Mon, 17 Jun 2019 12:29:51 +0200 Subject: [PATCH 02/42] script to drop indexes and FK and restore them this should spedup import dramatically --- _albion_create_indexes_and_constrains.sql | 61 + _albion_drop_indexes_and_constrains.sql | 58 + elementary_volume/__init__.py | 1 - import_test.py | 8 +- log_strati.py | 1 - plugin.py | 27 +- project.py | 39 +- res/template_project.qgs | 6463 ++++++++++----------- viewer_3d/viewer_3d.py | 7 +- viewer_3d/viewer_controls.py | 5 +- 10 files changed, 3232 insertions(+), 3438 deletions(-) create mode 100644 _albion_create_indexes_and_constrains.sql create mode 100644 _albion_drop_indexes_and_constrains.sql diff --git a/_albion_create_indexes_and_constrains.sql b/_albion_create_indexes_and_constrains.sql new file mode 100644 index 0000000..ee729ec --- /dev/null +++ b/_albion_create_indexes_and_constrains.sql @@ -0,0 +1,61 @@ +vacuum analyse +; +create index collar_geom_idx on _albion.collar using gist(geom) +; +alter table _albion.hole add constraint hole_collar_id_fkey foreign key (collar_id) references _albion.collar(id) +; +create index hole_geom_idx on _albion.hole using gist(geom) +; +create index hole_collar_id_idx on _albion.hole(collar_id) +; +alter table _albion.deviation add constraint deviation_hole_id_fkey foreign key (hole_id) references _albion.hole(id) +; +create index deviation_hole_id_idx on _albion.deviation(hole_id) +; +alter table _albion.radiometry add constraint radiometry_hole_id_fkey foreign key (hole_id) references _albion.hole(id) +; +create index radiometry_geom_idx on _albion.radiometry using gist(geom) +; +create index radiometry_hole_id_idx on _albion.radiometry(hole_id) +; +alter table _albion.resistivity add constraint resistivity_hole_id_fkey foreign key (hole_id) references _albion.hole(id) +; +create index resistivity_geom_idx on _albion.resistivity using gist(geom) +; +create index resistivity_hole_id_idx on _albion.resistivity(hole_id) +; +alter table _albion.formation add constraint formation_hole_id_fkey foreign key (hole_id) references _albion.hole(id) +; +create index formation_geom_idx on _albion.formation using gist(geom) +; +create index formation_hole_id_idx on _albion.formation(hole_id) +; +alter table _albion.lithology add constraint lithology_hole_id_fkey foreign key (hole_id) references _albion.hole(id) +; +create index lithology_geom_idx on _albion.lithology using gist(geom) +; +create index lithology_hole_id_idx on _albion.lithology(hole_id) +; +alter table _albion.facies add constraint facies_hole_id_fkey foreign key (hole_id) references _albion.hole(id) +; +create index facies_geom_idx on _albion.facies using gist(geom) +; +create index facies_hole_id_idx on _albion.facies(hole_id) +; +alter table _albion.chemical add constraint chemical_hole_id_fkey foreign key (hole_id) references _albion.hole(id) +; +create index chemical_hole_id_idx on _albion.chemical(hole_id) +; +alter table _albion.mineralization add constraint mineralization_hole_id_fkey foreign key (hole_id) references _albion.hole(id) +; +create index mineralization_geom_idx on _albion.mineralization using gist(geom) +; +create index mineralization_hole_id_idx on _albion.mineralization(hole_id) +; + + + + + + + diff --git a/_albion_drop_indexes_and_constrains.sql b/_albion_drop_indexes_and_constrains.sql new file mode 100644 index 0000000..8dcce30 --- /dev/null +++ b/_albion_drop_indexes_and_constrains.sql @@ -0,0 +1,58 @@ +drop index _albion.collar_geom_idx +; +alter table _albion.hole drop constraint hole_collar_id_fkey +; +drop index _albion.hole_geom_idx +; +drop index _albion.hole_collar_id_idx +; +alter table _albion.deviation drop constraint deviation_hole_id_fkey +; +drop index _albion.deviation_hole_id_idx +; +alter table _albion.radiometry drop constraint radiometry_hole_id_fkey +; +drop index _albion.radiometry_geom_idx +; +drop index _albion.radiometry_hole_id_idx +; +alter table _albion.resistivity drop constraint resistivity_hole_id_fkey +; +drop index _albion.resistivity_geom_idx +; +drop index _albion.resistivity_hole_id_idx +; +alter table _albion.formation drop constraint formation_hole_id_fkey +; +drop index _albion.formation_geom_idx +; +drop index _albion.formation_hole_id_idx +; +alter table _albion.lithology drop constraint lithology_hole_id_fkey +; +drop index _albion.lithology_geom_idx +; +drop index _albion.lithology_hole_id_idx +; +alter table _albion.facies drop constraint facies_hole_id_fkey +; +drop index _albion.facies_geom_idx +; +drop index _albion.facies_hole_id_idx +; +alter table _albion.chemical drop constraint chemical_hole_id_fkey +; +drop index _albion.chemical_hole_id_idx +; +alter table _albion.mineralization drop constraint mineralization_hole_id_fkey +; +drop index _albion.mineralization_geom_idx +; +drop index _albion.mineralization_hole_id_idx +; + + + + + + diff --git a/elementary_volume/__init__.py b/elementary_volume/__init__.py index 8de0fbe..ac8050e 100644 --- a/elementary_volume/__init__.py +++ b/elementary_volume/__init__.py @@ -1,4 +1,3 @@ -from __future__ import print_function # coding = utf-8 from builtins import next from builtins import str diff --git a/import_test.py b/import_test.py index d455ba0..eb13afd 100644 --- a/import_test.py +++ b/import_test.py @@ -9,16 +9,20 @@ project_name = "import_test" + if Project.exists(project_name): Project.delete(project_name) project = Project.create(project_name, 32632) start = time.time() project.import_data(sys.argv[1]) - # fix_print_with_import - print("time for import", time.time() - start, 'sec') + ## fix_print_with_import + #print("time for import", time.time() - start, 'sec') + #project = Project(project_name) # #project.triangulate() #project.create_section_view_0_90(4) + project.triangulate() + project.create_section_view_0_90(4) diff --git a/log_strati.py b/log_strati.py index 851dea1..63d2e86 100644 --- a/log_strati.py +++ b/log_strati.py @@ -2,7 +2,6 @@ from builtins import str from builtins import range -from qgis.core import QgsDataSourceURI from qgis.PyQt import uic from qgis.PyQt.QtWidgets import QGraphicsScene, QMainWindow diff --git a/plugin.py b/plugin.py index 7389a92..92aa79c 100644 --- a/plugin.py +++ b/plugin.py @@ -30,9 +30,9 @@ import atexit AXIS_LAYER_TYPE = AxisLayerType() -QgsPluginLayerRegistry.instance().addPluginLayerType(AXIS_LAYER_TYPE) +QgsApplication.pluginLayerRegistry().addPluginLayerType(AXIS_LAYER_TYPE) atexit.register( - QgsPluginLayerRegistry.instance().removePluginLayerType, AxisLayer.LAYER_TYPE + QgsApplication.pluginLayerRegistry().removePluginLayerType, AxisLayer.LAYER_TYPE ) @@ -330,7 +330,7 @@ def __layer(self, name): return lay def __current_section_changed(self, section_id): - layers = QgsMapLayerRegistry.instance().mapLayersByName(u"group_cell") + layers = QgsProject.instance().mapLayersByName(u"group_cell") if len(layers): layers[0].setSubsetString("section_id='{}'".format(section_id)) self.__refresh_layers("section") @@ -369,7 +369,7 @@ def __qgis__project__loaded(self): self.__current_section.addItems(self.project.sections()) self.__current_graph.addItems(self.project.graphs()) - layers = QgsMapLayerRegistry.instance().mapLayersByName("section.anchor") + layers = QgsProject.instance().mapLayersByName("section.anchor") if len(layers): layers[0].editingStopped.connect(self.__update_section_list) @@ -377,10 +377,10 @@ def __qgis__project__loaded(self): # We make sure that corresponding extents are valid when the project # is loaded - cell = QgsMapLayerRegistry.instance().mapLayersByName("cell")[0] + cell = QgsProject.instance().mapLayersByName("cell")[0] cell.updateExtents() - section_geom = QgsMapLayerRegistry.instance().mapLayersByName("section.geom") + section_geom = QgsProject.instance().mapLayersByName("section.geom") if section_geom: section_geom[0].updateExtents() @@ -413,9 +413,7 @@ def __new_project(self): return fil = fil if len(fil) > 4 and fil[-4:] == ".qgs" else fil + ".qgs" fil = fil.replace(" ", "_") - try: - fil.decode("ascii") - except UnicodeDecodeError: + if len(fil) != len(fil.encode()): self.__iface.messageBar().pushError( "Albion:", "project name may only contain asci character (no accent)" ) @@ -475,6 +473,7 @@ def __import_data(self): None, u"Data directory", QgsProject.instance().readEntry("albion", "last_dir", "")[0], + QFileDialog.ShowDirsOnly | QFileDialog.DontUseNativeDialog ) if not dir_: return @@ -486,9 +485,7 @@ def __import_data(self): progress = QProgressBar() progress.setAlignment(Qt.AlignLeft | Qt.AlignVCenter) progressMessageBar.layout().addWidget(progress) - self.__iface.messageBar().pushWidget( - progressMessageBar, self.__iface.messageBar().INFO - ) + self.__iface.messageBar().pushWidget(progressMessageBar) self.project.import_data(dir_, ProgressBar(progress)) self.project.triangulate() @@ -496,7 +493,7 @@ def __import_data(self): self.__iface.messageBar().clearWidgets() - collar = QgsMapLayerRegistry.instance().mapLayersByName("collar")[0] + collar = QgsProject.instance().mapLayersByName("collar")[0] collar.reload() collar.updateExtents() self.__iface.setActiveLayer(collar) @@ -562,13 +559,13 @@ def __delete_graph(self): def __toggle_axis(self): if self.__axis_layer: pass - QgsMapLayerRegistry.instance().removeMapLayer(self.__axis_layer.id()) + QgsProject.instance().removeMapLayer(self.__axis_layer.id()) self.__axis_layer = None else: self.__axis_layer = AxisLayer( self.__iface.mapCanvas().mapSettings().destinationCrs() ) - QgsMapLayerRegistry.instance().addMapLayer(self.__axis_layer) + QgsProject.instance().addMapLayer(self.__axis_layer) self.__refresh_layers() def __create_cells(self): diff --git a/project.py b/project.py index c502afd..1ac48f7 100644 --- a/project.py +++ b/project.py @@ -25,6 +25,34 @@ from qgis.core import QgsMessageLog +import time +from psycopg2.extras import LoggingConnection, LoggingCursor +import logging + +logging.basicConfig(level=logging.DEBUG) +logger = logging.getLogger(__name__) +# MyLoggingCursor simply sets self.timestamp at start of each query +class MyLoggingCursor(LoggingCursor): + def execute(self, query, vars=None): + self.timestamp = time.time() + return super(MyLoggingCursor, self).execute(query, vars) + + def callproc(self, procname, vars=None): + self.timestamp = time.time() + return super(MyLoggingCursor, self).callproc(procname, vars) + +# MyLogging Connection: +# a) calls MyLoggingCursor rather than the default +# b) adds resulting execution (+ transport) time via filter() +class MyLoggingConnection(LoggingConnection): + def filter(self, msg, curs): + return "{} {} ms".format(msg, int((time.time() - curs.timestamp) * 1000)) + + def cursor(self, *args, **kwargs): + kwargs.setdefault('cursor_factory', MyLoggingCursor) + return LoggingConnection.cursor(self, *args, **kwargs) + + if not check_cluster(): init_cluster() start_cluster() @@ -34,7 +62,7 @@ def find_in_dir(dir_, name): for filename in os.listdir(dir_): if filename.find(name) != -1: - return os.path.join(dir_, filename) + return os.path.abspath(os.path.join(dir_, filename)) return "" @@ -71,7 +99,9 @@ def __init__(self, project_name): self.__conn_info = "dbname={} {}".format(project_name, cluster_params()) def connect(self): - return psycopg2.connect(self.__conn_info) + con = psycopg2.connect(self.__conn_info, connection_factory=MyLoggingConnection) + con.initialize(logger) + return con def vacuum(self): with self.connect() as con: @@ -79,6 +109,7 @@ def vacuum(self): con.set_isolation_level(0) cur = con.cursor() cur.execute("vacuum analyze") + con.commit() @staticmethod def exists(project_name): @@ -853,8 +884,8 @@ def create_section_view_0_90(self, z_scale): ) ) - cur.execute("refresh materialized view albion.radiometry_section") - cur.execute("refresh materialized view albion.resistivity_section") + #cur.execute("refresh materialized view albion.radiometry_section") + #cur.execute("refresh materialized view albion.resistivity_section") con.commit() def closest_hole_id(self, x, y): diff --git a/res/template_project.qgs b/res/template_project.qgs index 9a82be1..f6c8921 100644 --- a/res/template_project.qgs +++ b/res/template_project.qgs @@ -1,67 +1,113 @@ - + + - + + + + +proj=utm +zone=32 +datum=WGS84 +units=m +no_defs + 3116 + 32632 + EPSG:32632 + WGS 84 / UTM zone 32N + utm + WGS84 + false + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + + + collar20170522101211588 + current_radiometry_section20171210141136639 + current_mineralization_section20171210141434594 + group_cell20171210141649354 + section_geom20171210141834658 + cell20171210155444151 + current_hole_section20171210181943739 + current_formation_section20171210182253618 + current_node_section20171211135743640 + current_edge_section20171211173954570 + edge20171211174003737 + possible_edge20171219072744468 + section_anchor20171220085838796 + Google_Satellite_2f49519b_bcb0_4cae_afbc_decbfac2af04 + + + + + + + + + + + + + + + + + + - + meters - 322700.65761908068088815 - 2074283.03263000538572669 - 324598.16511556104524061 - 2075541.11146176373586059 + 31739052.35575000196695328 + 33490786.30525000020861626 + 31739525.45425000041723251 + 33491101.08475000038743019 0 - 1 +proj=utm +zone=32 +datum=WGS84 +units=m +no_defs @@ -75,258 +121,179 @@ 0 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - - - collar20170522101211588 - metadata20170602185222421 - current_radiometry_section20171210141136639 - current_mineralization_section20171210141434594 - group_cell20171210141649354 - section_geom20171210141834658 - cell20171210155444151 - current_hole_section20171210181943739 - current_formation_section20171210182253618 - current_node_section20171211135743640 - current_edge_section20171211173954570 - edge20171211174003737 - Google_cn_Satellites20171215210416430 - possible_edge20171219072744468 - section_anchor20171220085838796 - - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + + - + -20037508.34278924390673637 - -20037508.34278924390673637 + -20037508.34278925508260727 20037508.34278924390673637 20037508.34278924390673637 - Google_cn_Satellites20171215210416430 - . + Google_Satellite_2f49519b_bcb0_4cae_afbc_decbfac2af04 + crs=EPSG:3857&format&type=xyz&url=https://mt1.google.com/vt/lyrs%3Ds%26x%3D%7Bx%7D%26y%3D%7By%7D%26z%3D%7Bz%7D&zmax=19&zmin=0 - Google.cn Satellites + Google Satellite +proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0 +k=1.0 +units=m +nadgrids=@null +wktext +no_defs 3857 3857 EPSG:3857 - WGS 84 / Pseudo Mercator + WGS 84 / Pseudo-Mercator merc WGS84 false + + + + + + + + + + + + + + 0 + 0 + + + + + true + + + + + wms + + + + + + + + 1 + 1 + 1 + - - - - - - - - - - - - - + + + + + + None + WholeRaster + Estimated + 0.02 + 0.98 + 2 + + + + + + + 0 - + - 323136.61999999999534339 - 2074866.80000000004656613 - 323587.19000000000232831 - 2075166.59000000008381903 + 31739063.62000000104308128 + 33490793.80000000074505806 + 31739514.19000000134110451 + 33491093.58999999985098839 cell20171210155444151 - dbname='template_project' host=localhost port=55432 sslmode=disable key='id' srid=32632 type=Polygon table="albion"."cell" (geom) sql= + dbname='template_project' host=localhost port=55432 sslmode=disable key='id' srid=32632 type=Polygon checkPrimaryKeyUnicity='1' table="albion"."cell" (geom) sql= @@ -343,269 +310,189 @@ false + + + + + + + + + + + + + + 0 + 0 + + + + + false + + + + postgres + + - - + + - - - - - - - - - - - - - - - + + + 1 + 1 + 1 + + - - - + + + - + + + + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 0 - 0 - id - - - - - - - + 1 + + + + - - - - - - - - - - - - - - - - - - - - - - - - . + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - + + + + - - + + + + + + + + + + + + + + + + + + + + + + + - - . + + + + + ../../areva/albion 0 - . + ../../areva/albion 0 generatedlayout + + - - - - - - - - - - - + "id" + - + - 323136.61999999999534339 - 2074866.80000000004656613 - 323587.19000000000232831 - 2075166.59000000008381903 + 31739063.62000000104308128 + 33490793.80000000074505806 + 31739514.19000000134110451 + 33491093.58999999985098839 collar20170522101211588 - dbname='template_project' host=localhost port=55432 sslmode=disable key='id' srid=32632 type=PointZ table="albion"."collar" (geom) sql= + dbname='template_project' host=localhost port=55432 sslmode=disable key='id' srid=32632 type=PointZ checkPrimaryKeyUnicity='1' table="albion"."collar" (geom) sql= @@ -662,271 +542,181 @@ def my_form_open(dialog, layer, feature): false + + + + + + + + + + + + + + 0 + 0 + + + + + false + + + + postgres + + - - + + - - - - - - - - - - - - + + + 1 + 1 + 1 + + - - + + - + - + - + + + + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 0 - 0 - id - - - - - - - + 1 + + + + - - - - - - - - - - - - - - - - - - - - - - - - . + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - + + + - - + + + + + + + + + + + + + + + + + + + + - - . + + + + + ../../areva/albion 0 - . + ../../areva/albion 0 generatedlayout + + - - - - - - - - - COALESCE( "id", '<NULL>' ) + - - - 323137.12120096100261435 - 2074749.36095459992066026 - 323737.77071975398575887 - 2075166.65021662996150553 - + current_edge_section20171211173954570 - dbname='template_project' host=localhost port=55432 sslmode=disable key='id' srid=32632 type=LineString table="albion"."current_edge_section" (geom) sql= + dbname='template_project' host=localhost port=55432 sslmode=disable key='id' srid=32632 type=LineString checkPrimaryKeyUnicity='1' table="albion"."current_edge_section" (geom) sql= @@ -982,45 +760,57 @@ def my_form_open(dialog, layer, feature): false + + + + + + + + + + + + + + 0 + 0 + + + + + false + + + + postgres + + - - + + - - - - - - - - - - - - - - - - - - - - - + + + 1 + 1 + 1 + + - - - + + + - - + + - + @@ -1029,17 +819,25 @@ def my_form_open(dialog, layer, feature): - + + - + + + + - - + + - + @@ -1048,17 +846,25 @@ def my_form_open(dialog, layer, feature): - + + - + + + + - - + + - + @@ -1067,19 +873,27 @@ def my_form_open(dialog, layer, feature): - + + - + + + + - - + + - + @@ -1088,240 +902,169 @@ def my_form_open(dialog, layer, feature): - + + - + + + + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 0 - 0 - id - - - - - - - + 1 + + + + - - - - - - - - - - - - - - - - - - - - - - - - . + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - + + + + + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - . + + + + + ../../areva/albion 0 - . + ../../areva/albion 0 generatedlayout + + - - - - - - - - - - - - COALESCE( "id", '<NULL>' ) + - + + + 31739063.62000000104308128 + 33490278.67379739880561829 + 31740023.05092709884047508 + 33491092.95009690150618553 + current_formation_section20171210182253618 - dbname='template_project' host=localhost port=55432 sslmode=disable key='id' srid=32632 type=LineString table="albion"."current_formation_section" (geom) sql= + dbname='template_project' host=localhost port=55432 sslmode=disable key='id' srid=32632 type=LineString checkPrimaryKeyUnicity='1' table="albion"."current_formation_section" (geom) sql= @@ -1374,50 +1114,62 @@ def my_form_open(dialog, layer, feature): false + + + + + + + + + + + + + + 0 + 0 + + + + + false + + + + postgres + + - - + + - - - - - - - - - - - - - - - - - - - - - + + + 1 + 1 + 1 + + - - - - - - - - + + + + + + + + - - + + - + @@ -1426,17 +1178,25 @@ def my_form_open(dialog, layer, feature): - + + - + + + + - - + + - + @@ -1445,17 +1205,25 @@ def my_form_open(dialog, layer, feature): - + + - + + + + - - + + - + @@ -1464,17 +1232,25 @@ def my_form_open(dialog, layer, feature): - + + - + + + + - - + + - + @@ -1483,17 +1259,25 @@ def my_form_open(dialog, layer, feature): - + + - + + + + - - + + - + @@ -1502,17 +1286,25 @@ def my_form_open(dialog, layer, feature): - + + - + + + + - - + + - + @@ -1521,17 +1313,25 @@ def my_form_open(dialog, layer, feature): - + + - + + + + - - + + - + @@ -1540,17 +1340,25 @@ def my_form_open(dialog, layer, feature): - + + - + + + + - - + + - + @@ -1559,19 +1367,27 @@ def my_form_open(dialog, layer, feature): - + + - + + + + - - + + - + @@ -1580,241 +1396,168 @@ def my_form_open(dialog, layer, feature): - + + - + + + + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 0 - 0 - id - - - - - - - + 1 + + + + - - - - - - - - - - - - - - - - - - - - - - - - . + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - + + + + + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + - - . + + + + + ../../areva/albion 0 - . + ../../areva/albion 0 generatedlayout + + - - - - - - - - - - - - - + "id" + - + current_hole_section20171210181943739 - dbname='template_project' host=localhost port=55432 sslmode=disable key='id' srid=32632 type=LineString table="albion"."current_hole_section" (geom) sql= + dbname='template_project' host=localhost port=55432 sslmode=disable key='id' srid=32632 type=LineString checkPrimaryKeyUnicity='1' table="albion"."current_hole_section" (geom) sql= @@ -1867,37 +1601,52 @@ def my_form_open(dialog, layer, feature): false + + + + + + + + + + + + + + 0 + 0 + + + + + false + + + + postgres + + - - + + - - - - - - - - - - - - - - - - - - + + + 1 + 1 + 1 + + - - + + - + @@ -1906,87 +1655,145 @@ def my_form_open(dialog, layer, feature): - + + - + + + + - + - 0 0 - 0 - id - - - - . + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - + + + + + - - + + + + + + + + + + + + + + + + + + + + + + + + - . + + + + + ../../areva/albion 0 - . + ../../areva/albion 0 generatedlayout + + - - - - - - - - - - - - + "id" + - + - 323288.30356994899921119 - 2074730.4480744400061667 - 323738.71807432197965682 - 2075067.08355449000373483 + 31739214.99657329916954041 + 33490407.22139409929513931 + 31739833.60740730166435242 + 33491092.41239940002560616 current_mineralization_section20171210141434594 - dbname='template_project' host=localhost port=55432 sslmode=disable key='id' srid=32632 type=LineString table="albion"."current_mineralization_section" (geom) sql= + dbname='template_project' host=localhost port=55432 sslmode=disable key='id' srid=32632 type=LineString checkPrimaryKeyUnicity='1' table="albion"."current_mineralization_section" (geom) sql= @@ -2003,51 +1810,57 @@ def my_form_open(dialog, layer, feature): false + + + + + + + + + + + + + + 0 + 0 + + + + + false + + + + postgres + + - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + 1 + 1 + 1 + + - - - + + + - - + + - + @@ -2056,17 +1869,25 @@ def my_form_open(dialog, layer, feature): - + + - + + + + - - + + - + @@ -2075,17 +1896,25 @@ def my_form_open(dialog, layer, feature): - + + - + + + + - - + + - + @@ -2094,19 +1923,27 @@ def my_form_open(dialog, layer, feature): - + + - + + + + - - + + - + @@ -2115,245 +1952,198 @@ def my_form_open(dialog, layer, feature): - + + - + + + + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 1 - 0 - id - - - - - - - + 1 + + + + - - - - - - - - - - - - - - - - - - - - - - - - . + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - + + + + + + + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - . + + + + + ../../areva/albion 0 - . + ../../areva/albion 0 generatedlayout + + - - - - - - - - - - - - - - - + "id" + - - - 323137.3236906590173021 - 2074746.90201969002373517 - 323741.30310256197117269 - 2075166.57410508999601007 - + current_node_section20171211135743640 - dbname='template_project' host=localhost port=55432 sslmode=disable key='id' srid=32632 type=LineString table="albion"."current_node_section" (geom) sql= + dbname='template_project' host=localhost port=55432 sslmode=disable key='id' srid=32632 type=LineString checkPrimaryKeyUnicity='1' table="albion"."current_node_section" (geom) sql= @@ -2414,48 +2187,57 @@ def my_form_open(dialog, layer, feature): false + + + + + + + + + + + + + + 0 + 0 + + + + + false + + + + postgres + + - - + + - - - - - - - - - - - - - - - - - - - - - - - - + + + 1 + 1 + 1 + + - - - + + + - - + + - + @@ -2464,17 +2246,25 @@ def my_form_open(dialog, layer, feature): - + + - + + + + - - + + - + @@ -2483,17 +2273,25 @@ def my_form_open(dialog, layer, feature): - + + - + + + + - - + + - + @@ -2502,19 +2300,27 @@ def my_form_open(dialog, layer, feature): - + + - + + + + - - + + - + @@ -2523,243 +2329,183 @@ def my_form_open(dialog, layer, feature): - + + - + + + + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 4 - 0 - id - - - - - - - + 1 + + + + - - - - - - - - - - - - - - - - - - - - - - - - . + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - + + + + + + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - . + + + + + ../../areva/albion 0 - . + ../../areva/albion 0 generatedlayout + + - - - - - - - - - - - - - COALESCE( "id", '<NULL>' ) + - + - 323136.99737213598564267 - 2074730.70236835000105202 - 323784.47420165798394009 - 2075092.06782471993938088 + 31739063.62000000104308128 + 33490278.75380950048565865 + 31740022.85106619819998741 + 33491092.94975600019097328 current_radiometry_section20171210141136639 - dbname='template_project' host=localhost port=55432 sslmode=disable key='id' srid=32632 type=LineString table="albion"."current_radiometry_section" (geom) sql= + dbname='template_project' host=localhost port=55432 sslmode=disable key='id' srid=32632 type=LineString checkPrimaryKeyUnicity='1' table="albion"."current_radiometry_section" (geom) sql= @@ -2819,37 +2555,52 @@ def my_form_open(dialog, layer, feature): false + + + + + + + + + + + + + + 0 + 0 + + + + + false + + + + postgres + + - - + + - - - - - - - - - - - - - - - - - - + + + 1 + 1 + 1 + + - - + + - + @@ -2858,243 +2609,159 @@ def my_form_open(dialog, layer, feature): - + + - - - - - + + + + + + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 0 - 0 - id - - - - - - - + 1 + + + + - - - - - - - - - - - - - - - - - - - - - - - - . + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - + + + + + - - + + + + + + + + + + + + + + + + + + + + + + + + - - . + + + + + ../../areva/albion 0 - . + ../../areva/albion 0 generatedlayout + + - - - - - - - - - - - - + "id" + - - - 323136.50877837499137968 - 2074866.45427859993651509 - 323588.2962775370106101 - 2075165.99685759004205465 - + edge20171211174003737 - dbname='template_project' host=localhost port=55432 sslmode=disable key='id' srid=32632 type=LineStringZ table="albion"."edge" (geom) sql= + dbname='template_project' host=localhost port=55432 sslmode=disable key='id' srid=32632 type=LineStringZ checkPrimaryKeyUnicity='1' table="albion"."edge" (geom) sql= @@ -3152,39 +2805,57 @@ def my_form_open(dialog, layer, feature): false + + + + + + + + + + + + + + 0 + 0 + + + + + false + + + + postgres + + - - + + - - - - - - - - - - - - - - - + + + 1 + 1 + 1 + + - - - + + + - - + + - + @@ -3193,17 +2864,25 @@ def my_form_open(dialog, layer, feature): - + + - + + + + - - + + - + @@ -3212,17 +2891,25 @@ def my_form_open(dialog, layer, feature): - + + - + + + + - - + + - + @@ -3231,19 +2918,27 @@ def my_form_open(dialog, layer, feature): - + + - + + + + - - + + - + @@ -3252,237 +2947,138 @@ def my_form_open(dialog, layer, feature): - + + - + + + + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 0 - 0 - id - - - - - - - + 1 + + + + - - - - - - - - - - - - - - - - - - - - - - - - . + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - + + + + - - + + + + + + + + + + + + + + + + + + + + + - - . + + + + + ../../areva/albion 0 - . + ../../areva/albion 0 generatedlayout + + - - - - - - - - - - COALESCE( "id", '<NULL>' ) + - - - 323136.61999999999534339 - 2074866.80000000004656613 - 323587.19000000000232831 - 2075166.59000000008381903 - + group_cell20171210141649354 - dbname='template_project' host=localhost port=55432 sslmode=disable key='id' srid=32632 type=Polygon table="albion"."group_cell" (geom) sql=section_id='WE' + dbname='template_project' host=localhost port=55432 sslmode=disable key='id' srid=32632 type=Polygon checkPrimaryKeyUnicity='1' table="albion"."group_cell" (geom) sql=section_id='SN x4' @@ -3539,321 +3122,260 @@ def my_form_open(dialog, layer, feature): false + + + + + + + + + + + + + + 0 + 0 + + + + + false + + + + postgres + + - - + + - - - - - - - - - - - - - - - + + + 1 + 1 + 1 + + - - - + + + - - - + + + - + + + + - - - + + + - + + + + - - - + + + - + + + + - - - + + + - + + + + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 0 - 0 - id - - - - - - - + 1 + + + + - - - - - - - - - - - - - - - - - - - - - - - - . + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - + + + + - - + + + + + + + + + + + + + + + + + + + + + - - . + + + + + ../../areva/albion 0 - . + ../../areva/albion 0 generatedlayout + + - - - - - - - - - - COALESCE( "id", '<NULL>' ) + - + metadata20170602185222421 - dbname='template_project' host=localhost port=55432 sslmode=disable key='id' table="albion"."metadata" sql= + dbname='template_project' host=localhost port=55432 sslmode=disable key='id' checkPrimaryKeyUnicity='1' table="albion"."metadata" sql= @@ -3904,106 +3419,250 @@ def my_form_open(dialog, layer, feature): true - + + + + + + + + + + + + + + 0 + 0 + + + + + false + + + + postgres + + - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - . + + + 1 + 1 + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - + + + + + + + + + + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - . + + + + + ../../areva/albion 0 - . + ../../areva/albion 0 generatedlayout + + - - - - - - - - - - - - - - - - COALESCE("id", '<NULL>') + - + possible_edge20171219072744468 - dbname='template_project' host=localhost port=55432 sslmode=disable key='id' srid=32632 type=LineStringZ table="albion"."possible_edge" (geom) sql= + dbname='template_project' host=localhost port=55432 sslmode=disable key='id' srid=32632 type=LineStringZ checkPrimaryKeyUnicity='1' table="albion"."possible_edge" (geom) sql= @@ -4020,42 +3679,57 @@ def my_form_open(dialog, layer, feature): false + + + + + + + + + + + + + + 0 + 0 + + + + + false + + + + postgres + + - - + + - - - - - - - - - - - - - - - - - - + + + 1 + 1 + 1 + + - - - + + + - - + + - + @@ -4064,17 +3738,25 @@ def my_form_open(dialog, layer, feature): - + + - + + + + - - + + - + @@ -4083,17 +3765,25 @@ def my_form_open(dialog, layer, feature): - + + - + + + + - - + + - + @@ -4102,19 +3792,27 @@ def my_form_open(dialog, layer, feature): - + + - + + + + - - + + - + @@ -4123,239 +3821,153 @@ def my_form_open(dialog, layer, feature): - + + - + + + + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 0 - 0 - id - - - - - - - + 1 + + + + - - - - - - - - - - - - - - - - - - - - - - - - . + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - + + + + + - - + + + + + + + + + + + + + + + + + + + + + + + + - - . + + + + + ../../areva/albion 0 - . + ../../areva/albion 0 generatedlayout + + - - - - - - - - - - - COALESCE( "id", '<NULL>' ) + - + section_anchor20171220085838796 - dbname='template_project' host=localhost port=55432 sslmode=disable key='id' srid=32632 type=LineString table="albion"."section" (anchor) sql= + dbname='template_project' host=localhost port=55432 sslmode=disable key='id' srid=32632 type=LineString checkPrimaryKeyUnicity='1' table="albion"."section" (anchor) sql= @@ -4407,34 +4011,52 @@ def my_form_open(dialog, layer, feature): false + + + + + + + + + + + + + + 0 + 0 + + + + + false + + + + postgres + + - - + + - - - - - - - - - - - - - - - + + + 1 + 1 + 1 + + - - + + - + @@ -4443,85 +4065,133 @@ def my_form_open(dialog, layer, feature): - + + - + + + + - + - 0 0 - 0 - id - - - - + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - + + + + - - + + + + + + + + + + + + + + + + + + + + + + + - + + + + + 0 0 generatedlayout + + - - - - - - - - - - - + "id" + - + - 323136.61999999999534339 - 2074912.64999999990686774 - 323587.19000000000232831 - 2075090.92999999993480742 + 31739063.62000000104308128 + 33490793.80000000074505806 + 31739514.19000000134110451 + 33491092.42000000178813934 section_geom20171210141834658 - dbname='template_project' host=localhost port=55432 sslmode=disable key='id' srid=32632 type=LineString table="albion"."section" (geom) sql= + dbname='template_project' host=localhost port=55432 sslmode=disable key='id' srid=32632 type=LineString checkPrimaryKeyUnicity='1' table="albion"."section" (geom) sql= @@ -4538,39 +4208,57 @@ def my_form_open(dialog, layer, feature): false + + + + + + + + + + + + + + 0 + 0 + + + + + false + + + + postgres + + - - + + - - - - - - - - - - - - - - - + + + 1 + 1 + 1 + + - - - + + + - - + + - + @@ -4579,17 +4267,25 @@ def my_form_open(dialog, layer, feature): - + + - + + + + - - + + - + @@ -4598,17 +4294,25 @@ def my_form_open(dialog, layer, feature): - + + - + + + + - - + + - + @@ -4617,19 +4321,27 @@ def my_form_open(dialog, layer, feature): - + + - + + + + - - + + - + @@ -4638,237 +4350,138 @@ def my_form_open(dialog, layer, feature): - + + - + + + + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 0 - 0 - id - - - - - - - + 1 + + + + - - - - - - - - - - - - - - - - - - - - - - - - . + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - + + + + - - + + + + + + + + + + + + + + + + + + + + + - - . + + + + + ../../areva/albion 0 - . + ../../areva/albion 0 generatedlayout + + - - - - - - - - - - - + "id" + + + + + + + + + + + + + + + + + - - template_project - /home/vmo/areva/albion - 32632 - dbname=template_project host=localhost port=55432 - - - meters - m2 - - - +proj=longlat +datum=WGS84 +no_defs - EPSG:4326 - 3452 - 1 - - - false - - - 0 - 255 - 255 - 255 - 255 - 255 - 255 - - 1 - - cell20171210155444151 - collar20170522101211588 - current_edge_section20171211173954570 - current_formation_section20171210182253618 - current_hole_section20171210181943739 - current_mineralization_section20171210141434594 - current_node_section20171211135743640 - current_radiometry_section20171210141136639 - edge20171211174003737 - group_cell20171210141649354 - possible_edge20171219072744468 - section_geom20171210141834658 - section_anchor20171220084145458 - - - disabled - disabled - disabled - disabled - disabled - disabled - disabled - disabled - disabled - disabled - disabled - disabled - disabled - - current_layer - - 2 - 2 - 2 - 2 - 2 - 2 - 2 - 2 - 2 - 2 - 2 - 2 - 2 - + 10 + 1 + off to_vertex_and_segment to_vertex_and_segment @@ -4994,8 +4544,36 @@ def my_form_open(dialog, layer, feature): to_vertex_and_segment to_vertex_and_segment - off - 10 + + disabled + disabled + disabled + disabled + disabled + disabled + disabled + disabled + disabled + disabled + disabled + disabled + disabled + + + cell20171210155444151 + collar20170522101211588 + current_edge_section20171211173954570 + current_formation_section20171210182253618 + current_hole_section20171210181943739 + current_mineralization_section20171210141434594 + current_node_section20171211135743640 + current_radiometry_section20171210141136639 + edge20171211174003737 + group_cell20171210141649354 + possible_edge20171219072744468 + section_geom20171210141834658 + section_anchor20171220084145458 + 0.000000 0.000000 @@ -5011,14 +4589,83 @@ def my_form_open(dialog, layer, feature): 0.000000 0.000000 + + 2 + 2 + 2 + 2 + 2 + 2 + 2 + 2 + 2 + 2 + 2 + 2 + 2 + + current_layer - - 2 - true - + + 255 + 255 + 255 + 255 + 0 + 255 + 255 + false + + m2 + meters + + + 50 + 16 + 30 + false + 0 + false + false + true + 0 + + + false + + + true + 2 + + + 3116 + +proj=utm +zone=32 +datum=WGS84 +units=m +no_defs + EPSG:32632 + 1 + + + dbname=template_project host=localhost port=55432 + /home/vmo/albion/nt + template_project + 32632 + + + + + + + + + + + + + + + diff --git a/viewer_3d/viewer_3d.py b/viewer_3d/viewer_3d.py index 75fc6fe..581bf5d 100644 --- a/viewer_3d/viewer_3d.py +++ b/viewer_3d/viewer_3d.py @@ -8,9 +8,10 @@ from OpenGL import GLU -from PyQt5.QtOpenGL import QGLWidget, QGLPixelBuffer, QGLFormat -from qgis.PyQt.QtCore import * -from qgis.PyQt.QtGui import * +from PyQt5.QtOpenGL import QGLWidget, QGLFormat +from qgis.PyQt.QtCore import Qt +from qgis.PyQt.QtGui import QVector3D +from qgis.PyQt.QtWidgets import QMessageBox, QMainWindow from qgis.PyQt import uic import os diff --git a/viewer_3d/viewer_controls.py b/viewer_3d/viewer_controls.py index fb9cc2c..3e58541 100644 --- a/viewer_3d/viewer_controls.py +++ b/viewer_3d/viewer_controls.py @@ -1,9 +1,6 @@ # coding=UTF-8 import os -#from qgis.core import * -#from qgis.gui import * -from qgis.PyQt.QtCore import * -from qgis.PyQt.QtGui import * +from qgis.PyQt.QtWidgets import QWidget, QMenu from qgis.PyQt import uic from functools import partial From 82b40f84e58328417ba7e3248c0969ea82cb807d Mon Sep 17 00:00:00 2001 From: Vincent Mora Date: Mon, 24 Jun 2019 16:14:28 +0200 Subject: [PATCH 03/42] change the possible edge to include to and bottom angles related to #67 --- albion.sql | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/albion.sql b/albion.sql index 7d915f3..45d5c2b 100644 --- a/albion.sql +++ b/albion.sql @@ -1005,8 +1005,16 @@ join _albion.hole as he on he.collar_id=e.end_ join _albion.node as ns on ns.hole_id=hs.id join _albion.node as ne on ne.hole_id=he.id, tan_ang where ns.graph_id = ne.graph_id -and abs(st_z(st_3dlineinterpolatepoint(ns.geom, .5))-st_z(st_3dlineinterpolatepoint(ne.geom,.5))) +and ( + abs(st_z(st_3dlineinterpolatepoint(ns.geom, .5))-st_z(st_3dlineinterpolatepoint(ne.geom, .5))) /st_distance(st_3dlineinterpolatepoint(ns.geom, .5), st_3dlineinterpolatepoint(ne.geom, .5)) < tan_ang.value + or + abs(st_z(st_3dlineinterpolatepoint(ns.geom, 0))-st_z(st_3dlineinterpolatepoint(ne.geom, 0))) + /st_distance(st_3dlineinterpolatepoint(ns.geom, 0), st_3dlineinterpolatepoint(ne.geom, 0)) < tan_ang.value + or + abs(st_z(st_3dlineinterpolatepoint(ns.geom, 1))-st_z(st_3dlineinterpolatepoint(ne.geom, 1))) + /st_distance(st_3dlineinterpolatepoint(ns.geom, 1), st_3dlineinterpolatepoint(ne.geom, 1)) < tan_ang.value + ) and st_distance( ne.geom, ns.geom ) < ( select correlation_distance from albion.metadata ) and ns.parent is null and ne.parent is null From e94598c26fcbec516c765a8672e818d81fdd81bc Mon Sep 17 00:00:00 2001 From: Vincent Mora Date: Mon, 24 Jun 2019 16:15:41 +0200 Subject: [PATCH 04/42] removes constrains before adding data in bulk re-create constrains afterward --- _albion_create_indexes_and_constrains.sql | 2 -- project.py | 20 +++++++++++++++++++- 2 files changed, 19 insertions(+), 3 deletions(-) diff --git a/_albion_create_indexes_and_constrains.sql b/_albion_create_indexes_and_constrains.sql index ee729ec..c0d7ab4 100644 --- a/_albion_create_indexes_and_constrains.sql +++ b/_albion_create_indexes_and_constrains.sql @@ -1,5 +1,3 @@ -vacuum analyse -; create index collar_geom_idx on _albion.collar using gist(geom) ; alter table _albion.hole add constraint hole_collar_id_fkey foreign key (collar_id) references _albion.collar(id) diff --git a/project.py b/project.py index 1ac48f7..c695f4d 100644 --- a/project.py +++ b/project.py @@ -56,7 +56,8 @@ def cursor(self, *args, **kwargs): if not check_cluster(): init_cluster() start_cluster() -# atexit.register(stop_cluster) + +#atexit.register(stop_cluster) def find_in_dir(dir_, name): @@ -273,6 +274,13 @@ def import_data(self, dir_, progress=None): with self.connect() as con: cur = con.cursor() + for statement in ( + open(os.path.join(os.path.dirname(__file__), '_albion_drop_indexes_and_constrains.sql')) + .read() + .split("\n;\n")[:-1] + ): + cur.execute(statement) + cur.execute( """ copy _albion.collar(id, x, y, z, date_, comments) from '{}' delimiter ';' csv header @@ -448,6 +456,16 @@ def import_data(self, dir_, progress=None): ) ) + progress.setPercent(90) + + + for statement in ( + open(os.path.join(os.path.dirname(__file__), '_albion_create_indexes_and_constrains.sql')) + .read() + .split("\n;\n")[:-1] + ): + cur.execute(statement) + progress.setPercent(100) con.commit() From 3879c9254827b324dddaf9b128f9ade59b3d7961 Mon Sep 17 00:00:00 2001 From: Vincent Mora Date: Tue, 2 Jul 2019 11:46:39 +0200 Subject: [PATCH 05/42] adds tests --- albion.sql | 49 +++++++------ test/__init__.py | 0 import_test.py => test/import_test.py | 17 ++--- test/parent_graph_test.py | 99 +++++++++++++++++++++++++++ 4 files changed, 132 insertions(+), 33 deletions(-) create mode 100644 test/__init__.py rename import_test.py => test/import_test.py (54%) create mode 100644 test/parent_graph_test.py diff --git a/albion.sql b/albion.sql index 45d5c2b..f6fcf07 100644 --- a/albion.sql +++ b/albion.sql @@ -991,10 +991,9 @@ select case when c < a then c else a end as start_, case when c < a then a else from _albion.cell ; -create view albion.possible_edge as +create or replace view albion.possible_edge as with tan_ang as ( select tan(correlation_angle*pi()/180) as value, tan(parent_correlation_angle*pi()/180) as parent_value - from _albion.metadata ), result as ( @@ -1006,20 +1005,24 @@ join _albion.node as ns on ns.hole_id=hs.id join _albion.node as ne on ne.hole_id=he.id, tan_ang where ns.graph_id = ne.graph_id and ( - abs(st_z(st_3dlineinterpolatepoint(ns.geom, .5))-st_z(st_3dlineinterpolatepoint(ne.geom, .5))) - /st_distance(st_3dlineinterpolatepoint(ns.geom, .5), st_3dlineinterpolatepoint(ne.geom, .5)) < tan_ang.value - or - abs(st_z(st_3dlineinterpolatepoint(ns.geom, 0))-st_z(st_3dlineinterpolatepoint(ne.geom, 0))) - /st_distance(st_3dlineinterpolatepoint(ns.geom, 0), st_3dlineinterpolatepoint(ne.geom, 0)) < tan_ang.value + ( + abs(ns.from_-ns.to_) >= abs(ne.from_-ne.to_) + and st_z(st_startpoint(ns.geom)) + st_distance(st_startpoint(ns.geom), st_startpoint(ne.geom))*tan_ang.value >= st_z(st_startpoint(ne.geom)) + and st_z(st_endpoint(ns.geom)) - st_distance(st_startpoint(ns.geom), st_startpoint(ne.geom))*tan_ang.value <= st_z(st_endpoint(ne.geom)) + ) or - abs(st_z(st_3dlineinterpolatepoint(ns.geom, 1))-st_z(st_3dlineinterpolatepoint(ne.geom, 1))) - /st_distance(st_3dlineinterpolatepoint(ns.geom, 1), st_3dlineinterpolatepoint(ne.geom, 1)) < tan_ang.value + ( + abs(ns.from_-ns.to_) < abs(ne.from_-ne.to_) + and st_z(st_startpoint(ne.geom)) + st_distance(st_startpoint(ns.geom), st_startpoint(ne.geom))*tan_ang.value >= st_z(st_startpoint(ns.geom)) + and st_z(st_endpoint(ne.geom)) - st_distance(st_startpoint(ns.geom), st_startpoint(ne.geom))*tan_ang.value <= st_z(st_endpoint(ns.geom)) + ) ) + and st_distance( ne.geom, ns.geom ) < ( select correlation_distance from albion.metadata ) and ns.parent is null and ne.parent is null -union all +union all -- for graphs with parents select ns.id as start_, ne.id as end_, ns.graph_id as graph_id, (st_makeline(st_3dlineinterpolatepoint(ns.geom, .5), st_3dlineinterpolatepoint(ne.geom, .5)))::geometry('LINESTRINGZ', $SRID) as geom, ns.parent as parent from _albion.edge as pe @@ -1028,25 +1031,21 @@ join _albion.node as pne on pne.id=pe.end_ join _albion.node as ns on ns.parent=pns.id join _albion.node as ne on ne.parent=pne.id, tan_ang where ns.graph_id = ne.graph_id -and abs( -- tan(A-B) = (tan(A)-tan(B))/(1+tan(A)tan(B) +and ( - (st_z(st_3dlineinterpolatepoint(ns.geom, .5))-st_z(st_3dlineinterpolatepoint(ne.geom,.5))) - /st_distance(st_3dlineinterpolatepoint(ns.geom, .5), st_3dlineinterpolatepoint(ne.geom, .5)) - - - (st_z(st_3dlineinterpolatepoint(pns.geom, .5))-st_z(st_3dlineinterpolatepoint(pne.geom,.5))) - /st_distance(st_3dlineinterpolatepoint(pns.geom, .5), st_3dlineinterpolatepoint(pne.geom, .5)) + abs(ns.from_-ns.to_) >= abs(ne.from_-ne.to_) + and st_z(st_startpoint(ns.geom)) + st_distance(st_startpoint(ns.geom), st_startpoint(ne.geom))*tan_ang.parent_value + (st_z(st_3dlineinterpolatepoint(pne.geom, .5)) - st_z(st_3dlineinterpolatepoint(pns.geom, .5))) >= st_z(st_startpoint(ne.geom)) + and st_z(st_endpoint(ns.geom)) - st_distance(st_startpoint(ns.geom), st_startpoint(ne.geom))*tan_ang.parent_value + (st_z(st_3dlineinterpolatepoint(pne.geom, .5)) - st_z(st_3dlineinterpolatepoint(pns.geom, .5))) <= st_z(st_endpoint(ne.geom)) + ) - / + or ( - 1.0 - + - (st_z(st_3dlineinterpolatepoint(ns.geom, .5))-st_z(st_3dlineinterpolatepoint(ne.geom,.5))) - /st_distance(st_3dlineinterpolatepoint(ns.geom, .5), st_3dlineinterpolatepoint(ne.geom, .5)) - * - (st_z(st_3dlineinterpolatepoint(pns.geom, .5))-st_z(st_3dlineinterpolatepoint(pne.geom,.5))) - /st_distance(st_3dlineinterpolatepoint(pns.geom, .5), st_3dlineinterpolatepoint(pne.geom, .5)) + abs(ns.from_-ns.to_) < abs(ne.from_-ne.to_) + and st_z(st_startpoint(ne.geom)) + st_distance(st_startpoint(ns.geom), st_startpoint(ne.geom))*tan_ang.parent_value + (st_z(st_3dlineinterpolatepoint(pns.geom, .5)) - st_z(st_3dlineinterpolatepoint(pne.geom, .5))) >= st_z(st_startpoint(ns.geom)) + + and st_z(st_endpoint(ne.geom)) - st_distance(st_startpoint(ns.geom), st_startpoint(ne.geom))*tan_ang.parent_value + (st_z(st_3dlineinterpolatepoint(pns.geom, .5)) - st_z(st_3dlineinterpolatepoint(pne.geom, .5)) ) <= st_z(st_endpoint(ns.geom)) + ) - ) < tan_ang.parent_value ) select row_number() over() as id, * from result ; diff --git a/test/__init__.py b/test/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/import_test.py b/test/import_test.py similarity index 54% rename from import_test.py rename to test/import_test.py index eb13afd..fa7e52e 100644 --- a/import_test.py +++ b/test/import_test.py @@ -6,6 +6,9 @@ import os import sys import time + import tempfile + import zipfile + project_name = "import_test" @@ -15,14 +18,12 @@ project = Project.create(project_name, 32632) start = time.time() - project.import_data(sys.argv[1]) - ## fix_print_with_import - #print("time for import", time.time() - start, 'sec') - - #project = Project(project_name) - # - #project.triangulate() - #project.create_section_view_0_90(4) + zip_ref = zipfile.ZipFile(os.path.join(os.path.dirname(__file__), '..', 'data', 'nt.zip'), 'r') + zip_ref.extractall(tempfile.gettempdir()) + zip_ref.close() + data_dir = os.path.join(tempfile.gettempdir(), 'nt') + print('###############################', data_dir) + project.import_data(data_dir) project.triangulate() project.create_section_view_0_90(4) diff --git a/test/parent_graph_test.py b/test/parent_graph_test.py new file mode 100644 index 0000000..851fe61 --- /dev/null +++ b/test/parent_graph_test.py @@ -0,0 +1,99 @@ +from __future__ import print_function +# coding = utf-8 + +# (1)<--------------100 m----------------->(2) +# 6||3 +# +# +# +# _ -50m +# | 5||2 +# | +# 1||4 +# | +# | _ -100 m + +SQL = """ +INSERT INTO albion.collar(id, geom) VALUES + (1, 'SRID=32632;POINT(0 0 0)'::geometry), + (2, 'SRID=32632;POINT(100 0 0)'::geometry), + (3, 'SRID=32632;POINT(100 100 0)'::geometry) +; +INSERT INTO albion.cell(id, a, b, c, geom) VALUES + (1, 1, 2, 3, 'SRID=32632;POLYGON((0 0, 100 0, 100 100, 0 0))'::geometry) +; +REFRESH MATERIALIZED VIEW albion.all_edge +; +INSERT INTO albion.hole(id, collar_id, depth_, geom) VALUES + (1, 1, 100, 'SRID=32632;LINESTRING(0 0 0, 0 0 -100)'::geometry), + (2, 2, 100, 'SRID=32632;LINESTRING(100 0 0, 100 0 -100)'::geometry) +; +INSERT INTO albion.graph(id) VALUES + ('graph1') +; +INSERT INTO albion.node(id, graph_id, hole_id, from_, to_, geom) VALUES + (1, 'graph1', 1, 50, 100, 'SRID=32632;LINESTRING(0 0 -50, 0 0 -100)'::geometry), + (2, 'graph1', 2, 50, 60, 'SRID=32632;LINESTRING(100 0 -50, 100 0 -60)'::geometry), + (3, 'graph1', 2, 0, 50, 'SRID=32632;LINESTRING(100 0 -40, 100 0 -50)'::geometry) +; +INSERT INTO albion.graph(id, parent) VALUES + ('graph2', 'graph1') +; +INSERT INTO albion.node(id, graph_id, hole_id, from_, to_, geom) VALUES + (4, 'graph2', 1, 70, 80, 'SRID=32632;LINESTRING(0 0 -70, 0 0 -80)'::geometry), + (5, 'graph2', 2, 50, 60, 'SRID=32632;LINESTRING(100 0 -50, 100 0 -60)'::geometry), + (6, 'graph2', 2, 0, 10, 'SRID=32632;LINESTRING(100 0 0, 100 0 -10)'::geometry) +; +; +""" + + +if __name__ == "__main__": + from albion.project import Project + import os + import sys + import time + + + project_name = "parent_graph_test" + + if Project.exists(project_name): + Project.delete(project_name) + + project = Project.create(project_name, 32632) + start = time.time() + + with project.connect() as con: + cur = con.cursor() + for sql in SQL.split("\n;\n")[:-1]: + cur.execute(sql) + con.commit() + + cur.execute(""" + UPDATE albion.metadata SET correlation_angle=1 ; + """) + + cur.execute(""" + SELECT start_, end_ FROM albion.possible_edge + """) + for s,e in cur.fetchall(): + print(s,e) + + cur.execute(""" + INSERT INTO albion.edge(start_, end_, graph_id, geom) SELECT start_, end_, graph_id, geom FROM albion.possible_edge + """) + + cur.execute(""" + SELECT start_, end_ FROM albion.possible_edge + """) + + edges = [(s,e) for s,e in cur.fetchall()] + print(edges) + assert(('1','2') in edges) + assert(('4','5') in edges) + + + + + + From 5c4fe6627b543ce7be6aa288df25682ff4c985e8 Mon Sep 17 00:00:00 2001 From: Vincent Mora Date: Thu, 11 Jul 2019 19:21:05 +0200 Subject: [PATCH 06/42] refacto to ligthnen up database --- _albion.sql | 205 +---------- _albion_create_indexes_and_constrains.sql | 59 --- _albion_drop_indexes_and_constrains.sql | 58 --- _albion_table.sql | 7 + albion.sql | 430 ++++++---------------- albion_table.sql | 29 ++ data/nt.zip | Bin 2511775 -> 2512025 bytes plugin.py | 38 +- project.py | 215 +++++------ viewer_3d/scene.py | 3 +- 10 files changed, 283 insertions(+), 761 deletions(-) delete mode 100644 _albion_create_indexes_and_constrains.sql delete mode 100644 _albion_drop_indexes_and_constrains.sql create mode 100644 _albion_table.sql create mode 100644 albion_table.sql diff --git a/_albion.sql b/_albion.sql index a35baa7..af7f315 100644 --- a/_albion.sql +++ b/_albion.sql @@ -42,40 +42,24 @@ create table _albion.metadata( insert into _albion.metadata(srid) select $SRID ; -create table _albion.collar( +create table _albion.hole( id varchar primary key default _albion.unique_id()::varchar, - x double precision, - y double precision, - z real, date_ varchar, - geom geometry('POINTZ', $SRID), - comments varchar) -; - -create index collar_geom_idx on _albion.collar using gist(geom) -; - -create table _albion.hole( - id varchar primary key, - collar_id varchar unique not null references _albion.collar(id) on delete cascade on update cascade, - depth_ real, + depth_ real not null, + check(depth_ > 0), + x double precision not null, + y double precision not null, + z double precision not null, + comments varchar, geom geometry('LINESTRINGZ', $SRID)) ; -create index hole_geom_idx on _albion.hole using gist(geom) -; - -create index hole_collar_id_idx on _albion.hole(collar_id) +alter table _albion.hole add constraint hole_geom_length_chk check (geom is null or abs(st_3dlength(geom) - depth_) <= 1e-3) ; - -alter table _albion.hole alter column id set default _albion.unique_id()::varchar +create index hole_geom_idx on _albion.hole using gist(geom) ; -------------------------------------------------------------------------------- --- MEASURES -------------------------------------------------------------------------------- - create table _albion.deviation( hole_id varchar not null references _albion.hole(id) on delete cascade on update cascade, from_ real, @@ -83,140 +67,6 @@ create table _albion.deviation( azimuth real) ; -create index deviation_hole_id_idx on _albion.deviation(hole_id) -; - -create table _albion.radiometry( - id varchar primary key, - hole_id varchar not null references _albion.hole(id) on delete cascade on update cascade, - from_ real, - to_ real, - gamma real, - geom geometry('LINESTRINGZ', $SRID)) -; - -create index radiometry_geom_idx on _albion.radiometry using gist(geom) -; - -create index radiometry_hole_id_idx on _albion.radiometry(hole_id) -; - -alter table _albion.radiometry alter column id set default _albion.unique_id()::varchar -; - -create table _albion.resistivity( - id varchar primary key, - hole_id varchar not null references _albion.hole(id) on delete cascade on update cascade, - from_ real, - to_ real, - rho real, - geom geometry('LINESTRINGZ', $SRID)) -; - -create index resistivity_geom_idx on _albion.resistivity using gist(geom) -; - -create index resistivity_hole_id_idx on _albion.resistivity(hole_id) -; - -alter table _albion.resistivity alter column id set default _albion.unique_id()::varchar -; - - -create table _albion.formation( - id varchar primary key, - hole_id varchar not null references _albion.hole(id) on delete cascade on update cascade, - from_ real, - to_ real, - code integer, - comments varchar, - geom geometry('LINESTRINGZ', $SRID)) -; - -create index formation_geom_idx on _albion.formation using gist(geom) -; - -create index formation_hole_id_idx on _albion.formation(hole_id) -; - -alter table _albion.formation alter column id set default _albion.unique_id()::varchar -; - -create table _albion.lithology( - id varchar primary key, - hole_id varchar not null references _albion.hole(id) on delete cascade on update cascade, - from_ real, - to_ real, - code integer, - comments varchar, - geom geometry('LINESTRINGZ', $SRID)) -; - -create index lithology_geom_idx on _albion.lithology using gist(geom) -; - -create index lithology_hole_id_idx on _albion.lithology(hole_id) -; - -alter table _albion.lithology alter column id set default _albion.unique_id()::varchar -; - -create table _albion.facies( - id varchar primary key, - hole_id varchar not null references _albion.hole(id) on delete cascade on update cascade, - from_ real, - to_ real, - code integer, - comments varchar, - geom geometry('LINESTRINGZ', $SRID)) -; - -create index facies_geom_idx on _albion.facies using gist(geom) -; - -create index facies_hole_id_idx on _albion.facies(hole_id) -; - -alter table _albion.facies alter column id set default _albion.unique_id()::varchar -; - -create table _albion.chemical( - hole_id varchar not null references _albion.hole(id) on delete cascade on update cascade, - from_ real, - to_ real, - num_sample varchar, - element varchar, - thickness real, - gt real, -- thickness * grade - grade real, - equi real, - comments varchar) -; - -create index chemical_hole_id_idx on _albion.chemical(hole_id) -; - -create table _albion.mineralization( - id varchar primary key, - hole_id varchar not null references _albion.hole(id) on delete cascade on update cascade, - level_ real, - from_ real, - to_ real, - oc real, - accu real, - grade real, - comments varchar, - geom geometry('LINESTRINGZ', $SRID)) -; - -create index mineralization_geom_idx on _albion.mineralization using gist(geom) -; - -create index mineralization_hole_id_idx on _albion.mineralization(hole_id) -; - -alter table _albion.mineralization alter column id set default _albion.unique_id()::varchar -; ------------------------------------------------------------------------------- -- GRAPH @@ -276,9 +126,9 @@ alter table _albion.edge alter column id set default _albion.unique_id()::varcha create table _albion.cell( id varchar primary key, - a varchar not null references _albion.collar(id) on delete cascade on update cascade, - b varchar not null references _albion.collar(id) on delete cascade on update cascade, - c varchar not null references _albion.collar(id) on delete cascade on update cascade, + a varchar not null references _albion.hole(id) on delete cascade on update cascade, + b varchar not null references _albion.hole(id) on delete cascade on update cascade, + c varchar not null references _albion.hole(id) on delete cascade on update cascade, geom geometry('POLYGON', $SRID) not null check(st_isvalid(geom) and st_numpoints(geom)=4) ) ; @@ -350,7 +200,7 @@ create table _albion.end_node( id varchar primary key, geom geometry('LINESTRINGZ', $SRID) not null check (st_numpoints(geom)=2), node_id varchar not null references _albion.node(id) on delete cascade on update cascade, - collar_id varchar not null references _albion.collar(id) on delete cascade on update cascade, + hole_id varchar not null references _albion.hole(id) on delete cascade on update cascade, graph_id varchar references _albion.graph(id) on delete cascade ) ; @@ -361,32 +211,3 @@ create index end_node_geom_idx on _albion.end_node using gist(geom) alter table _albion.end_node alter column id set default _albion.unique_id()::varchar ; ---create table _albion.end_edge( --- id varchar primary key, --- start_ varchar not null , --- foreign key (graph_id, start_) references _albion.end_node(graph_id, id) on delete cascade on update cascade, --- end_ varchar not null, --- foreign key (graph_id, end_) references _albion.end_node(graph_id, id) on delete cascade on update cascade, --- unique (start_, end_), --- check (start_ < end_), --- graph_id varchar references _albion.graph(id) on delete cascade, --- geom geometry('LINESTRINGZ', $SRID) not null check (st_isvalid(geom)) ---) ---; --- ---create index end_edge_geom_idx on _albion.end_edge using gist(geom) ---; --- ---create index end_edge_graph_id_idx on _albion.end_edge(graph_id) ---; --- ---create index end_edge_start__idx on _albion.end_edge(start_) ---; --- ---create index end_edge_end__idx on _albion.end_edge(end_) ---; --- ---alter table _albion.end_edge alter column id set default _albion.unique_id()::varchar ---; - - diff --git a/_albion_create_indexes_and_constrains.sql b/_albion_create_indexes_and_constrains.sql deleted file mode 100644 index c0d7ab4..0000000 --- a/_albion_create_indexes_and_constrains.sql +++ /dev/null @@ -1,59 +0,0 @@ -create index collar_geom_idx on _albion.collar using gist(geom) -; -alter table _albion.hole add constraint hole_collar_id_fkey foreign key (collar_id) references _albion.collar(id) -; -create index hole_geom_idx on _albion.hole using gist(geom) -; -create index hole_collar_id_idx on _albion.hole(collar_id) -; -alter table _albion.deviation add constraint deviation_hole_id_fkey foreign key (hole_id) references _albion.hole(id) -; -create index deviation_hole_id_idx on _albion.deviation(hole_id) -; -alter table _albion.radiometry add constraint radiometry_hole_id_fkey foreign key (hole_id) references _albion.hole(id) -; -create index radiometry_geom_idx on _albion.radiometry using gist(geom) -; -create index radiometry_hole_id_idx on _albion.radiometry(hole_id) -; -alter table _albion.resistivity add constraint resistivity_hole_id_fkey foreign key (hole_id) references _albion.hole(id) -; -create index resistivity_geom_idx on _albion.resistivity using gist(geom) -; -create index resistivity_hole_id_idx on _albion.resistivity(hole_id) -; -alter table _albion.formation add constraint formation_hole_id_fkey foreign key (hole_id) references _albion.hole(id) -; -create index formation_geom_idx on _albion.formation using gist(geom) -; -create index formation_hole_id_idx on _albion.formation(hole_id) -; -alter table _albion.lithology add constraint lithology_hole_id_fkey foreign key (hole_id) references _albion.hole(id) -; -create index lithology_geom_idx on _albion.lithology using gist(geom) -; -create index lithology_hole_id_idx on _albion.lithology(hole_id) -; -alter table _albion.facies add constraint facies_hole_id_fkey foreign key (hole_id) references _albion.hole(id) -; -create index facies_geom_idx on _albion.facies using gist(geom) -; -create index facies_hole_id_idx on _albion.facies(hole_id) -; -alter table _albion.chemical add constraint chemical_hole_id_fkey foreign key (hole_id) references _albion.hole(id) -; -create index chemical_hole_id_idx on _albion.chemical(hole_id) -; -alter table _albion.mineralization add constraint mineralization_hole_id_fkey foreign key (hole_id) references _albion.hole(id) -; -create index mineralization_geom_idx on _albion.mineralization using gist(geom) -; -create index mineralization_hole_id_idx on _albion.mineralization(hole_id) -; - - - - - - - diff --git a/_albion_drop_indexes_and_constrains.sql b/_albion_drop_indexes_and_constrains.sql deleted file mode 100644 index 8dcce30..0000000 --- a/_albion_drop_indexes_and_constrains.sql +++ /dev/null @@ -1,58 +0,0 @@ -drop index _albion.collar_geom_idx -; -alter table _albion.hole drop constraint hole_collar_id_fkey -; -drop index _albion.hole_geom_idx -; -drop index _albion.hole_collar_id_idx -; -alter table _albion.deviation drop constraint deviation_hole_id_fkey -; -drop index _albion.deviation_hole_id_idx -; -alter table _albion.radiometry drop constraint radiometry_hole_id_fkey -; -drop index _albion.radiometry_geom_idx -; -drop index _albion.radiometry_hole_id_idx -; -alter table _albion.resistivity drop constraint resistivity_hole_id_fkey -; -drop index _albion.resistivity_geom_idx -; -drop index _albion.resistivity_hole_id_idx -; -alter table _albion.formation drop constraint formation_hole_id_fkey -; -drop index _albion.formation_geom_idx -; -drop index _albion.formation_hole_id_idx -; -alter table _albion.lithology drop constraint lithology_hole_id_fkey -; -drop index _albion.lithology_geom_idx -; -drop index _albion.lithology_hole_id_idx -; -alter table _albion.facies drop constraint facies_hole_id_fkey -; -drop index _albion.facies_geom_idx -; -drop index _albion.facies_hole_id_idx -; -alter table _albion.chemical drop constraint chemical_hole_id_fkey -; -drop index _albion.chemical_hole_id_idx -; -alter table _albion.mineralization drop constraint mineralization_hole_id_fkey -; -drop index _albion.mineralization_geom_idx -; -drop index _albion.mineralization_hole_id_idx -; - - - - - - diff --git a/_albion_table.sql b/_albion_table.sql new file mode 100644 index 0000000..e01fed7 --- /dev/null +++ b/_albion_table.sql @@ -0,0 +1,7 @@ +create table _albion.$NAME( + id varchar primary key default _albion.unique_id()::varchar, + hole_id varchar not null references _albion.hole(id) on delete cascade on update cascade, + from_ real check (from_>=0), + to_ real check (to_>=0), + ${FIELDS_DEFINITION}) +; diff --git a/albion.sql b/albion.sql index f6fcf07..ebc84b7 100644 --- a/albion.sql +++ b/albion.sql @@ -8,61 +8,6 @@ create schema albion ------------------------------------------------------------------------------- -- UTILITY FUNCTIONS ------------------------------------------------------------------------------- ---create or replace function public.st_3dlineinterpolatepoint(line_ geometry, sigma_ float) ---returns geometry ---language plpython3u immutable ---as ---$$ --- --- from shapely import wkb --- from shapely import geos --- from shapely.geometry import Point --- import numpy as np --- from numpy import array --- from numpy.linalg import norm --- geos.WKBWriter.defaults['include_srid'] = True --- --- if line_ is None: --- return None --- --- assert(sigma_ >=0 and sigma_ <=1) --- --- line = wkb.loads(bytes.fromhex(line_)) --- --- if sigma_ > 0 and sigma_ < 1: --- l = array(line.coords) --- seg = l[:-1] - l[1:] --- seg_length = np.sum(seg**2,axis=-1)**.5 --- line_length = np.sum(seg_length) --- target_length = line_length*sigma_ --- cum_length = np.cumsum(seg_length) --- idx = np.searchsorted(np.cumsum(seg_length), target_length) --- overshoot = cum_length[idx] - target_length --- a = overshoot/seg_length[idx] --- result = Point(l[idx]*a + l[idx+1]*(1.-a)) --- --- elif sigma_ == 1: --- result = Point(line.coords[-1]) --- --- elif sigma_ == 0: --- result = Point(line.coords[0]) --- --- geos.lgeos.GEOSSetSRID(result._geom, geos.lgeos.GEOSGetSRID(line._geom)) --- return result.wkb_hex --- ---$$ ---; - ---create or replace function albion.srid() ---returns integer ---language plpgsql stable ---as ---$$ --- begin --- return select (srid from _albion.metadata); --- end; ---$$ ---; create or replace function albion.hole_geom(hole_id_ varchar) returns geometry @@ -72,13 +17,15 @@ $$ declare depth_max_ real; hole_geom_ geometry; - collar_id_ varchar; + x_ double precision; + y_ double precision; + z_ double precision; collar_geom_ geometry; + path_ varchar; begin - select collar_id, depth_ from albion.hole where id=hole_id_ into collar_id_, depth_max_; - - select geom from albion.collar where id=collar_id_ into collar_geom_; + select x, y, z, depth_ from _albion.hole where id=hole_id_ into x_, y_, z_, depth_max_; + collar_geom_ := st_setsrid(st_makepoint(x_, y_, z_), $SRID); with dz as ( select from_ as md2, coalesce(lag(from_) over w, 0) as md1, @@ -91,9 +38,9 @@ $$ ), pt as ( select md2, wd2, haz2, - st_x(collar_geom_) + sum(0.5 * (md2 - md1) * (sin(wd1) * sin(haz1) + sin(wd2) * sin(haz2))) over w as x, - st_y(collar_geom_) + sum(0.5 * (md2 - md1) * (sin(wd1) * cos(haz1) + sin(wd2) * cos(haz2))) over w as y, - st_z(collar_geom_) - sum(0.5 * (md2 - md1) * (cos(wd2) + cos(wd1))) over w as z + x_ + sum(0.5 * (md2 - md1) * (sin(wd1) * sin(haz1) + sin(wd2) * sin(haz2))) over w as x, + y_ + sum(0.5 * (md2 - md1) * (sin(wd1) * cos(haz1) + sin(wd2) * cos(haz2))) over w as y, + z_ - sum(0.5 * (md2 - md1) * (cos(wd2) + cos(wd1))) over w as z from dz window w AS (order by md1) ), @@ -106,6 +53,7 @@ $$ into hole_geom_; if hole_geom_ is not null and st_3dlength(hole_geom_) < depth_max_ and st_3dlength(hole_geom_) > 0 then + path_ := 'too short'; -- holes is not long enough with last_segment as ( select st_pointn(hole_geom_, st_numpoints(hole_geom_)-1) as start_, st_endpoint(hole_geom_) as end_ @@ -128,9 +76,13 @@ $$ -- hole have no deviation elsif hole_geom_ is null or st_3dlength(hole_geom_) = 0 then + path_ := 'no length'; select st_makeline( collar_geom_, st_translate(collar_geom_, 0, 0, -depth_max_)) into hole_geom_; end if; + if abs(st_3dlength(hole_geom_) - depth_max_) > 1e-3 then + raise 'hole %s %s %s %', hole_id_, depth_max_, st_3dlength(hole_geom_), path_; + end if; return hole_geom_; end; $$ @@ -144,47 +96,26 @@ $$ begin return ( select st_makeline( - st_3dlineinterpolatepoint(geom, from_/depth_), - st_3dlineinterpolatepoint(geom, to_/depth_)) - from albion.hole where id=hole_id_ + st_3dlineinterpolatepoint(geom, least(from_/l, 1)), + st_3dlineinterpolatepoint(geom, least(to_/l, 1))) + from (select geom, st_3dlength(geom) as l from albion.hole where id=hole_id_) as t ); end; $$ ; -create view albion.collar as select id, geom, date_, comments from _albion.collar +create view albion.collar as select id, st_startpoint(geom) as geom, date_, comments, depth_ from _albion.hole ; create view albion.metadata as select id, srid, close_collar_distance, snap_distance, precision, interpolation, end_distance, end_angle, correlation_distance, correlation_angle, parent_correlation_angle from _albion.metadata ; -create view albion.hole as select id, collar_id, depth_, geom::geometry('LINESTRINGZ', $SRID) from _albion.hole +create view albion.hole as select id, depth_, geom::geometry('LINESTRINGZ', $SRID) from _albion.hole ; create view albion.deviation as select hole_id, from_, dip, azimuth from _albion.deviation ; -create view albion.formation as select id, hole_id, from_, to_, code, comments, geom::geometry('LINESTRINGZ', $SRID) from _albion.formation -; - -create view albion.resistivity as select id, hole_id, from_, to_, rho, geom::geometry('LINESTRINGZ', $SRID) from _albion.resistivity -; - -create view albion.radiometry as select id, hole_id, from_, to_, gamma, geom::geometry('LINESTRINGZ', $SRID) from _albion.radiometry -; - -create view albion.lithology as select id, hole_id, from_, to_, code, comments, geom::geometry('LINESTRINGZ', $SRID) from _albion.lithology -; - -create view albion.facies as select id, hole_id, from_, to_, code, comments, geom::geometry('LINESTRINGZ', $SRID) from _albion.facies -; - -create view albion.chemical as select hole_id, from_, to_, num_sample, element, thickness, gt, grade, equi, comments from _albion.chemical -; - -create view albion.mineralization as select id, hole_id, level_, from_, to_, oc, accu, grade, geom::geometry('LINESTRINGZ', $SRID) from _albion.mineralization -; - create or replace view albion.graph as select id, parent from _albion.graph ; @@ -213,6 +144,8 @@ $$ end if; end if; + new.geom := coalesce(new.geom, albion.hole_piece(new.from_, new.to_, new.hole_id)); + if tg_op = 'INSERT' then insert into _albion.node(id, graph_id, hole_id, from_, to_, geom, parent) values(new.id, new.graph_id, new.hole_id, new.from_, new.to_, new.geom, new.parent) @@ -239,7 +172,7 @@ create trigger node_instead_trig create or replace view albion.close_collar as -select a.id, a.geom from _albion.collar as a, _albion.collar as b, _albion.metadata as m +select a.id, a.geom from albion.collar as a, albion.collar as b, _albion.metadata as m where a.id != b.id and st_dwithin(a.geom, b.geom, m.close_collar_distance) ; @@ -255,15 +188,15 @@ $$ delete from _albion.cell; insert into _albion.cell(a, b, c, geom) with cell as ( - select ST_DelaunayTriangles(ST_Collect(ST_Force2D(geom))) as geom from _albion.collar + select ST_DelaunayTriangles(ST_Collect(ST_Force2D(geom))) as geom from albion.collar ), splt as ( select (ST_Dump(geom)).geom from cell ) select - (select c.id from _albion.collar as c where st_intersects(c.geom, st_pointn(st_exteriorring(s.geom), 1))), - (select c.id from _albion.collar as c where st_intersects(c.geom, st_pointn(st_exteriorring(s.geom), 2))), - (select c.id from _albion.collar as c where st_intersects(c.geom, st_pointn(st_exteriorring(s.geom), 3))), + (select c.id from albion.collar as c where st_intersects(c.geom, st_pointn(st_exteriorring(s.geom), 1))), + (select c.id from albion.collar as c where st_intersects(c.geom, st_pointn(st_exteriorring(s.geom), 2))), + (select c.id from albion.collar as c where st_intersects(c.geom, st_pointn(st_exteriorring(s.geom), 3))), s.geom from splt as s; @@ -546,39 +479,39 @@ create trigger group_cell_instead_trig for each row execute procedure albion.group_cell_instead_fct() ; -create view albion.current_section as -with hull as ( - select st_unaryunion(st_collect(c.geom)) as geom, gc.section_id - from _albion.cell as c - join _albion.group_cell as gc on gc.cell_id=c.id - group by gc.section_id -), -hull_contour as ( - select st_exteriorring(geom) as geom, section_id from hull -), -seg as ( - select ST_PointN(geom, generate_series(1, ST_NPoints(geom)-1)) as sp, ST_PointN(geom, generate_series(2, ST_NPoints(geom) )) as ep, section_id - from hull_contour -), -facing as ( - select st_force2d(st_makeline(seg.sp, seg.ep)) as geom, seg.section_id - from seg join _albion.section as s on s.id = seg.section_id - where albion.cos_angle(s.anchor, seg.sp, seg.ep) > cos(89*pi()/180) -), -merged as ( - select st_linemerge(st_collect(facing.geom)) as geom, section_id - from facing join _albion.section as s on s.id = facing.section_id - group by section_id, s.geom -), -sorted as ( - select rank() over(partition by section_id order by st_length(geom) desc) as rk, geom, section_id - from (select (st_dump(geom)).geom, section_id from merged) as t -) -select section_id as id, st_reverse(geom)::geometry('LINESTRING', $SRID) as geom from sorted where rk=1 -union all -select s.id, (albion.first_section(s.anchor))::geometry('LINESTRING', $SRID) as geom from albion.section as s -where not exists (select 1 from sorted as st where st.section_id=s.id) -; +-- create view albion.current_section as +-- with hull as ( +-- select st_unaryunion(st_collect(c.geom)) as geom, gc.section_id +-- from _albion.cell as c +-- join _albion.group_cell as gc on gc.cell_id=c.id +-- group by gc.section_id +-- ), +-- hull_contour as ( +-- select st_exteriorring(geom) as geom, section_id from hull +-- ), +-- seg as ( +-- select ST_PointN(geom, generate_series(1, ST_NPoints(geom)-1)) as sp, ST_PointN(geom, generate_series(2, ST_NPoints(geom) )) as ep, section_id +-- from hull_contour +-- ), +-- facing as ( +-- select st_force2d(st_makeline(seg.sp, seg.ep)) as geom, seg.section_id +-- from seg join _albion.section as s on s.id = seg.section_id +-- where albion.cos_angle(s.anchor, seg.sp, seg.ep) > cos(89*pi()/180) +-- ), +-- merged as ( +-- select st_linemerge(st_collect(facing.geom)) as geom, section_id +-- from facing join _albion.section as s on s.id = facing.section_id +-- group by section_id, s.geom +-- ), +-- sorted as ( +-- select rank() over(partition by section_id order by st_length(geom) desc) as rk, geom, section_id +-- from (select (st_dump(geom)).geom, section_id from merged) as t +-- ) +-- select section_id as id, st_reverse(geom)::geometry('LINESTRING', $SRID) as geom from sorted where rk=1 +-- union all +-- select s.id, (albion.first_section(s.anchor))::geometry('LINESTRING', $SRID) as geom from albion.section as s +-- where not exists (select 1 from sorted as st where st.section_id=s.id) +-- ; create or replace function albion.to_section(geom geometry, anchor geometry, z_scale real) returns geometry @@ -667,112 +600,22 @@ $$ $$ ; -create materialized view albion.radiometry_section as -select r.id as radiometry_id, s.id as section_id, - (albion.to_section(r.geom, s.anchor, s.scale))::geometry('LINESTRING', $SRID) as geom -from _albion.radiometry as r -join _albion.hole as h on h.id=r.hole_id, _albion.section as s -; - -create index radiometry_section_geom_idx on albion.radiometry_section using gist(geom) -; - -create index radiometry_section_radiometry_id_idx on albion.radiometry_section(radiometry_id) -; - -create materialized view albion.resistivity_section as -select r.id as resistivity_id, s.id as section_id, - (albion.to_section(r.geom, s.anchor, s.scale))::geometry('LINESTRING', $SRID) as geom -from _albion.resistivity as r -join _albion.hole as h on h.id=r.hole_id, _albion.section as s -; - -create index resistivity_section_geom_idx on albion.resistivity_section using gist(geom) -; - -create index resistivity_section_resistivity_id_idx on albion.resistivity_section(resistivity_id) -; - -create view albion.current_node_section as -select row_number() over() as id, n.id as node_id, h.collar_id, n.from_, n.to_, n.graph_id, s.id as section_id, - (albion.to_section(n.geom, s.anchor, s.scale))::geometry('LINESTRING', $SRID) as geom -from _albion.node as n -join _albion.hole as h on h.id=n.hole_id -join _albion.collar as c on c.id=h.collar_id -join _albion.section as s on st_intersects(s.geom, c.geom) -; - create view albion.hole_section as -select row_number() over() as id, h.id as hole_id, h.collar_id, h.depth_, s.id as section_id, +select row_number() over() as id, h.id as hole_id, h.depth_, s.id as section_id, (albion.to_section(h.geom, s.anchor, s.scale))::geometry('LINESTRING', $SRID) as geom -from _albion.hole as h -join _albion.collar as c on c.id=h.collar_id, _albion.section as s -; - -create view albion.current_hole_section as -select row_number() over() as id, h.id as hole_id, h.collar_id, h.depth_, s.id as section_id, - (albion.to_section(h.geom, s.anchor, s.scale))::geometry('LINESTRING', $SRID) as geom -from _albion.hole as h -join _albion.collar as c on c.id=h.collar_id -join _albion.section as s on st_intersects(s.geom, c.geom) -; - -create view albion.current_mineralization_section as -select row_number() over() as id, m.hole_id as hole_id, h.collar_id, m.level_, m.oc, m.accu, m.grade, s.id as section_id, - (albion.to_section(m.geom, s.anchor, s.scale))::geometry('LINESTRING', $SRID) as geom -from _albion.mineralization as m -join _albion.hole as h on h.id=m.hole_id -join _albion.collar as c on c.id=h.collar_id -join _albion.section as s on st_intersects(s.geom, c.geom) +from _albion.section as s +join _albion.hole as h on s.geom && h.geom and st_intersects(st_startpoint(h.geom), s.geom) ; -create view albion.current_radiometry_section as -select row_number() over() as id, r.hole_id as hole_id, h.collar_id, r.gamma, s.id as section_id, - rs.geom::geometry('LINESTRING', $SRID) as geom -from _albion.radiometry as r -join _albion.hole as h on h.id=r.hole_id -join _albion.collar as c on c.id=h.collar_id -join _albion.section as s on st_intersects(s.geom, c.geom) -join albion.radiometry_section as rs on rs.radiometry_id=r.id and rs.section_id=s.id -; - -create view albion.current_resistivity_section as -select row_number() over() as id, r.hole_id as hole_id, h.collar_id, r.rho, s.id as section_id, - rs.geom::geometry('LINESTRING', $SRID) as geom -from _albion.resistivity as r -join _albion.hole as h on h.id=r.hole_id -join _albion.collar as c on c.id=h.collar_id -join _albion.section as s on st_intersects(s.geom, c.geom) -join albion.resistivity_section as rs on rs.resistivity_id=r.id and rs.section_id=s.id -; - - -create view albion.current_formation_section as -select row_number() over() as id, r.hole_id as hole_id, h.collar_id, r.code, r.comments, s.id as section_id, - (albion.to_section(r.geom, s.anchor, s.scale))::geometry('LINESTRING', $SRID) as geom -from _albion.formation as r -join _albion.hole as h on h.id=r.hole_id -join _albion.collar as c on c.id=h.collar_id -join _albion.section as s on st_intersects(s.geom, c.geom) -; -create view albion.current_lithology_section as -select row_number() over() as id, r.hole_id as hole_id, h.collar_id, r.code, r.comments, s.id as section_id, - (albion.to_section(r.geom, s.anchor, s.scale))::geometry('LINESTRING', $SRID) as geom -from _albion.lithology as r -join _albion.hole as h on h.id=r.hole_id -join _albion.collar as c on c.id=h.collar_id -join _albion.section as s on st_intersects(s.geom, c.geom) +create view albion.node_section as +select row_number() over() as id, n.id as node_id, h.id as hole_id, n.from_, n.to_, n.graph_id, s.id as section_id, + (albion.to_section(n.geom, s.anchor, s.scale))::geometry('LINESTRING', $SRID) as geom +from _albion.section as s +join _albion.hole as h on s.geom && h.geom and st_intersects(st_startpoint(h.geom), s.geom) +join _albion.node as n on n.hole_id = h.id ; -create view albion.current_facies_section as -select row_number() over() as id, r.hole_id as hole_id, h.collar_id, r.code, r.comments, s.id as section_id, - (albion.to_section(r.geom, s.anchor, s.scale))::geometry('LINESTRING', $SRID) as geom -from _albion.facies as r -join _albion.hole as h on h.id=r.hole_id -join _albion.collar as c on c.id=h.collar_id -join _albion.section as s on st_intersects(s.geom, c.geom) -; create or replace function albion.section_at_group(section_id_ varchar, group_id_ integer) returns geometry @@ -933,53 +776,6 @@ $$ $$ ; -select hole_id, (t.r).level_, (t.r).from_, (t.r).to_, (t.r).oc, (t.r).accu, (t.r).grade -from ( -select hole_id, albion.segmentation( - array_agg(gamma order by from_),array_agg(from_ order by from_), array_agg(to_ order by from_), - 1., 1., 10) as r -from _albion.radiometry -group by hole_id -) as t -; - -create table albion.test_mineralization( - id varchar primary key default _albion.unique_id()::varchar, - hole_id varchar not null references _albion.hole(id) on delete cascade on update cascade, - level_ real, - from_ real, - to_ real, - oc real, - accu real, - grade real, - comments varchar, - geom geometry('LINESTRINGZ', $SRID)) -; - -insert into albion.test_mineralization(hole_id, level_, from_, to_, oc, accu, grade) -select hole_id, (t.r).level_, (t.r).from_, (t.r).to_, (t.r).oc, (t.r).accu, (t.r).grade -from ( -select hole_id, albion.segmentation( - array_agg(gamma order by from_),array_agg(from_ order by from_), array_agg(to_ order by from_), - 1., 1., 10) as r -from _albion.radiometry -group by hole_id -) as t -; - -update albion.test_mineralization set geom=albion.hole_piece(from_, to_, hole_id) -; - -create view albion.current_test_mineralization_section as -select row_number() over() as id, m.hole_id, h.collar_id, m.level_, m.oc, m.accu, m.grade, s.id as section_id, - (albion.to_section(m.geom, s.anchor, s.scale))::geometry('LINESTRING', $SRID) as geom -from albion.test_mineralization as m -join _albion.hole as h on h.id=m.hole_id -join _albion.collar as c on c.id=h.collar_id -join _albion.section as s on st_intersects(s.geom, c.geom) -; - - create materialized view albion.all_edge as select case when a < b then a else b end as start_, case when a < b then b else a end as end_ from _albion.cell @@ -999,8 +795,8 @@ with tan_ang as ( result as ( select ns.id as start_, ne.id as end_, ns.graph_id as graph_id, (st_makeline(st_3dlineinterpolatepoint(ns.geom, .5), st_3dlineinterpolatepoint(ne.geom, .5)))::geometry('LINESTRINGZ', $SRID) as geom, null as parent from albion.all_edge as e -join _albion.hole as hs on hs.collar_id=e.start_ -join _albion.hole as he on he.collar_id=e.end_ +join _albion.hole as hs on hs.id=e.start_ +join _albion.hole as he on he.id=e.end_ join _albion.node as ns on ns.hole_id=hs.id join _albion.node as ne on ne.hole_id=he.id, tan_ang where ns.graph_id = ne.graph_id @@ -1075,8 +871,8 @@ $$ -- @todo check that edge is in all_edge select count(1) from albion.all_edge as ae - join _albion.hole as hs on hs.collar_id=ae.start_ - join _albion.hole as he on he.collar_id=ae.end_ + join _albion.hole as hs on hs.id=ae.start_ + join _albion.hole as he on he.id=ae.end_ join _albion.node as ns on (ns.hole_id in (hs.id, he.id) and ns.id=new.start_) join _albion.node as ne on (ne.hole_id in (hs.id, he.id) and ne.id=new.end_) into edge_ok; @@ -1110,11 +906,11 @@ create trigger edge_instead_trig for each row execute procedure albion.edge_instead_fct() ; -create view albion.current_edge_section as -with collar_idx as ( - select c.id, rank() over(partition by s.id order by st_linelocatepoint(s.geom, c.geom)) as rk, c.geom, s.id as section_id +create view albion.edge_section as +with hole_idx as ( + select h.id, rank() over(partition by s.id order by st_linelocatepoint(s.geom, st_startpoint(h.geom))) as rk, s.id as section_id from _albion.section as s - join _albion.collar as c on st_intersects(s.geom, c.geom) and st_intersects(s.geom, c.geom) + join _albion.hole as h on s.geom && h.geom and st_intersects(s.geom, st_startpoint(h.geom)) ) select s.id || ' ' || e.id as id, e.id as edge_id, e.start_, e.end_, e.graph_id, s.id as section_id, (albion.to_section(e.geom, s.anchor, s.scale))::geometry('LINESTRING', $SRID) as geom @@ -1123,15 +919,15 @@ join _albion.node as ns on ns.id=e.start_ join _albion.node as ne on ne.id=e.end_ join _albion.hole as hs on hs.id=ns.hole_id join _albion.hole as he on he.id=ne.hole_id -join collar_idx as cs on cs.id=hs.collar_id -join collar_idx as ce on ce.id=he.collar_id, +join hole_idx as cs on cs.id=hs.id +join hole_idx as ce on ce.id=he.id, _albion.section as s where ((cs.rk = ce.rk + 1) or (ce.rk = cs.rk + 1)) and cs.section_id=s.id and ce.section_id=s.id ; -create or replace function albion.current_edge_section_instead_fct() +create or replace function albion.edge_section_instead_fct() returns trigger language plpgsql as @@ -1140,13 +936,13 @@ $$ new_geom geometry; begin if tg_op in ('INSERT', 'UPDATE') then - new.start_ := coalesce(new.start_, (select node_id from albion.current_node_section as n, _albion.metadata as m + new.start_ := coalesce(new.start_, (select node_id from albion.node_section as n, _albion.metadata as m where st_dwithin(n.geom, st_startpoint(new.geom), m.snap_distance) and graph_id=new.graph_id order by st_distance(n.geom, st_startpoint(new.geom)) asc limit 1 )); - new.end_ := coalesce(new.end_, (select node_id from albion.current_node_section as n, _albion.metadata as m + new.end_ := coalesce(new.end_, (select node_id from albion.node_section as n, _albion.metadata as m where st_dwithin(n.geom, st_endpoint(new.geom), m.snap_distance) and graph_id=new.graph_id order by st_distance(n.geom, st_endpoint(new.geom)) asc @@ -1178,12 +974,12 @@ $$ $$ ; -create trigger current_edge_section_instead_trig - instead of insert or update or delete on albion.current_edge_section - for each row execute procedure albion.current_edge_section_instead_fct() +create trigger edge_section_instead_trig + instead of insert or update or delete on albion.edge_section + for each row execute procedure albion.edge_section_instead_fct() ; -create view albion.current_possible_edge_section as +create view albion.possible_edge_section as select row_number() over() as id, e.start_, e.end_, e.graph_id, s.id as section_id, (albion.to_section(e.geom, s.anchor, s.scale))::geometry('LINESTRING', $SRID) as geom, e.parent from albion.possible_edge as e @@ -1191,9 +987,8 @@ join _albion.node as ns on ns.id=e.start_ join _albion.node as ne on ne.id=e.end_ join _albion.hole as hs on hs.id=ns.hole_id join _albion.hole as he on he.id=ne.hole_id -join _albion.collar as cs on cs.id=hs.collar_id -join _albion.collar as ce on ce.id=he.collar_id -join _albion.section as s on st_intersects(s.geom, cs.geom) and st_intersects(s.geom, ce.geom) +join _albion.section as s on s.geom && hs.geom and st_intersects(s.geom, st_startpoint(hs.geom)) and + s.geom && he.geom and st_intersects(s.geom, st_startpoint(he.geom)) ; @@ -1441,18 +1236,18 @@ $$ ; create view albion.end_node as -select id, geom, node_id, collar_id, graph_id +select id, geom, node_id, hole_id, graph_id from _albion.end_node ; -- view of termination edges create or replace view albion.half_edge as -select n.id as node_id, n.graph_id, h.collar_id, case when ae.start_=h.collar_id then ae.end_ else ae.start_ end as other +select n.id as node_id, n.graph_id, h.id as hole_id, case when ae.start_=h.id then ae.end_ else ae.start_ end as other from _albion.node as n join _albion.hole as h on h.id=n.hole_id -join albion.all_edge as ae on (ae.start_=h.collar_id or ae.end_=h.collar_id) +join albion.all_edge as ae on (ae.start_=h.id or ae.end_=h.id) except -select n.id, n.graph_id, h.collar_id, case when e.start_=n.id then he.collar_id else hs.collar_id end as other +select n.id, n.graph_id, h.id as hole_id, case when e.start_=n.id then he.id else hs.id end as other from _albion.node as n join _albion.hole as h on h.id=n.hole_id join _albion.edge as e on (e.start_=n.id or e.end_=n.id) @@ -1493,19 +1288,18 @@ $$ ; create view albion.dynamic_end_node as -select row_number() over() as id, he.graph_id, n.id as node_id, albion.end_node_geom(n.geom, c.geom)::geometry('LINESTRINGZ', $SRID) as geom, c.id as collar_id +select row_number() over() as id, he.graph_id, n.id as node_id, albion.end_node_geom(n.geom, st_startpoint(h.geom))::geometry('LINESTRINGZ', $SRID) as geom, h.id as hole_id from albion.half_edge as he join _albion.node as n on n.id=he.node_id join _albion.hole as h on h.id=he.other -join _albion.collar as c on c.id=h.collar_id ; -create view albion.current_end_node_section as -with collar_idx as ( - select c.id, rank() over(partition by s.id order by st_linelocatepoint(s.geom, c.geom)) as rk, c.id as collar_id, c.geom, s.id as section_id +create view albion.end_node_section as +with hole_idx as ( + select h.id, rank() over(partition by s.id order by st_linelocatepoint(s.geom, st_startpoint(h.geom))) as rk, h.id as hole_id, s.id as section_id from _albion.section as s - join _albion.collar as c on st_intersects(s.geom, c.geom) + join _albion.hole as h on s.geom && h.geom and st_intersects(s.geom, st_startpoint(h.geom)) ) select tn.id||' '||s.id as id, tn.id as end_node_id, n.id as node_id, tn.graph_id, s.id as section_id, (albion.to_section(tn.geom, s.anchor, s.scale))::geometry('LINESTRING', $SRID) as geom, @@ -1514,12 +1308,12 @@ from _albion.end_node as tn join _albion.node as n on n.id=tn.node_id join _albion.hole as h on h.id=n.hole_id join _albion.section as s on true -join collar_idx as cn on (cn.collar_id=h.collar_id and cn.section_id=s.id) -join collar_idx as cc on (cc.collar_id=tn.collar_id and cc.section_id=s.id) +join hole_idx as cn on (cn.id=h.id and cn.section_id=s.id) +join hole_idx as cc on (cc.id=tn.hole_id and cc.section_id=s.id) where cn.rk=cc.rk+1 or cc.rk=cn.rk+1 ; -create or replace function albion.current_end_node_section_instead_fct() +create or replace function albion.end_node_section_instead_fct() returns trigger language plpgsql as @@ -1548,18 +1342,18 @@ $$ $$ ; -create trigger current_end_node_section_instead_trig - instead of insert or update or delete on albion.current_end_node_section - for each row execute procedure albion.current_end_node_section_instead_fct() +create trigger end_node_section_instead_trig + instead of insert or update or delete on albion.end_node_section + for each row execute procedure albion.end_node_section_instead_fct() ; -create or replace view albion.current_section_polygon as +create or replace view albion.section_polygon as with node as ( - select node_id, section_id, geom from albion.current_node_section + select node_id, section_id, geom from albion.node_section ), edge as ( - select graph_id, section_id, start_, end_ from albion.current_edge_section + select graph_id, section_id, start_, end_ from albion.edge_section ), poly as ( select st_union( @@ -1585,16 +1379,16 @@ term as ( st_x(st_startpoint(t.node_geom)) ||' '||st_y(st_startpoint(t.node_geom))|| '))')::geometry as geom, t.graph_id, t.section_id - from albion.current_end_node_section as t + from albion.end_node_section as t ) select row_number() over() as id, geom::geometry('POLYGON', $SRID), graph_id, section_id from (select * from poly union all select * from term) as t ; -create or replace view albion.current_section_intersection as +create or replace view albion.section_intersection as with inter as ( select st_collectionextract((st_dump(st_intersection(a.geom, b.geom))).geom, 3) as geom - from albion.current_section_polygon as a, albion.current_section_polygon as b + from albion.section_polygon as a, albion.section_polygon as b where a.id>b.id and a.graph_id=b.graph_id and a.section_id=b.section_id @@ -1614,9 +1408,9 @@ select c.id as cell_id, g.id as graph_id, ed.starts, ed.ends, nd.hole_ids as hole_ids, nd.ids as node_ids, nd.geoms as node_geoms, en.ids as end_ids, en.geoms as end_geoms, c.geom, ARRAY[ha.id, hb.id, hc.id] as holes from _albion.graph as g join _albion.cell as c on true -join _albion.hole as ha on ha.collar_id = c.a -join _albion.hole as hb on hb.collar_id = c.b -join _albion.hole as hc on hc.collar_id = c.c +join _albion.hole as ha on ha.id = c.a +join _albion.hole as hb on hb.id = c.b +join _albion.hole as hc on hc.id = c.c join lateral ( select coalesce(array_agg(n.id), '{}'::varchar[]) as ids, coalesce(array_agg(n.hole_id), '{}'::varchar[]) as hole_ids, coalesce(array_agg(n.geom), '{}'::geometry[]) as geoms from _albion.node as n @@ -1635,7 +1429,7 @@ join lateral ( select coalesce(array_agg(en.node_id), '{}'::varchar[]) as ids, coalesce(array_agg(en.geom), '{}'::geometry[]) as geoms from _albion.end_node as en join _albion.node as n on n.id=en.node_id - where en.collar_id in (c.a, c.b, c.c) + where en.hole_id in (c.a, c.b, c.c) and n.hole_id in (ha.id, hb.id, hc.id) and en.graph_id=g.id ) as en on true diff --git a/albion_table.sql b/albion_table.sql new file mode 100644 index 0000000..42cb495 --- /dev/null +++ b/albion_table.sql @@ -0,0 +1,29 @@ +create view albion.${NAME} as +select id, hole_id, from_, to_, ${FIELDS} from _albion.${NAME} +; + +create materialized view albion.${NAME}_section_geom_cache as +select s.id as section_id, h.id as hole_id, r.id as ${NAME}_id, + (albion.to_section( + st_makeline(st_3dlineinterpolatepoint(h.geom, least(r.from_/h.depth_, 1)), + st_3dlineinterpolatepoint(h.geom, least(r.to_/h.depth_, 1))) + , s.anchor, s.scale)) as geom, + st_startpoint(h.geom) as collar +from _albion.section as s, _albion.${NAME} as r +join _albion.hole as h on h.id=r.hole_id +; + +create index ${NAME}_section_geom_cache_${NAME}_id_idx on albion.${NAME}_section_geom_cache(${NAME}_id) +; + +create index ${NAME}_section_geom_cache_colar_idx on albion.${NAME}_section_geom_cache using gist(collar) +; + + +create view albion.${NAME}_section as +select row_number() over() as id, r.id as ${NAME}_id, sc.section_id, r.hole_id, sc.geom::geometry('LINESTRING', ${SRID}), ${FIELDS} +from _albion.${NAME} as r +join albion.${NAME}_section_geom_cache as sc on sc.${NAME}_id = r.id +join _albion.section as s on st_intersects(s.geom, sc.collar) and sc.section_id = s.id +; + diff --git a/data/nt.zip b/data/nt.zip index 1526b0ccc77fa0a1b37a056b5098dd4b23a12931..263d071608f8de0d358a6870670e2303d730fdce 100644 GIT binary patch delta 3271 zcmZYBc{J4D{|E5FFeyv2PGe`r$BZQ(hHRsxh$JMDk?g`C%g8p=2PHKjjlJxmMm}UP zgOHDEjD0DL!G!EaWJ&tI`~J@NoXdEIl*c|I%8=E{DN%_VTjiU)ic z^t)L+NE46+;~L@EGz}>Cnk(sE6I2u2J+FvOrZzzV#{n>aG(ZL*3y=fI0~7#?040Dj zh1vv%YH>3nNG&=7NbsI61e?69BLENt2myovM*$*$V*pWr7(g5#0gwbpQI>U}v=C9J z8;cj6?WJ_&fnye;Kp+v2G->@3LX5x<;;95q8v+QAJObhZf8_yz{@XpwF|3AD1mmNB zWjWc}9JX(~5D!YoKTv$H@mTB;kLMA?R!oU<%8+bJu>fw8Y#uH4{Ss?`yYTK|q za|1gtyqbkc+*IW|v~6Q@u;0Nt*cg0vPiRL(MTUzk4Uu`>k@%C3cC*pHA*%7dU?L}G z3j5c5pN7Sq`6|bMLYuhSGwCqStFO}?yy2XLN9ozbQ%20fi9XVPMo@cKUv=741 z{zmS6#m9)G9Y<+G?S!nnYb>+H#{lzs$FvFMxVUMuwAr;%QxQg6zt&W<9>d#YB-7Gr zS^Z<_SE1Q$lsX&o_CI5ghWla-$68-Zz;(^;Bx) zkv8Yp!7nRkLOp4aY4vzx!)3R^6LK|AXS8Jl>)dP?#CxkGC2e#sQzh;lcT9>cq0qgo zGFpYDc*z6 z!(9}rSEZR#UC+bmikn&(SLvc8%c-fnv-fG4!;_Fl!UGwC;wN^Dj52c)qr+dE9!XNJ zeOTXrV=B;)O7zz|=RmW}$5mp3^+qqcT17xRcck9zSI-or@K-k(YD``Tk|NRD#mQm2YH)RfKf;)zz7` zwo$rHA0G~y_D%mL+G6}@&-Th2OS!1x022=LOhKf#T|@?tj=BGbua_2tY2hvnu9rH{)c`lql@!=cp9 zVq{BOt#@`lB56~BMdnAYO_XVUbUAiWx6K9>oXC5`YS#Y~$TpPmnn7M}E=6H*1 zMx2Q-khtiyWZSSOJyT#1{QXoa0eBu{9A(viz!W1iw;d^Do)lBqi1#Ut{^M#XJ&S?P z{F}KS=&mhHTwJk+;s17m=~k^kZR(38*}*sRXq`STKFvdLYhF)+4B-qW8Ht&iJ><|o zZV=;xzwW%viTd&hS3*h{{G=s%Hk{-AEmc4I&gr1!Z+>+-R&MKi;z2TfYTkuqjJR1>_=F*()$AXCd@)ELe>rOM}Ocj3J5dyheee3N@jv? zt_FC!P<@(u&iO#Hge5@&_tYsGRvLJTw-Ebk)NP@!?qxUnrmVw@)=uIJg)D_P=hv#P zi9;Om+SEi_yFvXhFz{KY{<4-AgsC}H;x|~uvV+V~au zH>AqCA2`XN8#eEs$b=4e`1D7;qBX0G@IQ?RI9s&PtaLBz3FD0tHu|LNAuo2Yb;P|b zu2H7y!>}48hEO^mcruI=fEJG0YTRKOKM@Whz;f?zuJn6Zl)hZ;A9j^?O;UfNB~tW& z(((2AO`GtQqw}4tDPOwf^5U&Q5B&U3zP0*_gwL>Y+S5O+nqW97A?b&cK1;M(DiKD4 zX^&mOn%tF{2=1sYS*(+!JB`E`$oK@Ml&86c_>&uU2u_z7ku2|q!s9`ho zc!EYhADN!>u(@+LAL2PyCETDJ;wEu0&fd=I>FjKy4Dt@~MGOrim4q=<|14PaTCZWy ztb)?*U}fZq7w!i6G$}JZSHn*oKH@^@MN2#{t3)PGeCjbFU*?#pI8bp4`fa@#8Lib# zhcw~{-GY0sVV|!(9b4kTxvah$k5P^)BhDw`_!zrm@%Uc50hy-HzG<6}MDuXTHancL zquqH1p=t?Ia>4dj2P01A@u!q`A{$6$C&0PWclGyUG!IepImZNZ=J{N0vYPcQQJHdI zzm~j6=&iD!E4;WTNPR}R;PCF}1=B&aiQ5i}5Gvp;IeJ^}HE%CO(U?M#)AAMdiFm9Q z^WF3bdZdThg>K{MzC^XS@}9mk(Z%rS*!k+79k7h|4#Y}qJF5yr{*}^#?gpRLcrCCx zXrL#*+V!agKR3LZe?8>e#3>(^(yiJ)MWs7g&l#zn=U=h6l zZSHQjURv#23^CeLw(pr2wbf-(?kV((i?5r0jp(^o-fxUoKi?&|}>8geKL520kpSmqa|r#2Ez@O2_ql zWuso5r5=!b1@9*_!uq^bzqEhwY*5quAo|a2kj-ZH^p_uhx~jHKYXz`KWol08Sr{~DQGp~GSymhV-CF~5Oif1{Ww6=b25;0~h@D} zXDvwiN6*_V?}ql}*YJJl4EKG#+VspRB|B7RFAI8Wu!@vc;8iOruSi85#u7grp~u>z{|eS=(Y&A;gyUgeoZj-m=d;jh2L6% z8}3OOS%PbVhk(FL;a`S_dLI7Yf;8_8Ba|w58_20BH$;EEpJ&7-{MfLW*?Q9-$@A zh)A%i>9n|A93luRTE&2bK~nz>_*_6=m+(M~v}ub#EByah{qI@$V(9OXEeZaeuu1av z2pBg|7L*-AntSFI>AW4nKt3+bT2iy?U{VAG!fJs)(0}bxl0dA6l6)(m(xg^9gd$KZ z(jT@6X`Z)jP?EVVLjQNMjO~E|Q#O?3Vvo=y$=M+eE6}{}T9Nurnj7#7fNlhx1_}LZ a$-0CM^W&sKTZAg}2_nhbZob&m9KcBze)EX*B*?lU9fW0-Ciw|`4 zU~lFL$Z@GGs=McD!l2T2u{Iq+XPc3{AP^Eo$-M`YAqKo^b3G3H$H(!5IJiE8L7=}E zQZb{!qf;<_iQ~H}qr6&e7xk12Wq*byZR+zoq}Y!vkZ+P?xooy9(_9+o{nshP@)CZH z_;Ytw>*u#`J4-8#le3Lw#P4&AmHV?dzAZ2siQj*GERp~5?Xa`Vyl(^M$#cT^a8r)} zCssk>3o1L8(zxHKeHu)b_f6i||GFk5|M=VFxwAnx6 z^s7wTz|%ct-T~tp19qDmcZwHyUN{m0zYlrMTZV8gbQI;GMes&)2(hoSS}jC~8ctpQ zJ!D(k*R-sC6+P&Lc#fpax?rDp`_oC)%rFc8w1>9NvR#3QvhMee7BP=gegShCD&>YC z<9zO3$A5oQm!Aoak~4U@>OR^&rT4$r1@w(A#W%Fo{X2y`k%%%QF%HYk3oPN)kZ|&G zHE20y^L$eVsUDwYl_~nw)`7!!(Gp)UrZwTQCG-%L^b!sf$K|K z`Re(82eoZnsf7xBC0I-4M+KpR1IWD4Cv`bef(=Zi@&i8Y$NsdFET#5)3WHyAQuW*x zO5awl&Rm$TCth>{-?Bd6p14ao_}EUj2&~D_ zVWF8b<=s2es^ab{dcvQ1Q_K3#C;pxv6t`nG5E?Qe^<;(c|;r5y^ zSH475w)$J61A^-Mr4}#erphnV<7_pNt^*`8O203*geN0o1P%FZ2BLqc7d&Dh>5{*L zwLSO#k9+ZjXBcD*5y^xYmk%rkO^SFH@`QJRTA2_`a^((+9o`yLY^(c--cVvm4K!(S zoov7atHTXoS^TxBuG6<-rI}m>KdwH+uZ0H$ma+a4hEkv8J@}A9MJGb~6Jl($-1|_l zTj$WawLx_;tzVJOAJSg*V9GU$r%+Z(;tZ*Mlx*Jtjy#qgKsPEG!P)zx9_J0S6oXXJGSnh} z((>e`Nl|sl+N#~=JZmN*7ix5egWhl~Pi0)XW?#p=xlr5vQS5_)Aaf%v=9YryfL6J{ zr_--(ym5Bg0}=Y8o6vXPeOH<6!qdk#&1&L^O|r&!Hx-=up4=W^CWUF>n79`PvMp2e z_EQKn*7NFc_rtsymMeW-)ogo6YIg_|uXX|*=6VCMTD6lfvOd;UDN@8t=&X?yZakTv zXGdeG=8luxhkN#>=bNbABYLNGugs=;Mym_eF~W9+v~NYcvcf&MIp8V!fhloUYmP>w z5BjDWi8I_?;{96V(J?1R$#RFcFfne{ed=;LOd7{~a3$$x==0Wl?R3pxE@iRdU3;&7 z-o5j|frqb~k&Dh&GQzn}T@Vfz%jrmcsGl*;^-P-DF#r7-STi_gbPJLAI8$BT0+BtLUO|ef z_P8{vl+7hS4()C~T%)g_Acnx)82rISqqw)|?H$A9g~ilv^Z7G1C54#}HnLW?u5`0G zji|5mbT`+!SaAG}CA+{x7n$samva;hQd+sPntAuJ&-P_SALr{i&zK1OjSPC?UB$$7 z!{3ek(Eqb%Uh34X(^#(yuejiS*Mij<>G2uQPK&6RI^Vg2cSyLYKzy-sPwf$T6MMen z^qmU++8Yl(VjOh`FQq7lv2TsrdDqj__NNBp{?tjXA1kvOsOIhG7UEzRROo-h9M$O< zt=|IM3})4xN806@^j?#Ae@Q^8o#uJ_dt+e^REG(<(^Jwi(vnZ|D z0QuWLhz@G8bCusG9-B;0FxeP6yCR|AGn+gyV&vBbmn|-qvGu&|72$5Voy|iKko*?i zOK^$o^MklC5r_p-eE+?Je!TUEGfB5hCNqBj0kd8&c7OfbMpD?xA><3rz>)AcmG-2L z?&<89*=Ee%-C9q_8!7!`@tt>UwtxGcV%u-DFqe#3@0qTmx*&|JQhs2hPX4`>p@x+L zNCRX5vH&@NJU{^e2PguR0LlPFry3S%&CB<1b!Iq)q9dUCPpJVNfs6qiK>!pW1P}&@ z07L;|fa8D@0C9i>K(cc{2i6nC*^ou~QV-MQf^7qrRA_)DaB##>N*ZB$|6Kb`BWzEE zbKND+@}E9Z2qXdriNHxBfJp={5&=RY93v69Ndz7eftN(!BN6!92?8)3PJ}zkpf 1 + + def import_data(self, dir_, progress=None): + progress = progress if progress is not None else DummyProgress() with self.connect() as con: cur = con.cursor() - for statement in ( - open(os.path.join(os.path.dirname(__file__), '_albion_drop_indexes_and_constrains.sql')) - .read() - .split("\n;\n")[:-1] - ): - cur.execute(statement) cur.execute( """ - copy _albion.collar(id, x, y, z, date_, comments) from '{}' delimiter ';' csv header + copy _albion.hole(id, x, y, z, depth_, date_, comments) from '{}' delimiter ';' csv header """.format( find_in_dir(dir_, "collar") ) @@ -293,29 +354,23 @@ def import_data(self, dir_, progress=None): cur.execute( """ - update _albion.collar set geom=format('SRID=%s;POINTZ(%s %s %s)',m. srid, x, y, z)::geometry - from albion.metadata as m - """ - ) - - cur.execute( - """ - insert into _albion.hole(id, collar_id) select id, id from _albion.collar; - """ + copy _albion.deviation(hole_id, from_, dip, azimuth) from '{}' delimiter ';' csv header + """.format( + find_in_dir(dir_, "devia") + ) ) progress.setPercent(10) cur.execute( """ - copy _albion.deviation(hole_id, from_, dip, azimuth) from '{}' delimiter ';' csv header - """.format( - find_in_dir(dir_, "devia") - ) + update _albion.hole set geom = albion.hole_geom(id) + """ ) progress.setPercent(15) + if find_in_dir(dir_, "avp"): cur.execute( """ @@ -371,100 +426,19 @@ def import_data(self, dir_, progress=None): progress.setPercent(40) - cur.execute( - """ - with dep as ( - select hole_id, max(to_) as mx - from ( - select hole_id, max(to_) as to_ from _albion.radiometry group by hole_id - union all - select hole_id, max(to_) as to_ from _albion.resistivity group by hole_id - union all - select hole_id, max(to_) as to_ from _albion.formation group by hole_id - union all - select hole_id, max(to_) as to_ from _albion.lithology group by hole_id - union all - select hole_id, max(to_) as to_ from _albion.facies group by hole_id - union all - select hole_id, max(from_) as to_ from _albion.deviation group by hole_id - ) as t - group by hole_id - ) - update _albion.hole as h set depth_=d.mx - from dep as d where h.id=d.hole_id - """ - ) - - progress.setPercent(50) - - cur.execute("update albion.hole set geom=albion.hole_geom(id)") - - progress.setPercent(55) - - cur.execute( - "update albion.lithology set geom=albion.hole_piece(from_, to_, hole_id)" - ) - - progress.setPercent(60) - - cur.execute( - "update albion.formation set geom=albion.hole_piece(from_, to_, hole_id)" - ) - - progress.setPercent(65) - - cur.execute( - "update albion.radiometry set geom=albion.hole_piece(from_, to_, hole_id)" - ) - - progress.setPercent(70) - - cur.execute( - "update albion.resistivity set geom=albion.hole_piece(from_, to_, hole_id)" - ) - - progress.setPercent(75) - - cur.execute( - "update albion.facies set geom=albion.hole_piece(from_, to_, hole_id)" - ) - - if find_in_dir(dir_, "mineralization"): - cur.execute( - """ - copy _albion.mineralization(hole_id, level_, from_, to_, oc, accu, grade) from '{}' delimiter ';' csv header - """.format( - find_in_dir(dir_, "mineralization") - ) - ) - - cur.execute( - "update albion.mineralization set geom=albion.hole_piece(from_, to_, hole_id)" - ) - - progress.setPercent(80) - if find_in_dir(dir_, "chemical"): cur.execute( """ copy _albion.chemical(hole_id, from_, to_, num_sample, - element, thickness, gt, grade, equi, comments - ) + element, thickness, gt, grade, equi, comments) from '{}' delimiter ';' csv header """.format( find_in_dir(dir_, "chemical") ) ) - progress.setPercent(90) - + progress.setPercent(45) - for statement in ( - open(os.path.join(os.path.dirname(__file__), '_albion_create_indexes_and_constrains.sql')) - .read() - .split("\n;\n")[:-1] - ): - cur.execute(statement) progress.setPercent(100) @@ -484,16 +458,11 @@ def refresh_all_edge(self): cur.execute("refresh materialized view albion.all_edge") con.commit() - def refresh_radiometry(self): - with self.connect() as con: - cur = con.cursor() - cur.execute("refresh materialized view albion.radiometry_section") - con.commit() - - def refresh_resistivity(self): + def refresh_sections(self): with self.connect() as con: cur = con.cursor() - cur.execute("refresh materialized view albion.resistivity_section") + cur.execute("refresh materialized view albion.radiometry_section_geom_cache") + cur.execute("refresh materialized view albion.resistivity_section_geom_cache") con.commit() def create_sections(self): @@ -669,13 +638,9 @@ def compute_mineralization(self, cutoff, ci, oc): oc=oc, ci=ci, cutoff=cutoff ) ) - cur.execute( - """ - update albion.mineralization set geom=albion.hole_piece(from_, to_, hole_id) - where geom is null - """ - ) + cur.execute("refresh materialized view albion.mineralization_section_geom_cache") con.commit() + def export_obj(self, graph_id, filename): with self.connect() as con: @@ -833,8 +798,8 @@ def create_terminations(self, graph_id): ) cur.execute( """ - insert into albion.end_node(geom, node_id, collar_id, graph_id) - select geom, node_id, collar_id, graph_id + insert into albion.end_node(geom, node_id, hole_id, graph_id) + select geom, node_id, hole_id, graph_id from albion.dynamic_end_node where graph_id='{}' """.format( @@ -944,7 +909,17 @@ def set_section_geom(self, section_id, geom): """ update albion.section set geom=ST_SetSRID('{wkb_hex}'::geometry, {srid}) where id='{id_}' """.format( - srid=srid, wkb_hex=binascii.hexlify(geom.wkb), id_=section_id + srid=srid, wkb_hex=geom.wkb_hex, id_=section_id ) ) con.commit() + + def add_to_graph_node(self, graph, features): + with self.connect() as con: + cur = con.cursor() + cur.executemany( + """ + insert into albion.node(from_, to_, hole_id, graph_id) values(%s, %s, %s, %s) + """, + [(f['from_'], f['to_'], f['hole_id'], graph) for f in features]) + diff --git a/viewer_3d/scene.py b/viewer_3d/scene.py index b5184ec..8dcbb08 100644 --- a/viewer_3d/scene.py +++ b/viewer_3d/scene.py @@ -452,8 +452,7 @@ def update(self, layer): cur.execute(""" select coalesce(st_collect(n.geom), 'GEOMETRYCOLLECTION EMPTY'::geometry) from albion.section as s - join albion.collar as c on st_intersects(s.geom, c.geom) - join albion.hole as h on h.collar_id=c.id + join albion.hole as h on s.geom && h.geom and st_intersects(s.geom, st_startpoint(h.geom)) join albion.node as n on n.hole_id=h.id where n.graph_id='{}' """.format(self.__param["graph_id"]) From 1ca9b8721e25e64ec5cdea8a61d296a0b531c12e Mon Sep 17 00:00:00 2001 From: Vincent Mora Date: Mon, 15 Jul 2019 09:22:26 +0200 Subject: [PATCH 07/42] fix section_polygon (fix #66) --- albion.sql | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/albion.sql b/albion.sql index ebc84b7..e6b1e96 100644 --- a/albion.sql +++ b/albion.sql @@ -1356,19 +1356,17 @@ edge as ( select graph_id, section_id, start_, end_ from albion.edge_section ), poly as ( - select st_union( + select ('SRID=$SRID; POLYGON(('|| st_x(st_startpoint(ns.geom)) ||' '||st_y(st_startpoint(ns.geom))||','|| st_x(st_endpoint(ns.geom)) ||' '||st_y(st_endpoint(ns.geom)) ||','|| st_x(st_endpoint(ne.geom)) ||' '||st_y(st_endpoint(ne.geom)) ||','|| st_x(st_startpoint(ne.geom)) ||' '||st_y(st_startpoint(ne.geom))||','|| st_x(st_startpoint(ns.geom)) ||' '||st_y(st_startpoint(ns.geom))|| - '))')::geometry - ) as geom, e.graph_id, e.section_id + '))')::geometry as geom, e.graph_id, e.section_id from edge as e join node as ns on ns.node_id=e.start_ and ns.section_id=e.section_id join node as ne on ne.node_id=e.end_ and ne.section_id=e.section_id - group by e.graph_id, e.section_id ), term as ( select ('SRID=$SRID; POLYGON(('|| @@ -1381,8 +1379,9 @@ term as ( t.graph_id, t.section_id from albion.end_node_section as t ) -select row_number() over() as id, geom::geometry('POLYGON', $SRID), graph_id, section_id +select row_number() over() as id, st_union(geom)::geometry('MULTIPOLYGON', $SRID) as geom, graph_id, section_id from (select * from poly union all select * from term) as t +group by graph_id, section_id ; create or replace view albion.section_intersection as From be39028afd73efa3fc4a5fde8253462b1576ecdc Mon Sep 17 00:00:00 2001 From: Vincent Mora Date: Mon, 15 Jul 2019 09:44:46 +0200 Subject: [PATCH 08/42] takes into account end_node_relative_distance (fix #49) --- _albion.sql | 4 ++-- albion.sql | 24 ++++++++++++++++++------ 2 files changed, 20 insertions(+), 8 deletions(-) diff --git a/_albion.sql b/_albion.sql index af7f315..c89264d 100644 --- a/_albion.sql +++ b/_albion.sql @@ -32,11 +32,11 @@ create table _albion.metadata( snap_distance real not null default 1, precision real default .01, interpolation interpolation_method default 'balanced_tangential', - end_distance real default 25, end_angle real default 5.0, correlation_distance real default 200, correlation_angle real default 5.0, - parent_correlation_angle real default 1.0) + parent_correlation_angle real default 1.0, + end_node_relative_distance real default .3) ; insert into _albion.metadata(srid) select $SRID diff --git a/albion.sql b/albion.sql index e6b1e96..d239cdf 100644 --- a/albion.sql +++ b/albion.sql @@ -9,6 +9,18 @@ create schema albion -- UTILITY FUNCTIONS ------------------------------------------------------------------------------- + +create function public.st_3dvolume(geom geometry) +return real +language plpgsql immutable +as +$$ + begin + return null; + end; +$$ +; + create or replace function albion.hole_geom(hole_id_ varchar) returns geometry language plpgsql stable @@ -107,7 +119,7 @@ $$ create view albion.collar as select id, st_startpoint(geom) as geom, date_, comments, depth_ from _albion.hole ; -create view albion.metadata as select id, srid, close_collar_distance, snap_distance, precision, interpolation, end_distance, end_angle, correlation_distance, correlation_angle, parent_correlation_angle from _albion.metadata +create view albion.metadata as select id, srid, close_collar_distance, snap_distance, precision, interpolation, end_node_relative_distance, end_angle, correlation_distance, correlation_angle, parent_correlation_angle from _albion.metadata ; create view albion.hole as select id, depth_, geom::geometry('LINESTRINGZ', $SRID) from _albion.hole @@ -1017,7 +1029,7 @@ $$ ; create or replace view albion.volume as -select id, graph_id, cell_id, triangulation +select id, graph_id, cell_id, triangulation, st_volume(triangulation) from _albion.volume ; @@ -1257,7 +1269,7 @@ join _albion.hole as hs on hs.id=ns.hole_id join _albion.hole as he on he.id=ne.hole_id ; -create function albion.end_node_geom(node_geom_ geometry, collar_geom_ geometry) +create function albion.end_node_geom(node_geom_ geometry, collar_geom_ geometry, rel_distance real default .3) returns geometry language plpython3u as @@ -1268,7 +1280,6 @@ $$ from shapely import geos geos.WKBWriter.defaults['include_srid'] = True - REL_DISTANCE = .3 HEIGHT = 1. node_geom = wkb.loads(bytes.fromhex(node_geom_)) @@ -1278,7 +1289,7 @@ $$ center = .5*(node_coords[0] + node_coords[1]) dir = array(collar_geom.coords[0]) - center dir[2] = 0 - dir *= REL_DISTANCE + dir *= rel_distance top = center + dir + array([0,0,.5*HEIGHT]) bottom = center + dir - array([0,0,.5*HEIGHT]) result = LineString([tuple(top), tuple(bottom)]) @@ -1288,10 +1299,11 @@ $$ ; create view albion.dynamic_end_node as -select row_number() over() as id, he.graph_id, n.id as node_id, albion.end_node_geom(n.geom, st_startpoint(h.geom))::geometry('LINESTRINGZ', $SRID) as geom, h.id as hole_id +select row_number() over() as id, he.graph_id, n.id as node_id, albion.end_node_geom(n.geom, st_startpoint(h.geom), m.end_node_relative_distance)::geometry('LINESTRINGZ', $SRID) as geom, h.id as hole_id from albion.half_edge as he join _albion.node as n on n.id=he.node_id join _albion.hole as h on h.id=he.other +join _albion.metadata as m ; From 7477cdb44e81858fb9b286446ddf4ee1a1133d91 Mon Sep 17 00:00:00 2001 From: Vincent Mora Date: Mon, 15 Jul 2019 11:00:20 +0200 Subject: [PATCH 09/42] adds thickness of end node --- _albion.sql | 1 + albion.sql | 12 +++++------- plugin.py | 29 ++++++++++++++++++++++++++--- project.py | 37 +++++++++++++++++++++++++------------ 4 files changed, 57 insertions(+), 22 deletions(-) diff --git a/_albion.sql b/_albion.sql index c89264d..3907f5d 100644 --- a/_albion.sql +++ b/_albion.sql @@ -37,6 +37,7 @@ create table _albion.metadata( correlation_angle real default 5.0, parent_correlation_angle real default 1.0, end_node_relative_distance real default .3) + end_node_thickness real default 1) ; insert into _albion.metadata(srid) select $SRID diff --git a/albion.sql b/albion.sql index d239cdf..10886a8 100644 --- a/albion.sql +++ b/albion.sql @@ -119,7 +119,7 @@ $$ create view albion.collar as select id, st_startpoint(geom) as geom, date_, comments, depth_ from _albion.hole ; -create view albion.metadata as select id, srid, close_collar_distance, snap_distance, precision, interpolation, end_node_relative_distance, end_angle, correlation_distance, correlation_angle, parent_correlation_angle from _albion.metadata +create view albion.metadata as select id, srid, close_collar_distance, snap_distance, precision, interpolation, end_node_relative_distance, end_node_thickness, end_angle, correlation_distance, correlation_angle, parent_correlation_angle from _albion.metadata ; create view albion.hole as select id, depth_, geom::geometry('LINESTRINGZ', $SRID) from _albion.hole @@ -1269,7 +1269,7 @@ join _albion.hole as hs on hs.id=ns.hole_id join _albion.hole as he on he.id=ne.hole_id ; -create function albion.end_node_geom(node_geom_ geometry, collar_geom_ geometry, rel_distance real default .3) +create function albion.end_node_geom(node_geom_ geometry, collar_geom_ geometry, rel_distance real default .3, thickness real default 1) returns geometry language plpython3u as @@ -1280,8 +1280,6 @@ $$ from shapely import geos geos.WKBWriter.defaults['include_srid'] = True - HEIGHT = 1. - node_geom = wkb.loads(bytes.fromhex(node_geom_)) collar_geom = wkb.loads(bytes.fromhex(collar_geom_)) @@ -1290,8 +1288,8 @@ $$ dir = array(collar_geom.coords[0]) - center dir[2] = 0 dir *= rel_distance - top = center + dir + array([0,0,.5*HEIGHT]) - bottom = center + dir - array([0,0,.5*HEIGHT]) + top = center + dir + array([0,0,.5*thickness]) + bottom = center + dir - array([0,0,.5*thickness]) result = LineString([tuple(top), tuple(bottom)]) geos.lgeos.GEOSSetSRID(result._geom, geos.lgeos.GEOSGetSRID(node_geom._geom)) return result.wkb_hex @@ -1299,7 +1297,7 @@ $$ ; create view albion.dynamic_end_node as -select row_number() over() as id, he.graph_id, n.id as node_id, albion.end_node_geom(n.geom, st_startpoint(h.geom), m.end_node_relative_distance)::geometry('LINESTRINGZ', $SRID) as geom, h.id as hole_id +select row_number() over() as id, he.graph_id, n.id as node_id, albion.end_node_geom(n.geom, st_startpoint(h.geom), m.end_node_relative_distance, end_node_thickness)::geometry('LINESTRINGZ', $SRID) as geom, h.id as hole_id from albion.half_edge as he join _albion.node as n on n.id=he.node_id join _albion.hole as h on h.id=he.other diff --git a/plugin.py b/plugin.py index 40b1b72..2b8f668 100644 --- a/plugin.py +++ b/plugin.py @@ -154,9 +154,17 @@ def __create_menu_entries(self): "&Import Data", self.__import_data, self.project is not None, - "Import data from directory. The data files are in ", + "Import data from directory", ) + self.__add_menu_entry( + "&Import selected layer", + self.__import_layer, + self.project is not None, + "Import data from layer.", + ) + + self.__menu.addSeparator() self.__add_menu_entry( @@ -219,6 +227,9 @@ def __create_menu_entries(self): self.__add_menu_entry( "Add selection to graph nodes", self.__add_selection_to_graph_node, self.project is not None ) + self.__add_menu_entry( + "Accept graph possible edges", self.__accept_possible_edge, self.project is not None + ) self.__menu.addSeparator() self.__add_menu_entry( "Create volumes", @@ -472,8 +483,7 @@ def __new_project(self): self.__qgis__project__loaded() def __import_data(self): - if self.project is None: - return + assert(self.project) if not QgsProject.instance().readEntry("albion", "conn_info", "")[0]: return dir_ = QFileDialog.getExistingDirectory( @@ -515,6 +525,14 @@ def __import_data(self): self.__current_section.clear() self.__current_section.addItems(self.project.sections()) + def __import_layer(self): + assert(self.project) + if self.__iface.activeLayer(): + for f in self.__iface.activeLayer().fields(): + print(f) + + + def __new_graph(self): graph, ok = QInputDialog.getText( @@ -559,6 +577,7 @@ def __delete_graph(self): self.__current_graph.removeItem(self.__current_graph.findText(graph)) def __add_selection_to_graph_node(self): + #TODO ADD DIALOG TO REMIND USER THE CURRENT GRAPH if ( self.__iface.activeLayer() @@ -570,6 +589,10 @@ def __add_selection_to_graph_node(self): self.__refresh_layers() + def __accept_possible_edge(self): + assert(false) + #TODO + def __toggle_axis(self): if self.__axis_layer: pass diff --git a/project.py b/project.py index 151c994..a887771 100644 --- a/project.py +++ b/project.py @@ -219,22 +219,35 @@ def create(project_name, srid): ) ) - - for file_ in ("_albion_table.sql", "albion_table.sql"): - for table in TABLES: - for statement in ( - open(os.path.join(os.path.dirname(__file__), file_)) - .read() - .split("\n;\n")[:-1] - ): - table['SRID'] = str(srid) - cur.execute( - string.Template(statement).substitute(table) - ) + for table in TABLES: + table['SRID'] = srid + self.add_table(table) con.commit() return project + + def add_table(self, table): + """ + table: a dict with keys + NAME: the name of the table to create + FIELDS_DEFINITION: the sql definition (name type) of the "additional" fields (i.e. excludes hole_id, from_ and to_) + FIELDS: comma-separated list of the fields names + SRID: the project's SRID + """ + for file_ in ("_albion_table.sql", "albion_table.sql"): + for statement in ( + open(os.path.join(os.path.dirname(__file__), file_)) + .read() + .split("\n;\n")[:-1] + ): + cur.execute( + string.Template(statement).substitute(table) + ) + + # TODO add a list of tables in _albion to be able to restore them on update + + def update(self): "reload schema albion without changing data" with self.connect() as con: From 0a770ec80b6e555e7311ea8adcb3b546ed5106d3 Mon Sep 17 00:00:00 2001 From: Vincent Mora Date: Mon, 15 Jul 2019 15:31:51 +0200 Subject: [PATCH 10/42] import table from a qgis layer that has hole_id, from_ and to_ fields --- plugin.py | 47 +++++++++++++++++++++++++++++++++++++++++++---- project.py | 49 ++++++++++++++++++++++++++++++++++++++----------- 2 files changed, 81 insertions(+), 15 deletions(-) diff --git a/plugin.py b/plugin.py index 2b8f668..0dcdf92 100644 --- a/plugin.py +++ b/plugin.py @@ -528,8 +528,47 @@ def __import_data(self): def __import_layer(self): assert(self.project) if self.__iface.activeLayer(): - for f in self.__iface.activeLayer().fields(): - print(f) + from_idx = None + to_idx = None + hole_id_idx= None + other_idx = [] + definitions = [] + fields = [] + for idx, f in enumerate(self.__iface.activeLayer().fields()): + if f.name().lower() == 'from' or f.name().lower() == 'from_': + from_idx = idx + elif f.name().lower() == 'to' or f.name().lower() == 'to_': + to_idx = idx + elif f.name().lower() == 'hole_id' or f.name().lower() == 'holeid': + hole_id_idx = idx + else: + other_idx.append(idx) + name = f.name().lower().replace(' ', '_') + fields.append(name) + type_ = 'varchar' + if f.typeName() == 'double': + type_ = 'double precision' + elif f.typeName() == 'integer': + type_ = 'integer' + definitions.append(name + ' ' + type_) + + table = { + 'NAME': self.__iface.activeLayer().name().lower().replace(' ', '_'), + 'FIELDS_DEFINITION': ', '.join(definitions), + 'FIELDS': ', '.join(fields), + 'SRID': self.project.srid + } + + if from_idx is None or to_idx is None or hole_id_idx is None: + self.__iface.messageBar().pushCritical( + "Albion", "imported layer must have 'to', 'from' and 'hole_id' fields") + return + + values = [] + for f in self.__iface.activeLayer().getFeatures(): + values.append((f[hole_id_idx], f[from_idx], f[to_idx]) + + tuple((f[i] for i in other_idx))) + self.project.add_table(table, values) @@ -590,8 +629,8 @@ def __add_selection_to_graph_node(self): self.__refresh_layers() def __accept_possible_edge(self): - assert(false) - #TODO + assert(self.project) + self.project.accept_possible_edge(self.__current_graph.currentText()) def __toggle_axis(self): if self.__axis_layer: diff --git a/project.py b/project.py index a887771..b288bc2 100644 --- a/project.py +++ b/project.py @@ -227,23 +227,38 @@ def create(project_name, srid): return project - def add_table(self, table): + def add_table(self, table, values=None): """ table: a dict with keys NAME: the name of the table to create FIELDS_DEFINITION: the sql definition (name type) of the "additional" fields (i.e. excludes hole_id, from_ and to_) - FIELDS: comma-separated list of the fields names + FIELDS: comma-separated list of the fields names, same order as FIELDS_DEFINITION SRID: the project's SRID + values: list of tuples (hole_id, from_, to_, table['FIELDS']) """ - for file_ in ("_albion_table.sql", "albion_table.sql"): - for statement in ( - open(os.path.join(os.path.dirname(__file__), file_)) - .read() - .split("\n;\n")[:-1] - ): - cur.execute( - string.Template(statement).substitute(table) - ) + with self.connect() as con: + cur = con.cursor() + for file_ in ("_albion_table.sql", "albion_table.sql"): + for statement in ( + open(os.path.join(os.path.dirname(__file__), file_)) + .read() + .split("\n;\n")[:-1] + ): + cur.execute( + string.Template(statement).substitute(table) + ) + if values is not None: + table['FORMAT'] = ','.join([' %s' for v in table['FIELDS'].split(',')]) + print(table) + cur.executemany(""" + insert into albion.{NAME}(hole_id, from_, to_, {FIELDS}) + values (%s, %s, %s, {FORMAT}) + """.format(**table), values) + cur.execute(""" + refresh materialized view albion.{NAME}_section_geom_cache + """.format(**table)) + con.commit() + self.vacuum() # TODO add a list of tables in _albion to be able to restore them on update @@ -935,4 +950,16 @@ def add_to_graph_node(self, graph, features): insert into albion.node(from_, to_, hole_id, graph_id) values(%s, %s, %s, %s) """, [(f['from_'], f['to_'], f['hole_id'], graph) for f in features]) + + def accept_possible_edge(self, graph): + with self.connect() as con: + cur = con.cursor() + cur.execute( + """ + insert into albion.edge(start_, end_, graph_id, geom, parent) + select start_, end_, graph_id, geom, parent from albion.possible_edge + where graph_id=%s + """, + (graph,)) + From 0da4a81171b165fe83016711b5327f408d65b73e Mon Sep 17 00:00:00 2001 From: Vincent Mora Date: Mon, 15 Jul 2019 23:35:02 +0200 Subject: [PATCH 11/42] [wip] adds section view and 3D visualization of section --- albion.sql | 46 ++++++++++++++++++++++++++++++++++++ viewer_3d/scene.py | 31 ++++++++++++++++++++---- viewer_3d/viewer_3d.py | 10 ++++++-- viewer_3d/viewer_controls.py | 1 + 4 files changed, 81 insertions(+), 7 deletions(-) diff --git a/albion.sql b/albion.sql index 10886a8..6629038 100644 --- a/albion.sql +++ b/albion.sql @@ -1489,3 +1489,49 @@ from res --'01050000A0787F00000E00000001020000800200000013154A5788BC1341F27E88ADD2A93F41DDC836A48ECB7640F78772A388BC13411BFEBE9FD2A93F41C0A2699C9393764001020000800200000059D97C6C85BC13418A67D48DBAA93F41FF7B08EA919F7640418F5F6685BC1341B0A9D78CBAA93F4178920C2DC58A764001020000800200000013154A5788BC1341F27E88ADD2A93F41DDC836A48ECB7640F78772A388BC13411BFEBE9FD2A93F41C0A2699C939376400102000080020000005E3F399385BC13419833B790BAA93F412744AD66C4EA764050BFC17285BC1341BB98A18EBAA93F4131BD49D291AF764001020000800200000013154A5788BC1341F27E88ADD2A93F41DDC836A48ECB7640F78772A388BC13411BFEBE9FD2A93F41C0A2699C93937640010200008002000000EAF7DBB529BC1341350EF10DD4A93F415EECEAE169E176400A74A55E2ABC1341E896ED28D4A93F4169719E7FAD947640010200008002000000EAF7DBB529BC1341350EF10DD4A93F415EECEAE169E176400A74A55E2ABC1341E896ED28D4A93F4169719E7FAD94764001020000800200000059D97C6C85BC13418A67D48DBAA93F41FF7B08EA919F7640418F5F6685BC1341B0A9D78CBAA93F4178920C2DC58A7640010200008002000000EAF7DBB529BC1341350EF10DD4A93F415EECEAE169E176400A74A55E2ABC1341E896ED28D4A93F4169719E7FAD9476400102000080020000005E3F399385BC13419833B790BAA93F412744AD66C4EA764050BFC17285BC1341BB98A18EBAA93F4131BD49D291AF764001020000800200000056B7652688BC1341EA1D85B9D2A93F41D7DF7D1858F87640E1BD403F88BC13418DABDEB2D2A93F41BFCC2B28C0DE76400102000080020000005E3F399385BC13419833B790BAA93F412744AD66C4EA764050BFC17285BC1341BB98A18EBAA93F4131BD49D291AF764001020000800200000056B7652688BC1341EA1D85B9D2A93F41D7DF7D1858F87640E1BD403F88BC13418DABDEB2D2A93F41BFCC2B28C0DE764001020000800200000042B5BD4C29BC134102FDA4FBD3A93F4171017AF02C16774018C4BC7729BC134173507003D4A93F4124AB1F80CAFF7640'::geometry)) --; +-- collect triangles of neighbor elementary volumes +create or replace function albion.triangle_intersection(t1_ geometry, t2_ geometry) +returns geometry +language plpython3u immutable +as +$$ + from shapely import geos + from shapely.geometry import MultiPolygon, Polygon + from shapely import wkb + import numpy + import plpy + geos.WKBWriter.defaults['include_srid'] = True + t1 = wkb.loads(bytes.fromhex(t1_)) + t2 = wkb.loads(bytes.fromhex(t2_)) + + t1s = set((tuple(t.exterior.coords[0:3]) for t in t1)) + t2s = set((tuple(reversed(t.exterior.coords[0:3])) for t in t2)) + + result = MultiPolygon([ Polygon(t) for t in t1s.intersection(t2s)]) + if not len(result): + return None + geos.lgeos.GEOSSetSRID(result._geom, geos.lgeos.GEOSGetSRID(t1._geom)) + return result.wkb_hex +$$ +; + + +create or replace view albion.volume_section as +with touching_cell as ( + select c.id, st_intersection(s.geom, c.geom) as geom, v.triangulation, s.id as section_id, v.graph_id + from _albion.section as s + join _albion.cell as c on c.geom && s.geom + and st_intersects(c.geom, s.geom) + and st_length(st_intersection(s.geom, c.geom)) > 0 + join _albion.volume as v on v.cell_id = c.id +), +tri as ( + select (st_dump(albion.triangle_intersection(c1.triangulation, c2.triangulation))).geom as geom, c1.section_id, c1.graph_id + from touching_cell as c1 + join touching_cell as c2 on c2.id > c1.id and st_length(st_intersection(c1.geom, c2.geom)) >0 and c1.section_id = c2.section_id and c1.graph_id = c2.graph_id +) +select row_number() over() as id, st_collect(geom)::geometry('MULTIPOLYGONZ', $SRID) as geom, section_id, graph_id +from tri +group by section_id, graph_id +; + diff --git a/viewer_3d/scene.py b/viewer_3d/scene.py index 8dcbb08..04b2a9d 100644 --- a/viewer_3d/scene.py +++ b/viewer_3d/scene.py @@ -53,6 +53,7 @@ def __init__(self, project, param, texture_binder, parent=None): "edge":None, "section":None, "volume":None, + "volume_section":None, "error":None, "end": None, "inconsistency":None} @@ -61,6 +62,7 @@ def __init__(self, project, param, texture_binder, parent=None): "edge":None, "section":None, "volume":None, + "volume_section":None, "error":None, "end":None} @@ -74,6 +76,7 @@ def __init__(self, project, param, texture_binder, parent=None): "end":None} self.nrml = { "volume":None, + "volume_section":None, "error":None} self.__labels = [] @@ -239,6 +242,8 @@ def rendergl(self, leftv, upv, eye, height, context): glDrawElementsui(GL_LINES, a) glEnable(GL_DEPTH_TEST) + if self.__param['section'] != self.__old_param['section']: + self.update('volume_section') # render volume if self.__param["transparency"] > 0.: @@ -260,8 +265,9 @@ def rendergl(self, leftv, upv, eye, height, context): glUseProgram(self.shaders) color = {'volume':[.7,.7,.7,1.], - 'error':[.8,.5,.5,1.]} - for layer in ['volume', 'error']: + 'error':[.8,.5,.5,1.], + 'volume_section':[.7,.7,.7,1.]} + for layer in ['volume', 'volume_section', 'error']: if self.__useProgram: glUniform4fv(self.shaders_color_location, 1, color[layer]) glUniform1f(self.shaders_transp_location, self.__param["transparency"]) @@ -514,6 +520,21 @@ def update(self, layer): self.idx[layer] = numpy.require(numpy.arange(len(self.vtx[layer])).reshape((-1,3)), numpy.int32, 'C') self.nrml[layer] = computeNormals(self.vtx[layer], self.idx[layer]) + elif layer=='volume_section': + cur.execute(""" + select geom + from albion.volume_section + where graph_id='{}' + """.format(self.__param["graph_id"])) + geom = wkb.loads(bytes.fromhex(cur.fetchone()[0])) + self.vtx[layer] = numpy.require(numpy.array([tri.exterior.coords[:-1] for tri in geom]).reshape((-1,3)), numpy.float32, 'C') + if len(self.vtx[layer]): + self.vtx[layer] += self.__offset + self.vtx[layer][:,2] *= self.__param["z_scale"] + self.idx[layer] = numpy.require(numpy.arange(len(self.vtx[layer])).reshape((-1,3)), numpy.int32, 'C') + self.nrml[layer] = computeNormals(self.vtx[layer], self.idx[layer]) + + elif layer=='error': cur.execute(""" select st_collectionhomogenize(coalesce(st_collect(triangulation), 'GEOMETRYCOLLECTION EMPTY'::geometry)) @@ -532,7 +553,7 @@ def update(self, layer): self.__old_param[layer] = self.__param[layer] def setGraph(self, graph_id): - for layer in ['node', 'edge', 'volume', 'section', 'error', 'end']: + for layer in ['node', 'edge', 'volume', 'volume_section', 'section', 'error', 'end']: if self.__param[layer] != self.__old_param[layer]: self.update(layer) self.__old_param["graph_id"] = graph_id @@ -541,10 +562,10 @@ def setGraph(self, graph_id): def setZscale(self, scale): factor = float(scale)/self.__old_param["z_scale"] - for layer in ['node', 'edge', 'volume', 'section', 'error', 'end']: + for layer in ['node', 'edge', 'volume', 'volume_section', 'section', 'error', 'end']: if self.vtx[layer] is not None: self.vtx[layer][:,2] *= factor - if layer in ['volume', 'error']: + if layer in ['volume', 'volume_section', 'error']: self.nrml[layer] = computeNormals(self.vtx[layer], self.idx[layer]) for scatter in self.__labels: diff --git a/viewer_3d/viewer_3d.py b/viewer_3d/viewer_3d.py index 581bf5d..cce118a 100644 --- a/viewer_3d/viewer_3d.py +++ b/viewer_3d/viewer_3d.py @@ -34,6 +34,7 @@ def __init__(self, project=None, parent=None): "end": False, "edge": False, "volume": False, + "volume_section": True, "error": False, "section": False, "z_scale": 1, @@ -54,7 +55,7 @@ def __init__(self, project=None, parent=None): def refresh_data(self): if self.scene and self.__project.has_collar: self.resetScene(self.__project, False) - for layer in ['node', 'edge', 'volume', 'section', 'error', 'end']: + for layer in ['node', 'edge', 'volume', 'volume_section', 'section', 'error', 'end']: self.scene.update(layer) self.update() @@ -68,7 +69,7 @@ def resetScene(self, project, resetCamera=True): self.camera = Camera(eye, at) if self.__param['graph_id']: - for layer in ['node', 'edge', 'volume', 'section', 'error', 'end']: + for layer in ['node', 'edge', 'volume', 'volume_section', 'section', 'error', 'end']: self.scene.update(layer) self.update() else: @@ -113,6 +114,11 @@ def toggle_volumes(self, state): self.__param["volume"] = state self.update() + def toggle_volumes_section(self, state): + self.__param["volume_section"] = state + self.update() + + def toggle_errors(self, state): self.__param["error"] = state self.update() diff --git a/viewer_3d/viewer_controls.py b/viewer_3d/viewer_controls.py index 3e58541..8e1a267 100644 --- a/viewer_3d/viewer_controls.py +++ b/viewer_3d/viewer_controls.py @@ -21,6 +21,7 @@ def __init__(self, viewer, iface=None, parent=None): ('edges', self.__viewer.toggle_edges, True), ('ends', self.__viewer.toggle_ends, True), ('volumes', self.__viewer.toggle_volumes, False), + ('volumes sections', self.__viewer.toggle_volumes_section, True), ('errors', self.__viewer.toggle_errors, False), ]: a = menu.addAction(l) From 5c0a65782fecfacec80082d9f887a8bd353e1bf3 Mon Sep 17 00:00:00 2001 From: Vincent Mora Date: Tue, 16 Jul 2019 08:12:52 +0200 Subject: [PATCH 12/42] visualize 3D sections --- plugin.py | 3 +++ viewer_3d/scene.py | 48 +++++++++++++++++++++++++++++++--------------- 2 files changed, 36 insertions(+), 15 deletions(-) diff --git a/plugin.py b/plugin.py index 0dcdf92..4b92616 100644 --- a/plugin.py +++ b/plugin.py @@ -318,6 +318,7 @@ def __next_section(self): self.project.next_section(self.__current_section.currentText()) self.__refresh_layers("section") self.__viewer3d.widget().scene.update("section") + self.__viewer3d.widget().scene.update("volume_section") self.__viewer3d.widget().update() def __previous_section(self): @@ -326,6 +327,7 @@ def __previous_section(self): self.project.previous_section(self.__current_section.currentText()) self.__refresh_layers("section") self.__viewer3d.widget().scene.update("section") + self.__viewer3d.widget().scene.update("volume_section") self.__viewer3d.widget().update() def __refresh_layers(self, name=None, updateExtent=False): @@ -846,6 +848,7 @@ def align(l): self.project.set_section_geom(self.__current_section.currentText(), line) self.__refresh_layers("section") self.__viewer3d.widget().scene.update("section") + self.__viewer3d.widget().scene.update("volume_section") self.__viewer3d.widget().update() def open_help(self): diff --git a/viewer_3d/scene.py b/viewer_3d/scene.py index 04b2a9d..69d404b 100644 --- a/viewer_3d/scene.py +++ b/viewer_3d/scene.py @@ -138,14 +138,6 @@ def compileShaders(self): gl_FragColor.rgb = mix(vec3(0.0), Idiff.xyz, edgeFactor()); gl_FragColor.a = 1. - uTransparency; - //if(any(lessThan(vBC, vec3(0.02)))){ - // gl_FragColor = vec4(0.0, 0.0, 0.0, 1.0); - //} - //else{ - // gl_FragColor = Idiff; - //} - //gl_FragColor = vec4(vBC.xyz, 1);//Idiff; - //gl_FragColor = Idiff; } """, GL_FRAGMENT_SHADER) @@ -242,9 +234,6 @@ def rendergl(self, leftv, upv, eye, height, context): glDrawElementsui(GL_LINES, a) glEnable(GL_DEPTH_TEST) - if self.__param['section'] != self.__old_param['section']: - self.update('volume_section') - # render volume if self.__param["transparency"] > 0.: glDisable(GL_DEPTH_TEST) @@ -265,9 +254,8 @@ def rendergl(self, leftv, upv, eye, height, context): glUseProgram(self.shaders) color = {'volume':[.7,.7,.7,1.], - 'error':[.8,.5,.5,1.], - 'volume_section':[.7,.7,.7,1.]} - for layer in ['volume', 'volume_section', 'error']: + 'error':[.8,.5,.5,1.]} + for layer in ['volume', 'error']: if self.__useProgram: glUniform4fv(self.shaders_color_location, 1, color[layer]) glUniform1f(self.shaders_transp_location, self.__param["transparency"]) @@ -299,6 +287,36 @@ def rendergl(self, leftv, upv, eye, height, context): if self.__useProgram: glUseProgram(0) + layer='volume_section' + if self.__param[layer]: + if self.__param[layer] != self.__old_param[layer]: + self.update(layer) + if self.vtx[layer] is not None and len(self.vtx[layer]): + glEnable(GL_COLOR_MATERIAL) + glDisable(GL_TEXTURE_2D) + glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, [7., 4., 4., 1.]) + glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, [7., 4., 4., 1.]) + glColor4f(.7, .4, .4, 1.) + glVertexPointerf(self.vtx[layer]) + glDisableClientState(GL_COLOR_ARRAY) + glDisable(GL_CULL_FACE) + glPolygonMode(GL_FRONT_AND_BACK, GL_FILL) + glNormalPointerf(self.nrml[layer]) + glDrawElementsui(GL_TRIANGLES, self.idx[layer]) + #if not self.__useProgram: + # glDisable(GL_LIGHTING) + # glDisableClientState(GL_COLOR_ARRAY) + # glColor4f(.1, .1, .1, 1.) + # glLineWidth(2) + # glEnable(GL_CULL_FACE) + # glPolygonMode(GL_FRONT,GL_LINE) + # glDrawElementsui(GL_TRIANGLES, self.idx[layer]) + # glPolygonMode(GL_FRONT,GL_FILL) + # glDisable(GL_CULL_FACE) + # glEnableClientState(GL_COLOR_ARRAY) + # glEnable(GL_LIGHTING) + glDisable(GL_COLOR_MATERIAL) + # current section, highlight nodes glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, [1., 1., 0., 1.]) glDisableClientState(GL_COLOR_ARRAY) @@ -522,7 +540,7 @@ def update(self, layer): elif layer=='volume_section': cur.execute(""" - select geom + select st_collectionhomogenize(st_collect(geom)) from albion.volume_section where graph_id='{}' """.format(self.__param["graph_id"])) From 25b828eae7ac5c4cd0ef4e4df448c223777cf2fd Mon Sep 17 00:00:00 2001 From: Vincent Mora Date: Fri, 2 Aug 2019 08:09:12 +0200 Subject: [PATCH 13/42] refacto --- _albion.sql | 41 +++--- albion.sql | 287 ++++++++++++++++++++++++++++++----------- albion_table.sql | 51 ++++++-- plugin.py | 176 ++++++++++++------------- project.py | 139 ++++++-------------- viewer_3d/scene.py | 2 +- viewer_3d/viewer_3d.py | 4 +- 7 files changed, 395 insertions(+), 305 deletions(-) diff --git a/_albion.sql b/_albion.sql index 3907f5d..9a02f4a 100644 --- a/_albion.sql +++ b/_albion.sql @@ -36,7 +36,7 @@ create table _albion.metadata( correlation_distance real default 200, correlation_angle real default 5.0, parent_correlation_angle real default 1.0, - end_node_relative_distance real default .3) + end_node_relative_distance real default .3, end_node_thickness real default 1) ; @@ -74,7 +74,7 @@ create table _albion.deviation( ------------------------------------------------------------------------------- create table _albion.node( - id varchar primary key, + id varchar primary key default _albion.unique_id()::varchar, graph_id varchar not null references _albion.graph(id) on delete cascade on update cascade, unique(id, graph_id), hole_id varchar references _albion.hole(id) on delete cascade, @@ -94,11 +94,8 @@ create index node_graph_id_idx on _albion.node(graph_id) create index node_hole_id_idx on _albion.node(hole_id) ; -alter table _albion.node alter column id set default _albion.unique_id()::varchar -; - create table _albion.edge( - id varchar primary key, + id varchar primary key default _albion.unique_id()::varchar, start_ varchar not null , foreign key (graph_id, start_) references _albion.node(graph_id, id) on delete cascade on update cascade, end_ varchar not null, @@ -122,11 +119,8 @@ create index edge_start__idx on _albion.edge(start_) create index edge_end__idx on _albion.edge(end_) ; -alter table _albion.edge alter column id set default _albion.unique_id()::varchar -; - create table _albion.cell( - id varchar primary key, + id varchar primary key default _albion.unique_id()::varchar, a varchar not null references _albion.hole(id) on delete cascade on update cascade, b varchar not null references _albion.hole(id) on delete cascade on update cascade, c varchar not null references _albion.hole(id) on delete cascade on update cascade, @@ -146,28 +140,21 @@ create index volume_cell_b_idx on _albion.cell(b) create index volume_cell_c_idx on _albion.cell(c) ; -alter table _albion.cell alter column id set default _albion.unique_id()::varchar -; - create table _albion.group( id integer primary key ) ; create table _albion.section( - id varchar primary key, + id varchar primary key default _albion.unique_id()::varchar, anchor geometry('LINESTRING', $SRID) not null check(st_numpoints(anchor)=2), - geom geometry('LINESTRING', $SRID) not null, - scale real not null default 1, - group_id integer references _albion.group(id) on delete set null on update cascade + geom geometry('MULTILINESTRING', $SRID) not null, + scale real not null default 1 ) ; -alter table _albion.section alter column id set default _albion.unique_id()::varchar -; - create table _albion.volume( - id varchar primary key, + id varchar primary key default _albion.unique_id()::varchar, graph_id varchar not null references _albion.graph(id) on delete cascade on update cascade, cell_id varchar not null references _albion.cell(id) on delete cascade on update cascade, triangulation geometry('MULTIPOLYGONZ', $SRID) not null @@ -179,9 +166,6 @@ create index volume_graph_id_idx on _albion.volume(graph_id) create index volume_cell_id_idx on _albion.volume(cell_id) ; -alter table _albion.volume alter column id set default _albion.unique_id()::varchar -; - create table _albion.group_cell( group_id integer not null references _albion.group(id) on delete cascade on update cascade, cell_id varchar not null references _albion.cell(id) on delete cascade on update cascade, @@ -198,7 +182,7 @@ create index group_cell_groupe_id_idx on _albion.group_cell(group_id) create table _albion.end_node( - id varchar primary key, + id varchar primary key default _albion.unique_id()::varchar, geom geometry('LINESTRINGZ', $SRID) not null check (st_numpoints(geom)=2), node_id varchar not null references _albion.node(id) on delete cascade on update cascade, hole_id varchar not null references _albion.hole(id) on delete cascade on update cascade, @@ -209,6 +193,11 @@ create table _albion.end_node( create index end_node_geom_idx on _albion.end_node using gist(geom) ; -alter table _albion.end_node alter column id set default _albion.unique_id()::varchar +create table _albion.named_section( + id varchar primary key default _albion.unique_id()::varchar, + geom geometry('LINESTRING', $SRID) not null, + cut geometry('MULTILINESTRING', $SRID) not null, + section varchar references _albion.section(id) not null +) ; diff --git a/albion.sql b/albion.sql index 6629038..201a55f 100644 --- a/albion.sql +++ b/albion.sql @@ -11,7 +11,7 @@ create schema albion create function public.st_3dvolume(geom geometry) -return real +returns real language plpgsql immutable as $$ @@ -116,9 +116,48 @@ $$ $$ ; -create view albion.collar as select id, st_startpoint(geom) as geom, date_, comments, depth_ from _albion.hole +create or replace view albion.collar as select id, st_startpoint(geom)::geometry('POINTZ', $SRID) as geom, date_, comments, depth_ from _albion.hole +; + +alter view albion.collar alter id set default _albion.unique_id()::varchar ; +create or replace function albion.collar_instead_fct() +returns trigger +language plpgsql +as +$$ + begin + if tg_op in ('INSERT', 'UPDATE') then + new.date_ := coalesce(new.date_, now()::date::varchar); + end if; + + if tg_op = 'INSERT' then + insert into _albion.hole(id, date_, depth_, x, y, z, comments) + values(new.id, new.date_, new.depth_, st_x(new.geom), st_y(new.geom), st_z(new.geom), new.comments) + returning id into new.id; + update _albion.hole set geom = albion.hole_geom(new.id) where id=new.id; + return new; + elsif tg_op = 'UPDATE' then + update _albion.hole set id=new.id, date_=new.date_, depth_=new.depth_, x=st_x(new.geom), y=st_y(new.geom), z=st_z(new.geom), comments=new.comments + where id=old.id; + update _albion.hole set geom = albion.hole_geom(new.id) where id=new.id; + return new; + elsif tg_op = 'DELETE' then + delete from _albion.collar where id=old.id; + return old; + end if; + end; +$$ +; + +create trigger collar_instead_trig + instead of insert or update or delete on albion.collar + for each row execute procedure albion.collar_instead_fct() +; + + + create view albion.metadata as select id, srid, close_collar_distance, snap_distance, precision, interpolation, end_node_relative_distance, end_node_thickness, end_angle, correlation_distance, correlation_angle, parent_correlation_angle from _albion.metadata ; @@ -191,6 +230,26 @@ where a.id != b.id and st_dwithin(a.geom, b.geom, m.close_collar_distance) create view albion.cell as select id, a, b, c, geom::geometry('POLYGON', $SRID) from _albion.cell ; +create or replace function albion.tesselate(polygon_ geometry, lines_ geometry, points_ geometry) +returns geometry +language plpython3u volatile +as +$$ + from shapely import wkb + from shapely import geos + geos.WKBWriter.defaults['include_srid'] = True + from fourmy import tessellate + + polygon = wkb.loads(bytes.fromhex(polygon_)) + lines = wkb.loads(bytes.fromhex(lines_)) if lines_ else None + points = wkb.loads(bytes.fromhex(points_)) if points_ else None + result = tessellate(polygon, lines, points) + + geos.lgeos.GEOSSetSRID(result._geom, geos.lgeos.GEOSGetSRID(polygon._geom)) + return result.wkb_hex +$$ +; + create or replace function albion.triangulate() returns integer language plpgsql volatile @@ -237,39 +296,6 @@ $$ $$ ; --- contour of the cells that face the line -create or replace function albion.first_section(anchor geometry) -returns geometry -language plpgsql stable -as -$$ - begin - return ( - with hull as ( - select st_exteriorring(st_unaryunion(st_collect(geom))) as geom from _albion.cell - ), - seg as ( - select ST_PointN(geom, generate_series(1, ST_NPoints(geom)-1)) as sp, ST_PointN(geom, generate_series(2, ST_NPoints(geom) )) as ep - from hull - ), - facing as ( - select st_force2d(st_makeline(sp, ep)) as geom - from seg - where -albion.cos_angle(anchor, sp, ep) > cos(60*pi()/180) - ), - merged as ( - select st_linemerge(st_collect(geom)) as geom from facing - ), - sorted as ( - select rank() over(order by st_length(geom) desc) as rk, geom - from (select (st_dump(geom)).geom from merged) as t - ) - select geom from sorted where rk=1 - ); - end; -$$ -; - create or replace function albion.is_touchingrightside(line geometry, poly geometry) returns boolean language plpgsql immutable @@ -402,7 +428,7 @@ $$ $$ ; -create view albion.section as select id, scale, group_id, anchor::geometry('LINESTRING', $SRID), geom::geometry('LINESTRING', $SRID) +create view albion.section as select id, scale, anchor::geometry('LINESTRING', $SRID), geom::geometry('MULTILINESTRING', $SRID) from _albion.section ; @@ -419,12 +445,12 @@ as $$ begin if tg_op = 'INSERT' then - insert into _albion.section(id, anchor, geom, scale, group_id) - values(new.id, new.anchor, coalesce(new.geom, albion.first_section(new.anchor)), new.scale, new.group_id) + insert into _albion.section(id, anchor, geom, scale) + values(new.id, new.anchor, new.geom, new.scale) returning id, geom into new.id, new.geom; return new; elsif tg_op = 'UPDATE' then - update _albion.section set id=new.id, anchor=new.anchor, geom=new.geom, scale=new.scale, group_id=new.group_id + update _albion.section set id=new.id, anchor=new.anchor, geom=new.geom, scale=new.scale where id=old.id; return new; elsif tg_op = 'DELETE' then @@ -491,40 +517,6 @@ create trigger group_cell_instead_trig for each row execute procedure albion.group_cell_instead_fct() ; --- create view albion.current_section as --- with hull as ( --- select st_unaryunion(st_collect(c.geom)) as geom, gc.section_id --- from _albion.cell as c --- join _albion.group_cell as gc on gc.cell_id=c.id --- group by gc.section_id --- ), --- hull_contour as ( --- select st_exteriorring(geom) as geom, section_id from hull --- ), --- seg as ( --- select ST_PointN(geom, generate_series(1, ST_NPoints(geom)-1)) as sp, ST_PointN(geom, generate_series(2, ST_NPoints(geom) )) as ep, section_id --- from hull_contour --- ), --- facing as ( --- select st_force2d(st_makeline(seg.sp, seg.ep)) as geom, seg.section_id --- from seg join _albion.section as s on s.id = seg.section_id --- where albion.cos_angle(s.anchor, seg.sp, seg.ep) > cos(89*pi()/180) --- ), --- merged as ( --- select st_linemerge(st_collect(facing.geom)) as geom, section_id --- from facing join _albion.section as s on s.id = facing.section_id --- group by section_id, s.geom --- ), --- sorted as ( --- select rank() over(partition by section_id order by st_length(geom) desc) as rk, geom, section_id --- from (select (st_dump(geom)).geom, section_id from merged) as t --- ) --- select section_id as id, st_reverse(geom)::geometry('LINESTRING', $SRID) as geom from sorted where rk=1 --- union all --- select s.id, (albion.first_section(s.anchor))::geometry('LINESTRING', $SRID) as geom from albion.section as s --- where not exists (select 1 from sorted as st where st.section_id=s.id) --- ; - create or replace function albion.to_section(geom geometry, anchor geometry, z_scale real) returns geometry language plpython3u immutable @@ -1029,7 +1021,7 @@ $$ ; create or replace view albion.volume as -select id, graph_id, cell_id, triangulation, st_volume(triangulation) +select id, graph_id, cell_id, triangulation, st_3dvolume(triangulation) as volume from _albion.volume ; @@ -1301,7 +1293,7 @@ select row_number() over() as id, he.graph_id, n.id as node_id, albion.end_node_ from albion.half_edge as he join _albion.node as n on n.id=he.node_id join _albion.hole as h on h.id=he.other -join _albion.metadata as m +join _albion.metadata as m on 't' ; @@ -1535,3 +1527,148 @@ from tri group by section_id, graph_id ; + +create or replace view albion.named_section as +select s.id, s.geom, s.section, rank() over (partition by section order by st_distance(s.geom, a.anchor)) as rank_, s.cut +from _albion.named_section as s +join _albion.section as a on s.section = a.id +; + +create or replace function albion.named_section_instead_fct() +returns trigger +language plpgsql +as +$$ + begin + if tg_op in ('INSERT', 'UPDATE') then + new.id := coalesce(new.id, _albion.unique_id()::varchar); + new.cut := coalesce(new.cut, ( + with geom as ( + select st_dumppoints(new.geom) as pt + ), + segment as ( + select st_makeline(lag((pt).geom) over (order by (pt).path), (pt).geom) as geom from geom + ), + filtered as ( + select geom from segment as s + except + select s.geom from segment as s + join _albion.named_section as o + on st_intersects(o.cut, s.geom) + and st_linelocatepoint(s.geom, st_intersection(o.cut, s.geom)) not in (0.0, 1.0) + and st_geometrytype(st_intersection(o.cut, s.geom)) = 'ST_Point' + ) + select st_multi(st_linemerge(st_collect(geom))) from filtered + )); + end if; + + + if tg_op = 'INSERT' then + insert into _albion.named_section(id, geom, cut, section) + values(new.id, new.geom, new.cut, new.section) + returning id into new.id; + return new; + elsif tg_op = 'UPDATE' then + update _albion.named_section set id=new.id, geom=new.geom, cut=new.cut, section=new.section + where id=old.id; + return new; + elsif tg_op = 'DELETE' then + delete from _albion.named_section where id=old.id; + return old; + end if; + end; +$$ +; + +create trigger named_section_instead_trig + instead of insert or update or delete on albion.named_section + for each row execute procedure albion.named_section_instead_fct() +; + + +create or replace function albion.next_section(section_ varchar) +returns geometry +language plpgsql stable +as +$$ + begin + return ( + select n.cut + from albion.named_section as n + join albion.section as s on s.id=n.section + where s.id=section_ and st_distance(n.cut, s.anchor) > st_distance(s.geom, s.anchor) + order by st_distance(n.cut, s.anchor) asc + limit 1 + ); + end; +$$ +; + +create or replace function albion.previous_section(section_ varchar) +returns geometry +language plpgsql stable +as +$$ + begin + return ( + select n.cut + from albion.named_section as n + join albion.section as s on s.id=n.section + where s.id=section_ and st_distance(n.cut, s.anchor) < st_distance(s.geom, s.anchor) + order by st_distance(n.cut, s.anchor) desc + limit 1 + ); + end; +$$ +; + + + + +with dc as ( + select +), +d ( + select n.section, n.cut as geom, st_distance(n.cut, s.anchor) as dist + from albion.named_section as n + join albion.section as s on s.id=n.section + where not n.cut=s.geom +), +f as ( + select d.section, d.geom, rank() over (partition by d.section order by d.dist) + where dist - st_s +; + + +create view albion.previous_section as +select n.section as id, n.cut as geom +from albion.named_section as n +join albion.section as s on s.id=n.section +where not n.cut=s.geom +partition by n.section +order by st_distance(s.anchor, n.geom) - st_distance(s.anchor, s.geom) desc +limit 1 +; + + +-- TODO +-- [x] ajout de collar stérile (avec note) +-- [ ] polygone de maillage convex hull ou un trou +-- supprimer des cellules et les edges associés + +-- Methode +-- import des collar et deviations dans répertoire + option data to_ from_ +-- calcul des minéralisations +-- ajout de collar stériles flmaggés (verticaux) +-- creation des sections nommées +-- triangulation +-- effacer des cellules +-- creation de graph + + + +/* +select (st_dumppoints(st_intersection(a.geom, b.geom))).geom as geom from albion.named_section as a join albion.named_section as b on st_intersects(a.geom, b.geom) and a.id > b.id +except +select st_force2d(geom) as geom from albion.collar +*/ diff --git a/albion_table.sql b/albion_table.sql index 42cb495..4d40d89 100644 --- a/albion_table.sql +++ b/albion_table.sql @@ -1,16 +1,49 @@ create view albion.${NAME} as -select id, hole_id, from_, to_, ${FIELDS} from _albion.${NAME} +select t.id, t.hole_id, t.from_, t.to_, st_startpoint(h.geom)::geometry('POINTZ', ${SRID}) as geom, ${T_FIELDS} +from _albion.${NAME} as t +join _albion.hole as h on h.id = t.hole_id +; + +alter view albion.${NAME} alter column id set default _albion.unique_id() +; + +create or replace function albion.${NAME}_instead_fct() +returns trigger +language plpgsql +as +$$$$ + begin + if tg_op = 'INSERT' then + insert into _albion.${NAME}(id, hole_id, from_, to_, ${FIELDS}) + values(new.id, new.hole_id, new.from_, new.to_, ${NEW_FIELDS}) + returning id into new.id; + return new; + elsif tg_op = 'UPDATE' then + update _albion.${NAME} set id=new.id, hole_id=new.hole_id, from_=new.from_, to_=new.to_, ${SET_FIELDS} + where id=old.id; + return new; + elsif tg_op = 'DELETE' then + delete from _albion.${NAME} where id=old.id; + return old; + end if; + end; +$$$$ +; + +create trigger ${NAME}_instead_trig + instead of insert or update or delete on albion.${NAME} + for each row execute procedure albion.${NAME}_instead_fct() ; create materialized view albion.${NAME}_section_geom_cache as -select s.id as section_id, h.id as hole_id, r.id as ${NAME}_id, +select s.id as section_id, h.id as hole_id, t.id as ${NAME}_id, (albion.to_section( - st_makeline(st_3dlineinterpolatepoint(h.geom, least(r.from_/h.depth_, 1)), - st_3dlineinterpolatepoint(h.geom, least(r.to_/h.depth_, 1))) + st_makeline(st_3dlineinterpolatepoint(h.geom, least(t.from_/h.depth_, 1)), + st_3dlineinterpolatepoint(h.geom, least(t.to_/h.depth_, 1))) , s.anchor, s.scale)) as geom, st_startpoint(h.geom) as collar -from _albion.section as s, _albion.${NAME} as r -join _albion.hole as h on h.id=r.hole_id +from _albion.section as s, _albion.${NAME} as t +join _albion.hole as h on h.id=t.hole_id ; create index ${NAME}_section_geom_cache_${NAME}_id_idx on albion.${NAME}_section_geom_cache(${NAME}_id) @@ -21,9 +54,9 @@ create index ${NAME}_section_geom_cache_colar_idx on albion.${NAME}_section_geom create view albion.${NAME}_section as -select row_number() over() as id, r.id as ${NAME}_id, sc.section_id, r.hole_id, sc.geom::geometry('LINESTRING', ${SRID}), ${FIELDS} -from _albion.${NAME} as r -join albion.${NAME}_section_geom_cache as sc on sc.${NAME}_id = r.id +select row_number() over() as id, t.id as ${NAME}_id, sc.section_id, t.hole_id, sc.geom::geometry('LINESTRING', ${SRID}), ${T_FIELDS} +from _albion.${NAME} as t +join albion.${NAME}_section_geom_cache as sc on sc.${NAME}_id = t.id join _albion.section as s on st_intersects(s.geom, sc.collar) and sc.section_id = s.id ; diff --git a/plugin.py b/plugin.py index 4b92616..8da0378 100644 --- a/plugin.py +++ b/plugin.py @@ -69,6 +69,7 @@ def initGui(self): (Qt.CTRL + Qt.ALT + Qt.Key_S, self.__select_next_group), (Qt.CTRL + Qt.ALT + Qt.Key_N, self.__next_section), (Qt.CTRL + Qt.ALT + Qt.Key_B, self.__previous_section), + (Qt.CTRL + Qt.ALT + Qt.Key_M, self.__add_section_from_selection), ): short = QShortcut(QKeySequence(keyseq), self.__iface.mainWindow()) @@ -143,121 +144,113 @@ def __add_menu_entry(self, name, callback, enabled=True, help_str=""): return act def __create_menu_entries(self): + self.__menu.clear() + self.__add_menu_entry("New &Project", self.__new_project) + self.__add_menu_entry("Import Project", self.__import_project) + + self.__add_menu_entry("Export Project", self.__export_project, self.project is not None) + self.__add_menu_entry("Upgrade Project", self.__upgrade_project) self.__menu.addSeparator() self.__add_menu_entry( - "&Import Data", + "&Import directory", self.__import_data, self.project is not None, - "Import data from directory", + "Import data from directory" ) self.__add_menu_entry( - "&Import selected layer", - self.__import_layer, + "&Import holes", + None, #self.__import_holes, self.project is not None, - "Import data from layer.", + "Import hole data from directory" ) - - self.__menu.addSeparator() - self.__add_menu_entry( - "Create cells", - self.__create_cells, - self.project is not None and self.project.has_collar, - "Create Delaunay triangulation of collar layer.", + "Export holes", + None, #self.__export_holes, + self.project is not None ) self.__add_menu_entry( - "Refresh all edges", - self.__refresh_all_edge, - self.project is not None and self.project.has_cell, - "Refresh materialized view of all cell edges used by graph possible edges.", + "Import layer", + self.__import_layer, + self.project is not None, + "Import data from selected layer." ) self.__add_menu_entry( - "Refresh sections", - self.__refresh_sections, - self.project is not None, - "Refresh materialized views (can take some time).", + "Export layer", + None, #self.__export_layer, + self.project is not None ) + self.__add_menu_entry( + "Compute &Mineralization", + self.__compute_mineralization, + self.project is not None and self.project.has_radiometry, + "", + ) self.__menu.addSeparator() - # self.__add_menu_entry(u'Create section views 0° and 90°', self.__create_section_view_0_90, - # False and self.project is not None and self.project.has_hole, - # "Create section views (i.e. cut directions) to work West-East and South-North for this project") - # self.__add_menu_entry(u'Create section views -45° and 45°', None, - # False and self.project is not None and self.project.has_hole, - # "Create section views (i.e. cut directions) to work SE-NW and SW-NE for this project") - # - # self.__menu.addSeparator() + self.__menu.addSeparator() self.__add_menu_entry( - "Create sections", + "Create sections (to be removed)", self.__create_sections, self.project is not None and self.project.has_group_cell, "Once cell groups have been defined, create section lines.", ) - self.__menu.addSeparator() - self.__add_menu_entry( - "Compute &Mineralization", - self.__compute_mineralization, - self.project is not None and self.project.has_radiometry, - "", + "Create cells", + self.__create_cells, + self.project is not None and self.project.has_hole, + "Create Delaunay triangulation of collar layer.", ) + self.__menu.addSeparator() + self.__add_menu_entry( "New &Graph", self.__new_graph, self.project is not None, - "Create a new grap.h", + "Create a new graph", ) + self.__add_menu_entry( "Delete Graph", self.__delete_graph, self.project is not None ) + self.__add_menu_entry( "Add selection to graph nodes", self.__add_selection_to_graph_node, self.project is not None ) + self.__add_menu_entry( "Accept graph possible edges", self.__accept_possible_edge, self.project is not None ) - self.__menu.addSeparator() - self.__add_menu_entry( - "Create volumes", - self.__create_volumes, - self.project is not None and bool(self.__current_graph.currentText()), - "Create volumes associated with current graph.", - ) - self.__menu.addSeparator() + self.__add_menu_entry( "Create terminations", self.__create_terminations, self.project is not None and bool(self.__current_graph.currentText()), "Create terminations associated with current graph.", ) - self.__menu.addSeparator() - self.__add_menu_entry("Toggle axis", self.__toggle_axis) self.__menu.addSeparator() - + self.__add_menu_entry( - "Export Project", self.__export_project, self.project is not None - ) - self.__add_menu_entry( - "Export Sections", - None, - self.project is not None and self.project.has_section, - "Export triangulated section in .obj or .dxf format", + "Create volumes", + self.__create_volumes, + self.project is not None and bool(self.__current_graph.currentText()), + "Create volumes associated with current graph.", ) + self.__add_menu_entry( "Export Volume", self.__export_volume, @@ -272,6 +265,17 @@ def __create_menu_entries(self): "Export an elementary volume of current graph in .obj or .dxf format", ) + self.__add_menu_entry( + "Export Sections", + None, #self.__export_sections + self.project is not None and self.project.has_section, + "Export triangulated section in .obj or .dxf format", + ) + + self.__menu.addSeparator() + + self.__add_menu_entry("Toggle axis", self.__toggle_axis) + self.__menu.addSeparator() self.__menu.addAction("Help").triggered.connect(self.open_help) @@ -290,31 +294,16 @@ def __getattr__(self, name): else: raise AttributeError(name) - def __refresh_all_edge(self): - if self.project is None: - return - self.project.refresh_all_edge() - - def __refresh_sections(self): - if self.project: - self.project.refresh_sections() - def __create_terminations(self): - if self.project is None: - return self.project.create_terminations(self.__current_graph.currentText()) self.__viewer3d.widget().refresh_data() self.__refresh_layers("section") def __create_volumes(self): - if self.project is None: - return self.project.create_volumes(self.__current_graph.currentText()) self.__viewer3d.widget().refresh_data() def __next_section(self): - if self.project is None: - return self.project.next_section(self.__current_section.currentText()) self.__refresh_layers("section") self.__viewer3d.widget().scene.update("section") @@ -322,8 +311,6 @@ def __next_section(self): self.__viewer3d.widget().update() def __previous_section(self): - if self.project is None: - return self.project.previous_section(self.__current_section.currentText()) self.__refresh_layers("section") self.__viewer3d.widget().scene.update("section") @@ -352,8 +339,7 @@ def __current_section_changed(self, section_id): def __select_next_group(self): if ( - self.project - and self.__iface.activeLayer() + self.__iface.activeLayer() and self.__iface.activeLayer().name() == u"cell" ): self.__iface.activeLayer().removeSelection() @@ -363,8 +349,7 @@ def __select_next_group(self): def __create_group(self): if ( - self.project - and self.__iface.activeLayer() + self.__iface.activeLayer() and self.__iface.activeLayer().name() == u"cell" ): if self.__iface.activeLayer().selectedFeatureCount(): @@ -475,6 +460,7 @@ def __new_project(self): open(resource("template_project.qgs")) .read() .replace("template_project", project_name) + .replace("32632", str(srid)) ) self.__iface.newProject() QgsProject.instance().setFileName(fil) @@ -616,8 +602,10 @@ def __delete_graph(self): return self.__current_graph.removeItem(self.__current_graph.findText(graph)) + self.project.delete_graph(graph) def __add_selection_to_graph_node(self): + assert(self.project) #TODO ADD DIALOG TO REMIND USER THE CURRENT GRAPH if ( @@ -647,22 +635,19 @@ def __toggle_axis(self): self.__refresh_layers() def __create_cells(self): - if self.project is None: - return + assert(self.project) self.project.triangulate() self.__refresh_layers("cells") def __create_sections(self): - if self.project is None: - return + assert(self.project) self.project.create_sections() def __compute_mineralization(self): MineralizationDialog(self.project).exec_() def __export_volume(self): - if self.project is None: - return + assert(self.project) fil, __ = QFileDialog.getSaveFileName( None, @@ -685,8 +670,7 @@ def __export_volume(self): ) def __export_elementary_volume(self): - if self.project is None: - return + assert(self.project) layer = self.__layer("cell") if not layer: @@ -774,11 +758,6 @@ def __export_project(self): os.path.split(QgsProject.instance().fileName())[1], ) - def __create_section_view_0_90(self): - if self.project is None: - return - self.project.create_section_view_0_90() - def __log_strati_clicked(self): # @todo switch behavior when in section view -> ortho self.__click_tool = QgsMapToolEmitPoint(self.__iface.mapCanvas()) @@ -809,10 +788,7 @@ def __map_log_clicked(self, point, button): self.__log_strati.show() self.__log_strati.raise_() - def __section_from_selection(self): - if self.project is None: - return - + def __line_from_selection(self): if ( self.__iface.activeLayer() and self.__iface.activeLayer().name() == u"collar" @@ -845,6 +821,22 @@ def align(l): align(numpy.array([f.geometry().asPoint() for f in selection])) ) collar.removeSelection() + return line + else: + return None + + def __add_section_from_selection(self): + assert(self.project) + line = self.__line_from_selection() + if line: + self.project.add_named_section(self.__current_section.currentText(), line) + self.__refresh_layers("named_section") + + + def __section_from_selection(self): + assert(self.project) + line = self.__line_from_selection() + if line: self.project.set_section_geom(self.__current_section.currentText(), line) self.__refresh_layers("section") self.__viewer3d.widget().scene.update("section") diff --git a/project.py b/project.py index b288bc2..197ea74 100644 --- a/project.py +++ b/project.py @@ -62,31 +62,24 @@ def cursor(self, *args, **kwargs): TABLES = [ {'NAME': 'radiometry', 'FIELDS_DEFINITION': 'gamma real', - 'FIELDS': 'gamma', }, {'NAME': 'resistivity', 'FIELDS_DEFINITION': 'rho real', - 'FIELDS': 'rho', }, {'NAME': 'formation', 'FIELDS_DEFINITION': 'code integer, comments varchar', - 'FIELDS': 'code, comments', }, {'NAME': 'lithology', 'FIELDS_DEFINITION': 'code integer, comments varchar', - 'FIELDS': 'code, comments', }, {'NAME': 'facies', 'FIELDS_DEFINITION': 'code integer, comments varchar', - 'FIELDS': 'code, comments', }, {'NAME': 'chemical', 'FIELDS_DEFINITION': 'num_sample varchar, element varchar, thickness real, gt real, grade real, equi real, comments varchar', - 'FIELDS': 'num_sample, element, thickness, gt, grade, equi, comments', }, {'NAME': 'mineralization', 'FIELDS_DEFINITION': 'level_ real, oc real, accu real, grade real, comments varchar', - 'FIELDS': 'level_, oc, accu, grade, comments' }] @@ -218,12 +211,12 @@ def create(project_name, srid): "$INCLUDE_ELEMENTARY_VOLUME", include_elementary_volume ) ) + con.commit() - for table in TABLES: - table['SRID'] = srid - self.add_table(table) + for table in TABLES: + table['SRID'] = srid + project.add_table(table) - con.commit() return project @@ -232,10 +225,16 @@ def add_table(self, table, values=None): table: a dict with keys NAME: the name of the table to create FIELDS_DEFINITION: the sql definition (name type) of the "additional" fields (i.e. excludes hole_id, from_ and to_) - FIELDS: comma-separated list of the fields names, same order as FIELDS_DEFINITION SRID: the project's SRID - values: list of tuples (hole_id, from_, to_, table['FIELDS']) + values: list of tuples (hole_id, from_, to_, ...) """ + + fields = [f.split()[0].strip() for f in table['FIELDS_DEFINITION'].split(',')] + table['FIELDS'] = ', '.join(fields) + table['T_FIELDS'] = ', '.join(['t.{}'.format(f.replace(' ', '')) for f in fields]) + table['FORMAT'] = ','.join([' %s' for v in fields]) + table['NEW_FIELDS'] = ','.join(['new.{}'.format(v) for v in fields]) + table['SET_FIELDS'] = ','.join(['{}=new.{}'.format(v,v) for v in fields]) with self.connect() as con: cur = con.cursor() for file_ in ("_albion_table.sql", "albion_table.sql"): @@ -248,15 +247,14 @@ def add_table(self, table, values=None): string.Template(statement).substitute(table) ) if values is not None: - table['FORMAT'] = ','.join([' %s' for v in table['FIELDS'].split(',')]) print(table) cur.executemany(""" insert into albion.{NAME}(hole_id, from_, to_, {FIELDS}) values (%s, %s, %s, {FORMAT}) """.format(**table), values) - cur.execute(""" - refresh materialized view albion.{NAME}_section_geom_cache - """.format(**table)) + cur.execute(""" + refresh materialized view albion.{NAME}_section_geom_cache + """.format(**table)) con.commit() self.vacuum() @@ -306,9 +304,7 @@ def __srid(self): return srid def __getattr__(self, name): - if name == "has_collar": - return self.__has_collar() - elif name == "has_hole": + if name == "has_hole": return self.__has_hole() elif name == "has_section": return self.__has_section() @@ -331,12 +327,6 @@ def __has_cell(self): cur.execute("select count(1) from albion.cell") return cur.fetchone()[0] > 1 - def __has_collar(self): - with self.connect() as con: - cur = con.cursor() - cur.execute("select count(1) from albion.collar") - return cur.fetchone()[0] > 1 - def __has_hole(self): with self.connect() as con: cur = con.cursor() @@ -478,21 +468,9 @@ def triangulate(self): with self.connect() as con: cur = con.cursor() cur.execute("select albion.triangulate()") - con.commit() - - def refresh_all_edge(self): - with self.connect() as con: - cur = con.cursor() cur.execute("refresh materialized view albion.all_edge") con.commit() - def refresh_sections(self): - with self.connect() as con: - cur = con.cursor() - cur.execute("refresh materialized view albion.radiometry_section_geom_cache") - cur.execute("refresh materialized view albion.resistivity_section_geom_cache") - con.commit() - def create_sections(self): with self.connect() as con: cur = con.cursor() @@ -522,7 +500,7 @@ def new_graph(self, graph, parent=None): cur.execute("insert into albion.graph(id) values ('{}');".format(graph)) con.commit() - def delete_graph(self): + def delete_graph(self, graph): with self.connect() as con: cur = con.cursor() cur.execute("delete from albion.graph cascade where id='{}';".format(graph)) @@ -534,38 +512,8 @@ def previous_section(self, section): cur = con.cursor() cur.execute( """ - select group_id from albion.section where id='{}' - """.format( - section - ) - ) - group, = cur.fetchone() - group = group or 0 - cur.execute( - """ - select group_id, geom from albion.section_geom - where section_id='{section}' - and group_id < {group} - order by group_id desc - limit 1 - """.format( - group=group, section=section - ) - ) - res = cur.fetchone() - if res: - sql = """ - update albion.section set group_id={}, geom='{}'::geometry where id='{}' - """.format( - res[0], res[1], section - ) - else: - sql = """ - update albion.section set group_id=null, geom=albion.first_section(anchor) where id='{}' - """.format( - section - ) - cur.execute(sql) + update albion.section set geom=coalesce(albion.previous_section(%s), geom) where id=%s + """, (section, section)) con.commit() def next_section(self, section): @@ -575,33 +523,9 @@ def next_section(self, section): cur = con.cursor() cur.execute( """ - select group_id from albion.section where id='{}' - """.format( - section - ) - ) - group, = cur.fetchone() - group = group or 0 - cur.execute( - """ - select group_id, geom from albion.section_geom - where section_id='{section}' - and group_id > {group} - order by group_id asc - limit 1 - """.format( - group=group, section=section - ) - ) - res = cur.fetchone() - if res: - sql = """ - update albion.section set group_id={}, geom='{}'::geometry where id='{}' - """.format( - res[0], res[1], section - ) - cur.execute(sql) - con.commit() + update albion.section set geom=coalesce(albion.next_section(%s), geom) where id=%s + """, (section, section)) + con.commit() def next_group_ids(self): with self.connect() as con: @@ -917,7 +841,7 @@ def closest_hole_id(self, x, y): if not res: cur.execute( """ - select hole_id from albion.current_hole_section + select hole_id from albion.hole_section where st_dwithin(geom, 'SRID={srid} ;POINT({x} {y})'::geometry, 25) order by st_distance('SRID={srid} ;POINT({x} {y})'::geometry, geom) limit 1""".format( @@ -928,6 +852,21 @@ def closest_hole_id(self, x, y): return res[0] if res else None + def add_named_section(self, section_id, geom): + with self.connect() as con: + cur = con.cursor() + cur.execute("select srid from albion.metadata") + srid, = cur.fetchone() + cur.execute( + """ + insert into albion.named_section(geom, section) + values (ST_SetSRID('{wkb_hex}'::geometry, {srid}), '{section_id}') + """.format( + srid=srid, wkb_hex=geom.wkb_hex, section_id=section_id + ) + ) + con.commit() + def set_section_geom(self, section_id, geom): with self.connect() as con: cur = con.cursor() @@ -935,7 +874,7 @@ def set_section_geom(self, section_id, geom): srid, = cur.fetchone() cur.execute( """ - update albion.section set geom=ST_SetSRID('{wkb_hex}'::geometry, {srid}) where id='{id_}' + update albion.section set geom=st_multi(ST_SetSRID('{wkb_hex}'::geometry, {srid})) where id='{id_}' """.format( srid=srid, wkb_hex=geom.wkb_hex, id_=section_id ) diff --git a/viewer_3d/scene.py b/viewer_3d/scene.py index 69d404b..d7679b5 100644 --- a/viewer_3d/scene.py +++ b/viewer_3d/scene.py @@ -540,7 +540,7 @@ def update(self, layer): elif layer=='volume_section': cur.execute(""" - select st_collectionhomogenize(st_collect(geom)) + select st_collectionhomogenize(coalesce(st_collect(geom), 'GEOMETRYCOLLECTION EMPTY'::geometry)) from albion.volume_section where graph_id='{}' """.format(self.__param["graph_id"])) diff --git a/viewer_3d/viewer_3d.py b/viewer_3d/viewer_3d.py index cce118a..590aac6 100644 --- a/viewer_3d/viewer_3d.py +++ b/viewer_3d/viewer_3d.py @@ -53,14 +53,14 @@ def __init__(self, project=None, parent=None): self.previous_pick = None def refresh_data(self): - if self.scene and self.__project.has_collar: + if self.scene and self.__project.has_hole: self.resetScene(self.__project, False) for layer in ['node', 'edge', 'volume', 'volume_section', 'section', 'error', 'end']: self.scene.update(layer) self.update() def resetScene(self, project, resetCamera=True): - if project and project.has_collar: + if project and project.has_hole: self.scene = Scene(project, self.__param, self.bindTexture, self) if resetCamera: at = self.scene.center From c0c32d9e67ab6b3da91081b3d2d5a8a8bf6addb9 Mon Sep 17 00:00:00 2001 From: Vincent Mora Date: Fri, 2 Aug 2019 08:11:26 +0200 Subject: [PATCH 14/42] fixup --- albion.sql | 39 +-------------------------------------- 1 file changed, 1 insertion(+), 38 deletions(-) diff --git a/albion.sql b/albion.sql index 201a55f..79654f2 100644 --- a/albion.sql +++ b/albion.sql @@ -467,17 +467,6 @@ create trigger section_instead_trig ; -create or replace function albion.next_group() -returns integer -language plpgsql stable -as -$$ - begin - return (select coalesce(max(id), 0) + 1 from _albion.group); - end; -$$ -; - create view albion.group as select id from _albion.group ; @@ -1623,33 +1612,7 @@ $$ ; - - -with dc as ( - select -), -d ( - select n.section, n.cut as geom, st_distance(n.cut, s.anchor) as dist - from albion.named_section as n - join albion.section as s on s.id=n.section - where not n.cut=s.geom -), -f as ( - select d.section, d.geom, rank() over (partition by d.section order by d.dist) - where dist - st_s -; - - -create view albion.previous_section as -select n.section as id, n.cut as geom -from albion.named_section as n -join albion.section as s on s.id=n.section -where not n.cut=s.geom -partition by n.section -order by st_distance(s.anchor, n.geom) - st_distance(s.anchor, s.geom) desc -limit 1 -; - +--SELECT row_number() over () AS _uid_,* FROM (select albion.tesselate(st_convexhull((select st_collect(st_force2d(geom)) from albion.collar)), st_multi((select st_collectionhomogenize(st_collect(cut)) from albion.named_section)), st_multi((select st_collect(st_force2d(geom)) from albion.collar))) as geom -- TODO -- [x] ajout de collar stérile (avec note) From b301d76cb7ad4c59c9b155d64419c7d15edb073b Mon Sep 17 00:00:00 2001 From: Vincent Mora Date: Thu, 22 Aug 2019 16:32:10 +0200 Subject: [PATCH 15/42] adds icons --- res/next_line_big.svg | 81 +++++++++++++++++++++++++++++++++++++++ res/previous_line_big.svg | 81 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 162 insertions(+) create mode 100644 res/next_line_big.svg create mode 100644 res/previous_line_big.svg diff --git a/res/next_line_big.svg b/res/next_line_big.svg new file mode 100644 index 0000000..fe34c3c --- /dev/null +++ b/res/next_line_big.svg @@ -0,0 +1,81 @@ + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + diff --git a/res/previous_line_big.svg b/res/previous_line_big.svg new file mode 100644 index 0000000..dba587c --- /dev/null +++ b/res/previous_line_big.svg @@ -0,0 +1,81 @@ + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + From 012ba8342ccbd0c025300777274f840f5b228342 Mon Sep 17 00:00:00 2001 From: Vincent Mora Date: Thu, 22 Aug 2019 17:58:42 +0200 Subject: [PATCH 16/42] restores mandala and integrates with named sections --- albion.sql | 84 ++++++++++++++++++++++++----------- plugin.py | 71 ++++++++++++++++++++---------- project.py | 93 +++++++++++++++++++++++++++++++++------ test/parent_graph_test.py | 12 ++--- 4 files changed, 190 insertions(+), 70 deletions(-) diff --git a/albion.sql b/albion.sql index 79654f2..7fcf8eb 100644 --- a/albion.sql +++ b/albion.sql @@ -223,7 +223,7 @@ create trigger node_instead_trig create or replace view albion.close_collar as -select a.id, a.geom from albion.collar as a, albion.collar as b, _albion.metadata as m +select distinct on (a.id) a.id, a.geom from albion.collar as a, albion.collar as b, _albion.metadata as m where a.id != b.id and st_dwithin(a.geom, b.geom, m.close_collar_distance) ; @@ -259,7 +259,11 @@ $$ delete from _albion.cell; insert into _albion.cell(a, b, c, geom) with cell as ( - select ST_DelaunayTriangles(ST_Collect(ST_Force2D(geom))) as geom from albion.collar + select albion.tesselate( + st_convexhull((select st_collect(st_force2d(geom)) from albion.collar)), + st_multi((select st_collectionhomogenize(st_collect(cut)) from albion.named_section)), + st_multi((select st_collect(st_force2d(geom)) from albion.collar)) + ) as geom ), splt as ( select (ST_Dump(geom)).geom from cell @@ -271,6 +275,8 @@ $$ s.geom from splt as s; + refresh materialized view albion.all_edge; + return (select count(1) from _albion.cell); end; $$ @@ -361,7 +367,7 @@ select albion.is_touchingrightside('LINESTRING(327627.06 2079630.27,327229.65 20 ; --- triangle is visible if points are on the line, or by removing the trinagle edge that touch +-- polygon is visible if points are on the line, or by removing the edge that touches -- the line, the line of sight from anchor to point doesn't cross the line create or replace function albion.is_visible(anchor geometry, section geometry, poly geometry) returns boolean @@ -372,24 +378,30 @@ $$ nb_visible integer; ring geometry; occluder geometry; + point_on_poly geometry; line_od_sight geometry; begin nb_visible := 0; ring := st_exteriorring(poly); - for i in 1..st_numpoints(ring) loop - if st_intersects(section, st_pointn(ring, i)) then - nb_visible := nb_visible + 1; - else - occluder := coalesce(occluder, st_difference(section, ring)); - line_od_sight := st_makeline(st_closestpoint(anchor, st_pointn(ring, i)), st_pointn(ring, i)); - --raise notice 'occluder %', st_astext(occluder); - --raise notice 'los %', st_astext(line_od_sight); - if not st_intersects(line_od_sight, occluder) then + occluder := st_difference(section, ring); + if occluder is not null then + for i in 1..st_numpoints(ring) loop + if st_intersects(section, st_pointn(ring, i)) then nb_visible := nb_visible + 1; + else + line_od_sight := st_makeline(st_closestpoint(anchor, st_pointn(ring, i)), st_pointn(ring, i)); + --raise notice 'occluder %', st_astext(occluder); + --raise notice 'los %', st_astext(line_od_sight); + if not st_intersects(line_od_sight, occluder) then + nb_visible := nb_visible + 1; + end if; end if; - end if; - end loop; - return nb_visible = st_numpoints(ring); + end loop; + end if; + -- we also check that the line between a point on surface and the anchor crosses the section (we are looking "away" from anchor) + point_on_poly := st_pointonsurface(poly); + line_od_sight := st_makeline(st_closestpoint(anchor, point_on_poly), point_on_poly); + return nb_visible = st_numpoints(ring) and st_intersects(line_od_sight, section); end; $$ ; @@ -471,9 +483,6 @@ create view albion.group as select id from _albion.group ; -alter view albion.group alter column id set default albion.next_group() -; - create view albion.group_cell as select gc.section_id || ' ' || gc.cell_id as id, gc.cell_id, c.geom, gc.group_id, gc.section_id from _albion.cell as c @@ -618,13 +627,13 @@ $$ begin return ( with hull as ( - select st_unaryunion(st_collect(c.geom)) as geom + select st_multi(st_unaryunion(st_collect(c.geom))) as geom from _albion.cell as c join _albion.group_cell as gc on gc.cell_id=c.id where gc.section_id=section_id_ and gc.group_id <= group_id_ ), hull_contour as ( - select st_exteriorring(geom) as geom from hull + select st_exteriorring(geom) as geom from (select (st_dump(geom)).geom from hull) as t ), seg as ( select ST_PointN(geom, generate_series(1, ST_NPoints(geom)-1)) as sp, ST_PointN(geom, generate_series(2, ST_NPoints(geom) )) as ep @@ -1250,15 +1259,17 @@ join _albion.hole as hs on hs.id=ns.hole_id join _albion.hole as he on he.id=ne.hole_id ; -create function albion.end_node_geom(node_geom_ geometry, collar_geom_ geometry, rel_distance real default .3, thickness real default 1) +create or replace function albion.end_node_geom(node_geom_ geometry, collar_geom_ geometry, rel_distance real default .3, thickness real default 1, nx real default null, ny real default null, nz real default null) returns geometry language plpython3u as $$ from numpy import array + from numpy import cross from shapely import wkb from shapely.geometry import LineString from shapely import geos + from math import sqrt geos.WKBWriter.defaults['include_srid'] = True node_geom = wkb.loads(bytes.fromhex(node_geom_)) @@ -1269,20 +1280,44 @@ $$ dir = array(collar_geom.coords[0]) - center dir[2] = 0 dir *= rel_distance + dir = cross(array([nx, ny, nz]), cross(dir, array([0,0,1]))) top = center + dir + array([0,0,.5*thickness]) bottom = center + dir - array([0,0,.5*thickness]) result = LineString([tuple(top), tuple(bottom)]) + geos.lgeos.GEOSSetSRID(result._geom, geos.lgeos.GEOSGetSRID(node_geom._geom)) return result.wkb_hex $$ ; -create view albion.dynamic_end_node as -select row_number() over() as id, he.graph_id, n.id as node_id, albion.end_node_geom(n.geom, st_startpoint(h.geom), m.end_node_relative_distance, end_node_thickness)::geometry('LINESTRINGZ', $SRID) as geom, h.id as hole_id +create or replace view albion.normal as +select e.id, e.start_, e.end_, + - (st_x(st_endpoint(geom)) - st_x(st_startpoint(geom))) * ((st_z(st_endpoint(geom)) - st_z(st_startpoint(geom)))) as nx, + - (st_y(st_endpoint(geom)) - st_y(st_startpoint(geom))) * ((st_z(st_endpoint(geom)) - st_z(st_startpoint(geom)))) as ny, + (st_x(st_endpoint(geom)) - st_x(st_startpoint(geom)))^2 + ((st_y(st_endpoint(geom)) - st_y(st_startpoint(geom))))^2 as nz, + (180/pi())*atan(abs(st_z(st_endpoint(geom)) - st_z(st_startpoint(geom)))/st_length(geom)) as angl +from _albion.edge as e +; + +create or replace view albion.average_normal as +with nrml as ( + select avg(nx) as nx, avg(ny) as ny, avg(nz) as nz, n.id + from _albion.node as n + left join albion.normal as e on e.start_=n.id or e.end_=n.id + group by n.id +) +select id, coalesce(nx/sqrt(nx^2+ny^2+nz^2), 0) as nx, coalesce(ny/sqrt(nx^2+ny^2+nz^2), 0) as ny, coalesce(nz/sqrt(nx^2+ny^2+nz^2), 1) as nz +from nrml +; + + +create or replace view albion.dynamic_end_node as +select row_number() over() as id, he.graph_id, n.id as node_id, albion.end_node_geom(n.geom, st_startpoint(h.geom), m.end_node_relative_distance, end_node_thickness, nrml.nx::real, nrml.ny::real, nrml.nz::real)::geometry('LINESTRINGZ', $SRID) as geom, h.id as hole_id from albion.half_edge as he join _albion.node as n on n.id=he.node_id join _albion.hole as h on h.id=he.other join _albion.metadata as m on 't' +join albion.average_normal as nrml on nrml.id = coalesce(n.parent, n.id); ; @@ -1612,11 +1647,10 @@ $$ ; ---SELECT row_number() over () AS _uid_,* FROM (select albion.tesselate(st_convexhull((select st_collect(st_force2d(geom)) from albion.collar)), st_multi((select st_collectionhomogenize(st_collect(cut)) from albion.named_section)), st_multi((select st_collect(st_force2d(geom)) from albion.collar))) as geom -- TODO -- [x] ajout de collar stérile (avec note) --- [ ] polygone de maillage convex hull ou un trou +-- [x] polygone de maillage convex hull ou un trou -- supprimer des cellules et les edges associés -- Methode diff --git a/plugin.py b/plugin.py index 8da0378..ad2f84f 100644 --- a/plugin.py +++ b/plugin.py @@ -66,7 +66,7 @@ def initGui(self): for keyseq, slot in ( (Qt.CTRL + Qt.ALT + Qt.Key_K, self.__create_group), - (Qt.CTRL + Qt.ALT + Qt.Key_S, self.__select_next_group), +# (Qt.CTRL + Qt.ALT + Qt.Key_S, self.__select_next_group), (Qt.CTRL + Qt.ALT + Qt.Key_N, self.__next_section), (Qt.CTRL + Qt.ALT + Qt.Key_B, self.__previous_section), (Qt.CTRL + Qt.ALT + Qt.Key_M, self.__add_section_from_selection), @@ -99,13 +99,23 @@ def initGui(self): ) self.__toolbar.addAction( - icon("previous_line.svg"), "previous section (Ctrl+Alt+b)" + icon("previous_line_big.svg"), "previous section (Ctrl+Alt+b)" ).triggered.connect(self.__previous_section) + + self.__toolbar.addAction( + icon("previous_line.svg"), "previous sub section" + ).triggered.connect(self.__previous_subsection) + self.__toolbar.addAction( - icon("next_line.svg"), "next section (Ctrl+Alt+n)" + icon("next_line.svg"), "next sub section" + ).triggered.connect(self.__next_subsection) + + self.__toolbar.addAction( + icon("next_line_big.svg"), "next section (Ctrl+Alt+n)" ).triggered.connect(self.__next_section) + self.__toolbar.addAction( icon("line_from_selected.svg"), "create temporary section" ).triggered.connect(self.__section_from_selection) @@ -200,12 +210,12 @@ def __create_menu_entries(self): self.__menu.addSeparator() - self.__add_menu_entry( - "Create sections (to be removed)", - self.__create_sections, - self.project is not None and self.project.has_group_cell, - "Once cell groups have been defined, create section lines.", - ) +# self.__add_menu_entry( +# "Create sections (to be removed)", +# self.__create_sections, +# self.project is not None and self.project.has_group_cell, +# "Once cell groups have been defined, create section lines.", +# ) self.__add_menu_entry( "Create cells", @@ -317,6 +327,21 @@ def __previous_section(self): self.__viewer3d.widget().scene.update("volume_section") self.__viewer3d.widget().update() + def __next_subsection(self): + self.project.next_subsection(self.__current_section.currentText()) + self.__refresh_layers("section") + self.__viewer3d.widget().scene.update("section") + self.__viewer3d.widget().scene.update("volume_section") + self.__viewer3d.widget().update() + + def __previous_subsection(self): + self.project.previous_subsection(self.__current_section.currentText()) + self.__refresh_layers("section") + self.__viewer3d.widget().scene.update("section") + self.__viewer3d.widget().scene.update("volume_section") + self.__viewer3d.widget().update() + + def __refresh_layers(self, name=None, updateExtent=False): for layer in self.__iface.mapCanvas().layers(): if name is None or layer.name().find(name) != -1: @@ -332,21 +357,21 @@ def __layer(self, name): return lay def __current_section_changed(self, section_id): - layers = QgsProject.instance().mapLayersByName(u"group_cell") - if len(layers): - layers[0].setSubsetString("section_id='{}'".format(section_id)) + #layers = QgsProject.instance().mapLayersByName(u"group_cell") + #if len(layers): + # layers[0].setSubsetString("section_id='{}'".format(section_id)) self.__refresh_layers("section") - def __select_next_group(self): - if ( - self.__iface.activeLayer() - and self.__iface.activeLayer().name() == u"cell" - ): - self.__iface.activeLayer().removeSelection() - self.__iface.activeLayer().selectByExpression( - "id in ({})".format(",".join(project.next_group_ids())) - ) - +# def __select_next_group(self): +# if ( +# self.__iface.activeLayer() +# and self.__iface.activeLayer().name() == u"cell" +# ): +# self.__iface.activeLayer().removeSelection() +# self.__iface.activeLayer().selectByExpression( +# "id in ({})".format(",".join(project.next_group_ids())) +# ) +# def __create_group(self): if ( self.__iface.activeLayer() @@ -637,7 +662,7 @@ def __toggle_axis(self): def __create_cells(self): assert(self.project) self.project.triangulate() - self.__refresh_layers("cells") + self.__refresh_layers("cell") def __create_sections(self): assert(self.project) diff --git a/project.py b/project.py index 197ea74..b4f523b 100644 --- a/project.py +++ b/project.py @@ -308,8 +308,8 @@ def __getattr__(self, name): return self.__has_hole() elif name == "has_section": return self.__has_section() - elif name == "has_group_cell": - return self.__has_group_cell() +# elif name == "has_group_cell": +# return self.__has_group_cell() elif name == "has_radiometry": return self.__has_radiometry() elif name == "has_cell": @@ -339,11 +339,11 @@ def __has_section(self): cur.execute("select count(1) from albion.section_geom") return cur.fetchone()[0] > 1 - def __has_group_cell(self): - with self.connect() as con: - cur = con.cursor() - cur.execute("select count(1) from albion.group_cell") - return cur.fetchone()[0] > 1 +# def __has_group_cell(self): +# with self.connect() as con: +# cur = con.cursor() +# cur.execute("select count(1) from albion.group_cell") +# return cur.fetchone()[0] > 1 def __has_radiometry(self): with self.connect() as con: @@ -468,7 +468,6 @@ def triangulate(self): with self.connect() as con: cur = con.cursor() cur.execute("select albion.triangulate()") - cur.execute("refresh materialized view albion.all_edge") con.commit() def create_sections(self): @@ -527,18 +526,84 @@ def next_section(self, section): """, (section, section)) con.commit() - def next_group_ids(self): + def next_subsection(self, section): with self.connect() as con: cur = con.cursor() cur.execute( """ - select cell_id from albion.next_group where section_id='{}' - """.format( - self.__current_section.currentText() - ) + select sg.group_id + from albion.section_geom sg + join albion.section s on s.id=sg.section_id + where s.id='{section}' + order by st_distance(s.geom, sg.geom), st_HausdorffDistance(s.geom, sg.geom) asc + limit 1 + """.format(section=section)) + res = cur.fetchone() + if not res: + return + group = res[0] or 0 + cur.execute( + """ + select geom from albion.section_geom + where section_id='{section}' + and group_id > {group} + order by group_id asc + limit 1 """.format( group=group, section=section) ) - return [cell_id for cell_id, in cur.fetchall()] + res = cur.fetchone() + if res: + sql = """ + update albion.section set geom=st_multi('{}'::geometry) where id='{}' + """.format(res[0], section) + cur.execute(sql) + con.commit() + def previous_subsection(self, section): + with self.connect() as con: + cur = con.cursor() + cur.execute( + """ + select sg.group_id + from albion.section_geom sg + join albion.section s on s.id=sg.section_id + where s.id='{section}' + order by st_distance(s.geom, sg.geom), st_HausdorffDistance(s.geom, sg.geom) asc + limit 1 + """.format(section=section)) + res = cur.fetchone() + if not res: + return + group = res[0] or 0 + cur.execute( + """ + select geom from albion.section_geom + where section_id='{section}' + and group_id < {group} + order by group_id desc + limit 1 + """.format(group=group, section=section)) + res = cur.fetchone() + if res: + sql = """ + update albion.section set geom=st_multi('{}'::geometry) where id='{}' + """.format(res[0], section) + cur.execute(sql) + con.commit() + + + +# def next_group_ids(self): +# with self.connect() as con: +# cur = con.cursor() +# cur.execute( +# """ +# select cell_id from albion.next_group where section_id='{}' +# """.format( +# self.__current_section.currentText() +# ) +# ) +# return [cell_id for cell_id, in cur.fetchall()] +# def create_group(self, section, ids): with self.connect() as con: # add group diff --git a/test/parent_graph_test.py b/test/parent_graph_test.py index 851fe61..7515ebf 100644 --- a/test/parent_graph_test.py +++ b/test/parent_graph_test.py @@ -14,20 +14,16 @@ # | _ -100 m SQL = """ -INSERT INTO albion.collar(id, geom) VALUES - (1, 'SRID=32632;POINT(0 0 0)'::geometry), - (2, 'SRID=32632;POINT(100 0 0)'::geometry), - (3, 'SRID=32632;POINT(100 100 0)'::geometry) +INSERT INTO albion.collar(id, geom, depth_) VALUES + (1, 'SRID=32632;POINT(0 0 0)'::geometry, 100), + (2, 'SRID=32632;POINT(100 0 0)'::geometry, 100), + (3, 'SRID=32632;POINT(100 100 0)'::geometry, 100) ; INSERT INTO albion.cell(id, a, b, c, geom) VALUES (1, 1, 2, 3, 'SRID=32632;POLYGON((0 0, 100 0, 100 100, 0 0))'::geometry) ; REFRESH MATERIALIZED VIEW albion.all_edge ; -INSERT INTO albion.hole(id, collar_id, depth_, geom) VALUES - (1, 1, 100, 'SRID=32632;LINESTRING(0 0 0, 0 0 -100)'::geometry), - (2, 2, 100, 'SRID=32632;LINESTRING(100 0 0, 100 0 -100)'::geometry) -; INSERT INTO albion.graph(id) VALUES ('graph1') ; From 8fd4fa2d80f1c093e9e37874f6a0bdfd197415ae Mon Sep 17 00:00:00 2001 From: Vincent Mora Date: Fri, 23 Aug 2019 11:03:43 +0200 Subject: [PATCH 17/42] fixup --- plugin.py | 20 ++++++++++---------- project.py | 14 +++++++------- 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/plugin.py b/plugin.py index ad2f84f..9d508f0 100644 --- a/plugin.py +++ b/plugin.py @@ -210,13 +210,6 @@ def __create_menu_entries(self): self.__menu.addSeparator() -# self.__add_menu_entry( -# "Create sections (to be removed)", -# self.__create_sections, -# self.project is not None and self.project.has_group_cell, -# "Once cell groups have been defined, create section lines.", -# ) - self.__add_menu_entry( "Create cells", self.__create_cells, @@ -224,6 +217,13 @@ def __create_menu_entries(self): "Create Delaunay triangulation of collar layer.", ) + self.__add_menu_entry( + "Create subsections", + self.__create_sections, + self.project is not None and self.project.has_group_cell, + "Once cell groups have been defined, create section lines.", + ) + self.__menu.addSeparator() self.__add_menu_entry( @@ -357,9 +357,9 @@ def __layer(self, name): return lay def __current_section_changed(self, section_id): - #layers = QgsProject.instance().mapLayersByName(u"group_cell") - #if len(layers): - # layers[0].setSubsetString("section_id='{}'".format(section_id)) + layers = QgsProject.instance().mapLayersByName(u"group_cell") + if len(layers): + layers[0].setSubsetString("section_id='{}'".format(section_id)) self.__refresh_layers("section") # def __select_next_group(self): diff --git a/project.py b/project.py index b4f523b..56d879e 100644 --- a/project.py +++ b/project.py @@ -308,8 +308,8 @@ def __getattr__(self, name): return self.__has_hole() elif name == "has_section": return self.__has_section() -# elif name == "has_group_cell": -# return self.__has_group_cell() + elif name == "has_group_cell": + return self.__has_group_cell() elif name == "has_radiometry": return self.__has_radiometry() elif name == "has_cell": @@ -339,11 +339,11 @@ def __has_section(self): cur.execute("select count(1) from albion.section_geom") return cur.fetchone()[0] > 1 -# def __has_group_cell(self): -# with self.connect() as con: -# cur = con.cursor() -# cur.execute("select count(1) from albion.group_cell") -# return cur.fetchone()[0] > 1 + def __has_group_cell(self): + with self.connect() as con: + cur = con.cursor() + cur.execute("select count(1) from albion.group_cell") + return cur.fetchone()[0] > 1 def __has_radiometry(self): with self.connect() as con: From 003f767ae1f704188247341514d8314f60da043e Mon Sep 17 00:00:00 2001 From: Vincent Mora Date: Fri, 23 Aug 2019 18:24:53 +0200 Subject: [PATCH 18/42] fixup --- _albion.sql | 9 +- _albion_table.sql | 3 + albion.sql | 30 +- plugin.py | 58 +- project.py | 32 +- res/template_project.qgs | 3900 +++++++++++--------------------------- 6 files changed, 1204 insertions(+), 2828 deletions(-) diff --git a/_albion.sql b/_albion.sql index 9a02f4a..df5539c 100644 --- a/_albion.sql +++ b/_albion.sql @@ -43,6 +43,11 @@ create table _albion.metadata( insert into _albion.metadata(srid) select $SRID ; +create table _albion.layer( + name varchar primary key, + fields_definition text not null) +; + create table _albion.hole( id varchar primary key default _albion.unique_id()::varchar, date_ varchar, @@ -148,7 +153,7 @@ create table _albion.group( create table _albion.section( id varchar primary key default _albion.unique_id()::varchar, anchor geometry('LINESTRING', $SRID) not null check(st_numpoints(anchor)=2), - geom geometry('MULTILINESTRING', $SRID) not null, + geom geometry('MULTILINESTRING', $SRID), scale real not null default 1 ) ; @@ -197,7 +202,7 @@ create table _albion.named_section( id varchar primary key default _albion.unique_id()::varchar, geom geometry('LINESTRING', $SRID) not null, cut geometry('MULTILINESTRING', $SRID) not null, - section varchar references _albion.section(id) not null + section varchar not null references _albion.section(id) on delete cascade on update cascade ) ; diff --git a/_albion_table.sql b/_albion_table.sql index e01fed7..53014c4 100644 --- a/_albion_table.sql +++ b/_albion_table.sql @@ -5,3 +5,6 @@ create table _albion.$NAME( to_ real check (to_>=0), ${FIELDS_DEFINITION}) ; + +insert into _albion.layer(name, fields_definition) values ('$NAME', '$FIELDS_DEFINITION') +; diff --git a/albion.sql b/albion.sql index 7fcf8eb..b2915b4 100644 --- a/albion.sql +++ b/albion.sql @@ -10,7 +10,7 @@ create schema albion ------------------------------------------------------------------------------- -create function public.st_3dvolume(geom geometry) +create or replace function public.st_3dvolume(geom geometry) returns real language plpgsql immutable as @@ -156,11 +156,12 @@ create trigger collar_instead_trig for each row execute procedure albion.collar_instead_fct() ; - - create view albion.metadata as select id, srid, close_collar_distance, snap_distance, precision, interpolation, end_node_relative_distance, end_node_thickness, end_angle, correlation_distance, correlation_angle, parent_correlation_angle from _albion.metadata ; +create view albion.layer as select name, fields_definition from _albion.layer +; + create view albion.hole as select id, depth_, geom::geometry('LINESTRINGZ', $SRID) from _albion.hole ; @@ -795,7 +796,8 @@ with tan_ang as ( from _albion.metadata ), result as ( -select ns.id as start_, ne.id as end_, ns.graph_id as graph_id, (st_makeline(st_3dlineinterpolatepoint(ns.geom, .5), st_3dlineinterpolatepoint(ne.geom, .5)))::geometry('LINESTRINGZ', $SRID) as geom, null as parent +select ns.id as start_, ne.id as end_, ns.graph_id as graph_id, (st_makeline(st_3dlineinterpolatepoint(ns.geom, .5), st_3dlineinterpolatepoint(ne.geom, .5)))::geometry('LINESTRINGZ', $SRID) as geom --, null as parent + from albion.all_edge as e join _albion.hole as hs on hs.id=e.start_ join _albion.hole as he on he.id=e.end_ @@ -822,7 +824,7 @@ and ne.parent is null union all -- for graphs with parents -select ns.id as start_, ne.id as end_, ns.graph_id as graph_id, (st_makeline(st_3dlineinterpolatepoint(ns.geom, .5), st_3dlineinterpolatepoint(ne.geom, .5)))::geometry('LINESTRINGZ', $SRID) as geom, ns.parent as parent +select ns.id as start_, ne.id as end_, ns.graph_id as graph_id, (st_makeline(st_3dlineinterpolatepoint(ns.geom, .5), st_3dlineinterpolatepoint(ne.geom, .5)))::geometry('LINESTRINGZ', $SRID) as geom --, ns.parent as parent from _albion.edge as pe join _albion.node as pns on pns.id=pe.start_ join _albion.node as pne on pne.id=pe.end_ @@ -910,7 +912,7 @@ create trigger edge_instead_trig create view albion.edge_section as with hole_idx as ( - select h.id, rank() over(partition by s.id order by st_linelocatepoint(s.geom, st_startpoint(h.geom))) as rk, s.id as section_id + select h.id, rank() over(partition by s.id order by st_linelocatepoint(s.anchor, st_startpoint(h.geom))) as rk, s.id as section_id from _albion.section as s join _albion.hole as h on s.geom && h.geom and st_intersects(s.geom, st_startpoint(h.geom)) ) @@ -983,7 +985,7 @@ create trigger edge_section_instead_trig create view albion.possible_edge_section as select row_number() over() as id, e.start_, e.end_, e.graph_id, s.id as section_id, - (albion.to_section(e.geom, s.anchor, s.scale))::geometry('LINESTRING', $SRID) as geom, e.parent + (albion.to_section(e.geom, s.anchor, s.scale))::geometry('LINESTRING', $SRID) as geom --, e.parent from albion.possible_edge as e join _albion.node as ns on ns.id=e.start_ join _albion.node as ne on ne.id=e.end_ @@ -1321,9 +1323,9 @@ join albion.average_normal as nrml on nrml.id = coalesce(n.parent, n.id); ; -create view albion.end_node_section as +create or replace view albion.end_node_section as with hole_idx as ( - select h.id, rank() over(partition by s.id order by st_linelocatepoint(s.geom, st_startpoint(h.geom))) as rk, h.id as hole_id, s.id as section_id + select h.id, rank() over(partition by s.id order by st_linelocatepoint(s.anchor, st_startpoint(h.geom))) as rk, h.id as hole_id, s.id as section_id from _albion.section as s join _albion.hole as h on s.geom && h.geom and st_intersects(s.geom, st_startpoint(h.geom)) ) @@ -1383,7 +1385,7 @@ edge as ( ), poly as ( select - ('SRID=$SRID; POLYGON(('|| + ('SRID=32632; POLYGON(('|| st_x(st_startpoint(ns.geom)) ||' '||st_y(st_startpoint(ns.geom))||','|| st_x(st_endpoint(ns.geom)) ||' '||st_y(st_endpoint(ns.geom)) ||','|| st_x(st_endpoint(ne.geom)) ||' '||st_y(st_endpoint(ne.geom)) ||','|| @@ -1395,7 +1397,7 @@ poly as ( join node as ne on ne.node_id=e.end_ and ne.section_id=e.section_id ), term as ( - select ('SRID=$SRID; POLYGON(('|| + select ('SRID=32632; POLYGON(('|| st_x(st_startpoint(t.node_geom)) ||' '||st_y(st_startpoint(t.node_geom))||','|| st_x(st_endpoint(t.node_geom)) ||' '||st_y(st_endpoint(t.node_geom)) ||','|| st_x(st_endpoint(t.geom)) ||' '||st_y(st_endpoint(t.geom)) ||','|| @@ -1405,7 +1407,7 @@ term as ( t.graph_id, t.section_id from albion.end_node_section as t ) -select row_number() over() as id, st_union(geom)::geometry('MULTIPOLYGON', $SRID) as geom, graph_id, section_id +select row_number() over() as id, st_multi(st_union(geom))::geometry('MULTIPOLYGON', 32632) as geom, graph_id, section_id from (select * from poly union all select * from term) as t group by graph_id, section_id ; @@ -1620,7 +1622,7 @@ $$ select n.cut from albion.named_section as n join albion.section as s on s.id=n.section - where s.id=section_ and st_distance(n.cut, s.anchor) > st_distance(s.geom, s.anchor) + where s.id=section_ and st_distance(n.cut, s.anchor) > coalesce(st_distance(s.geom, s.anchor), 0) order by st_distance(n.cut, s.anchor) asc limit 1 ); @@ -1638,7 +1640,7 @@ $$ select n.cut from albion.named_section as n join albion.section as s on s.id=n.section - where s.id=section_ and st_distance(n.cut, s.anchor) < st_distance(s.geom, s.anchor) + where s.id=section_ and st_distance(n.cut, s.anchor) < coalesce(st_distance(s.geom, s.anchor), 9999999) order by st_distance(n.cut, s.anchor) desc limit 1 ); diff --git a/plugin.py b/plugin.py index 9d508f0..cfe17e1 100644 --- a/plugin.py +++ b/plugin.py @@ -224,6 +224,13 @@ def __create_menu_entries(self): "Once cell groups have been defined, create section lines.", ) + self.__add_menu_entry( + "Refresh selected layers sections", + self.__refresh_selected_layers_sections, + self.project is not None, + "" + ) + self.__menu.addSeparator() self.__add_menu_entry( @@ -277,8 +284,8 @@ def __create_menu_entries(self): self.__add_menu_entry( "Export Sections", - None, #self.__export_sections - self.project is not None and self.project.has_section, + self.__export_sections, + self.project is not None and bool(self.__current_graph.currentText()) and self.project.has_section and self.project.has_volume, "Export triangulated section in .obj or .dxf format", ) @@ -402,8 +409,9 @@ def __qgis__project__loaded(self): # We make sure that corresponding extents are valid when the project # is loaded - cell = QgsProject.instance().mapLayersByName("cell")[0] - cell.updateExtents() + cell = QgsProject.instance().mapLayersByName("cell") + if len(cell): + cell[0].updateExtents() section_geom = QgsProject.instance().mapLayersByName("section.geom") if section_geom: @@ -477,16 +485,19 @@ def __new_project(self): return Project.delete(project_name) + if os.path.exists(fil): + os.remove(fil) + self.__iface.messageBar().pushInfo("Albion:", "creating project...") Project.create(project_name, srid) # load template - open(fil, "w").write( - open(resource("template_project.qgs")) - .read() - .replace("template_project", project_name) - .replace("32632", str(srid)) - ) + #open(fil, "w").write( + # open(resource("template_project.qgs")) + # .read() + # .replace("template_project", project_name) + # .replace("32632", str(srid)) + #) self.__iface.newProject() QgsProject.instance().setFileName(fil) QgsProject.instance().read() @@ -497,8 +508,6 @@ def __new_project(self): def __import_data(self): assert(self.project) - if not QgsProject.instance().readEntry("albion", "conn_info", "")[0]: - return dir_ = QFileDialog.getExistingDirectory( None, u"Data directory", @@ -523,14 +532,15 @@ def __import_data(self): self.__iface.messageBar().clearWidgets() - collar = QgsProject.instance().mapLayersByName("collar")[0] - collar.reload() - collar.updateExtents() - self.__iface.setActiveLayer(collar) - QApplication.instance().processEvents() - while self.__iface.mapCanvas().isDrawing(): + collar = QgsProject.instance().mapLayersByName("collar") + if len(collar): + collar[0].reload() + collar[0].updateExtents() + self.__iface.setActiveLayer(collar[0]) QApplication.instance().processEvents() - self.__iface.zoomToActiveLayer() + while self.__iface.mapCanvas().isDrawing(): + QApplication.instance().processEvents() + self.__iface.zoomToActiveLayer() self.__iface.actionSaveProject().trigger() @@ -668,6 +678,12 @@ def __create_sections(self): assert(self.project) self.project.create_sections() + def __refresh_selected_layers_sections(self): + assert(self.project) + for l in iface.layerTreeView().selectedLayers(): + uri = QgsDataSourceUri(l.dataProvider().dataSourceUri()) + self.project.refresh_section_geom(uri.table()) + def __compute_mineralization(self): MineralizationDialog(self.project).exec_() @@ -706,6 +722,10 @@ def __export_elementary_volume(self): export_widget.show() export_widget.exec_() + def __export_sections(self): + assert(self.project) + self.project.export_sections(self.__current_graph.currentText()) + def __import_project(self): fil, __ = QFileDialog.getOpenFileName( None, diff --git a/project.py b/project.py index 56d879e..5da0736 100644 --- a/project.py +++ b/project.py @@ -123,8 +123,8 @@ def __init__(self, project_name): self.__conn_info = "dbname={} {}".format(project_name, cluster_params()) def connect(self): - con = psycopg2.connect(self.__conn_info, connection_factory=MyLoggingConnection) - con.initialize(logger) + con = psycopg2.connect(self.__conn_info)#, connection_factory=MyLoggingConnection) + #con.initialize(logger) return con def vacuum(self): @@ -284,7 +284,9 @@ def update(self): ) ) - for table in TABLES: + cur.execute("select name, fields_definition from albion.layers") + tables = [{'NAME': r[0], 'FIELDS_DEFINITION': r[1]} for r in cur.fetchall()] + for table in tables: for statement in ( open(os.path.join(os.path.dirname(__file__), "albion_table.sql")) .read() @@ -296,6 +298,10 @@ def update(self): ) con.commit() + def export_sections(self, graph): + assert(False) + pass + def __srid(self): with self.connect() as con: cur = con.cursor() @@ -308,6 +314,8 @@ def __getattr__(self, name): return self.__has_hole() elif name == "has_section": return self.__has_section() + elif name == "has_volume": + return self.__has_volume() elif name == "has_group_cell": return self.__has_group_cell() elif name == "has_radiometry": @@ -333,6 +341,12 @@ def __has_hole(self): cur.execute("select count(1) from albion.hole") return cur.fetchone()[0] > 1 + def __has_volume(self): + with self.connect() as con: + cur = con.cursor() + cur.execute("select count(1) from albion.volume") + return cur.fetchone()[0] > 1 + def __has_section(self): with self.connect() as con: cur = con.cursor() @@ -888,6 +902,14 @@ def create_section_view_0_90(self, z_scale): #cur.execute("refresh materialized view albion.resistivity_section") con.commit() + def refresh_section_geom(self, table): + with self.connect() as con: + cur = con.cursor() + cur.execute("select count(1) from albion.layer where id='{}'".format(table)) + if cur.fetchone()[0]: + cur.execute("refresh materialized view albion.{}_section_geom_cache".format(table)) + con.commit() + def closest_hole_id(self, x, y): with self.connect() as con: cur = con.cursor() @@ -960,8 +982,8 @@ def accept_possible_edge(self, graph): cur = con.cursor() cur.execute( """ - insert into albion.edge(start_, end_, graph_id, geom, parent) - select start_, end_, graph_id, geom, parent from albion.possible_edge + insert into albion.edge(start_, end_, graph_id, geom) + select start_, end_, graph_id, geom from albion.possible_edge where graph_id=%s """, (graph,)) diff --git a/res/template_project.qgs b/res/template_project.qgs index f6c8921..ae810ec 100644 --- a/res/template_project.qgs +++ b/res/template_project.qgs @@ -1,5 +1,5 @@ - + @@ -19,93 +19,96 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - collar20170522101211588 - current_radiometry_section20171210141136639 - current_mineralization_section20171210141434594 - group_cell20171210141649354 - section_geom20171210141834658 - cell20171210155444151 - current_hole_section20171210181943739 - current_formation_section20171210182253618 - current_node_section20171211135743640 - current_edge_section20171211173954570 - edge20171211174003737 - possible_edge20171219072744468 - section_anchor20171220085838796 - Google_Satellite_2f49519b_bcb0_4cae_afbc_decbfac2af04 + cell_99e875c2_110e_4f52_a7f4_54ea9cff1367 + collar_7e814841_4cc9_495a_8ef6_9229fcfffb5e + edge_32c6a82a_82cd_477f_b119_398536a6b6ed + edge_section_8b745326_1406_43a8_803e_8ee85be59103 + end_node_section_node_geom_f653243c_2e98_4638_b428_1acca01868dc + group_cell_ec51a010_ab41_49d7_ac55_8ce0cfbb8838 + hole_section_1f8c7d9f_7032_4a97_8033_d7ee1c22ea2a + named_section_cut_47ba5a59_cd54_4752_9fee_3cbe01d07af4 + node_section_63e3816d_ea42_44c6_937c_65c10a3b3ac4 + possible_edge_a6b83b46_56da_4098_b0fe_e703633800f5 + possible_edge_section_04705590_fcdc_4fe9_8309_3d2c648db28f + section_anchor_5a49e7a1_cea4_4a35_982c_00e7801cd6da + section_geom_7c5467f1_628b_4313_a00b_a79b3801f4c0 + section_intersection_13a1d3a9_897b_48fc_9714_e20439ad1ff6 + section_polygon_f49e48f4_9101_4351_a07c_0a99748eaca2 - + - - - - - - - - - - - - - + + + + + + + + + + + + + + + - + meters - 31739052.35575000196695328 - 33490786.30525000020861626 - 31739525.45425000041723251 - 33491101.08475000038743019 + 31738882.47595356032252312 + 33490501.01186897233128548 + 31740105.545461256057024 + 33491314.78998938575387001 0 @@ -123,177 +126,94 @@ 0 - - - - - - -20037508.34278924390673637 - -20037508.34278925508260727 - 20037508.34278924390673637 - 20037508.34278924390673637 - - Google_Satellite_2f49519b_bcb0_4cae_afbc_decbfac2af04 - crs=EPSG:3857&format&type=xyz&url=https://mt1.google.com/vt/lyrs%3Ds%26x%3D%7Bx%7D%26y%3D%7By%7D%26z%3D%7Bz%7D&zmax=19&zmin=0 - - - - Google Satellite - - - +proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0 +k=1.0 +units=m +nadgrids=@null +wktext +no_defs - 3857 - 3857 - EPSG:3857 - WGS 84 / Pseudo-Mercator - merc - WGS84 - false - - - - - - - - - - - - - - - - 0 - 0 - - - - - true - - - - - wms - - - - - - - - 1 - 1 - 1 - - - - - - - - - None - WholeRaster - Estimated - 0.02 - 0.98 - 2 - - - - - - - 0 - - + 31739063.62000000104308128 33490793.80000000074505806 31739514.19000000134110451 33491093.58999999985098839 - cell20171210155444151 - dbname='template_project' host=localhost port=55432 sslmode=disable key='id' srid=32632 type=Polygon checkPrimaryKeyUnicity='1' table="albion"."cell" (geom) sql= + cell_99e875c2_110e_4f52_a7f4_54ea9cff1367 + dbname='template_project' host=127.0.0.1 port=55432 sslmode=disable key='"id"' srid=32632 type=Polygon checkPrimaryKeyUnicity='1' table="albion"."cell" (geom) sql= @@ -314,7 +234,7 @@ - + dataset @@ -322,13 +242,13 @@ - - 0 - 0 - - - - + +proj=utm +zone=32 +datum=WGS84 +units=m +no_defs + 3116 + 32632 + EPSG:32632 + WGS 84 / UTM zone 32N + utm + WGS84 false @@ -349,26 +269,26 @@ 1 1 - + - - + + - + - + @@ -377,80 +297,49 @@ - - - - - + 0 0 1 - - - - - - - - - - - - + - + - + - + - + - + - + - + - - - - + + + + @@ -461,71 +350,50 @@ - - - - + + + + - - - - + + + + - + - - + - ../../areva/albion + 0 - ../../areva/albion - + + 0 generatedlayout - "id" + - + 31739063.62000000104308128 33490793.80000000074505806 31739514.19000000134110451 33491093.58999999985098839 - collar20170522101211588 - dbname='template_project' host=localhost port=55432 sslmode=disable key='id' srid=32632 type=PointZ checkPrimaryKeyUnicity='1' table="albion"."collar" (geom) sql= + collar_7e814841_4cc9_495a_8ef6_9229fcfffb5e + dbname='template_project' host=127.0.0.1 port=55432 sslmode=disable key='"id"' srid=32632 type=PointZ checkPrimaryKeyUnicity='1' table="albion"."collar" (geom) sql= @@ -546,7 +414,7 @@ def my_form_open(dialog, layer, feature): - + dataset @@ -554,13 +422,13 @@ def my_form_open(dialog, layer, feature): - - 0 - 0 - - - - + +proj=utm +zone=32 +datum=WGS84 +units=m +no_defs + 3116 + 32632 + EPSG:32632 + WGS 84 / UTM zone 32N + utm + WGS84 false @@ -581,33 +449,33 @@ def my_form_open(dialog, layer, feature): 1 1 - + - - + + - + - + - - + + @@ -616,69 +484,49 @@ def my_form_open(dialog, layer, feature): - - - - - + 0 0 1 - - - - - - - - - - - - + - + - + - + - + + + + + + + - + - - - + + + + @@ -686,68 +534,51 @@ def my_form_open(dialog, layer, feature): + - - - + + + + - - - + + + + - + - - - + + - ../../areva/albion + 0 - ../../areva/albion - + + 0 generatedlayout - COALESCE( "id", '<NULL>' ) + - - current_edge_section20171211173954570 - dbname='template_project' host=localhost port=55432 sslmode=disable key='id' srid=32632 type=LineString checkPrimaryKeyUnicity='1' table="albion"."current_edge_section" (geom) sql= + + edge_32c6a82a_82cd_477f_b119_398536a6b6ed + dbname='template_project' host=127.0.0.1 port=55432 sslmode=disable key='"id"' srid=32632 type=LineStringZ checkPrimaryKeyUnicity='1' table="albion"."edge" (geom) sql= - current_edge_section + edge +proj=utm +zone=32 +datum=WGS84 +units=m +no_defs @@ -764,7 +595,7 @@ def my_form_open(dialog, layer, feature): - + dataset @@ -772,13 +603,13 @@ def my_form_open(dialog, layer, feature): - - 0 - 0 - - - - + +proj=utm +zone=32 +datum=WGS84 +units=m +no_defs + 3116 + 32632 + EPSG:32632 + WGS 84 / UTM zone 32N + utm + WGS84 false @@ -799,78 +630,19 @@ def my_form_open(dialog, layer, feature): 1 1 - - - - - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + - + - + @@ -880,228 +652,112 @@ def my_form_open(dialog, layer, feature): - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + 0 0 1 - - - - - - - - - - - - - - - - - - - + - + - + - + - + - + - - - - - - - - + - + - - - - - - + + + + - - - - - - - - + + + + - - - - - - + + + + - + - - + - ../../areva/albion + 0 - ../../areva/albion - + + 0 generatedlayout - COALESCE( "id", '<NULL>' ) + - - - 31739063.62000000104308128 - 33490278.67379739880561829 - 31740023.05092709884047508 - 33491092.95009690150618553 - - current_formation_section20171210182253618 - dbname='template_project' host=localhost port=55432 sslmode=disable key='id' srid=32632 type=LineString checkPrimaryKeyUnicity='1' table="albion"."current_formation_section" (geom) sql= + + edge_section_8b745326_1406_43a8_803e_8ee85be59103 + dbname='template_project' host=127.0.0.1 port=55432 sslmode=disable key='"id"' srid=32632 type=LineString checkPrimaryKeyUnicity='1' table="albion"."edge_section" (geom) sql= - current_formation_section + edge_section +proj=utm +zone=32 +datum=WGS84 +units=m +no_defs @@ -1118,7 +774,7 @@ def my_form_open(dialog, layer, feature): - + dataset @@ -1126,13 +782,13 @@ def my_form_open(dialog, layer, feature): - - 0 - 0 - - - - + +proj=utm +zone=32 +datum=WGS84 +units=m +no_defs + 3116 + 32632 + EPSG:32632 + WGS 84 / UTM zone 32N + utm + WGS84 false @@ -1153,137 +809,19 @@ def my_form_open(dialog, layer, feature): 1 1 - - - - - - - - - - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + - + - + @@ -1293,302 +831,134 @@ def my_form_open(dialog, layer, feature): - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + 0 0 1 - - - - - - - - - - - - + - + - - + + - + - - + + - + - - + + - + - - + + - + - + - + - - - - - - + + + + + + - - - - + + + + - - - - - - + + + + + + - - - - - - + + + + + + - + + + - - + - ../../areva/albion + 0 - ../../areva/albion - + + 0 generatedlayout - "id" + - - current_hole_section20171210181943739 - dbname='template_project' host=localhost port=55432 sslmode=disable key='id' srid=32632 type=LineString checkPrimaryKeyUnicity='1' table="albion"."current_hole_section" (geom) sql= + + end_node_section_node_geom_f653243c_2e98_4638_b428_1acca01868dc + dbname='template_project' host=127.0.0.1 port=55432 sslmode=disable key='"id"' srid=32632 type=LineString checkPrimaryKeyUnicity='1' table="albion"."end_node_section" (node_geom) sql= - current_hole_section + end_node_section.node_geom +proj=utm +zone=32 +datum=WGS84 +units=m +no_defs @@ -1605,7 +975,7 @@ def my_form_open(dialog, layer, feature): - + dataset @@ -1613,13 +983,13 @@ def my_form_open(dialog, layer, feature): - - 0 - 0 - - - - + +proj=utm +zone=32 +datum=WGS84 +units=m +no_defs + 3116 + 32632 + EPSG:32632 + WGS 84 / UTM zone 32N + utm + WGS84 false @@ -1640,17 +1010,17 @@ def my_form_open(dialog, layer, feature): 1 1 - + - - + + - + @@ -1662,9 +1032,9 @@ def my_form_open(dialog, layer, feature): @@ -1683,88 +1053,86 @@ def my_form_open(dialog, layer, feature): - + - + - - + + - + - - + + - + - - + + - + - + - + + + + + + + - - - - - + + + + + + - - - + + + + - - - - - + + + + + + - - - - - + + + + + + - + + + @@ -1772,32 +1140,26 @@ def my_form_open(dialog, layer, feature): - ../../areva/albion + 0 - ../../areva/albion + 0 generatedlayout - "id" + - - - 31739214.99657329916954041 - 33490407.22139409929513931 - 31739833.60740730166435242 - 33491092.41239940002560616 - - current_mineralization_section20171210141434594 - dbname='template_project' host=localhost port=55432 sslmode=disable key='id' srid=32632 type=LineString checkPrimaryKeyUnicity='1' table="albion"."current_mineralization_section" (geom) sql= + + group_cell_ec51a010_ab41_49d7_ac55_8ce0cfbb8838 + dbname='template_project' host=127.0.0.1 port=55432 sslmode=disable key='"id"' srid=32632 type=Polygon checkPrimaryKeyUnicity='1' table="albion"."group_cell" (geom) sql= - current_mineralization_section + group_cell +proj=utm +zone=32 +datum=WGS84 +units=m +no_defs @@ -1814,7 +1176,7 @@ def my_form_open(dialog, layer, feature): - + dataset @@ -1822,13 +1184,13 @@ def my_form_open(dialog, layer, feature): - - 0 - 0 - - - - + +proj=utm +zone=32 +datum=WGS84 +units=m +no_defs + 3116 + 32632 + EPSG:32632 + WGS 84 / UTM zone 32N + utm + WGS84 false @@ -1849,332 +1211,129 @@ def my_form_open(dialog, layer, feature): 1 1 - - - - - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + - - - - - + - - - + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + 0 - 1 + 0 1 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - + - - + + - + - - + + - + - + - + - - - - - - - - + + + + - - - - - - + + - - - - - - - - + + + + - - - - - - - - + + + + - + + + - - + - ../../areva/albion + 0 - ../../areva/albion - + + 0 generatedlayout - "id" + - - current_node_section20171211135743640 - dbname='template_project' host=localhost port=55432 sslmode=disable key='id' srid=32632 type=LineString checkPrimaryKeyUnicity='1' table="albion"."current_node_section" (geom) sql= + + hole_section_1f8c7d9f_7032_4a97_8033_d7ee1c22ea2a + dbname='template_project' host=127.0.0.1 port=55432 sslmode=disable key='"id"' srid=32632 type=LineString checkPrimaryKeyUnicity='1' table="albion"."hole_section" (geom) sql= - current_node_section + hole_section +proj=utm +zone=32 +datum=WGS84 +units=m +no_defs @@ -2191,7 +1350,7 @@ def my_form_open(dialog, layer, feature): - + dataset @@ -2199,13 +1358,13 @@ def my_form_open(dialog, layer, feature): - - 0 - 0 - - - - + +proj=utm +zone=32 +datum=WGS84 +units=m +no_defs + 3116 + 32632 + EPSG:32632 + WGS 84 / UTM zone 32N + utm + WGS84 false @@ -2226,24 +1385,19 @@ def my_form_open(dialog, layer, feature): 1 1 - - - - - - + - - - + + + - + - + @@ -2253,296 +1407,112 @@ def my_form_open(dialog, layer, feature): - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + 0 - 4 + 0 1 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - + - - + + - + - - + + - + - + - + - - - - - - - + + + + - - - - - + + - - - - - - - + + + + - - - - - - - + + + + - + + + - - + - ../../areva/albion + 0 - ../../areva/albion - + + 0 generatedlayout - COALESCE( "id", '<NULL>' ) + - - - 31739063.62000000104308128 - 33490278.75380950048565865 - 31740022.85106619819998741 - 33491092.94975600019097328 - - current_radiometry_section20171210141136639 - dbname='template_project' host=localhost port=55432 sslmode=disable key='id' srid=32632 type=LineString checkPrimaryKeyUnicity='1' table="albion"."current_radiometry_section" (geom) sql= + + named_section_cut_47ba5a59_cd54_4752_9fee_3cbe01d07af4 + dbname='template_project' host=127.0.0.1 port=55432 sslmode=disable key='"id"' srid=32632 type=MultiLineString checkPrimaryKeyUnicity='1' table="albion"."named_section" (cut) sql= - current_radiometry_section + named_section.cut +proj=utm +zone=32 +datum=WGS84 +units=m +no_defs @@ -2559,7 +1529,7 @@ def my_form_open(dialog, layer, feature): - + dataset @@ -2567,13 +1537,13 @@ def my_form_open(dialog, layer, feature): - - 0 - 0 - - - - + +proj=utm +zone=32 +datum=WGS84 +units=m +no_defs + 3116 + 32632 + EPSG:32632 + WGS 84 / UTM zone 32N + utm + WGS84 false @@ -2594,20 +1564,20 @@ def my_form_open(dialog, layer, feature): 1 1 - + - - - + + + - + - + @@ -2616,15 +1586,9 @@ def my_form_open(dialog, layer, feature): - - @@ -2633,166 +1597,101 @@ def my_form_open(dialog, layer, feature): - - - - - + 0 0 1 - - - - - - - - - - - - - - - - - - - + - + - - + + - + - - + + - + - - + + - + - - - - - + + + + - - - - + + + - - - - - + + + + - - - - - + + + + - + + + - - + - ../../areva/albion + 0 - ../../areva/albion - + + 0 generatedlayout - "id" + - - edge20171211174003737 - dbname='template_project' host=localhost port=55432 sslmode=disable key='id' srid=32632 type=LineStringZ checkPrimaryKeyUnicity='1' table="albion"."edge" (geom) sql= + + node_section_63e3816d_ea42_44c6_937c_65c10a3b3ac4 + dbname='template_project' host=127.0.0.1 port=55432 sslmode=disable key='"id"' srid=32632 type=LineString checkPrimaryKeyUnicity='1' table="albion"."node_section" (geom) sql= - edge + node_section +proj=utm +zone=32 +datum=WGS84 +units=m +no_defs @@ -2809,7 +1708,7 @@ def my_form_open(dialog, layer, feature): - + dataset @@ -2817,13 +1716,13 @@ def my_form_open(dialog, layer, feature): - - 0 - 0 - - - - + +proj=utm +zone=32 +datum=WGS84 +units=m +no_defs + 3116 + 32632 + EPSG:32632 + WGS 84 / UTM zone 32N + utm + WGS84 false @@ -2844,76 +1743,17 @@ def my_form_open(dialog, layer, feature): 1 1 - - - - - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + - + @@ -2925,191 +1765,145 @@ def my_form_open(dialog, layer, feature): - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + 0 0 1 - - - - - - - - - - - - + - + - - + + - + - - + + + + + + + + + + + + + + - + - + - + + + + + + + - - - - + + + + + + + - - + + + + + - - - - + + + + + + + - - - - + + + + + + + - + + + - - + - ../../areva/albion + 0 - ../../areva/albion - + + 0 generatedlayout - COALESCE( "id", '<NULL>' ) + - - group_cell20171210141649354 - dbname='template_project' host=localhost port=55432 sslmode=disable key='id' srid=32632 type=Polygon checkPrimaryKeyUnicity='1' table="albion"."group_cell" (geom) sql=section_id='SN x4' + + possible_edge_a6b83b46_56da_4098_b0fe_e703633800f5 + dbname='template_project' host=127.0.0.1 port=55432 sslmode=disable key='"id"' srid=32632 type=LineStringZ checkPrimaryKeyUnicity='1' table="albion"."possible_edge" (geom) sql= - group_cell + possible_edge +proj=utm +zone=32 +datum=WGS84 +units=m +no_defs @@ -3126,7 +1920,7 @@ def my_form_open(dialog, layer, feature): - + dataset @@ -3134,13 +1928,13 @@ def my_form_open(dialog, layer, feature): - - 0 - 0 - - - - + +proj=utm +zone=32 +datum=WGS84 +units=m +no_defs + 3116 + 32632 + EPSG:32632 + WGS 84 / UTM zone 32N + utm + WGS84 false @@ -3161,269 +1955,151 @@ def my_form_open(dialog, layer, feature): 1 1 - - - - - - + - - - - + + + + + + + - + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + - - - - - - - - - - - - - - - - - - - - - - - - - + 0 0 1 - - - - - - - - - - - - + - + - - + + - + - - + + - + - - + + - + - - - - + + + + - - - + + + - - - - + + + + - - - - + + + + - + + + - - + - ../../areva/albion + 0 - ../../areva/albion - + + 0 generatedlayout - COALESCE( "id", '<NULL>' ) + - - metadata20170602185222421 - dbname='template_project' host=localhost port=55432 sslmode=disable key='id' checkPrimaryKeyUnicity='1' table="albion"."metadata" sql= + + possible_edge_section_04705590_fcdc_4fe9_8309_3d2c648db28f + dbname='template_project' host=127.0.0.1 port=55432 sslmode=disable key='"id"' srid=32632 type=LineString checkPrimaryKeyUnicity='1' table="albion"."possible_edge_section" (geom) sql= - metadata + possible_edge_section - +proj=longlat +datum=WGS84 +no_defs - 3452 - 4326 - EPSG:4326 - WGS 84 - longlat + +proj=utm +zone=32 +datum=WGS84 +units=m +no_defs + 3116 + 32632 + EPSG:32632 + WGS 84 / UTM zone 32N + utm WGS84 - true + false - + dataset @@ -3431,13 +2107,13 @@ def my_form_open(dialog, layer, feature): - - 0 - 0 - - - - + +proj=utm +zone=32 +datum=WGS84 +units=m +no_defs + 3116 + 32632 + EPSG:32632 + WGS 84 / UTM zone 32N + utm + WGS84 false @@ -3458,113 +2134,77 @@ def my_form_open(dialog, layer, feature): 1 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 0 + 0 + 1 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - + - - + + - + - - + + - + - - + + - + - + - - - - - - - - - - - + + + + + - - - - - - - - - - + + + + - - - - - - - - - - - + + + + + - - - - - - - - - - - + + + + + - + + + - - + - ../../areva/albion + 0 - ../../areva/albion + 0 generatedlayout - COALESCE("id", '<NULL>') + - - possible_edge20171219072744468 - dbname='template_project' host=localhost port=55432 sslmode=disable key='id' srid=32632 type=LineStringZ checkPrimaryKeyUnicity='1' table="albion"."possible_edge" (geom) sql= + + + 31739063.30036709830164909 + 33490657.7391928993165493 + 31739651.99177160114049911 + 33491093.58999999985098839 + + section_anchor_5a49e7a1_cea4_4a35_982c_00e7801cd6da + dbname='template_project' host=127.0.0.1 port=55432 sslmode=disable key='"id"' srid=32632 type=LineString checkPrimaryKeyUnicity='1' table="albion"."section" (anchor) sql= - possible_edge + section.anchor +proj=utm +zone=32 +datum=WGS84 +units=m +no_defs @@ -3683,7 +2295,7 @@ def my_form_open(dialog, layer, feature): - + dataset @@ -3691,13 +2303,13 @@ def my_form_open(dialog, layer, feature): - - 0 - 0 - - - - + +proj=utm +zone=32 +datum=WGS84 +units=m +no_defs + 3116 + 32632 + EPSG:32632 + WGS 84 / UTM zone 32N + utm + WGS84 false @@ -3718,49 +2330,17 @@ def my_form_open(dialog, layer, feature): 1 1 - - - - - - + - - - - - - - - - - - - - - - - - - - - - - - - - + + - + @@ -3772,22 +2352,163 @@ def my_form_open(dialog, layer, feature): - - + + + + + + 0 + 0 + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 0 + + + 0 + generatedlayout + + + + + + + + section_geom_7c5467f1_628b_4313_a00b_a79b3801f4c0 + dbname='template_project' host=127.0.0.1 port=55432 sslmode=disable key='"id"' srid=32632 type=MultiLineString checkPrimaryKeyUnicity='1' table="albion"."section" (geom) sql= + + + + section.geom + + + +proj=utm +zone=32 +datum=WGS84 +units=m +no_defs + 3116 + 32632 + EPSG:32632 + WGS 84 / UTM zone 32N + utm + WGS84 + false + + + + + + + dataset + + + + + + + + +proj=utm +zone=32 +datum=WGS84 +units=m +no_defs + 3116 + 32632 + EPSG:32632 + WGS 84 / UTM zone 32N + utm + WGS84 + false + + + + + postgres + + + + + + + + + + + 1 + 1 + 1 + + + + + - + @@ -3799,206 +2520,101 @@ def my_form_open(dialog, layer, feature): - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + 0 0 1 - - - - - - - - - - - - - - - - - - - - - - - - - - + - + - - + + - + - - + + - + - - - - - + + + - - - - + + - - - - - + + + - - - - - + + + - - - - + + + + + - ../../areva/albion + 0 - ../../areva/albion - + + 0 generatedlayout - COALESCE( "id", '<NULL>' ) + - - section_anchor20171220085838796 - dbname='template_project' host=localhost port=55432 sslmode=disable key='id' srid=32632 type=LineString checkPrimaryKeyUnicity='1' table="albion"."section" (anchor) sql= + + section_intersection_13a1d3a9_897b_48fc_9714_e20439ad1ff6 + dbname='template_project' host=127.0.0.1 port=55432 sslmode=disable key='"id"' srid=32632 type=Polygon checkPrimaryKeyUnicity='1' table="albion"."section_intersection" (geom) sql= - section.anchor + section_intersection +proj=utm +zone=32 +datum=WGS84 +units=m +no_defs @@ -4015,7 +2631,7 @@ def my_form_open(dialog, layer, feature): - + dataset @@ -4023,13 +2639,13 @@ def my_form_open(dialog, layer, feature): - - 0 - 0 - - - - + +proj=utm +zone=32 +datum=WGS84 +units=m +no_defs + 3116 + 32632 + EPSG:32632 + WGS 84 / UTM zone 32N + utm + WGS84 false @@ -4050,31 +2666,26 @@ def my_form_open(dialog, layer, feature): 1 1 - + - - - - - - - + + + + - - - - - + - - - + + + + + @@ -4093,77 +2704,32 @@ def my_form_open(dialog, layer, feature): - - - - - - - - - - - - - - - - - - - - - - + - + - - - - + - - - - - - - + - - - - + - + - + @@ -4180,22 +2746,16 @@ def my_form_open(dialog, layer, feature): - "id" + - - - 31739063.62000000104308128 - 33490793.80000000074505806 - 31739514.19000000134110451 - 33491092.42000000178813934 - - section_geom20171210141834658 - dbname='template_project' host=localhost port=55432 sslmode=disable key='id' srid=32632 type=LineString checkPrimaryKeyUnicity='1' table="albion"."section" (geom) sql= + + section_polygon_f49e48f4_9101_4351_a07c_0a99748eaca2 + dbname='template_project' host=127.0.0.1 port=55432 sslmode=disable key='"id"' srid=32632 type=MultiPolygon checkPrimaryKeyUnicity='1' table="albion"."section_polygon" (geom) sql= - section.geom + section_polygon +proj=utm +zone=32 +datum=WGS84 +units=m +no_defs @@ -4212,7 +2772,7 @@ def my_form_open(dialog, layer, feature): - + dataset @@ -4220,13 +2780,13 @@ def my_form_open(dialog, layer, feature): - - 0 - 0 - - - - + +proj=utm +zone=32 +datum=WGS84 +units=m +no_defs + 3116 + 32632 + EPSG:32632 + WGS 84 / UTM zone 32N + utm + WGS84 false @@ -4247,411 +2807,175 @@ def my_form_open(dialog, layer, feature): 1 1 - - - - - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + - - - - - + - - - + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + 0 0 1 - - - - - - - - - - - - - - - - - - - + - + - - + + - + - - + + - + - - - - + + + - - - + + - - - - + + + - - - - + + + - + + + - - + - ../../areva/albion + 0 - ../../areva/albion - + + 0 generatedlayout - "id" + - - - - - - - - - - - - - - + + + + + + + + + + + + + + + - - - 10 - 1 - off - - to_vertex_and_segment - to_vertex_and_segment - to_vertex_and_segment - to_vertex_and_segment - to_vertex_and_segment - to_vertex_and_segment - to_vertex_and_segment - to_vertex_and_segment - to_vertex_and_segment - to_vertex_and_segment - to_vertex_and_segment - to_vertex_and_segment - to_vertex_and_segment - - - disabled - disabled - disabled - disabled - disabled - disabled - disabled - disabled - disabled - disabled - disabled - disabled - disabled - - - cell20171210155444151 - collar20170522101211588 - current_edge_section20171211173954570 - current_formation_section20171210182253618 - current_hole_section20171210181943739 - current_mineralization_section20171210141434594 - current_node_section20171211135743640 - current_radiometry_section20171210141136639 - edge20171211174003737 - group_cell20171210141649354 - possible_edge20171219072744468 - section_geom20171210141834658 - section_anchor20171220084145458 - - - 0.000000 - 0.000000 - 0.000000 - 0.000000 - 0.000000 - 0.000000 - 0.000000 - 0.000000 - 0.000000 - 0.000000 - 0.000000 - 0.000000 - 0.000000 - - - 2 - 2 - 2 - 2 - 2 - 2 - 2 - 2 - 2 - 2 - 2 - 2 - 2 - - current_layer - + + WGS84 + - 255 - 255 - 255 255 + 255 + 255 0 255 - 255 + 255 + 255 - - false - - - m2 - meters - - 50 - 16 - 30 false - 0 + 16 false + 0 false + 50 true - 0 + 0 + 30 + + 1 + false + + false + - true 2 + true - - 3116 - +proj=utm +zone=32 +datum=WGS84 +units=m +no_defs - EPSG:32632 - 1 - - dbname=template_project host=localhost port=55432 - /home/vmo/albion/nt - template_project 32632 + template_project + /home/vmo/albion/nt + + m2 + meters + @@ -4664,7 +2988,7 @@ def my_form_open(dialog, layer, feature): - + 2019-08-23T18:21:56 From e90a9f0b3a88433d1d8501c3f9a6723345e9037e Mon Sep 17 00:00:00 2001 From: Vincent Mora Date: Wed, 23 Oct 2019 13:43:00 +0200 Subject: [PATCH 19/42] adds conversion for projects created with previous version of albion --- _albion.sql | 6 +- _albion_v1_to_v2.sql | 91 + albion.sql | 99 +- elementary_volume/__init__.py | 56 +- plugin.py | 29 +- project.py | 21 + res/template_project.qgs | 1624 ++++++++++------- test/deviation_bug.py | 14 + test/end_node.py | 64 + test/{import_test.py => import.py} | 0 test/mineralisation.py | 38 + .../{parent_graph_test.py => parent_graph.py} | 0 test/tutorial.py | 88 + 13 files changed, 1377 insertions(+), 753 deletions(-) create mode 100644 _albion_v1_to_v2.sql create mode 100644 test/deviation_bug.py create mode 100644 test/end_node.py rename test/{import_test.py => import.py} (100%) create mode 100644 test/mineralisation.py rename test/{parent_graph_test.py => parent_graph.py} (100%) create mode 100644 test/tutorial.py diff --git a/_albion.sql b/_albion.sql index df5539c..1d57fb3 100644 --- a/_albion.sql +++ b/_albion.sql @@ -32,15 +32,15 @@ create table _albion.metadata( snap_distance real not null default 1, precision real default .01, interpolation interpolation_method default 'balanced_tangential', - end_angle real default 5.0, correlation_distance real default 200, correlation_angle real default 5.0, parent_correlation_angle real default 1.0, end_node_relative_distance real default .3, - end_node_thickness real default 1) + end_node_thickness real default 1, + version varchar) ; -insert into _albion.metadata(srid) select $SRID +insert into _albion.metadata(srid, version) select $SRID, '2.0' ; create table _albion.layer( diff --git a/_albion_v1_to_v2.sql b/_albion_v1_to_v2.sql new file mode 100644 index 0000000..509843f --- /dev/null +++ b/_albion_v1_to_v2.sql @@ -0,0 +1,91 @@ +-- changed metadata +alter table _albion.metadata drop column end_angle +; +alter table _albion.metadata drop column end_distance +; +alter table _albion.metadata add column end_node_relative_distance real default .3 +; +alter table _albion.metadata add column end_node_thickness real default 1 +; +alter table _albion.metadata add column version varchar default '2.0' +; + +-- add layer table +create table _albion.layer( + name varchar primary key, + fields_definition text not null) +; + +insert into _albion.layer(name, fields_definition) +select t.name, t.fields_definition +from (VALUES + ('radiometry', 'gamma real'), + ('resistivity', 'rho real'), + ('formation', 'code integer, comments varchar'), + ('lithology', 'code integer, comments varchar'), + ('facies', 'code integer, comments varchar'), + ('chemical', 'num_sample varchar, element varchar, thickness real, gt real, grade real, equi real, comments varchar'), + ('mineralization', 'level_ real, oc real, accu real, grade real, comments varchar') + ) as t(name, fields_definition) +join information_schema.tables on table_schema = '_albion' and table_name = t.name +; + +-- merge collar and hole tables +alter table _albion.hole alter column id set default _albion.unique_id()::varchar +; +alter table _albion.hole add column date_ varchar +; +alter table _albion.hole add constraint depth_check check(depth_ > 0) +; +alter table _albion.hole add column x double precision +; +alter table _albion.hole add column y double precision +; +alter table _albion.hole add column z double precision +; +alter table _albion.hole add column comments varchar +; +update _albion.hole as h set x=c.x, y=c.y, z=c.z, date_=c.date_, comments=c.comments +from _albion.collar as c where h.collar_id=c.id +; +alter table _albion.hole alter column x set not null +; +alter table _albion.hole alter column y set not null +; +alter table _albion.hole alter column z set not null +; +alter table _albion.hole drop column collar_id +; +alter table _albion.hole add constraint hole_geom_length_chk check (geom is null or abs(st_3dlength(geom) - depth_) <= 1e-3) +; + +-- cell now references holes rather than collar +alter table _albion.cell drop constraint cell_a_fkey +; +alter table _albion.cell drop constraint cell_b_fkey +; +alter table _albion.cell drop constraint cell_c_fkey +; +alter table _albion.cell add constraint cell_a_fkey foreign key(a) REFERENCES _albion.hole(id); +; +alter table _albion.cell add constraint cell_b_fkey foreign key(b) REFERENCES _albion.hole(id); +; +alter table _albion.cell add constraint cell_c_fkey foreign key(c) REFERENCES _albion.hole(id); +; + +-- change section +alter table _albion.section alter column geom type geometry('MULTILINESTRING', $SRID) using st_multi(geom) +; +alter table _albion.section drop column group_id +; + +-- end_node now reference hole rather than collar +alter table _albion.end_node drop constraint end_node_collar_id_fkey; +; +alter table _albion.end_node rename column collar_id to hole_id +; +alter table _albion.end_node add constraint end_node_hole_id_fkey foreign key(hole_id) REFERENCES _albion.hole(id); +; + +drop table _albion.collar +; diff --git a/albion.sql b/albion.sql index b2915b4..369a9b8 100644 --- a/albion.sql +++ b/albion.sql @@ -10,17 +10,6 @@ create schema albion ------------------------------------------------------------------------------- -create or replace function public.st_3dvolume(geom geometry) -returns real -language plpgsql immutable -as -$$ - begin - return null; - end; -$$ -; - create or replace function albion.hole_geom(hole_id_ varchar) returns geometry language plpgsql stable @@ -156,7 +145,7 @@ create trigger collar_instead_trig for each row execute procedure albion.collar_instead_fct() ; -create view albion.metadata as select id, srid, close_collar_distance, snap_distance, precision, interpolation, end_node_relative_distance, end_node_thickness, end_angle, correlation_distance, correlation_angle, parent_correlation_angle from _albion.metadata +create view albion.metadata as select id, srid, close_collar_distance, snap_distance, precision, interpolation, end_node_relative_distance, end_node_thickness, correlation_distance, correlation_angle, parent_correlation_angle, version from _albion.metadata ; create view albion.layer as select name, fields_definition from _albion.layer @@ -832,6 +821,7 @@ join _albion.node as ns on ns.parent=pns.id join _albion.node as ne on ne.parent=pne.id, tan_ang where ns.graph_id = ne.graph_id and + ( ( abs(ns.from_-ns.to_) >= abs(ne.from_-ne.to_) and st_z(st_startpoint(ns.geom)) + st_distance(st_startpoint(ns.geom), st_startpoint(ne.geom))*tan_ang.parent_value + (st_z(st_3dlineinterpolatepoint(pne.geom, .5)) - st_z(st_3dlineinterpolatepoint(pns.geom, .5))) >= st_z(st_startpoint(ne.geom)) @@ -846,6 +836,7 @@ and and st_z(st_endpoint(ne.geom)) - st_distance(st_startpoint(ns.geom), st_startpoint(ne.geom))*tan_ang.parent_value + (st_z(st_3dlineinterpolatepoint(pns.geom, .5)) - st_z(st_3dlineinterpolatepoint(pne.geom, .5)) ) <= st_z(st_endpoint(ns.geom)) ) + ) ) select row_number() over() as id, * from result ; @@ -959,6 +950,8 @@ $$ select st_makeline(st_3dlineinterpolatepoint(s.geom, .5), st_3dlineinterpolatepoint(e.geom, .5)) from _albion.node as s, _albion.node as e where s.id=new.start_ and e.id=new.end_ into new_geom; + + -- TODO test if edge is possible end if; if tg_op = 'INSERT' then @@ -1001,28 +994,47 @@ returns setof geometry language plpython3u immutable as $$ -#open('/tmp/debug_input_%s.txt'%(cell_id_), 'w').write( -# cell_id_+'\n'+ -# graph_id_+'\n'+ -# geom_+'\n'+ -# ' '.join(holes_)+'\n'+ -# ' '.join(starts_)+'\n'+ -# ' '.join(ends_)+'\n'+ -# ' '.join(hole_ids_)+'\n'+ -# ' '.join(node_ids_)+'\n'+ -# ' '.join(nodes_)+'\n'+ -# ' '.join(end_ids_)+'\n'+ -# ' '.join(end_geoms_)+'\n' -#) +open('/tmp/debug_input_%s.txt'%(cell_id_), 'w').write( + cell_id_+'\n'+ + graph_id_+'\n'+ + geom_+'\n'+ + ' '.join(holes_)+'\n'+ + ' '.join(starts_)+'\n'+ + ' '.join(ends_)+'\n'+ + ' '.join(hole_ids_)+'\n'+ + ' '.join(node_ids_)+'\n'+ + ' '.join(nodes_)+'\n'+ + ' '.join(end_ids_)+'\n'+ + ' '.join(end_geoms_)+'\n' +) $INCLUDE_ELEMENTARY_VOLUME for v in elementary_volumes(holes_, starts_, ends_, hole_ids_, node_ids_, nodes_, end_ids_, end_geoms_, $SRID): yield v $$ ; -create or replace view albion.volume as -select id, graph_id, cell_id, triangulation, st_3dvolume(triangulation) as volume -from _albion.volume +create or replace function albion.volume_of_geom(multipoly geometry) +returns real +language plpython3u immutable +as +$$ + from shapely import wkb + import plpy + from numpy import array, average + + m = wkb.loads(bytes.fromhex(multipoly)) + volume = 0 + for p in m: + r = p.exterior.coords + v210 = r[2][0]*r[1][1]*r[0][2]; + v120 = r[1][0]*r[2][1]*r[0][2]; + v201 = r[2][0]*r[0][1]*r[1][2]; + v021 = r[0][0]*r[2][1]*r[1][2]; + v102 = r[1][0]*r[0][1]*r[2][2]; + v012 = r[0][0]*r[1][1]*r[2][2]; + volume += (1./6.)*(-v210 + v120 + v201 - v021 - v102 + v012) + return volume +$$ ; create or replace function albion.is_closed_volume(multipoly geometry) @@ -1045,6 +1057,11 @@ $$ $$ ; +create or replace view albion.volume as +select id, graph_id, cell_id, triangulation, albion.volume_of_geom(triangulation) as volume--, albion.is_closed_volume(triangulation) as is_closed +from _albion.volume +; + create or replace function albion.mesh_boundarie(multipoly geometry) returns geometry language plpython3u immutable @@ -1070,30 +1087,6 @@ $$ $$ ; -create or replace function albion.volume_of_geom(multipoly geometry) -returns real -language plpython3u immutable -as -$$ - from shapely import wkb - import plpy - from numpy import array, average - - m = wkb.loads(bytes.fromhex(multipoly)) - volume = 0 - for p in m: - r = p.exterior.coords - v210 = r[2][0]*r[1][1]*r[0][2]; - v120 = r[1][0]*r[2][1]*r[0][2]; - v201 = r[2][0]*r[0][1]*r[1][2]; - v021 = r[0][0]*r[2][1]*r[1][2]; - v102 = r[1][0]*r[0][1]*r[2][2]; - v012 = r[0][0]*r[1][1]*r[2][2]; - volume += (1./6.)*(-v210 + v120 + v201 - v021 - v102 + v012) - return volume -$$ -; - create or replace function albion.volume_union(multipoly geometry) returns geometry @@ -1408,7 +1401,7 @@ term as ( from albion.end_node_section as t ) select row_number() over() as id, st_multi(st_union(geom))::geometry('MULTIPOLYGON', 32632) as geom, graph_id, section_id -from (select * from poly union all select * from term) as t +from (select * from poly union all select * from term where st_isvalid(geom)) as t group by graph_id, section_id ; diff --git a/elementary_volume/__init__.py b/elementary_volume/__init__.py index ac8050e..601b250 100644 --- a/elementary_volume/__init__.py +++ b/elementary_volume/__init__.py @@ -197,8 +197,9 @@ def offset_coords(offsets, coords): def elementary_volumes(holes_, starts_, ends_, hole_ids_, node_ids_, nodes_, end_ids_, end_geoms_, srid_=32632): + #TODO add REL_DISTANCE and HEIGHT as parameters DEBUG = False - PRECI = 9 + PRECI = 6 REL_DISTANCE = .3 HEIGHT = 1. debug_files = [] @@ -211,6 +212,19 @@ def elementary_volumes(holes_, starts_, ends_, hole_ids_, node_ids_, nodes_, end edges = [(s, e) for s, e in zip(starts_, ends_)] assert(len(edges) == len(set(edges))) + + # translate everything close to origin to avoid numerical issues + translation = None + for id_ in nodes.keys(): + if translation is None: + translation = nodes[id_].coords[0] + nodes[id_] = translate(nodes[id_], -translation[0], -translation[1], -translation[2]) + + for id_ in ends.keys(): + for i in range(len(ends[id_])): + ends[id_][i] = translate(ends[id_][i], -translation[0], -translation[1], -translation[2]) + + graph = defaultdict(set) # undirected (edge in both directions) for e in edges: graph[e[0]].add(e[1]) @@ -291,9 +305,10 @@ def elementary_volumes(holes_, starts_, ends_, hole_ids_, node_ids_, nodes_, end if p and p not in offsets: if face_lines[i].points[0] in offsets and face_lines[i].points[-1] in offsets\ and face_lines[j].points[0] in offsets and face_lines[j].points[-1] in offsets: - offsets[p] = sym_split( + splt = sym_split( offset_coords(offsets, [face_lines[i].points[0], face_lines[i].points[-1]]), offset_coords(offsets, [face_lines[j].points[0], face_lines[j].points[-1]])) + offsets[p] = splt if splt else p else: offsets[p] = p @@ -522,9 +537,40 @@ def pop_connected(n, graph): connected.append(pop_connected(n, graph)) for c in connected: - r = MultiPolygon([result[i] for i in c]) - geos.lgeos.GEOSSetSRID(r._geom, srid_) - yield r.wkb_hex + res = MultiPolygon([result[i] for i in c]) + if DEBUG: + open("/tmp/volume_tr.obj", 'w').write(to_obj(res.wkb_hex)) + # check volume is closed + edges = set() + for p in res: + for s, e in zip(p.exterior.coords[:-1], p.exterior.coords[1:]): + if (e, s) in edges: + edges.remove((e, s)) + else: + edges.add((s, e)) + if len(edges): + print("volume is not closed", edges) + open("/tmp/unconnected_edge.vtk", 'w').write(to_vtk(MultiLineString([LineString(e) for e in edges]).wkb_hex)) + + + # check volume is positive + volume = 0 + for p in res: + r = p.exterior.coords + v210 = r[2][0]*r[1][1]*r[0][2]; + v120 = r[1][0]*r[2][1]*r[0][2]; + v201 = r[2][0]*r[0][1]*r[1][2]; + v021 = r[0][0]*r[2][1]*r[1][2]; + v102 = r[1][0]*r[0][1]*r[2][2]; + v012 = r[0][0]*r[1][1]*r[2][2]; + volume += (1./6.)*(-v210 + v120 + v201 - v021 - v102 + v012) + if volume <= 0 : + print("volume is", volume) + + res = translate(res, translation[0], translation[1], translation[2]) + geos.lgeos.GEOSSetSRID(res._geom, srid_) + + yield res.wkb_hex for f in debug_files: os.remove(f) diff --git a/plugin.py b/plugin.py index cfe17e1..53448d4 100644 --- a/plugin.py +++ b/plugin.py @@ -69,7 +69,7 @@ def initGui(self): # (Qt.CTRL + Qt.ALT + Qt.Key_S, self.__select_next_group), (Qt.CTRL + Qt.ALT + Qt.Key_N, self.__next_section), (Qt.CTRL + Qt.ALT + Qt.Key_B, self.__previous_section), - (Qt.CTRL + Qt.ALT + Qt.Key_M, self.__add_section_from_selection), + (Qt.CTRL + Qt.ALT + Qt.Key_J, self.__add_section_from_selection), ): short = QShortcut(QKeySequence(keyseq), self.__iface.mainWindow()) @@ -482,22 +482,22 @@ def __new_project(self): QMessageBox.Yes | QMessageBox.No, ).exec_() ): - return - Project.delete(project_name) + self.__iface.messageBar().pushInfo("Albion:", "keeping existing database...") + else: + Project.delete(project_name) + self.__iface.messageBar().pushInfo("Albion:", "creating project...") + Project.create(project_name, srid) if os.path.exists(fil): os.remove(fil) - self.__iface.messageBar().pushInfo("Albion:", "creating project...") - Project.create(project_name, srid) - # load template - #open(fil, "w").write( - # open(resource("template_project.qgs")) - # .read() - # .replace("template_project", project_name) - # .replace("32632", str(srid)) - #) + open(fil, "w").write( + open(resource("template_project.qgs")) + .read() + .replace("template_project", project_name) + .replace("32632", str(srid)) + ) self.__iface.newProject() QgsProject.instance().setFileName(fil) QgsProject.instance().read() @@ -527,7 +527,7 @@ def __import_data(self): self.__iface.messageBar().pushWidget(progressMessageBar) self.project.import_data(dir_, ProgressBar(progress)) - self.project.triangulate() + #self.project.triangulate() self.project.create_section_view_0_90(4) self.__iface.messageBar().clearWidgets() @@ -715,6 +715,9 @@ def __export_elementary_volume(self): layer = self.__layer("cell") if not layer: + self.__iface.messageBar().pushWarning( + "Albion", "cell layer must be selected" + ) return graph = self.__current_graph.currentText() diff --git a/project.py b/project.py index 5da0736..f8896b3 100644 --- a/project.py +++ b/project.py @@ -263,11 +263,32 @@ def add_table(self, table, values=None): def update(self): "reload schema albion without changing data" + + with self.connect() as con: cur = con.cursor() cur.execute("select srid from albion.metadata") srid, = cur.fetchone() cur.execute("drop schema if exists albion cascade") + + # test if version number is in metadata + cur.execute(""" + select column_name + from information_schema.columns where table_name = 'metadata' + and column_name='version' + """); + if cur.fetchone(): + # here goes future upgrades + cur.execute("select version from albion.metadata") + else: + # old albion version, we upgrade the data + for statement in ( + open(os.path.join(os.path.dirname(__file__), "_albion_v1_to_v2.sql")) + .read() + .split("\n;\n")[:-1] + ): + cur.execute(statement.replace("$SRID", str(srid))) + include_elementary_volume = open( os.path.join( os.path.dirname(__file__), "elementary_volume", "__init__.py" diff --git a/res/template_project.qgs b/res/template_project.qgs index ae810ec..457c4fe 100644 --- a/res/template_project.qgs +++ b/res/template_project.qgs @@ -19,49 +19,55 @@ - + - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - + - + - + @@ -80,35 +86,37 @@ section_geom_7c5467f1_628b_4313_a00b_a79b3801f4c0 section_intersection_13a1d3a9_897b_48fc_9714_e20439ad1ff6 section_polygon_f49e48f4_9101_4351_a07c_0a99748eaca2 + close_collar_95b0fcfd_f8c9_476f_9b9d_39d3d8c782f7 - + - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + meters - 31738882.47595356032252312 - 33490501.01186897233128548 - 31740105.545461256057024 - 33491314.78998938575387001 + 31739052.35575000196695328 + 33490786.30525000020861626 + 31739525.45425000041723251 + 33491101.08475000038743019 0 @@ -127,91 +135,92 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 31739063.62000000104308128 - 33490793.80000000074505806 - 31739514.19000000134110451 - 33491093.58999999985098839 - + cell_99e875c2_110e_4f52_a7f4_54ea9cff1367 dbname='template_project' host=127.0.0.1 port=55432 sslmode=disable key='"id"' srid=32632 type=Polygon checkPrimaryKeyUnicity='1' table="albion"."cell" (geom) sql= @@ -269,26 +278,26 @@ 1 1 - + - - - - - - - - - - - - - + + + + + + + + + + + + + @@ -336,24 +345,24 @@ - - - - + + + + - - - - + + + + - - - - + + + + @@ -365,7 +374,7 @@ - + @@ -385,7 +394,212 @@ - + + close_collar_95b0fcfd_f8c9_476f_9b9d_39d3d8c782f7 + dbname='import_test' host=127.0.0.1 port=55432 sslmode=disable key='"id"' srid=32632 type=PointZ checkPrimaryKeyUnicity='1' table="albion"."close_collar" (geom) sql= + + + + close_collar + + + +proj=utm +zone=32 +datum=WGS84 +units=m +no_defs + 3116 + 32632 + EPSG:32632 + WGS 84 / UTM zone 32N + utm + WGS84 + false + + + + + + + dataset + + + + + + + + + + + + + + + + + +proj=utm +zone=32 +datum=WGS84 +units=m +no_defs + 3116 + 32632 + EPSG:32632 + WGS 84 / UTM zone 32N + utm + WGS84 + false + + + + + + + + + + + + + postgres + + + + + + + + + + + 1 + 1 + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 0 + 0 + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 0 + + + 0 + generatedlayout + + + + + + + + id + + + 31739063.62000000104308128 33490793.80000000074505806 @@ -449,33 +663,33 @@ 1 1 - + - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + @@ -523,24 +737,24 @@ - - - - + + + + - - - - + + + + - - - - + + + + @@ -552,7 +766,7 @@ - + @@ -572,7 +786,7 @@ - + edge_32c6a82a_82cd_477f_b119_398536a6b6ed dbname='template_project' host=127.0.0.1 port=55432 sslmode=disable key='"id"' srid=32632 type=LineStringZ checkPrimaryKeyUnicity='1' table="albion"."edge" (geom) sql= @@ -630,31 +844,31 @@ 1 1 - + - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + @@ -702,24 +916,24 @@ - - - - + + + + - - - - + + + + - - - - + + + + @@ -731,7 +945,7 @@ - + @@ -751,7 +965,7 @@ - + edge_section_8b745326_1406_43a8_803e_8ee85be59103 dbname='template_project' host=127.0.0.1 port=55432 sslmode=disable key='"id"' srid=32632 type=LineString checkPrimaryKeyUnicity='1' table="albion"."edge_section" (geom) sql= @@ -809,31 +1023,31 @@ 1 1 - + - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + @@ -895,30 +1109,30 @@ - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + @@ -932,7 +1146,7 @@ - + @@ -952,7 +1166,7 @@ - + end_node_section_node_geom_f653243c_2e98_4638_b428_1acca01868dc dbname='template_project' host=127.0.0.1 port=55432 sslmode=disable key='"id"' srid=32632 type=LineString checkPrimaryKeyUnicity='1' table="albion"."end_node_section" (node_geom) sql= @@ -1010,31 +1224,31 @@ 1 1 - + - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + @@ -1096,30 +1310,30 @@ - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + @@ -1133,7 +1347,7 @@ - + @@ -1153,9 +1367,9 @@ - + group_cell_ec51a010_ab41_49d7_ac55_8ce0cfbb8838 - dbname='template_project' host=127.0.0.1 port=55432 sslmode=disable key='"id"' srid=32632 type=Polygon checkPrimaryKeyUnicity='1' table="albion"."group_cell" (geom) sql= + dbname='template_project' host=127.0.0.1 port=55432 sslmode=disable key='id' srid=32632 type=Polygon checkPrimaryKeyUnicity='1' table="albion"."group_cell" (geom) sql=section_id='SN x4' @@ -1211,26 +1425,26 @@ 1 1 - + - - - - - - - - - - - - - + + + + + + + + + + + + + @@ -1278,24 +1492,24 @@ - - - - + + + + - - - - + + + + - - - - + + + + @@ -1307,7 +1521,7 @@ - + @@ -1327,7 +1541,7 @@ - + hole_section_1f8c7d9f_7032_4a97_8033_d7ee1c22ea2a dbname='template_project' host=127.0.0.1 port=55432 sslmode=disable key='"id"' srid=32632 type=LineString checkPrimaryKeyUnicity='1' table="albion"."hole_section" (geom) sql= @@ -1385,31 +1599,31 @@ 1 1 - + - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + @@ -1457,24 +1671,24 @@ - - - - + + + + - - - - + + + + - - - - + + + + @@ -1486,7 +1700,7 @@ - + @@ -1506,7 +1720,7 @@ - + named_section_cut_47ba5a59_cd54_4752_9fee_3cbe01d07af4 dbname='template_project' host=127.0.0.1 port=55432 sslmode=disable key='"id"' srid=32632 type=MultiLineString checkPrimaryKeyUnicity='1' table="albion"."named_section" (cut) sql= @@ -1564,31 +1778,31 @@ 1 1 - + - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + @@ -1636,24 +1850,24 @@ - - - - + + + + - - - - + + + + - - - - + + + + @@ -1665,7 +1879,7 @@ - + @@ -1685,7 +1899,7 @@ - + node_section_63e3816d_ea42_44c6_937c_65c10a3b3ac4 dbname='template_project' host=127.0.0.1 port=55432 sslmode=disable key='"id"' srid=32632 type=LineString checkPrimaryKeyUnicity='1' table="albion"."node_section" (geom) sql= @@ -1743,31 +1957,31 @@ 1 1 - + - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + @@ -1836,33 +2050,33 @@ - - - - - - - + + + + + + + - - - - - - - + + + + + + + - - - - - - - + + + + + + + @@ -1877,7 +2091,7 @@ - + @@ -1897,7 +2111,7 @@ - + possible_edge_a6b83b46_56da_4098_b0fe_e703633800f5 dbname='template_project' host=127.0.0.1 port=55432 sslmode=disable key='"id"' srid=32632 type=LineStringZ checkPrimaryKeyUnicity='1' table="albion"."possible_edge" (geom) sql= @@ -1955,31 +2169,31 @@ 1 1 - + - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + @@ -2027,24 +2241,24 @@ - - - - + + + + - - - - + + + + - - - - + + + + @@ -2056,7 +2270,7 @@ - + @@ -2076,7 +2290,7 @@ - + possible_edge_section_04705590_fcdc_4fe9_8309_3d2c648db28f dbname='template_project' host=127.0.0.1 port=55432 sslmode=disable key='"id"' srid=32632 type=LineString checkPrimaryKeyUnicity='1' table="albion"."possible_edge_section" (geom) sql= @@ -2134,31 +2348,31 @@ 1 1 - + - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + @@ -2213,27 +2427,27 @@ - - - - - + + + + + - - - - - + + + + + - - - - - + + + + + @@ -2246,7 +2460,7 @@ - + @@ -2266,13 +2480,7 @@ - - - 31739063.30036709830164909 - 33490657.7391928993165493 - 31739651.99177160114049911 - 33491093.58999999985098839 - + section_anchor_5a49e7a1_cea4_4a35_982c_00e7801cd6da dbname='template_project' host=127.0.0.1 port=55432 sslmode=disable key='"id"' srid=32632 type=LineString checkPrimaryKeyUnicity='1' table="albion"."section" (anchor) sql= @@ -2330,31 +2538,31 @@ 1 1 - + - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + @@ -2395,21 +2603,21 @@ - - - + + + - - - + + + - - - + + + @@ -2420,7 +2628,7 @@ - + @@ -2440,7 +2648,7 @@ - + section_geom_7c5467f1_628b_4313_a00b_a79b3801f4c0 dbname='template_project' host=127.0.0.1 port=55432 sslmode=disable key='"id"' srid=32632 type=MultiLineString checkPrimaryKeyUnicity='1' table="albion"."section" (geom) sql= @@ -2498,31 +2706,31 @@ 1 1 - + - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + @@ -2563,21 +2771,21 @@ - - - + + + - - - + + + - - - + + + @@ -2588,7 +2796,7 @@ - + @@ -2608,7 +2816,7 @@ - + section_intersection_13a1d3a9_897b_48fc_9714_e20439ad1ff6 dbname='template_project' host=127.0.0.1 port=55432 sslmode=disable key='"id"' srid=32632 type=Polygon checkPrimaryKeyUnicity='1' table="albion"."section_intersection" (geom) sql= @@ -2634,6 +2842,15 @@ dataset + + + + + + + + + @@ -2649,7 +2866,15 @@ false - + + + + + + + + + postgres @@ -2666,26 +2891,26 @@ 1 1 - + - - - - - - - - - - - - - + + + + + + + + + + + + + @@ -2694,17 +2919,35 @@ - + + + + + 0 0 1 + + + + + + + + + + - + @@ -2712,15 +2955,15 @@ - + - + - + @@ -2729,8 +2972,11 @@ - - + + + @@ -2740,16 +2986,35 @@ 0 - + 0 generatedlayout - - + + + + + + - + id - + section_polygon_f49e48f4_9101_4351_a07c_0a99748eaca2 dbname='template_project' host=127.0.0.1 port=55432 sslmode=disable key='"id"' srid=32632 type=MultiPolygon checkPrimaryKeyUnicity='1' table="albion"."section_polygon" (geom) sql= @@ -2807,26 +3072,26 @@ 1 1 - + - - - - - - - - - - - - - + + + + + + + + + + + + + @@ -2867,21 +3132,21 @@ - - - + + + - - - + + + - - - + + + @@ -2892,7 +3157,7 @@ - + @@ -2929,30 +3194,38 @@ + + + /home/vmo/albion/nt + 32632 + template_project + WGS84 - - 255 - 255 - 255 - 0 - 255 - 255 - 255 - + + meters + m2 + + + 2 + true + + + false + - false + true 16 + false + 30 false + 0 + false 0 - false 50 - true - 0 - 30 1 @@ -2960,22 +3233,15 @@ false - - false - - - 2 - true - - - 32632 - template_project - /home/vmo/albion/nt - - - m2 - meters - + + 255 + 255 + 255 + 255 + 255 + 0 + 255 + diff --git a/test/deviation_bug.py b/test/deviation_bug.py new file mode 100644 index 0000000..7c90872 --- /dev/null +++ b/test/deviation_bug.py @@ -0,0 +1,14 @@ +from __future__ import print_function +# coding = utf-8 + +if __name__ == "__main__": + from albion.project import Project + import os + from pglite import import_db + + for f,dbname in (('git1.dump', 'deviation_bug_test_1'), ('git2.dump', 'deviation_bug_test_2')): + if Project.exists(dbname): + Project.delete(dbname) + import_db(os.path.join(os.path.dirname(__file__), f), dbname) + + diff --git a/test/end_node.py b/test/end_node.py new file mode 100644 index 0000000..4cc9dd5 --- /dev/null +++ b/test/end_node.py @@ -0,0 +1,64 @@ +from __future__ import print_function +# coding = utf-8 + + +SQL = """ +INSERT INTO albion.collar(id, geom, depth_) VALUES + (1, 'SRID=32632;POINT(0 0 0)'::geometry, 100), + (2, 'SRID=32632;POINT(100 0 0)'::geometry, 100), + (3, 'SRID=32632;POINT(200 0 0)'::geometry, 100), + (4, 'SRID=32632;POINT(300 0 0)'::geometry, 100), + (5, 'SRID=32632;POINT(0 100 0)'::geometry, 100) +; +SELECT albion.triangulate() +; +REFRESH MATERIALIZED VIEW albion.all_edge +; +INSERT INTO albion.graph(id) VALUES + ('graph1') +; +INSERT INTO albion.node(id, graph_id, hole_id, from_, to_, geom) VALUES + (1, 'graph1', 2, 50, 100, albion.hole_piece(50, 100, '2')), + (2, 'graph1', 3, 0, 50, albion.hole_piece(0, 50, '3')) +; +INSERT INTO albion.edge(id, graph_id, start_, end_, geom) VALUES + (1, 'graph1', 1, 2, 'SRID=32632;LINESTRING(100 0 -75, 200 0 -25)'::geometry) +; +""" + + +if __name__ == "__main__": + from albion.project import Project + import os + import sys + import time + + + project_name = "end_node_test" + + if Project.exists(project_name): + Project.delete(project_name) + + project = Project.create(project_name, 32632) + start = time.time() + + with project.connect() as con: + cur = con.cursor() + for sql in SQL.split("\n;\n")[:-1]: + cur.execute(sql) + con.commit() + + cur.execute(""" + SELECT node_id, hole_id, st_astext(geom) + FROM albion.dynamic_end_node + WHERE hole_id !='5' + """) + for r in cur.fetchall(): + print(r) + + + + + + + diff --git a/test/import_test.py b/test/import.py similarity index 100% rename from test/import_test.py rename to test/import.py diff --git a/test/mineralisation.py b/test/mineralisation.py new file mode 100644 index 0000000..92f6a72 --- /dev/null +++ b/test/mineralisation.py @@ -0,0 +1,38 @@ + +""" +create table albion.test_mineralization( + id varchar primary key default _albion.unique_id()::varchar, + hole_id varchar not null references _albion.hole(id) on delete cascade on update cascade, + level_ real, + from_ real, + to_ real, + oc real, + accu real, + grade real, + comments varchar, + geom geometry('LINESTRINGZ', $SRID)) +; + +insert into albion.test_mineralization(hole_id, level_, from_, to_, oc, accu, grade) +select hole_id, (t.r).level_, (t.r).from_, (t.r).to_, (t.r).oc, (t.r).accu, (t.r).grade +from ( +select hole_id, albion.segmentation( + array_agg(gamma order by from_),array_agg(from_ order by from_), array_agg(to_ order by from_), + 1., 1., 10) as r +from _albion.radiometry +group by hole_id +) as t +; + +update albion.test_mineralization set geom=albion.hole_piece(from_, to_, hole_id) +; + +create view albion.current_test_mineralization_section as +select row_number() over() as id, m.hole_id, h.collar_id, m.level_, m.oc, m.accu, m.grade, s.id as section_id, + (albion.to_section(m.geom, s.anchor, s.scale))::geometry('LINESTRING', $SRID) as geom +from albion.test_mineralization as m +join _albion.hole as h on h.id=m.hole_id +join _albion.collar as c on c.id=h.collar_id +join _albion.section as s on st_intersects(s.geom, c.geom) +; +""" diff --git a/test/parent_graph_test.py b/test/parent_graph.py similarity index 100% rename from test/parent_graph_test.py rename to test/parent_graph.py diff --git a/test/tutorial.py b/test/tutorial.py new file mode 100644 index 0000000..bc77ef6 --- /dev/null +++ b/test/tutorial.py @@ -0,0 +1,88 @@ +from __future__ import print_function +# coding = utf-8 + +if __name__ == "__main__": + from albion.project import Project + import os + import sys + import time + import tempfile + import zipfile + + + + project_name = "tutorial_test" + + if Project.exists(project_name): + Project.delete(project_name) + + project = Project.create(project_name, 32632) + start = time.time() + zip_ref = zipfile.ZipFile(os.path.join(os.path.dirname(__file__), '..', 'data', 'nt.zip'), 'r') + zip_ref.extractall(tempfile.gettempdir()) + zip_ref.close() + data_dir = os.path.join(tempfile.gettempdir(), 'nt') + project.import_data(data_dir) + project.create_section_view_0_90(4) + project.compute_mineralization(1000, 1, 1) + + project.triangulate() + + with project.connect() as con: + cur = con.cursor() + cur.execute("select name from albion.layer") + layers = [r[0] for r in cur.fetchall()] + + print(layers) + #for l in layers: + # project.refresh_section_geom(l) + + + project.new_graph('330') + project.new_graph('min1000', '330') + + with project.connect() as con: + cur = con.cursor() + cur.execute(""" + insert into albion.node(from_, to_, hole_id, graph_id) + select from_, to_, hole_id, '330' from albion.formation where code=330 + """) + con.commit() + + project.accept_possible_edge('330') + project.create_volumes('330') + + # test that all volumes are closed and positive + with project.connect() as con: + cur = con.cursor() + cur.execute(""" + select cell_id from albion.volume where not albion.is_closed_volume(triangulation) limit 3 + """ + ) + print("unclosed volume for cells", cur.fetchall()) + cur.execute(""" + select count(1) from albion.volume where not albion.is_closed_volume(triangulation) + """ + ) + assert(cur.fetchone()[0]==0) + cur.execute(""" + select count(1) from albion.volume where albion.volume_of_geom(triangulation) <= 0 + """ + ) + assert(cur.fetchone()[0]==0) + + + with project.connect() as con: + cur = con.cursor() + cur.execute(""" + insert into albion.node(from_, to_, hole_id, graph_id) + select from_, to_, hole_id, 'min1000' from albion.mineralization + """) + + con.commit() + + project.accept_possible_edge('min1000') + project.create_volumes('min1000') + + + From 11eb32d1040f795509dc346231e2ace54ae85229 Mon Sep 17 00:00:00 2001 From: Vincent Mora Date: Wed, 23 Oct 2019 13:43:54 +0200 Subject: [PATCH 20/42] adds python dependencies in requirements.txt --- requirements.txt | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 requirements.txt diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..b2b297e --- /dev/null +++ b/requirements.txt @@ -0,0 +1,7 @@ +gitpython +dxfwrite +PyOpenGL +pglite +pyqt5 +psycopg2 +shapely From 442ce2dc957d185f4a054a5b032eeccddfa0f79c Mon Sep 17 00:00:00 2001 From: Vincent Mora Date: Thu, 24 Oct 2019 17:15:19 +0200 Subject: [PATCH 21/42] fixes import from older project --- _albion_v1_to_v2.sql | 13 + albion.sql | 16 + plugin.py | 11 +- project.py | 34 +- res/template_project.qgs | 1338 +++++++++++++++++++++++++------------- 5 files changed, 950 insertions(+), 462 deletions(-) diff --git a/_albion_v1_to_v2.sql b/_albion_v1_to_v2.sql index 509843f..41e121c 100644 --- a/_albion_v1_to_v2.sql +++ b/_albion_v1_to_v2.sql @@ -30,6 +30,9 @@ from (VALUES join information_schema.tables on table_schema = '_albion' and table_name = t.name ; +alter table if exists _albion.chemical add column id varchar primary key default _albion.unique_id()::varchar +; + -- merge collar and hole tables alter table _albion.hole alter column id set default _albion.unique_id()::varchar ; @@ -89,3 +92,13 @@ alter table _albion.end_node add constraint end_node_hole_id_fkey foreign key(ho drop table _albion.collar ; + +-- adds named_section +create table _albion.named_section( + id varchar primary key default _albion.unique_id()::varchar, + geom geometry('LINESTRING', $SRID) not null, + cut geometry('MULTILINESTRING', $SRID) not null, + section varchar not null references _albion.section(id) on delete cascade on update cascade +) +; + diff --git a/albion.sql b/albion.sql index 369a9b8..476d5df 100644 --- a/albion.sql +++ b/albion.sql @@ -1526,6 +1526,22 @@ $$ $$ ; +--create or replace function albion.triangle_intersection(t1_ geometry, t2_ geometry) +--returns geometry +--language plpgsql immutable +--as +--$$ +-- begin +-- return (select st_collect(geom) from +-- ( select a.geom +-- from st_dump(t1_) a, st_dump(t2_) b +-- where a.geom = st_reverse(b.geom) +-- ) as t); +-- +-- end; +--$$ +--; + create or replace view albion.volume_section as with touching_cell as ( diff --git a/plugin.py b/plugin.py index 53448d4..89fef86 100644 --- a/plugin.py +++ b/plugin.py @@ -4,7 +4,7 @@ from qgis.core import * from qgis.gui import * -from qgis.PyQt.QtCore import QObject, Qt, QFileInfo, QUrl +from qgis.PyQt.QtCore import QObject, Qt, QUrl from qgis.PyQt.QtWidgets import QComboBox, QShortcut, QToolBar, QMenu, QFileDialog, QInputDialog, QLineEdit, QMessageBox, QProgressBar, QApplication, QDockWidget from qgis.PyQt.QtGui import QKeySequence, QIcon, QDesktopServices @@ -336,10 +336,15 @@ def __previous_section(self): def __next_subsection(self): self.project.next_subsection(self.__current_section.currentText()) + print("refresh") self.__refresh_layers("section") + print("section") self.__viewer3d.widget().scene.update("section") + print("volume section") self.__viewer3d.widget().scene.update("volume_section") + print("3D update") self.__viewer3d.widget().update() + print("done done") def __previous_subsection(self): self.project.previous_subsection(self.__current_section.currentText()) @@ -476,7 +481,7 @@ def __new_project(self): != QMessageBox( QMessageBox.Information, "Delete existing DB", - "Database {} exits, to you want to delete it ?".format( + "Database {} exits, do you want to delete it ?".format( project_name ), QMessageBox.Yes | QMessageBox.No, @@ -777,7 +782,7 @@ def __import_project(self): project = Project.import_(dbname, dump) - QgsProject.instance().read(QFileInfo(prj)) + QgsProject.instance().read(prj) def __export_project(self): if self.project is None: diff --git a/project.py b/project.py index f8896b3..f6410a6 100644 --- a/project.py +++ b/project.py @@ -129,7 +129,6 @@ def connect(self): def vacuum(self): with self.connect() as con: - old_isolation_level = con.isolation_level con.set_isolation_level(0) cur = con.cursor() cur.execute("vacuum analyze") @@ -220,7 +219,7 @@ def create(project_name, srid): return project - def add_table(self, table, values=None): + def add_table(self, table, values=None, view_only=False): """ table: a dict with keys NAME: the name of the table to create @@ -237,7 +236,7 @@ def add_table(self, table, values=None): table['SET_FIELDS'] = ','.join(['{}=new.{}'.format(v,v) for v in fields]) with self.connect() as con: cur = con.cursor() - for file_ in ("_albion_table.sql", "albion_table.sql"): + for file_ in (("albion_table.sql",) if view_only else ("_albion_table.sql", "albion_table.sql")): for statement in ( open(os.path.join(os.path.dirname(__file__), file_)) .read() @@ -279,7 +278,7 @@ def update(self): """); if cur.fetchone(): # here goes future upgrades - cur.execute("select version from albion.metadata") + cur.execute("select version from _albion.metadata") else: # old albion version, we upgrade the data for statement in ( @@ -305,21 +304,19 @@ def update(self): ) ) - cur.execute("select name, fields_definition from albion.layers") - tables = [{'NAME': r[0], 'FIELDS_DEFINITION': r[1]} for r in cur.fetchall()] - for table in tables: - for statement in ( - open(os.path.join(os.path.dirname(__file__), "albion_table.sql")) - .read() - .split("\n;\n")[:-1] - ): - table['SRID'] = str(srid) - cur.execute( - string.Template(statement).substitute(table) - ) con.commit() + cur.execute("select name, fields_definition from albion.layer") + tables = [{'NAME': r[0], 'FIELDS_DEFINITION': r[1]} for r in cur.fetchall()] + + for table in tables: + table['SRID'] = str(srid) + self.add_table(table, view_only=True) + + self.vacuum() + def export_sections(self, graph): + # TODO assert(False) pass @@ -563,6 +560,7 @@ def next_section(self, section): def next_subsection(self, section): with self.connect() as con: + print("select section from distance") cur = con.cursor() cur.execute( """ @@ -577,6 +575,7 @@ def next_subsection(self, section): if not res: return group = res[0] or 0 + print("select geom for next") cur.execute( """ select geom from albion.section_geom @@ -586,12 +585,14 @@ def next_subsection(self, section): limit 1 """.format( group=group, section=section) ) res = cur.fetchone() + print("update section") if res: sql = """ update albion.section set geom=st_multi('{}'::geometry) where id='{}' """.format(res[0], section) cur.execute(sql) con.commit() + print("done") def previous_subsection(self, section): with self.connect() as con: @@ -867,6 +868,7 @@ def export(self, filename): def import_(name, filename): import_db(filename, name) project = Project(name) + project.update() project.create_sections() return project diff --git a/res/template_project.qgs b/res/template_project.qgs index 457c4fe..109d571 100644 --- a/res/template_project.qgs +++ b/res/template_project.qgs @@ -1,5 +1,5 @@ - + @@ -19,57 +19,66 @@ - + - + - + - + - - + + + + + + + + + + + + + + + + + + + + - - + + + + + + + + + + + - + - + - + - + - + - - - - - - - - - - - - - - - - - - cell_99e875c2_110e_4f52_a7f4_54ea9cff1367 collar_7e814841_4cc9_495a_8ef6_9229fcfffb5e @@ -78,45 +87,45 @@ end_node_section_node_geom_f653243c_2e98_4638_b428_1acca01868dc group_cell_ec51a010_ab41_49d7_ac55_8ce0cfbb8838 hole_section_1f8c7d9f_7032_4a97_8033_d7ee1c22ea2a - named_section_cut_47ba5a59_cd54_4752_9fee_3cbe01d07af4 node_section_63e3816d_ea42_44c6_937c_65c10a3b3ac4 possible_edge_a6b83b46_56da_4098_b0fe_e703633800f5 possible_edge_section_04705590_fcdc_4fe9_8309_3d2c648db28f section_anchor_5a49e7a1_cea4_4a35_982c_00e7801cd6da - section_geom_7c5467f1_628b_4313_a00b_a79b3801f4c0 section_intersection_13a1d3a9_897b_48fc_9714_e20439ad1ff6 section_polygon_f49e48f4_9101_4351_a07c_0a99748eaca2 close_collar_95b0fcfd_f8c9_476f_9b9d_39d3d8c782f7 + section_geom_cbc425ee_c515_4cda_8fec_53f986b4dc2f + named_section_geom_d56ae49a_c71c_485f_84ea_2a788ff48e0b - + - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + meters - 31739052.35575000196695328 - 33490786.30525000020861626 - 31739525.45425000041723251 - 33491101.08475000038743019 + 31739170.31633691489696503 + 33490644.32408057525753975 + 31740053.80415702611207962 + 33491232.15907534584403038 0 @@ -134,93 +143,106 @@ 0 + - - - - - + + - + - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - + - + - + - - - - - - - - - - - - - - - - - - - + + + 31739063.62000000104308128 + 33490793.80000000074505806 + 31739514.19000000134110451 + 33491093.58999999985098839 + cell_99e875c2_110e_4f52_a7f4_54ea9cff1367 dbname='template_project' host=127.0.0.1 port=55432 sslmode=disable key='"id"' srid=32632 type=Polygon checkPrimaryKeyUnicity='1' table="albion"."cell" (geom) sql= @@ -278,10 +300,10 @@ 1 1 - + - - + + @@ -295,9 +317,9 @@ @@ -359,20 +381,20 @@ - - - - + + + + - - - - + + + + - + @@ -394,9 +416,9 @@ - + close_collar_95b0fcfd_f8c9_476f_9b9d_39d3d8c782f7 - dbname='import_test' host=127.0.0.1 port=55432 sslmode=disable key='"id"' srid=32632 type=PointZ checkPrimaryKeyUnicity='1' table="albion"."close_collar" (geom) sql= + dbname='template_project' host=127.0.0.1 port=55432 sslmode=disable key='"id"' srid=32632 type=PointZ checkPrimaryKeyUnicity='1' table="albion"."close_collar" (geom) sql= @@ -445,7 +467,7 @@ - + @@ -469,10 +491,10 @@ 1 1 - + - - + + @@ -493,9 +515,9 @@ @@ -505,24 +527,25 @@ - + 0 0 1 - - + + + - + @@ -548,19 +571,19 @@ - + - + - + - @@ -593,13 +616,13 @@ def my_form_open(dialog, layer, feature): - + id - + 31739063.62000000104308128 33490793.80000000074505806 @@ -663,10 +686,10 @@ def my_form_open(dialog, layer, feature): 1 1 - + - - + + @@ -687,9 +710,9 @@ def my_form_open(dialog, layer, feature): @@ -751,20 +774,20 @@ def my_form_open(dialog, layer, feature): - - - - + + + + - - - - + + + + - + @@ -786,7 +809,13 @@ def my_form_open(dialog, layer, feature): - + + + 31739088.55057749897241592 + 33490793.3475789986550808 + 31739505.09139769896864891 + 33491092.41476880013942719 + edge_32c6a82a_82cd_477f_b119_398536a6b6ed dbname='template_project' host=127.0.0.1 port=55432 sslmode=disable key='"id"' srid=32632 type=LineStringZ checkPrimaryKeyUnicity='1' table="albion"."edge" (geom) sql= @@ -844,10 +873,10 @@ def my_form_open(dialog, layer, feature): 1 1 - + - - + + @@ -866,9 +895,9 @@ def my_form_open(dialog, layer, feature): @@ -930,20 +959,20 @@ def my_form_open(dialog, layer, feature): - - - - + + + + - - - - + + + + - + @@ -965,7 +994,13 @@ def my_form_open(dialog, layer, feature): - + + + 31739237.11582300066947937 + 33490483.44733380153775215 + 31739828.13419400155544281 + 33491092.31071420013904572 + edge_section_8b745326_1406_43a8_803e_8ee85be59103 dbname='template_project' host=127.0.0.1 port=55432 sslmode=disable key='"id"' srid=32632 type=LineString checkPrimaryKeyUnicity='1' table="albion"."edge_section" (geom) sql= @@ -1023,10 +1058,10 @@ def my_form_open(dialog, layer, feature): 1 1 - + - - + + @@ -1045,9 +1080,9 @@ def my_form_open(dialog, layer, feature): @@ -1127,24 +1162,24 @@ def my_form_open(dialog, layer, feature): - - - - - - + + + + + + - - - - - - + + + + + + - + @@ -1166,7 +1201,13 @@ def my_form_open(dialog, layer, feature): - + + + 31739088.52377190068364143 + 33490480.24929559975862503 + 31739830.13416960090398788 + 33491017.96951229870319366 + end_node_section_node_geom_f653243c_2e98_4638_b428_1acca01868dc dbname='template_project' host=127.0.0.1 port=55432 sslmode=disable key='"id"' srid=32632 type=LineString checkPrimaryKeyUnicity='1' table="albion"."end_node_section" (node_geom) sql= @@ -1224,10 +1265,10 @@ def my_form_open(dialog, layer, feature): 1 1 - + - - + + @@ -1246,9 +1287,9 @@ def my_form_open(dialog, layer, feature): @@ -1328,24 +1369,24 @@ def my_form_open(dialog, layer, feature): - - - - - - + + + + + + - - - - - - + + + + + + - + @@ -1367,9 +1408,15 @@ def my_form_open(dialog, layer, feature): - + + + 31739104.19999999925494194 + 33490793.80000000074505806 + 31739505.76999999955296516 + 33490839.64999999850988388 + group_cell_ec51a010_ab41_49d7_ac55_8ce0cfbb8838 - dbname='template_project' host=127.0.0.1 port=55432 sslmode=disable key='id' srid=32632 type=Polygon checkPrimaryKeyUnicity='1' table="albion"."group_cell" (geom) sql=section_id='SN x4' + dbname='template_project' host=127.0.0.1 port=55432 sslmode=disable key='id' srid=32632 type=Polygon checkPrimaryKeyUnicity='1' table="albion"."group_cell" (geom) sql=section_id='WE x4' @@ -1425,10 +1472,10 @@ def my_form_open(dialog, layer, feature): 1 1 - + - - + + @@ -1442,9 +1489,9 @@ def my_form_open(dialog, layer, feature): @@ -1506,20 +1553,20 @@ def my_form_open(dialog, layer, feature): - - - - + + + + - - - - + + + + - + @@ -1541,7 +1588,13 @@ def my_form_open(dialog, layer, feature): - + + + 31739063.6191214993596077 + 33490411.37305669859051704 + 31739921.39477939903736115 + 33491092.86334149911999702 + hole_section_1f8c7d9f_7032_4a97_8033_d7ee1c22ea2a dbname='template_project' host=127.0.0.1 port=55432 sslmode=disable key='"id"' srid=32632 type=LineString checkPrimaryKeyUnicity='1' table="albion"."hole_section" (geom) sql= @@ -1599,10 +1652,10 @@ def my_form_open(dialog, layer, feature): 1 1 - + - - + + @@ -1621,9 +1674,9 @@ def my_form_open(dialog, layer, feature): @@ -1685,20 +1738,20 @@ def my_form_open(dialog, layer, feature): - - - - + + + + - - - - + + + + - + @@ -1720,13 +1773,19 @@ def my_form_open(dialog, layer, feature): - - named_section_cut_47ba5a59_cd54_4752_9fee_3cbe01d07af4 - dbname='template_project' host=127.0.0.1 port=55432 sslmode=disable key='"id"' srid=32632 type=MultiLineString checkPrimaryKeyUnicity='1' table="albion"."named_section" (cut) sql= + + + 31739063.62000000104308128 + 33490793.80000000074505806 + 31739514.19000000134110451 + 33491093.58999999985098839 + + named_section_geom_d56ae49a_c71c_485f_84ea_2a788ff48e0b + dbname='template_project' host=127.0.0.1 port=55432 sslmode=disable key='"id"' srid=32632 type=LineString checkPrimaryKeyUnicity='1' table="albion"."named_section" (geom) sql= - named_section.cut + named_section.geom +proj=utm +zone=32 +datum=WGS84 +units=m +no_defs @@ -1746,6 +1805,15 @@ def my_form_open(dialog, layer, feature): dataset + + + + + + + + + @@ -1761,7 +1829,15 @@ def my_form_open(dialog, layer, feature): false - + + + + + + + + + postgres @@ -1769,8 +1845,8 @@ def my_form_open(dialog, layer, feature): - - + + @@ -1778,19 +1854,78 @@ def my_form_open(dialog, layer, feature): 1 1 - + + + + + + - - + + - + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -1800,49 +1935,97 @@ def my_form_open(dialog, layer, feature): + + + + + + + + + + + + + + + + + + + + + + + + + + - + + + + + 0 0 1 + + + + + + + + + + - + - - + + - - + + - - + + @@ -1851,36 +2034,42 @@ def my_form_open(dialog, layer, feature): - - - + + + - + - - - - + + + + - - - - + + + + - + - + + @@ -1890,16 +2079,48 @@ def my_form_open(dialog, layer, feature): 0 - + 0 generatedlayout - - + + + + + + + + + + + + - + id - + + + 31739088.52377190068364143 + 33490480.24929559975862503 + 31739830.13416960090398788 + 33491092.32762109860777855 + node_section_63e3816d_ea42_44c6_937c_65c10a3b3ac4 dbname='template_project' host=127.0.0.1 port=55432 sslmode=disable key='"id"' srid=32632 type=LineString checkPrimaryKeyUnicity='1' table="albion"."node_section" (geom) sql= @@ -1957,10 +2178,10 @@ def my_form_open(dialog, layer, feature): 1 1 - + - - + + @@ -1979,9 +2200,9 @@ def my_form_open(dialog, layer, feature): @@ -2070,26 +2291,26 @@ def my_form_open(dialog, layer, feature): - - - - - - - + + + + + + + - - - - - - - + + + + + + + - + @@ -2111,7 +2332,13 @@ def my_form_open(dialog, layer, feature): - + + + 31739088.55057749897241592 + 33490793.3475789986550808 + 31739505.09139769896864891 + 33491092.41476880013942719 + possible_edge_a6b83b46_56da_4098_b0fe_e703633800f5 dbname='template_project' host=127.0.0.1 port=55432 sslmode=disable key='"id"' srid=32632 type=LineStringZ checkPrimaryKeyUnicity='1' table="albion"."possible_edge" (geom) sql= @@ -2169,10 +2396,10 @@ def my_form_open(dialog, layer, feature): 1 1 - + - - + + @@ -2191,9 +2418,9 @@ def my_form_open(dialog, layer, feature): @@ -2239,12 +2466,20 @@ def my_form_open(dialog, layer, feature): + + + + + + + @@ -2253,22 +2488,25 @@ def my_form_open(dialog, layer, feature): + - - - - + + + + + - - - - + + + + + - + @@ -2290,7 +2528,13 @@ def my_form_open(dialog, layer, feature): - + + + 31739237.11582300066947937 + 33490483.44733380153775215 + 31739828.13419400155544281 + 33491092.31071420013904572 + possible_edge_section_04705590_fcdc_4fe9_8309_3d2c648db28f dbname='template_project' host=127.0.0.1 port=55432 sslmode=disable key='"id"' srid=32632 type=LineString checkPrimaryKeyUnicity='1' table="albion"."possible_edge_section" (geom) sql= @@ -2348,10 +2592,10 @@ def my_form_open(dialog, layer, feature): 1 1 - + - - + + @@ -2370,9 +2614,9 @@ def my_form_open(dialog, layer, feature): @@ -2425,6 +2669,13 @@ def my_form_open(dialog, layer, feature): + + + + + + @@ -2432,6 +2683,7 @@ def my_form_open(dialog, layer, feature): + @@ -2441,24 +2693,27 @@ def my_form_open(dialog, layer, feature): + - - - - - + + + + + + - - - - - + + + + + + - + @@ -2480,7 +2735,13 @@ def my_form_open(dialog, layer, feature): - + + + 31739063.30036709830164909 + 33490657.7391928993165493 + 31739651.99177160114049911 + 33491093.58999999985098839 + section_anchor_5a49e7a1_cea4_4a35_982c_00e7801cd6da dbname='template_project' host=127.0.0.1 port=55432 sslmode=disable key='"id"' srid=32632 type=LineString checkPrimaryKeyUnicity='1' table="albion"."section" (anchor) sql= @@ -2538,10 +2799,10 @@ def my_form_open(dialog, layer, feature): 1 1 - + - - + + @@ -2560,9 +2821,9 @@ def my_form_open(dialog, layer, feature): @@ -2594,6 +2855,13 @@ def my_form_open(dialog, layer, feature): + + + + + + @@ -2605,28 +2873,32 @@ def my_form_open(dialog, layer, feature): - + + + - - - + + + + - - - + + + + - + @@ -2648,8 +2920,14 @@ def my_form_open(dialog, layer, feature): - - section_geom_7c5467f1_628b_4313_a00b_a79b3801f4c0 + + + 31739104.19999999925494194 + 33490793.85999999940395355 + 31739505.76999999955296516 + 33491092.85000000149011612 + + section_geom_cbc425ee_c515_4cda_8fec_53f986b4dc2f dbname='template_project' host=127.0.0.1 port=55432 sslmode=disable key='"id"' srid=32632 type=MultiLineString checkPrimaryKeyUnicity='1' table="albion"."section" (geom) sql= @@ -2674,6 +2952,15 @@ def my_form_open(dialog, layer, feature): dataset + + + + + + + + + @@ -2689,7 +2976,15 @@ def my_form_open(dialog, layer, feature): false - + + + + + + + + + postgres @@ -2697,8 +2992,8 @@ def my_form_open(dialog, layer, feature): - - + + @@ -2706,19 +3001,51 @@ def my_form_open(dialog, layer, feature): 1 1 - + + + + + + - - + + - + - + + + + + + + + + + + + + + + + + + + + + + + + @@ -2728,42 +3055,124 @@ def my_form_open(dialog, layer, feature): + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + + + + 0 0 1 + + + + + + + + + + - + - + + + + + + + - + @@ -2773,31 +3182,41 @@ def my_form_open(dialog, layer, feature): - + + + - - - + + + + - - - + + + + - + - + + @@ -2807,16 +3226,42 @@ def my_form_open(dialog, layer, feature): 0 - + 0 generatedlayout - - + + + + + + + + + + + + - + id - + section_intersection_13a1d3a9_897b_48fc_9714_e20439ad1ff6 dbname='template_project' host=127.0.0.1 port=55432 sslmode=disable key='"id"' srid=32632 type=Polygon checkPrimaryKeyUnicity='1' table="albion"."section_intersection" (geom) sql= @@ -2867,7 +3312,7 @@ def my_form_open(dialog, layer, feature): - + @@ -2891,10 +3336,10 @@ def my_form_open(dialog, layer, feature): 1 1 - + - - + + @@ -2908,9 +3353,9 @@ def my_form_open(dialog, layer, feature): @@ -2920,24 +3365,25 @@ def my_form_open(dialog, layer, feature): - + 0 0 1 - - + + + - + @@ -2963,19 +3409,19 @@ def my_form_open(dialog, layer, feature): - + - + - + - @@ -3008,13 +3454,19 @@ def my_form_open(dialog, layer, feature): - + id - + + + 31739081.25440400093793869 + 33490480.24929559975862503 + 31739830.13419400155544281 + 33491092.32762109860777855 + section_polygon_f49e48f4_9101_4351_a07c_0a99748eaca2 dbname='template_project' host=127.0.0.1 port=55432 sslmode=disable key='"id"' srid=32632 type=MultiPolygon checkPrimaryKeyUnicity='1' table="albion"."section_polygon" (geom) sql= @@ -3072,10 +3524,10 @@ def my_form_open(dialog, layer, feature): 1 1 - + - - + + @@ -3089,9 +3541,9 @@ def my_form_open(dialog, layer, feature): @@ -3144,18 +3596,18 @@ def my_form_open(dialog, layer, feature): - - - + + + - - - + + + - + @@ -3186,61 +3638,61 @@ def my_form_open(dialog, layer, feature): - - + + + + 1 + + + false + 16 + 30 + 0 + true + false + false + 50 + 0 + + + false + + + meters + m2 + - /home/vmo/albion/nt 32632 + /home/vmo/albion/nt template_project WGS84 - - meters - m2 - - 2 true + 2 - - false - - - true - 16 - false - 30 - false - 0 - false - 0 - 50 - - - 1 - false - 255 - 255 - 255 255 - 255 0 255 + 255 + 255 + 255 + 255 From 9e363af27deaffc720dcf09cb933ee38b485c2c1 Mon Sep 17 00:00:00 2001 From: Vincent Mora Date: Sat, 26 Oct 2019 19:10:03 +0200 Subject: [PATCH 22/42] fix volume generation and accelarates export of elementary volumes --- _albion.sql | 11 ++++++ albion.sql | 50 ++++++++++++++++++++++++--- elementary_volume/__init__.py | 9 +++-- export_elementary_volume.py | 45 ++++++++---------------- project.py | 64 ++++++++++++++--------------------- test/export.py | 19 +++++++++++ test/tutorial.py | 32 ++++++++++++------ 7 files changed, 144 insertions(+), 86 deletions(-) create mode 100644 test/export.py diff --git a/_albion.sql b/_albion.sql index 1d57fb3..0dc32de 100644 --- a/_albion.sql +++ b/_albion.sql @@ -206,3 +206,14 @@ create table _albion.named_section( ) ; +create table _albion.vertical_face( + id varchar primary key default _albion.unique_id()::varchar, + graph_id varchar not null references _albion.graph(id) on delete cascade on update cascade, + left_hole_id varchar not null references _albion.hole(id) on delete cascade on update cascade, + right_hole_id varchar not null references _albion.hole(id) on delete cascade on update cascade, + triangulation geometry('MULTIPOLYGONZ', $SRID) not null +); + + + + diff --git a/albion.sql b/albion.sql index 476d5df..eabf6b2 100644 --- a/albion.sql +++ b/albion.sql @@ -9,6 +9,26 @@ create schema albion -- UTILITY FUNCTIONS ------------------------------------------------------------------------------- +create or replace function albion.triangle_aspect_ratio(geom geometry) +returns float +language plpgsql +as +$$ + declare + a float; + b float; + c float; + s float; + begin + a := st_distance(st_pointn(st_exteriorring(geom), 1), st_pointn(st_exteriorring(geom), 2)); + b := st_distance(st_pointn(st_exteriorring(geom), 2), st_pointn(st_exteriorring(geom), 3)); + c := st_distance(st_pointn(st_exteriorring(geom), 3), st_pointn(st_exteriorring(geom), 1)); + s := (a+b+c)/2; + return a*b*c/(8*(s-a)*(s-b)*(s-c)); + + end; +$$ +; create or replace function albion.hole_geom(hole_id_ varchar) returns geometry @@ -217,7 +237,28 @@ select distinct on (a.id) a.id, a.geom from albion.collar as a, albion.collar as where a.id != b.id and st_dwithin(a.geom, b.geom, m.close_collar_distance) ; -create view albion.cell as select id, a, b, c, geom::geometry('POLYGON', $SRID) from _albion.cell +create view albion.cell as select id, a, b, c, geom::geometry('POLYGON', $SRID), albion.triangle_aspect_ratio(geom) as aspect_ratio from _albion.cell +; + +create or replace function albion.cell_after_fct() +returns trigger +language plpgsql +as +$$ + begin + refresh materialized view albion.all_edge; + return null; + end; +$$ +; + +-- this trigger should work on the view instead of the table, but for unknown reason it doesn't, so we put it on the table +drop trigger if exists cell_after_trig ON _albion.cell +; + +create trigger cell_after_trig + after delete on _albion.cell + for each statement execute procedure albion.cell_after_fct() ; create or replace function albion.tesselate(polygon_ geometry, lines_ geometry, points_ geometry) @@ -1378,7 +1419,7 @@ edge as ( ), poly as ( select - ('SRID=32632; POLYGON(('|| + ('SRID=$SRID; POLYGON(('|| st_x(st_startpoint(ns.geom)) ||' '||st_y(st_startpoint(ns.geom))||','|| st_x(st_endpoint(ns.geom)) ||' '||st_y(st_endpoint(ns.geom)) ||','|| st_x(st_endpoint(ne.geom)) ||' '||st_y(st_endpoint(ne.geom)) ||','|| @@ -1390,7 +1431,7 @@ poly as ( join node as ne on ne.node_id=e.end_ and ne.section_id=e.section_id ), term as ( - select ('SRID=32632; POLYGON(('|| + select ('SRID=$SRID; POLYGON(('|| st_x(st_startpoint(t.node_geom)) ||' '||st_y(st_startpoint(t.node_geom))||','|| st_x(st_endpoint(t.node_geom)) ||' '||st_y(st_endpoint(t.node_geom)) ||','|| st_x(st_endpoint(t.geom)) ||' '||st_y(st_endpoint(t.geom)) ||','|| @@ -1400,7 +1441,7 @@ term as ( t.graph_id, t.section_id from albion.end_node_section as t ) -select row_number() over() as id, st_multi(st_union(geom))::geometry('MULTIPOLYGON', 32632) as geom, graph_id, section_id +select row_number() over() as id, st_multi(st_union(geom))::geometry('MULTIPOLYGON', $SRID) as geom, graph_id, section_id from (select * from poly union all select * from term where st_isvalid(geom)) as t group by graph_id, section_id ; @@ -1658,7 +1699,6 @@ $$ ; - -- TODO -- [x] ajout de collar stérile (avec note) -- [x] polygone de maillage convex hull ou un trou diff --git a/elementary_volume/__init__.py b/elementary_volume/__init__.py index 601b250..481ff8a 100644 --- a/elementary_volume/__init__.py +++ b/elementary_volume/__init__.py @@ -164,7 +164,7 @@ def linemerge(lines): return merged def has_proper_2d_topology(line): - SIN_MIN_ANGLE = 5.*PI/180 + SIN_MIN_ANGLE = .01*PI/180 l = line if len(l) <=2 : return False @@ -198,7 +198,7 @@ def offset_coords(offsets, coords): def elementary_volumes(holes_, starts_, ends_, hole_ids_, node_ids_, nodes_, end_ids_, end_geoms_, srid_=32632): #TODO add REL_DISTANCE and HEIGHT as parameters - DEBUG = False + DEBUG = True PRECI = 6 REL_DISTANCE = .3 HEIGHT = 1. @@ -479,6 +479,7 @@ def elementary_volumes(holes_, starts_, ends_, hole_ids_, node_ids_, nodes_, end if DEBUG: open("/tmp/linework_%s.vtk"%(face), 'w').write(to_vtk(MultiLineString([LineString(e) for e in merged]).wkb_hex)) + face_triangles = [] for m in merged: if has_proper_2d_topology(m): node_map = {(round(x[0], PRECI), round(x[1], PRECI)): x for x in m} @@ -491,6 +492,10 @@ def elementary_volumes(holes_, starts_, ends_, hole_ids_, node_ids_, nodes_, end if face == 'bottom' else \ Polygon([node_map[tri[2]], node_map[tri[1]], node_map[tri[0]]]) result.append(q) + face_triangles.append(q) + if DEBUG: + open("/tmp/face_{}.obj".format(face), 'w').write(to_obj(MultiPolygon(face_triangles).wkb_hex)) + # adds isolated nodes terminations for n, l in list(ends.items()): diff --git a/export_elementary_volume.py b/export_elementary_volume.py index ff9c8eb..3025e04 100644 --- a/export_elementary_volume.py +++ b/export_elementary_volume.py @@ -47,36 +47,19 @@ def __export(self): QApplication.setOverrideCursor(QCursor(Qt.WaitCursor)) QApplication.processEvents() - for fid in fids: - request = QgsFeatureRequest(fid) - - ft = None - for feature in self.cell_layer.getFeatures(request): - ft = feature - - if not ft: - return - - cell = ft["id"] - outdir = self.mOutputDir.text() - - if self.mFormat.currentText() == "OBJ": - self.project.export_elementary_volume_obj( - self.graph, cell, outdir, True - ) - else: # DXF - self.project.export_elementary_volume_dxf( - self.graph, cell, outdir, True - ) - - if not closed_only: - if self.mFormat.currentText() == "OBJ": - self.project.export_elementary_volume_obj( - self.graph, cell, outdir, False - ) - else: # DXF - self.project.export_elementary_volume_dxf( - self.graph, cell, outdir, False - ) + cell_ids = [feature["id"] + for feature in self.cell_layer.getFeatures(QgsFeatureRequest(fid)): + for fid in fids] + + outdir = self.mOutputDir.text() + + if self.mFormat.currentText() == "OBJ": + self.project.export_elementary_volume_obj( + self.graph, cell_ids, outdir, closed_only + ) + else: # DXF + self.project.export_elementary_volume_dxf( + self.graph, cell_ids, outdir, closed_only + ) QApplication.restoreOverrideCursor() diff --git a/project.py b/project.py index f6410a6..8b6cff8 100644 --- a/project.py +++ b/project.py @@ -711,60 +711,50 @@ def export_obj(self, graph_id, filename): ) open(filename, "w").write(cur.fetchone()[0]) - def export_elementary_volume_obj(self, graph_id, cell_id, outdir, closed): + def export_elementary_volume_obj(self, graph_id, cell_ids, outdir, closed_only=False): with self.connect() as con: - closed_sql = "" - if not closed: - closed_sql = "not" - cur = con.cursor() cur.execute( """ - select albion.to_obj(geom) from albion.dynamic_volume - where cell_id='{}' and graph_id='{}' - and {} albion.is_closed_volume(geom) + select cell_id, row_number() over(partition by cell_id order by closed desc), obj, closed + from ( + select cell_id, albion.to_obj(triangulation) as obj, albion.is_closed_volume(triangulation) as closed + from albion.volume + where cell_id in ({}) and graph_id='{}' + ) as t """.format( - cell_id, graph_id, closed_sql + ','.join(["'{}'".format(c) for c in cell_ids]), graph_id ) ) - - status = "opened" - if closed: - status = "closed" - - i = 0 - for obj in cur.fetchall(): - filename = '{}_{}_{}_{}.obj'.format(cell_id, graph_id, status, i) - i += 1 + for cell_id, i, obj, closed in cur.fetchall(): + if closed_only and not closed: + continue + filename = '{}_{}_{}_{}.obj'.format(cell_id, graph_id, "closed" if closed else "opened", i) path = os.path.join(outdir, filename) open(path, "w").write(obj[0]) + - def export_elementary_volume_dxf(self, graph_id, cell_id, outdir, closed): + def export_elementary_volume_dxf(self, graph_id, cell_ids, outdir, closed_only=False): with self.connect() as con: - closed_sql = "" - if not closed: - closed_sql = "not" - cur = con.cursor() cur.execute( """ - select geom from albion.dynamic_volume - where cell_id='{}' and graph_id='{}' - and {} albion.is_closed_volume(geom) + select cell_id, row_number() over(partition by cell_id order by closed desc), geom, closed + from ( + select cell_id, triangulation as geom, albion.is_closed_volume(triangulation) as closed + from albion.volume + where cell_id in ({}) and graph_id='{}' + ) as t """.format( - cell_id, graph_id, closed_sql + ','.join(["'{}'".format(c) for c in cell_ids]), graph_id ) ) - status = "opened" - if closed: - status = "closed" - - i = 0 - for wkb_geom in cur.fetchall(): - geom = wkb.loads(bytes.fromhex(wkb_geom[0])) - - filename = '{}_{}_{}_{}.dxf'.format(cell_id, graph_id, status, i) + for cell_id, i, wkb_geom, closed in cur.fetchall(): + geom = wkb.loads(bytes.fromhex(wkb_geom)) + if closed_only and not closed: + continue + filename = '{}_{}_{}_{}.dxf'.format(cell_id, graph_id, "closed" if closed else "opened", i) path = os.path.join(outdir, filename) drawing = dxf.drawing(path) @@ -775,8 +765,6 @@ def export_elementary_volume_dxf(self, graph_id, cell_id, outdir, closed): ) drawing.save() - i += 1 - def errors_obj(self, graph_id, filename): with self.connect() as con: cur = con.cursor() diff --git a/test/export.py b/test/export.py new file mode 100644 index 0000000..0aa3626 --- /dev/null +++ b/test/export.py @@ -0,0 +1,19 @@ +if __name__ == "__main__": + + from albion.project import Project + import os + import shutil + + project = Project("tutorial_test") + + with project.connect() as con: + cur = con.cursor() + cur.execute("select id from albion.cell") + if os.path.isdir('/tmp/min1000'): + shutil.rmtree('/tmp/min1000') + os.mkdir('/tmp/min1000') + cells = [r for r, in cur.fetchall()] + project.export_elementary_volume_obj('min1000', cells, '/tmp/min1000') + project.export_elementary_volume_dxf('min1000', cells, '/tmp/min1000') + + diff --git a/test/tutorial.py b/test/tutorial.py index bc77ef6..431e5e4 100644 --- a/test/tutorial.py +++ b/test/tutorial.py @@ -9,8 +9,6 @@ import tempfile import zipfile - - project_name = "tutorial_test" if Project.exists(project_name): @@ -28,12 +26,17 @@ project.triangulate() + with project.connect() as con: + cur = con.cursor() + cur.execute("delete from albion.cell where aspect_ratio > 10") + con.commit() + with project.connect() as con: cur = con.cursor() cur.execute("select name from albion.layer") layers = [r[0] for r in cur.fetchall()] + print(layers) - print(layers) #for l in layers: # project.refresh_section_geom(l) @@ -50,21 +53,20 @@ con.commit() project.accept_possible_edge('330') + project.create_terminations('330') project.create_volumes('330') # test that all volumes are closed and positive with project.connect() as con: cur = con.cursor() cur.execute(""" - select cell_id from albion.volume where not albion.is_closed_volume(triangulation) limit 3 + select cell_id from albion.volume where not albion.is_closed_volume(triangulation) """ ) - print("unclosed volume for cells", cur.fetchall()) - cur.execute(""" - select count(1) from albion.volume where not albion.is_closed_volume(triangulation) - """ - ) - assert(cur.fetchone()[0]==0) + unclosed = cur.fetchall() + if len(unclosed): + print("unclosed volume for cells", unclosed) + assert(len(unclosed) == 0) cur.execute(""" select count(1) from albion.volume where albion.volume_of_geom(triangulation) <= 0 """ @@ -82,7 +84,17 @@ con.commit() project.accept_possible_edge('min1000') + project.create_terminations('min1000') project.create_volumes('min1000') + with project.connect() as con: + cur = con.cursor() + cur.execute("select id from albion.cell") + os.mkdir('/tmp/min1000') + cells = [r for r, in cur.fetchall()] + for i, cell_id in enumerate(cells): + print(i/len(cells)) + project.export_elementary_volume_obj('min1000', cell_id, '/tmp/min1000', False) + From 6fa405dde1de0fed4692028008f32ececa8f4934 Mon Sep 17 00:00:00 2001 From: Vincent Mora Date: Sat, 26 Oct 2019 19:14:51 +0200 Subject: [PATCH 23/42] fixup --- export_elementary_volume.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/export_elementary_volume.py b/export_elementary_volume.py index 3025e04..3e8e872 100644 --- a/export_elementary_volume.py +++ b/export_elementary_volume.py @@ -48,8 +48,9 @@ def __export(self): QApplication.setOverrideCursor(QCursor(Qt.WaitCursor)) QApplication.processEvents() cell_ids = [feature["id"] - for feature in self.cell_layer.getFeatures(QgsFeatureRequest(fid)): - for fid in fids] + for fid in fids + for feature in self.cell_layer.getFeatures(QgsFeatureRequest(fid)) + ] outdir = self.mOutputDir.text() From a92bc15ef6a608a9dab4a26ad2c32d27d6bf7452 Mon Sep 17 00:00:00 2001 From: Vincent Mora Date: Sat, 26 Oct 2019 19:44:03 +0200 Subject: [PATCH 24/42] takes end node thickness and distance from metadata --- albion.sql | 10 +++++----- elementary_volume/__init__.py | 11 ++++------- plugin.py | 7 +++++-- project.py | 2 +- test/tutorial.py | 8 -------- 5 files changed, 15 insertions(+), 23 deletions(-) diff --git a/albion.sql b/albion.sql index eabf6b2..2c2b910 100644 --- a/albion.sql +++ b/albion.sql @@ -1030,7 +1030,7 @@ join _albion.section as s on s.geom && hs.geom and st_intersects(s.geom, st_star ; -create or replace function albion.elementary_volumes(cell_id_ varchar, graph_id_ varchar, geom_ geometry, holes_ varchar[], starts_ varchar[], ends_ varchar[], hole_ids_ varchar[], node_ids_ varchar[], nodes_ geometry[], end_ids_ varchar[], end_geoms_ geometry[]) +create or replace function albion.elementary_volumes(cell_id_ varchar, graph_id_ varchar, geom_ geometry, holes_ varchar[], starts_ varchar[], ends_ varchar[], hole_ids_ varchar[], node_ids_ varchar[], nodes_ geometry[], end_ids_ varchar[], end_geoms_ geometry[], end_node_relative_distance real, end_node_thickness real) returns setof geometry language plpython3u immutable as @@ -1049,7 +1049,7 @@ open('/tmp/debug_input_%s.txt'%(cell_id_), 'w').write( ' '.join(end_geoms_)+'\n' ) $INCLUDE_ELEMENTARY_VOLUME -for v in elementary_volumes(holes_, starts_, ends_, hole_ids_, node_ids_, nodes_, end_ids_, end_geoms_, $SRID): +for v in elementary_volumes(holes_, starts_, ends_, hole_ids_, node_ids_, nodes_, end_ids_, end_geoms_, $SRID, end_node_relative_distance, end_node_thickness): yield v $$ ; @@ -1348,7 +1348,7 @@ from nrml create or replace view albion.dynamic_end_node as -select row_number() over() as id, he.graph_id, n.id as node_id, albion.end_node_geom(n.geom, st_startpoint(h.geom), m.end_node_relative_distance, end_node_thickness, nrml.nx::real, nrml.ny::real, nrml.nz::real)::geometry('LINESTRINGZ', $SRID) as geom, h.id as hole_id +select row_number() over() as id, he.graph_id, n.id as node_id, albion.end_node_geom(n.geom, st_startpoint(h.geom), m.end_node_relative_distance, m.end_node_thickness, nrml.nx::real, nrml.ny::real, nrml.nz::real)::geometry('LINESTRINGZ', $SRID) as geom, h.id as hole_id from albion.half_edge as he join _albion.node as n on n.id=he.node_id join _albion.hole as h on h.id=he.other @@ -1495,8 +1495,8 @@ join lateral ( and en.graph_id=g.id ) as en on true ) -select cell_id, graph_id, albion.elementary_volumes(cell_id, graph_id, st_force3d(geom), holes, starts, ends, hole_ids, node_ids, node_geoms, end_ids, end_geoms)::geometry('MULTIPOLYGONZ', $SRID) as geom, starts, ends, holes, hole_ids, node_ids, end_ids, end_geoms -from res +select cell_id, graph_id, albion.elementary_volumes(cell_id, graph_id, st_force3d(geom), holes, starts, ends, hole_ids, node_ids, node_geoms, end_ids, end_geoms, m.end_node_relative_distance, m.end_node_thickness)::geometry('MULTIPOLYGONZ', $SRID) as geom, starts, ends, holes, hole_ids, node_ids, end_ids, end_geoms +from res, albion.metadata m ; diff --git a/elementary_volume/__init__.py b/elementary_volume/__init__.py index 481ff8a..35e9a6f 100644 --- a/elementary_volume/__init__.py +++ b/elementary_volume/__init__.py @@ -195,13 +195,10 @@ def offset_coords(offsets, coords): return [offsets[c] if c in offsets else c for c in coords] -def elementary_volumes(holes_, starts_, ends_, hole_ids_, node_ids_, nodes_, end_ids_, end_geoms_, srid_=32632): +def elementary_volumes(holes_, starts_, ends_, hole_ids_, node_ids_, nodes_, end_ids_, end_geoms_, srid_=32632, end_node_relative_distance=0.3, end_node_thickness=1): - #TODO add REL_DISTANCE and HEIGHT as parameters DEBUG = True PRECI = 6 - REL_DISTANCE = .3 - HEIGHT = 1. debug_files = [] nodes = {id_: wkb.loads(bytes.fromhex(geom)) for id_, geom in zip(node_ids_, nodes_)} @@ -266,9 +263,9 @@ def elementary_volumes(holes_, starts_, ends_, hole_ids_, node_ids_, nodes_, end if p: A, B, C = array(nodes[n].coords[0][:2]), array(nodes[p[0]].coords[0][:2]),array(nodes[p[1]].coords[0][:2]) c = average(array(nodes[n].coords), (0,)) - u = .5*(normalized(B-A)+normalized(C-A))*REL_DISTANCE*.5*(norm(B-A)+norm(C-A)) - offsets[nodes[n].coords[0]] = tuple(c+array((u[0], u[1], +.5*HEIGHT))) - offsets[nodes[n].coords[-1]] = tuple(c+array((u[0], u[1], -.5*HEIGHT))) + u = .5*(normalized(B-A)+normalized(C-A))*end_node_relative_distance*.5*(norm(B-A)+norm(C-A)) + offsets[nodes[n].coords[0]] = tuple(c+array((u[0], u[1], +.5*end_node_thickness))) + offsets[nodes[n].coords[-1]] = tuple(c+array((u[0], u[1], -.5*end_node_thickness))) if DEBUG: diff --git a/plugin.py b/plugin.py index 89fef86..5065a0d 100644 --- a/plugin.py +++ b/plugin.py @@ -685,9 +685,12 @@ def __create_sections(self): def __refresh_selected_layers_sections(self): assert(self.project) - for l in iface.layerTreeView().selectedLayers(): + for l in self.__iface.layerTreeView().selectedLayers(): uri = QgsDataSourceUri(l.dataProvider().dataSourceUri()) - self.project.refresh_section_geom(uri.table()) + table = uri.table() + if table.endswith('_section'): + table = table[:-8] + self.project.refresh_section_geom(table) def __compute_mineralization(self): MineralizationDialog(self.project).exec_() diff --git a/project.py b/project.py index 8b6cff8..4fc1e35 100644 --- a/project.py +++ b/project.py @@ -916,7 +916,7 @@ def create_section_view_0_90(self, z_scale): def refresh_section_geom(self, table): with self.connect() as con: cur = con.cursor() - cur.execute("select count(1) from albion.layer where id='{}'".format(table)) + cur.execute("select count(1) from albion.layer where name='{}'".format(table)) if cur.fetchone()[0]: cur.execute("refresh materialized view albion.{}_section_geom_cache".format(table)) con.commit() diff --git a/test/tutorial.py b/test/tutorial.py index 431e5e4..0ddbe33 100644 --- a/test/tutorial.py +++ b/test/tutorial.py @@ -87,14 +87,6 @@ project.create_terminations('min1000') project.create_volumes('min1000') - with project.connect() as con: - cur = con.cursor() - cur.execute("select id from albion.cell") - os.mkdir('/tmp/min1000') - cells = [r for r, in cur.fetchall()] - for i, cell_id in enumerate(cells): - print(i/len(cells)) - project.export_elementary_volume_obj('min1000', cell_id, '/tmp/min1000', False) From d8e432bc05eddda6d699c88bbaddf851ae1bc3d2 Mon Sep 17 00:00:00 2001 From: Vincent Mora Date: Mon, 28 Oct 2019 16:45:58 +0100 Subject: [PATCH 25/42] speedup (orders of magnitude) the volume section fetch --- _albion.sql | 8 ++- _albion_v1_to_v2.sql | 9 ++++ albion.sql | 93 ++++++++++++++++++++++++++--------- elementary_volume/__init__.py | 72 ++++++++++++++++++++++----- project.py | 4 +- 5 files changed, 147 insertions(+), 39 deletions(-) diff --git a/_albion.sql b/_albion.sql index 0dc32de..33b9912 100644 --- a/_albion.sql +++ b/_albion.sql @@ -162,8 +162,12 @@ create table _albion.volume( id varchar primary key default _albion.unique_id()::varchar, graph_id varchar not null references _albion.graph(id) on delete cascade on update cascade, cell_id varchar not null references _albion.cell(id) on delete cascade on update cascade, - triangulation geometry('MULTIPOLYGONZ', $SRID) not null -); + triangulation geometry('MULTIPOLYGONZ', $SRID) not null, + face1 geometry('MULTIPOLYGONZ', $SRID), + face2 geometry('MULTIPOLYGONZ', $SRID), + face3 geometry('MULTIPOLYGONZ', $SRID) +) +; create index volume_graph_id_idx on _albion.volume(graph_id) ; diff --git a/_albion_v1_to_v2.sql b/_albion_v1_to_v2.sql index 41e121c..5239f7b 100644 --- a/_albion_v1_to_v2.sql +++ b/_albion_v1_to_v2.sql @@ -93,6 +93,15 @@ alter table _albion.end_node add constraint end_node_hole_id_fkey foreign key(ho drop table _albion.collar ; +alter table _albion.volume add column face1 geometry('MULTIPOLYGONZ', $SRID) +; + +alter table _albion.volume add column face2 geometry('MULTIPOLYGONZ', $SRID) +; + +alter table _albion.volume add column face3 geometry('MULTIPOLYGONZ', $SRID) +; + -- adds named_section create table _albion.named_section( id varchar primary key default _albion.unique_id()::varchar, diff --git a/albion.sql b/albion.sql index 2c2b910..555458c 100644 --- a/albion.sql +++ b/albion.sql @@ -1029,9 +1029,15 @@ join _albion.section as s on s.geom && hs.geom and st_intersects(s.geom, st_star s.geom && he.geom and st_intersects(s.geom, st_startpoint(he.geom)) ; +create type albion.volume_row as ( + geom geometry('MULTIPOLYGONZ', $SRID), + face1 geometry('MULTIPOLYGONZ', $SRID), + face2 geometry('MULTIPOLYGONZ', $SRID), + face3 geometry('MULTIPOLYGONZ', $SRID)) +; -create or replace function albion.elementary_volumes(cell_id_ varchar, graph_id_ varchar, geom_ geometry, holes_ varchar[], starts_ varchar[], ends_ varchar[], hole_ids_ varchar[], node_ids_ varchar[], nodes_ geometry[], end_ids_ varchar[], end_geoms_ geometry[], end_node_relative_distance real, end_node_thickness real) -returns setof geometry +create or replace function albion.elementary_volumes(cell_id_ varchar, graph_id_ varchar, geom_ geometry, holes_ varchar[], starts_ varchar[], ends_ varchar[], hole_ids_ varchar[], node_ids_ varchar[], nodes_ geometry[], end_ids_ varchar[], end_geoms_ geometry[], end_holes_ varchar[], end_node_relative_distance real, end_node_thickness real) +returns setof albion.volume_row language plpython3u immutable as $$ @@ -1049,8 +1055,8 @@ open('/tmp/debug_input_%s.txt'%(cell_id_), 'w').write( ' '.join(end_geoms_)+'\n' ) $INCLUDE_ELEMENTARY_VOLUME -for v in elementary_volumes(holes_, starts_, ends_, hole_ids_, node_ids_, nodes_, end_ids_, end_geoms_, $SRID, end_node_relative_distance, end_node_thickness): - yield v +for g, f1, f2, f3 in elementary_volumes(holes_, starts_, ends_, hole_ids_, node_ids_, nodes_, end_ids_, end_geoms_, end_holes_, $SRID, end_node_relative_distance, end_node_thickness): + yield g, f1, f2, f3 $$ ; @@ -1466,7 +1472,7 @@ where not st_isempty(geom) create or replace view albion.dynamic_volume as with res as ( select -c.id as cell_id, g.id as graph_id, ed.starts, ed.ends, nd.hole_ids as hole_ids, nd.ids as node_ids, nd.geoms as node_geoms, en.ids as end_ids, en.geoms as end_geoms, c.geom, ARRAY[ha.id, hb.id, hc.id] as holes +c.id as cell_id, g.id as graph_id, ed.starts, ed.ends, nd.hole_ids as hole_ids, nd.ids as node_ids, nd.geoms as node_geoms, en.ids as end_ids, en.geoms as end_geoms, c.geom, ARRAY[ha.id, hb.id, hc.id] as holes, en.end_holes from _albion.graph as g join _albion.cell as c on true join _albion.hole as ha on ha.id = c.a @@ -1487,7 +1493,7 @@ join lateral ( and e.graph_id=g.id ) as ed on true join lateral ( - select coalesce(array_agg(en.node_id), '{}'::varchar[]) as ids, coalesce(array_agg(en.geom), '{}'::geometry[]) as geoms + select coalesce(array_agg(en.node_id), '{}'::varchar[]) as ids, coalesce(array_agg(en.geom), '{}'::geometry[]) as geoms, coalesce(array_agg(en.hole_id), '{}'::varchar[]) as end_holes from _albion.end_node as en join _albion.node as n on n.id=en.node_id where en.hole_id in (c.a, c.b, c.c) @@ -1495,8 +1501,14 @@ join lateral ( and en.graph_id=g.id ) as en on true ) -select cell_id, graph_id, albion.elementary_volumes(cell_id, graph_id, st_force3d(geom), holes, starts, ends, hole_ids, node_ids, node_geoms, end_ids, end_geoms, m.end_node_relative_distance, m.end_node_thickness)::geometry('MULTIPOLYGONZ', $SRID) as geom, starts, ends, holes, hole_ids, node_ids, end_ids, end_geoms +select cell_id, graph_id, + t.geom::geometry('MULTIPOLYGONZ', $SRID), + t.face1::geometry('MULTIPOLYGONZ', $SRID), + t.face2::geometry('MULTIPOLYGONZ', $SRID), + t.face3::geometry('MULTIPOLYGONZ', $SRID), + starts, ends, holes, hole_ids, node_ids, end_ids, end_geoms from res, albion.metadata m +join lateral albion.elementary_volumes(cell_id, graph_id, st_force3d(geom), holes, starts, ends, hole_ids, node_ids, node_geoms, end_ids, end_geoms, end_holes, m.end_node_relative_distance, m.end_node_thickness) as t on true ; @@ -1584,23 +1596,60 @@ $$ --; -create or replace view albion.volume_section as -with touching_cell as ( - select c.id, st_intersection(s.geom, c.geom) as geom, v.triangulation, s.id as section_id, v.graph_id +--create or replace view albion.volume_section as +--with touching_cell as ( +-- select c.id, st_intersection(s.geom, c.geom) as geom, v.triangulation, s.id as section_id, v.graph_id +-- from _albion.section as s +-- join _albion.cell as c on c.geom && s.geom +-- and st_intersects(c.geom, s.geom) +-- and st_length(st_intersection(s.geom, c.geom)) > 0 +-- join _albion.volume as v on v.cell_id = c.id +--), +--tri as ( +-- select (st_dump(albion.triangle_intersection(c1.triangulation, c2.triangulation))).geom as geom, c1.section_id, c1.graph_id +-- from touching_cell as c1 +-- join touching_cell as c2 on c2.id > c1.id and st_length(st_intersection(c1.geom, c2.geom)) >0 and c1.section_id = c2.section_id and c1.graph_id = c2.graph_id +--) +--select row_number() over() as id, st_collect(geom)::geometry('MULTIPOLYGONZ', $SRID) as geom, section_id, graph_id +--from tri +--group by section_id, graph_id +--; + + +create or replace view albion.edge_face as +select t.n[1] as start_, t.n[2] as end_, face1 as geom, graph_id +from _albion.volume v +join _albion.cell c on c.id = v.cell_id +join lateral (select array_agg(x order by x) as n from (values (a), (b), (c)) as v(x)) as t on true +union all +select t.n[2] as start_, t.n[3] as end_, face2 as geom, graph_id +from _albion.volume v +join _albion.cell c on c.id = v.cell_id +join lateral (select array_agg(x order by x) as n from (values (a), (b), (c)) as v(x)) as t on true +union all +select t.n[1] as start_, t.n[3] as end_, face3 as geom, graph_id +from _albion.volume v +join _albion.cell c on c.id = v.cell_id +join lateral (select array_agg(x order by x) as n from (values (a), (b), (c)) as v(x)) as t on true +; + +create view albion.section_edge as +with hole_idx as ( + select s.id as section_id, h.id as hole_id from _albion.section as s - join _albion.cell as c on c.geom && s.geom - and st_intersects(c.geom, s.geom) - and st_length(st_intersection(s.geom, c.geom)) > 0 - join _albion.volume as v on v.cell_id = c.id -), -tri as ( - select (st_dump(albion.triangle_intersection(c1.triangulation, c2.triangulation))).geom as geom, c1.section_id, c1.graph_id - from touching_cell as c1 - join touching_cell as c2 on c2.id > c1.id and st_length(st_intersection(c1.geom, c2.geom)) >0 and c1.section_id = c2.section_id and c1.graph_id = c2.graph_id + join _albion.hole as h on s.geom && h.geom and st_intersects(s.geom, st_startpoint(h.geom)) ) -select row_number() over() as id, st_collect(geom)::geometry('MULTIPOLYGONZ', $SRID) as geom, section_id, graph_id -from tri -group by section_id, graph_id +select e.start_, e.end_, hs.section_id +from albion.all_edge as e +join hole_idx as hs on hs.hole_id = e.start_ +join hole_idx as he on he.hole_id = e.end_ and he.section_id = hs.section_id +; + +create or replace view albion.volume_section as +select se.section_id, ef.graph_id, st_collectionhomogenize(st_collect(ef.geom))::geometry('MULTIPOLYGONZ', 32632) as geom +from albion.section_edge as se +join albion.edge_face as ef on ef.start_ = se.start_ and ef.end_ = se.end_ and not st_isempty(ef.geom) +group by se.section_id, ef.graph_id ; diff --git a/elementary_volume/__init__.py b/elementary_volume/__init__.py index 35e9a6f..0667426 100644 --- a/elementary_volume/__init__.py +++ b/elementary_volume/__init__.py @@ -195,16 +195,18 @@ def offset_coords(offsets, coords): return [offsets[c] if c in offsets else c for c in coords] -def elementary_volumes(holes_, starts_, ends_, hole_ids_, node_ids_, nodes_, end_ids_, end_geoms_, srid_=32632, end_node_relative_distance=0.3, end_node_thickness=1): +def elementary_volumes(holes_, starts_, ends_, hole_ids_, node_ids_, nodes_, end_ids_, end_geoms_, end_holes_, srid_=32632, end_node_relative_distance=0.3, end_node_thickness=1): - DEBUG = True + DEBUG = False PRECI = 6 debug_files = [] nodes = {id_: wkb.loads(bytes.fromhex(geom)) for id_, geom in zip(node_ids_, nodes_)} ends = defaultdict(list) - for id_, geom in zip(end_ids_, end_geoms_): + end_holes = defaultdict(list) + for id_, geom, hole_id in zip(end_ids_, end_geoms_, end_holes_): ends[id_].append(wkb.loads(bytes.fromhex(geom))) + end_holes[id_].append(hole_id) holes = {n: h for n, h in zip(node_ids_, hole_ids_)} edges = [(s, e) for s, e in zip(starts_, ends_)] assert(len(edges) == len(set(edges))) @@ -247,8 +249,6 @@ def elementary_volumes(holes_, starts_, ends_, hole_ids_, node_ids_, nodes_, end triangle_edges.add(tri[0:1]+tri[2:3]) triangle_nodes.update(tri) - result = [] - termination = [] # compute face offset direction for termination corners @@ -278,6 +278,9 @@ def elementary_volumes(holes_, starts_, ends_, hole_ids_, node_ids_, nodes_, end face_idx = -1 lines = [] + faces = defaultdict(list) + result = [] + termination = [] for hl, hr in ((sorted_holes[0], sorted_holes[1]), (sorted_holes[1], sorted_holes[2]), (sorted_holes[0], sorted_holes[2])): @@ -403,6 +406,7 @@ def elementary_volumes(holes_, starts_, ends_, hole_ids_, node_ids_, nodes_, end term_tri.append(q) result += domain_tri + faces[(hl, hr)] += domain_tri top_lines = [l for l in face_lines if l.side==Line.TOP] bottom_lines = [l for l in face_lines if l.side==Line.BOTTOM] @@ -414,6 +418,8 @@ def elementary_volumes(holes_, starts_, ends_, hole_ids_, node_ids_, nodes_, end to_vtk(MultiLineString([LineString([k, v]) for k, v in list(offsets.items())]).wkb_hex)) # create terminations + terms = [] + no_offest_terms = [] edges = set() for t in term_tri: for s, e in zip(t.exterior.coords[:-1], t.exterior.coords[1:]): @@ -429,17 +435,20 @@ def elementary_volumes(holes_, starts_, ends_, hole_ids_, node_ids_, nodes_, end break if share: continue - termination.append(t) - termination.append(Polygon(offset_coords(offsets, t.exterior.coords[::-1]))) + terms.append(t) + no_offest_terms.append(t) + terms.append(Polygon(offset_coords(offsets, t.exterior.coords[::-1]))) for s in zip(t.exterior.coords[:-1], t.exterior.coords[1:]): if s in edges: if (is_segment(s, top_lines) or is_segment(s, bottom_lines) or s in end_lines)\ and s[0] in offsets and s[1] in offsets: - termination.append(Polygon([offsets[s[0]], s[1], s[0]])) - termination.append(Polygon([offsets[s[0]], offsets[s[1]], s[1]])) + terms.append(Polygon([offsets[s[0]], s[1], s[0]])) + terms.append(Polygon([offsets[s[0]], offsets[s[1]], s[1]])) if (s[1], s[0]) in end_lines: - termination.append(Polygon([s[1], s[0], offsets[s[1]]])) - termination.append(Polygon([s[0], offsets[s[0]], offsets[s[1]]])) + terms.append(Polygon([s[1], s[0], offsets[s[1]]])) + terms.append(Polygon([s[0], offsets[s[0]], offsets[s[1]]])) + termination += terms + faces[(hl, hr)] += no_offest_terms if DEBUG: open("/tmp/faces.obj", 'w').write(to_obj(MultiPolygon(result).wkb_hex)) @@ -510,9 +519,22 @@ def elementary_volumes(holes_, starts_, ends_, hole_ids_, node_ids_, nodes_, end Polygon([l[0].coords[0], l[0].coords[1], l[1].coords[0]]), Polygon([l[0].coords[1], l[1].coords[1], l[1].coords[0]]) ] + faces[tuple(sorted((holes[n], end_holes[n][0])))] += [ + Polygon([node.coords[0], node.coords[1], l[0].coords[0]]), + Polygon([node.coords[1], l[0].coords[1], l[0].coords[0]]), + ] + faces[tuple(sorted((holes[n], end_holes[n][1])))] += [ + Polygon([l[1].coords[0], node.coords[1], node.coords[0]]), + Polygon([l[1].coords[0], l[1].coords[1], node.coords[1]]), + ] result += termination + if DEBUG: + for hp, tri in faces.items(): + open("/tmp/face_{}_{}.obj".format(hp[0], hp[1]), 'w').write(to_obj(MultiPolygon([t for t in tri]).wkb_hex)) + + # decompose volume in connected components edges = {} graph = {i:set() for i in range(len(result))} @@ -539,7 +561,22 @@ def pop_connected(n, graph): connected.append(pop_connected(n, graph)) for c in connected: - res = MultiPolygon([result[i] for i in c]) + face1 = [] + face2 = [] + face3 = [] + triangles = [result[i] for i in c] + res = MultiPolygon(triangles) + + for f in faces[(sorted_holes[0], sorted_holes[1])]: + if f in triangles: + face1.append(f) + for f in faces[(sorted_holes[1], sorted_holes[2])]: + if f in triangles: + face2.append(f) + for f in faces[(sorted_holes[0], sorted_holes[2])]: + if f in triangles: + face3.append(f) + if DEBUG: open("/tmp/volume_tr.obj", 'w').write(to_obj(res.wkb_hex)) # check volume is closed @@ -571,8 +608,17 @@ def pop_connected(n, graph): res = translate(res, translation[0], translation[1], translation[2]) geos.lgeos.GEOSSetSRID(res._geom, srid_) + + face1 = translate(MultiPolygon(face1), translation[0], translation[1], translation[2]) + geos.lgeos.GEOSSetSRID(face1._geom, srid_) + + face2 = translate(MultiPolygon(face2), translation[0], translation[1], translation[2]) + geos.lgeos.GEOSSetSRID(face2._geom, srid_) + + face3 = translate(MultiPolygon(face3), translation[0], translation[1], translation[2]) + geos.lgeos.GEOSSetSRID(face3._geom, srid_) - yield res.wkb_hex + yield res.wkb_hex, face1.wkb_hex, face2.wkb_hex, face3.wkb_hex for f in debug_files: os.remove(f) diff --git a/project.py b/project.py index 4fc1e35..11d9a4a 100644 --- a/project.py +++ b/project.py @@ -816,8 +816,8 @@ def create_volumes(self, graph_id): ) cur.execute( """ - insert into albion.volume(graph_id, cell_id, triangulation) - select graph_id, cell_id, geom + insert into _albion.volume(graph_id, cell_id, triangulation, face1, face2, face3) + select graph_id, cell_id, geom, face1, face2, face3 from albion.dynamic_volume where graph_id='{}' and geom is not null --not st_isempty(geom) From ac72fa14417a6bf7a18225addf3a9ded0c60cb86 Mon Sep 17 00:00:00 2001 From: Vincent Mora Date: Wed, 30 Oct 2019 13:19:40 +0100 Subject: [PATCH 26/42] adds export of sections and holes --- albion.sql | 3 +- elementary_volume/__init__.py | 11 +++-- elementary_volume/__main__.py | 6 ++- plugin.py | 53 ++++++++++++++++++-- project.py | 91 ++++++++++++++++++++++++++++++++--- test/tutorial.py | 19 ++++++++ 6 files changed, 168 insertions(+), 15 deletions(-) diff --git a/albion.sql b/albion.sql index 555458c..f126380 100644 --- a/albion.sql +++ b/albion.sql @@ -1052,7 +1052,8 @@ open('/tmp/debug_input_%s.txt'%(cell_id_), 'w').write( ' '.join(node_ids_)+'\n'+ ' '.join(nodes_)+'\n'+ ' '.join(end_ids_)+'\n'+ - ' '.join(end_geoms_)+'\n' + ' '.join(end_geoms_)+'\n'+ + ' '.join(end_holes_)+'\n' ) $INCLUDE_ELEMENTARY_VOLUME for g, f1, f2, f3 in elementary_volumes(holes_, starts_, ends_, hole_ids_, node_ids_, nodes_, end_ids_, end_geoms_, end_holes_, $SRID, end_node_relative_distance, end_node_thickness): diff --git a/elementary_volume/__init__.py b/elementary_volume/__init__.py index 0667426..69cc4f3 100644 --- a/elementary_volume/__init__.py +++ b/elementary_volume/__init__.py @@ -209,7 +209,10 @@ def elementary_volumes(holes_, starts_, ends_, hole_ids_, node_ids_, nodes_, end end_holes[id_].append(hole_id) holes = {n: h for n, h in zip(node_ids_, hole_ids_)} edges = [(s, e) for s, e in zip(starts_, ends_)] - assert(len(edges) == len(set(edges))) + #assert(len(edges) == len(set(edges))) + #assert(len(holes_) == 3) + #assert(set(hole_ids_).intersection(set(holes_)) == set(hole_ids_)) + #assert(set(end_holes_).intersection(set(holes_)) == set(end_holes_)) # translate everything close to origin to avoid numerical issues @@ -447,12 +450,13 @@ def elementary_volumes(holes_, starts_, ends_, hole_ids_, node_ids_, nodes_, end if (s[1], s[0]) in end_lines: terms.append(Polygon([s[1], s[0], offsets[s[1]]])) terms.append(Polygon([s[0], offsets[s[0]], offsets[s[1]]])) + #faces[(hl, hr)] += terms[-2:] termination += terms - faces[(hl, hr)] += no_offest_terms + #faces[(hl, hr)] += no_offest_terms if DEBUG: open("/tmp/faces.obj", 'w').write(to_obj(MultiPolygon(result).wkb_hex)) - open("/tmp/term.obj", 'w').write(to_obj(MultiPolygon(termination).wkb_hex)) + open("/tmp/termination.obj", 'w').write(to_obj(MultiPolygon(termination).wkb_hex)) if len(result): @@ -519,6 +523,7 @@ def elementary_volumes(holes_, starts_, ends_, hole_ids_, node_ids_, nodes_, end Polygon([l[0].coords[0], l[0].coords[1], l[1].coords[0]]), Polygon([l[0].coords[1], l[1].coords[1], l[1].coords[0]]) ] + assert(len(end_holes[n])==2) faces[tuple(sorted((holes[n], end_holes[n][0])))] += [ Polygon([node.coords[0], node.coords[1], l[0].coords[0]]), Polygon([node.coords[1], l[0].coords[1], l[0].coords[0]]), diff --git a/elementary_volume/__main__.py b/elementary_volume/__main__.py index 86df4f5..654b5da 100644 --- a/elementary_volume/__main__.py +++ b/elementary_volume/__main__.py @@ -13,7 +13,11 @@ nodes_ = f.readline().rstrip().split() end_ids_ = f.readline().rstrip().split() end_geoms_ = f.readline().rstrip().split() + end_holes_ = f.readline().rstrip().split() idx = 0 - for v in elementary_volumes(holes_, starts_, ends_, hole_ids_, node_ids_, nodes_, end_ids_, end_geoms_): + for v, f1, f2, f3 in elementary_volumes(holes_, starts_, ends_, hole_ids_, node_ids_, nodes_, end_ids_, end_geoms_, end_holes_): open("/tmp/volume%d.obj"%(idx), 'w').write(to_obj(v)) + open("/tmp/face1_%d.obj"%(idx), 'w').write(to_obj(f1)) + open("/tmp/face2_%d.obj"%(idx), 'w').write(to_obj(f2)) + open("/tmp/face3_%d.obj"%(idx), 'w').write(to_obj(f3)) idx += 1 diff --git a/plugin.py b/plugin.py index 5065a0d..aa43747 100644 --- a/plugin.py +++ b/plugin.py @@ -177,14 +177,15 @@ def __create_menu_entries(self): self.__add_menu_entry( "&Import holes", None, #self.__import_holes, - self.project is not None, + self.project is not None and False, "Import hole data from directory" ) self.__add_menu_entry( "Export holes", - None, #self.__export_holes, - self.project is not None + self.__export_holes, + self.project is not None and self.project.has_hole, + "Export hole trace in .vtk or .dxf format", ) self.__add_menu_entry( @@ -735,7 +736,51 @@ def __export_elementary_volume(self): def __export_sections(self): assert(self.project) - self.project.export_sections(self.__current_graph.currentText()) + + fil, __ = QFileDialog.getSaveFileName( + None, + u"Export named sections for current graph", + QgsProject.instance().readEntry("albion", "last_dir", "")[0], + "File formats (*.dxf *.obj)", + ) + if not fil: + return + + QgsProject.instance().writeEntry("albion", "last_dir", os.path.dirname(fil)) + + if fil[-4:] == ".obj": + self.project.export_sections_obj(self.__current_graph.currentText(), fil) + elif fil[-4:] == ".dxf": + self.project.export_sections_dxf(self.__current_graph.currentText(), fil) + else: + self.__iface.messageBar().pushWarning( + "Albion", "unsupported extension for section export" + ) + + + def __export_holes(self): + assert(self.project) + + fil, __ = QFileDialog.getSaveFileName( + None, + u"Export holes", + QgsProject.instance().readEntry("albion", "last_dir", "")[0], + "File formats (*.dxf *.vtk)", + ) + if not fil: + return + + QgsProject.instance().writeEntry("albion", "last_dir", os.path.dirname(fil)) + + if fil[-4:] == ".vtk": + self.project.export_holes_vtk(fil) + elif fil[-4:] == ".dxf": + self.project.export_holes_dxf(fil) + else: + self.__iface.messageBar().pushWarning( + "Albion", "unsupported extension for hole export" + ) + def __import_project(self): fil, __ = QFileDialog.getOpenFileName( diff --git a/project.py b/project.py index 11d9a4a..aaff6a4 100644 --- a/project.py +++ b/project.py @@ -315,10 +315,60 @@ def update(self): self.vacuum() - def export_sections(self, graph): - # TODO - assert(False) - pass + def export_sections_obj(self, graph, filename): + + with self.connect() as con: + cur = con.cursor() + cur.execute( + """ + with hole_idx as ( + select s.id as section_id, h.id as hole_id + from _albion.named_section as s + join _albion.hole as h on s.geom && h.geom and st_intersects(s.geom, st_startpoint(h.geom)) + ) + select albion.to_obj(st_collectionhomogenize(st_collect(ef.geom))) + from albion.all_edge as e + join hole_idx as hs on hs.hole_id = e.start_ + join hole_idx as he on he.hole_id = e.end_ and he.section_id = hs.section_id + join albion.edge_face as ef on ef.start_ = e.start_ and ef.end_ = e.end_ and not st_isempty(ef.geom) + where ef.graph_id='{}' + """.format( + graph + ) + ) + open(filename, "w").write(cur.fetchone()[0]) + + def export_sections_dxf(self, graph, filename): + + with self.connect() as con: + cur = con.cursor() + cur.execute( + """ + with hole_idx as ( + select s.id as section_id, h.id as hole_id + from _albion.named_section as s + join _albion.hole as h on s.geom && h.geom and st_intersects(s.geom, st_startpoint(h.geom)) + ) + select st_collectionhomogenize(st_collect(ef.geom)) + from albion.all_edge as e + join hole_idx as hs on hs.hole_id = e.start_ + join hole_idx as he on he.hole_id = e.end_ and he.section_id = hs.section_id + join albion.edge_face as ef on ef.start_ = e.start_ and ef.end_ = e.end_ and not st_isempty(ef.geom) + where ef.graph_id='{}' + """.format( + graph + ) + ) + + drawing = dxf.drawing(filename) + m = wkb.loads(bytes.fromhex(cur.fetchone()[0])) + for p in m: + r = p.exterior.coords + drawing.add( + dxf.face3d([tuple(r[0]), tuple(r[1]), tuple(r[2])], flags=1) + ) + drawing.save() + def __srid(self): with self.connect() as con: @@ -356,7 +406,7 @@ def __has_cell(self): def __has_hole(self): with self.connect() as con: cur = con.cursor() - cur.execute("select count(1) from albion.hole") + cur.execute("select count(1) from albion.hole where geom is not null") return cur.fetchone()[0] > 1 def __has_volume(self): @@ -368,7 +418,7 @@ def __has_volume(self): def __has_section(self): with self.connect() as con: cur = con.cursor() - cur.execute("select count(1) from albion.section_geom") + cur.execute("select count(1) from albion.named_section") return cur.fetchone()[0] > 1 def __has_group_cell(self): @@ -804,6 +854,35 @@ def export_dxf(self, graph_id, filename): ) drawing.save() + def export_holes_vtk(self, filename): + with self.connect() as con: + cur = con.cursor() + cur.execute( + """ + select albion.to_vtk(st_collect(geom)) + from albion.hole + """ + ) + open(filename, "w").write(cur.fetchone()[0]) + + def export_holes_dxf(self, filename): + with self.connect() as con: + cur = con.cursor() + cur.execute( + """ + select st_collect(geom) + from albion.hole + """ + ) + drawing = dxf.drawing(filename) + m = wkb.loads(bytes.fromhex(cur.fetchone()[0])) + for l in m: + r = l.coords + drawing.add( + dxf.polyline(list(l.coords)) + ) + drawing.save() + def create_volumes(self, graph_id): with self.connect() as con: cur = con.cursor() diff --git a/test/tutorial.py b/test/tutorial.py index 0ddbe33..c84aa3c 100644 --- a/test/tutorial.py +++ b/test/tutorial.py @@ -8,6 +8,7 @@ import time import tempfile import zipfile + from osgeo import ogr project_name = "tutorial_test" @@ -24,6 +25,21 @@ project.create_section_view_0_90(4) project.compute_mineralization(1000, 1, 1) + # import named section from file + with project.connect() as con: + driver = ogr.GetDriverByName('GPKG') + dataSource = driver.Open(os.path.join(os.path.dirname(__file__), 'tutorial_named_section.gpkg'), 0) + data = [(feature.GetField('section'), feature.GetGeometryRef().ExportToWkb().hex()) + for feature in dataSource.GetLayer()] + cur = con.cursor() + cur.execute("delete from albion.named_section") + cur.executemany(""" + insert into albion.named_section(section, geom) + values (%s, st_setsrid(%s::geometry, 32632)) + """, data) + con.commit() + + project.triangulate() with project.connect() as con: @@ -87,6 +103,9 @@ project.create_terminations('min1000') project.create_volumes('min1000') + project.export_sections_obj('min1000', '/tmp/min1000_section.obj') + project.export_sections_obj('330', '/tmp/330_section.obj') + From 511167acba2203088b514c495b7ecbb35250203b Mon Sep 17 00:00:00 2001 From: Vincent Mora Date: Wed, 30 Oct 2019 15:32:26 +0100 Subject: [PATCH 27/42] fix bug in volume faces --- albion.sql | 6 +++--- elementary_volume/__init__.py | 22 ++++++++++++++-------- 2 files changed, 17 insertions(+), 11 deletions(-) diff --git a/albion.sql b/albion.sql index f126380..2b1d47d 100644 --- a/albion.sql +++ b/albion.sql @@ -1618,17 +1618,17 @@ $$ create or replace view albion.edge_face as -select t.n[1] as start_, t.n[2] as end_, face1 as geom, graph_id +select t.n[1] as start_, t.n[2] as end_, face1 as geom, graph_id, cell_id from _albion.volume v join _albion.cell c on c.id = v.cell_id join lateral (select array_agg(x order by x) as n from (values (a), (b), (c)) as v(x)) as t on true union all -select t.n[2] as start_, t.n[3] as end_, face2 as geom, graph_id +select t.n[2] as start_, t.n[3] as end_, face2 as geom, graph_id, cell_id from _albion.volume v join _albion.cell c on c.id = v.cell_id join lateral (select array_agg(x order by x) as n from (values (a), (b), (c)) as v(x)) as t on true union all -select t.n[1] as start_, t.n[3] as end_, face3 as geom, graph_id +select t.n[1] as start_, t.n[3] as end_, face3 as geom, graph_id, cell_id from _albion.volume v join _albion.cell c on c.id = v.cell_id join lateral (select array_agg(x order by x) as n from (values (a), (b), (c)) as v(x)) as t on true diff --git a/elementary_volume/__init__.py b/elementary_volume/__init__.py index 69cc4f3..5f5553d 100644 --- a/elementary_volume/__init__.py +++ b/elementary_volume/__init__.py @@ -226,7 +226,6 @@ def elementary_volumes(holes_, starts_, ends_, hole_ids_, node_ids_, nodes_, end for i in range(len(ends[id_])): ends[id_][i] = translate(ends[id_][i], -translation[0], -translation[1], -translation[2]) - graph = defaultdict(set) # undirected (edge in both directions) for e in edges: graph[e[0]].add(e[1]) @@ -422,7 +421,6 @@ def elementary_volumes(holes_, starts_, ends_, hole_ids_, node_ids_, nodes_, end # create terminations terms = [] - no_offest_terms = [] edges = set() for t in term_tri: for s, e in zip(t.exterior.coords[:-1], t.exterior.coords[1:]): @@ -439,7 +437,7 @@ def elementary_volumes(holes_, starts_, ends_, hole_ids_, node_ids_, nodes_, end if share: continue terms.append(t) - no_offest_terms.append(t) + faces[(hl, hr)] += [t] terms.append(Polygon(offset_coords(offsets, t.exterior.coords[::-1]))) for s in zip(t.exterior.coords[:-1], t.exterior.coords[1:]): if s in edges: @@ -452,7 +450,6 @@ def elementary_volumes(holes_, starts_, ends_, hole_ids_, node_ids_, nodes_, end terms.append(Polygon([s[0], offsets[s[0]], offsets[s[1]]])) #faces[(hl, hr)] += terms[-2:] termination += terms - #faces[(hl, hr)] += no_offest_terms if DEBUG: open("/tmp/faces.obj", 'w').write(to_obj(MultiPolygon(result).wkb_hex)) @@ -512,7 +509,11 @@ def elementary_volumes(holes_, starts_, ends_, hole_ids_, node_ids_, nodes_, end if len(l) == 2: node = nodes[n] A, B, C = array(node.coords[0]), array(l[0].coords[0]), array(l[1].coords[0]) - l = l if dot(cross(B-A, C-A), array((0.,0.,1.))) > 0 else list(reversed(l)) + k1, k2 = tuple(sorted((holes[n], end_holes[n][0]))), tuple(sorted((holes[n], end_holes[n][1]))) + l = l + if dot(cross(B-A, C-A), array((0.,0.,1.))) <= 0: + l = list(reversed(l)) + k1, k2 = k2, k1 termination += [ Polygon([node.coords[0], l[0].coords[0], l[1].coords[0]]), Polygon([l[1].coords[-1], l[0].coords[-1], node.coords[-1]]), @@ -524,11 +525,11 @@ def elementary_volumes(holes_, starts_, ends_, hole_ids_, node_ids_, nodes_, end Polygon([l[0].coords[1], l[1].coords[1], l[1].coords[0]]) ] assert(len(end_holes[n])==2) - faces[tuple(sorted((holes[n], end_holes[n][0])))] += [ + faces[k1] += [ Polygon([node.coords[0], node.coords[1], l[0].coords[0]]), Polygon([node.coords[1], l[0].coords[1], l[0].coords[0]]), ] - faces[tuple(sorted((holes[n], end_holes[n][1])))] += [ + faces[k2] += [ Polygon([l[1].coords[0], node.coords[1], node.coords[0]]), Polygon([l[1].coords[0], l[1].coords[1], node.coords[1]]), ] @@ -565,13 +566,15 @@ def pop_connected(n, graph): n = next(iter(list(graph.keys()))) connected.append(pop_connected(n, graph)) + i=0 for c in connected: + i+=1 face1 = [] face2 = [] face3 = [] triangles = [result[i] for i in c] res = MultiPolygon(triangles) - + for f in faces[(sorted_holes[0], sorted_holes[1])]: if f in triangles: face1.append(f) @@ -583,6 +586,9 @@ def pop_connected(n, graph): face3.append(f) if DEBUG: + open("/tmp/face1_tr_%d.obj"%(i), 'w').write(to_obj(face1.wkb_hex)) + open("/tmp/face2_tr_%d.obj"%(i), 'w').write(to_obj(face2.wkb_hex)) + open("/tmp/face3_tr_%d.obj"%(i), 'w').write(to_obj(face3.wkb_hex)) open("/tmp/volume_tr.obj", 'w').write(to_obj(res.wkb_hex)) # check volume is closed edges = set() From c39da41a0584ef3d45d7f2583ae63f4448bae522 Mon Sep 17 00:00:00 2001 From: Vincent Mora Date: Wed, 30 Oct 2019 15:52:46 +0100 Subject: [PATCH 28/42] fix missing volume section --- albion.sql | 35 ++++++++++++++++++----------------- elementary_volume/__init__.py | 11 ++++++----- 2 files changed, 24 insertions(+), 22 deletions(-) diff --git a/albion.sql b/albion.sql index 2b1d47d..73a1afe 100644 --- a/albion.sql +++ b/albion.sql @@ -993,6 +993,7 @@ $$ where s.id=new.start_ and e.id=new.end_ into new_geom; -- TODO test if edge is possible + end if; if tg_op = 'INSERT' then @@ -1041,20 +1042,20 @@ returns setof albion.volume_row language plpython3u immutable as $$ -open('/tmp/debug_input_%s.txt'%(cell_id_), 'w').write( - cell_id_+'\n'+ - graph_id_+'\n'+ - geom_+'\n'+ - ' '.join(holes_)+'\n'+ - ' '.join(starts_)+'\n'+ - ' '.join(ends_)+'\n'+ - ' '.join(hole_ids_)+'\n'+ - ' '.join(node_ids_)+'\n'+ - ' '.join(nodes_)+'\n'+ - ' '.join(end_ids_)+'\n'+ - ' '.join(end_geoms_)+'\n'+ - ' '.join(end_holes_)+'\n' -) +#open('/tmp/debug_input_%s.txt'%(cell_id_), 'w').write( +# cell_id_+'\n'+ +# graph_id_+'\n'+ +# geom_+'\n'+ +# ' '.join(holes_)+'\n'+ +# ' '.join(starts_)+'\n'+ +# ' '.join(ends_)+'\n'+ +# ' '.join(hole_ids_)+'\n'+ +# ' '.join(node_ids_)+'\n'+ +# ' '.join(nodes_)+'\n'+ +# ' '.join(end_ids_)+'\n'+ +# ' '.join(end_geoms_)+'\n'+ +# ' '.join(end_holes_)+'\n' +#) $INCLUDE_ELEMENTARY_VOLUME for g, f1, f2, f3 in elementary_volumes(holes_, starts_, ends_, hole_ids_, node_ids_, nodes_, end_ids_, end_geoms_, end_holes_, $SRID, end_node_relative_distance, end_node_thickness): yield g, f1, f2, f3 @@ -1618,17 +1619,17 @@ $$ create or replace view albion.edge_face as -select t.n[1] as start_, t.n[2] as end_, face1 as geom, graph_id, cell_id +select t.n[1] as start_, t.n[2] as end_, face1 as geom, graph_id, cell_id, 'face1' as face from _albion.volume v join _albion.cell c on c.id = v.cell_id join lateral (select array_agg(x order by x) as n from (values (a), (b), (c)) as v(x)) as t on true union all -select t.n[2] as start_, t.n[3] as end_, face2 as geom, graph_id, cell_id +select t.n[2] as start_, t.n[3] as end_, face2 as geom, graph_id, cell_id, 'face2' as face from _albion.volume v join _albion.cell c on c.id = v.cell_id join lateral (select array_agg(x order by x) as n from (values (a), (b), (c)) as v(x)) as t on true union all -select t.n[1] as start_, t.n[3] as end_, face3 as geom, graph_id, cell_id +select t.n[1] as start_, t.n[3] as end_, face3 as geom, graph_id, cell_id, 'face3' as face from _albion.volume v join _albion.cell c on c.id = v.cell_id join lateral (select array_agg(x order by x) as n from (values (a), (b), (c)) as v(x)) as t on true diff --git a/elementary_volume/__init__.py b/elementary_volume/__init__.py index 5f5553d..c5c9134 100644 --- a/elementary_volume/__init__.py +++ b/elementary_volume/__init__.py @@ -283,9 +283,10 @@ def elementary_volumes(holes_, starts_, ends_, hole_ids_, node_ids_, nodes_, end faces = defaultdict(list) result = [] termination = [] - for hl, hr in ((sorted_holes[0], sorted_holes[1]), - (sorted_holes[1], sorted_holes[2]), - (sorted_holes[0], sorted_holes[2])): + for hl, hr, other_hole in ( + (sorted_holes[0], sorted_holes[1], sorted_holes[2]), + (sorted_holes[1], sorted_holes[2], sorted_holes[0]), + (sorted_holes[0], sorted_holes[2], sorted_holes[1])): face_idx += 1 direct_orientation = (hl, hr) == (holes_[0], holes_[1]) or (hl, hr) == (holes_[1], holes_[2]) or (hl, hr) == (holes_[2], holes_[0]) @@ -412,7 +413,7 @@ def elementary_volumes(holes_, starts_, ends_, hole_ids_, node_ids_, nodes_, end top_lines = [l for l in face_lines if l.side==Line.TOP] bottom_lines = [l for l in face_lines if l.side==Line.BOTTOM] - end_lines = [tuple(nodes[n].coords) for n in list(ends.keys())] + end_lines = {tuple(nodes[n].coords): holes[n] for n in list(ends.keys())} if DEBUG: open('/tmp/top_lines_face_{}.vtk'.format(face_idx), 'w').write(to_vtk(MultiLineString([l.points for l in top_lines]).wkb_hex)) open('/tmp/bottom_lines_face_{}.vtk'.format(face_idx), 'w').write(to_vtk(MultiLineString([l.points for l in bottom_lines]).wkb_hex)) @@ -448,7 +449,7 @@ def elementary_volumes(holes_, starts_, ends_, hole_ids_, node_ids_, nodes_, end if (s[1], s[0]) in end_lines: terms.append(Polygon([s[1], s[0], offsets[s[1]]])) terms.append(Polygon([s[0], offsets[s[0]], offsets[s[1]]])) - #faces[(hl, hr)] += terms[-2:] + faces[tuple(sorted((end_lines[(s[1], s[0])], other_hole)))] += terms[-2:] termination += terms if DEBUG: From 45503d766b0b47e1f97ef779108ae3c1153d26fb Mon Sep 17 00:00:00 2001 From: Vincent Mora Date: Wed, 30 Oct 2019 16:06:37 +0100 Subject: [PATCH 29/42] test if edge is possible in section edge edition --- albion.sql | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/albion.sql b/albion.sql index 73a1afe..1a8081f 100644 --- a/albion.sql +++ b/albion.sql @@ -992,7 +992,14 @@ $$ from _albion.node as s, _albion.node as e where s.id=new.start_ and e.id=new.end_ into new_geom; - -- TODO test if edge is possible + -- test if edge is possible + if not exists (select 1 + from albion.all_edge as ae + join _albion.node as ns on ae.start_ = ns.hole_id + join _albion.node as ne on ae.end_ = ne.hole_id + where ns.id = new.start_ and ne.id = new.end_) then + raise 'impossible edge'; + end if; end if; From 827aadfb9458db28b4f415c4cddf11be6c4afc5c Mon Sep 17 00:00:00 2001 From: Vincent Mora Date: Wed, 30 Oct 2019 16:32:56 +0100 Subject: [PATCH 30/42] removes stratigraphic log window --- albion.sql | 2 +- plugin.py | 91 +++++++++++++++++++++++++++++++----------------------- project.py | 24 ++++++++------ 3 files changed, 67 insertions(+), 50 deletions(-) diff --git a/albion.sql b/albion.sql index 1a8081f..eb6c493 100644 --- a/albion.sql +++ b/albion.sql @@ -904,7 +904,7 @@ $$ if new.start_ > new.end_ then select new.start_, new.end_ into new.end_, new.start_; end if; - -- @todo check that edge is in all_edge + -- check that edge is in all_edge select count(1) from albion.all_edge as ae join _albion.hole as hs on hs.id=ae.start_ diff --git a/plugin.py b/plugin.py index aa43747..ebd3a71 100644 --- a/plugin.py +++ b/plugin.py @@ -19,7 +19,7 @@ from .axis_layer import AxisLayer, AxisLayerType from .viewer_3d.viewer_3d import Viewer3d from .viewer_3d.viewer_controls import ViewerControls -from .log_strati import BoreHoleWindow +#from .log_strati import BoreHoleWindow from .export_elementary_volume import ExportElementaryVolume @@ -84,9 +84,9 @@ def initGui(self): self.__toolbar = QToolBar("Albion") self.__iface.addToolBar(self.__toolbar) - self.__toolbar.addAction( - icon("log_strati.svg"), "stratigraphic log" - ).triggered.connect(self.__log_strati_clicked) + #self.__toolbar.addAction( + # icon("log_strati.svg"), "stratigraphic log" + #).triggered.connect(self.__log_strati_clicked) self.__toolbar.addWidget(self.__current_graph) self.__current_graph.currentIndexChanged[str].connect( @@ -242,15 +242,16 @@ def __create_menu_entries(self): ) self.__add_menu_entry( - "Delete Graph", self.__delete_graph, self.project is not None + "Delete Graph", self.__delete_graph, self.project is not None and self.project.has_graph ) self.__add_menu_entry( - "Add selection to graph nodes", self.__add_selection_to_graph_node, self.project is not None + "Add selection to graph nodes", self.__add_selection_to_graph_node, self.project is not None and self.project.has_graph + ) self.__add_menu_entry( - "Accept graph possible edges", self.__accept_possible_edge, self.project is not None + "Accept graph possible edges", self.__accept_possible_edge, self.project is not None and self.project.has_graph ) self.__add_menu_entry( @@ -446,7 +447,6 @@ def __upgrade_project(self): def __new_project(self): - # @todo open dialog to configure project name and srid fil, __ = QFileDialog.getSaveFileName( None, u"New project name (no space, plain ascii)", @@ -648,13 +648,26 @@ def __delete_graph(self): def __add_selection_to_graph_node(self): assert(self.project) #TODO ADD DIALOG TO REMIND USER THE CURRENT GRAPH - if ( self.__iface.activeLayer() and self.__iface.activeLayer().selectedFeatures() ): selection = self.__iface.activeLayer().selectedFeatures() graph = self.__current_graph.currentText() + if ( + QMessageBox.Yes + != QMessageBox( + QMessageBox.Information, + "Adding selected edges", + "Do you want to add {} selected edges to {} ?".format( + len(selection), + graph + ), + QMessageBox.Yes | QMessageBox.No, + ).exec_() + ): + return + self.project.add_to_graph_node(graph, selection) self.__refresh_layers() @@ -678,7 +691,7 @@ def __toggle_axis(self): def __create_cells(self): assert(self.project) self.project.triangulate() - self.__refresh_layers("cell") + self.__refresh_layers() def __create_sections(self): assert(self.project) @@ -859,35 +872,35 @@ def __export_project(self): os.path.split(QgsProject.instance().fileName())[1], ) - def __log_strati_clicked(self): - # @todo switch behavior when in section view -> ortho - self.__click_tool = QgsMapToolEmitPoint(self.__iface.mapCanvas()) - self.__iface.mapCanvas().setMapTool(self.__click_tool) - self.__click_tool.canvasClicked.connect(self.__map_log_clicked) - - def __map_log_clicked(self, point, button): - self.__click_tool.setParent(None) - self.__click_tool = None - - if self.project is None: - self.__log_strati and self.__log_strati.setParent(None) - self.__log_strati = None - return - - if self.__log_strati is None: - self.__log_strati = QDockWidget("Stratigraphic Log") - self.__log_strati.setWidget(BoreHoleWindow(self.project)) - self.__iface.addDockWidget(Qt.LeftDockWidgetArea, self.__log_strati) - self.__iface.mainWindow().tabifyDockWidget( - self.__iface.mainWindow().findChild(QDockWidget, "Layers"), - self.__log_strati, - ) - - res = self.project.closest_hole_id(point.x(), point.y()) - if res: - self.__log_strati.widget().scene.set_current_id(res) - self.__log_strati.show() - self.__log_strati.raise_() + #def __log_strati_clicked(self): + # # @todo switch behavior when in section view -> ortho + # self.__click_tool = QgsMapToolEmitPoint(self.__iface.mapCanvas()) + # self.__iface.mapCanvas().setMapTool(self.__click_tool) + # self.__click_tool.canvasClicked.connect(self.__map_log_clicked) + + #def __map_log_clicked(self, point, button): + # self.__click_tool.setParent(None) + # self.__click_tool = None + + # if self.project is None: + # self.__log_strati and self.__log_strati.setParent(None) + # self.__log_strati = None + # return + + # if self.__log_strati is None: + # self.__log_strati = QDockWidget("Stratigraphic Log") + # self.__log_strati.setWidget(BoreHoleWindow(self.project)) + # self.__iface.addDockWidget(Qt.LeftDockWidgetArea, self.__log_strati) + # self.__iface.mainWindow().tabifyDockWidget( + # self.__iface.mainWindow().findChild(QDockWidget, "Layers"), + # self.__log_strati, + # ) + + # res = self.project.closest_hole_id(point.x(), point.y()) + # if res: + # self.__log_strati.widget().scene.set_current_id(res) + # self.__log_strati.show() + # self.__log_strati.raise_() def __line_from_selection(self): if ( diff --git a/project.py b/project.py index aaff6a4..c4fccc4 100644 --- a/project.py +++ b/project.py @@ -246,7 +246,6 @@ def add_table(self, table, values=None, view_only=False): string.Template(statement).substitute(table) ) if values is not None: - print(table) cur.executemany(""" insert into albion.{NAME}(hole_id, from_, to_, {FIELDS}) values (%s, %s, %s, {FORMAT}) @@ -257,13 +256,10 @@ def add_table(self, table, values=None, view_only=False): con.commit() self.vacuum() - # TODO add a list of tables in _albion to be able to restore them on update - def update(self): "reload schema albion without changing data" - with self.connect() as con: cur = con.cursor() cur.execute("select srid from albion.metadata") @@ -386,6 +382,8 @@ def __getattr__(self, name): return self.__has_volume() elif name == "has_group_cell": return self.__has_group_cell() + elif name == "has_graph": + return self.__has_graph() elif name == "has_radiometry": return self.__has_radiometry() elif name == "has_cell": @@ -401,37 +399,43 @@ def __has_cell(self): with self.connect() as con: cur = con.cursor() cur.execute("select count(1) from albion.cell") - return cur.fetchone()[0] > 1 + return cur.fetchone()[0] > 0 def __has_hole(self): with self.connect() as con: cur = con.cursor() cur.execute("select count(1) from albion.hole where geom is not null") - return cur.fetchone()[0] > 1 + return cur.fetchone()[0] > 0 def __has_volume(self): with self.connect() as con: cur = con.cursor() cur.execute("select count(1) from albion.volume") - return cur.fetchone()[0] > 1 + return cur.fetchone()[0] > 0 def __has_section(self): with self.connect() as con: cur = con.cursor() cur.execute("select count(1) from albion.named_section") - return cur.fetchone()[0] > 1 + return cur.fetchone()[0] > 0 def __has_group_cell(self): with self.connect() as con: cur = con.cursor() cur.execute("select count(1) from albion.group_cell") - return cur.fetchone()[0] > 1 + return cur.fetchone()[0] > 0 + + def __has_graph(self): + with self.connect() as con: + cur = con.cursor() + cur.execute("select count(1) from albion.graph") + return cur.fetchone()[0] > 0 def __has_radiometry(self): with self.connect() as con: cur = con.cursor() cur.execute("select count(1) from albion.radiometry") - return cur.fetchone()[0] > 1 + return cur.fetchone()[0] > 0 From 6568513a6757b2a28212034328c026609a3c796d Mon Sep 17 00:00:00 2001 From: Vincent Mora Date: Mon, 6 Jan 2020 15:03:19 +0100 Subject: [PATCH 31/42] removes useless test --- test/__main__.py | 6 ++++++ test/deviation_bug.py | 14 -------------- test/end_node.py | 3 +-- test/tutorial_named_section.gpkg | Bin 0 -> 106496 bytes 4 files changed, 7 insertions(+), 16 deletions(-) create mode 100644 test/__main__.py delete mode 100644 test/deviation_bug.py create mode 100644 test/tutorial_named_section.gpkg diff --git a/test/__main__.py b/test/__main__.py new file mode 100644 index 0000000..59baf84 --- /dev/null +++ b/test/__main__.py @@ -0,0 +1,6 @@ +import os +import re + +for f in os.listdir(os.path.dirname(__file__)): + if re.match('^[a-z].*\.py', f): + print(f) diff --git a/test/deviation_bug.py b/test/deviation_bug.py deleted file mode 100644 index 7c90872..0000000 --- a/test/deviation_bug.py +++ /dev/null @@ -1,14 +0,0 @@ -from __future__ import print_function -# coding = utf-8 - -if __name__ == "__main__": - from albion.project import Project - import os - from pglite import import_db - - for f,dbname in (('git1.dump', 'deviation_bug_test_1'), ('git2.dump', 'deviation_bug_test_2')): - if Project.exists(dbname): - Project.delete(dbname) - import_db(os.path.join(os.path.dirname(__file__), f), dbname) - - diff --git a/test/end_node.py b/test/end_node.py index 4cc9dd5..7ed3072 100644 --- a/test/end_node.py +++ b/test/end_node.py @@ -12,8 +12,7 @@ ; SELECT albion.triangulate() ; -REFRESH MATERIALIZED VIEW albion.all_edge -; + INSERT INTO albion.graph(id) VALUES ('graph1') ; diff --git a/test/tutorial_named_section.gpkg b/test/tutorial_named_section.gpkg new file mode 100644 index 0000000000000000000000000000000000000000..2c4d2268b13be62a506ef005d8332c0edfe9dbf0 GIT binary patch literal 106496 zcmeI53v`>smB%H&9miJQh9o3k1i|(}N&Lu5K$beO;)vL?Bg;)q2&%9?I|5rWl8l|S z1#Bm!oWo9z&B-9CVpr4+W0ZQ%fImoBAj%l4Ghvj2O( zZ=`QzC9xAIq`f-U_jzXS%-s8%JM+z4C34@su0+-}hEnO#Sk`EBEpoZtuD2M5%Y|QE zu9bMJ*Bbm%rV_ZjU9N^FDc#w-x6_gD{B@CQ*Rq=ZuDX`m$LijPU*shOgn$qb0zyCt z2mv7=1cbnR2^^i6`r~BPHrMi!o3^<2clH_EHyfLb{z$iRB$YIcw$@Ofx3Ba1$=-0! zrMvnLc#Dd7eVu`x&U~@g*U=v7?`G*}i+}rOudlCnPaxbA>`*OueOueMZEtDY=40YjZfWuRH@6kj!Qax_T3mMG*R%ErjiF3&Ixys`Ws7UjzfhnW0>Rp`LJL zPqA?WvNpnbxvO%AYkAe$(f(xI97-h3xG`*|hSRaJLy1A7FWeXE2?fSgS?(97&|oT+ zjwg~ad@`Iihs?B@95jv0;Y`*XJ@Be}RbJ#;?p}L!zL&vRI%{TtRdw=euJPP2MqcOy zolFniHB@~8X3x>usdMbP0UP3GHZe&4yXd*U^qDb|N)EHLZ&F@wssF$c4WRC36SWyjNIrg&*t*g|x_;z-wQ|h;OlZXYYSkUrPcDF6ZqIWr{K!iP2mv7=1cZPP z5CTF#2nYcoAOwVf5ICa=oL%a#E*>e6^Zyw=u%f&W5CTF#2nYcoAOwVf5D)@FKnMr{ z2Z7_C|E+)j|BTD?j6+<06#_y)2nYcoAOwVf5D)@FKnMr{As__KI07r(rG9tukN*w% z{Qry_PElA02mv7=1cZPP5CTF#2nYcoAOwWKaR{93^Z!R(o=1;URkDSE5D)@FKnMr{ zAs_^VfDjM@LO=)zfj1w44em<+@^vLuRmDH>$6rwx?FxnheUWf5gg-!Heg6NH%k$Km z&lJ%}2nYcoAOwVf5D)@FKnMr{As_^VfDo7?fi-3R<;VH%KZ*s&zyF^jM-dYOLO=)z z0U;m+gn$qb0zyCt2mvARrYCUXfB)}V^rkmJ6chqNKnMr{As_^VfDjM@LO=)z0U;m+ zPJ;k_{x9eM(*P({g@6zc0zyCt2mv7=1cZPP5CTF#2%G@~=aP5U8zt z$+gJ+5m(*s7yh{J-nw@#bT9m1^`V;2*IZqBUG>`X`^qQEwwF8)f$ljNRQFQJhvy(B zBJ(3K-La^0RsV*nql>fY#PG109v-`TIGRn2n9_cZ~AZ#=gmKSTI!Pptt-4hNN!BAfy95H%Av+Fe&kT3%6yY?92p8crM84MYH zfv&)=h!JiN_5~W-clLxMKBK|X%Sa`SZ0yPr(`cBbLqmgcZ6Y-i%bFQuFqOte@v1BrpHLf&`5i^r9vWH?xqotwA*uN(LO&ddj{Tns;i;b41i;O_1WBO80 z<*I$axbAoukEBwg(Gl}nb0j)G7Ka*zkWLD5Rtq_V{ko@ zGm^-f(b#x4#p!6F+eKRnbLwVxEv&5Hu)+OqKToE@^1^hj^4#{FT>+!8)M(^JqRH5( zX+#2Vix{CEy!*Sld=68Cp-6z1j$D~G&5l=k$V?0$%3=j6sLackHKU7{9k1e8ViNOn zGMY&oF^!I%eljShl2v%Pc;T*|5dQ2ZYcdH47^1w`_4Avzja% zmuSYEwT@F>%?U@7B%IdhBkHu-mq}-$iTLcn8BHXkle6Gb?%~JclO|9#$wq-Y$TdChoYIo8Kcn_Z0fA3s6Vh}&hr%HXU|m{ zkA+8Fm6i3|wz+Ryo1d@r{mW)HeKXySo9M^2{UaKSl;W4o0-9MVl11$ZkQjq%JhZ?-$*QzjSga4JB;TW_KcBW zcm4@yD8WYTj)$^|QM0jO{lJFxqZ`)8BkT8ExW4opK~Sm8O{~l zH|kipQRG;#3!V$JCqtU113fuTWp&LhuKu!$`tF7kj<6a9dm^Z0xxaMoRV~L?Rm*Vp zs-pAPbg7%4y)#XD=O}m%uKEMi>p6dl)byTJm8&xTs+p91=CE(kxH)2C1FbD8(c*vq zuz0Q-Q~Pl2J%xt7M*HpvcE=q!`r@32qq4VnUtar+Y##_`t*S?%08@VH#ZGO*g!zuNKorpCh zM#nQ8U>Hv0F@=?zV+{FI9nDCNGia6mDt9yvuCUmyniJboJRCdwev=)KovIn9$#P)% zocz=}4xXN$YHb|XPwj)}>4m~hJ#u5QwUwA3Tf36OPnXTfPi-!z<)>O3IksH)qcbl{l}a0cCf^XYMiR07HcF&Gryv0VsF@zs%ud!&R9HbYX^SvaoashEVlJ? zV|$8@s;T=XTTwOLipCu0hO+i$*UI8MwW*2KmGu`~;GS8Z-wm6Sh*)K?5w#){`Q&o7 zU&==l^M$hxOtXRzzMOEexPxQ!s)r&ogQ;1^D@T}N*o~Rjruy8};@(_@-uZz=dw--S7(zSU0cSAQ z@KTJ=Yjg!e0esvM40ZYpFSS9dDSpkEgA^IC(oN+s*X?D*~o9mvaYpoq!_@0{E7u;HXQ&qMyRdH2$e_3zofs!Hj zU9Mk3Xzs76B}*z?({*RpclNqUC$D$8hK7df9`3lV9rqP)t*!JC)P3UavAgKL;EB6O4qI)U|8Cq_sY>*$1eL(U4?XmL zs_@`%8-GMrs0PCKt%;G6zub4|J-_c$r1U2{p9| z5Zw6=ONmxWzhl`aze7eqshyODT$GG>x$$!D2u8d>qyd4`P;#1#Pzu1PrDO!kRr{<6 z8?ntYBJHVg%{a&d$PJI8FVua4?$EVu5^Z1%T^6 zi1w0E7@;pw8Y9Fb17p8TX*Du%i-#$V{NIyN9~s;6fL%UCMqwoHr!*8{zr@IV)h_?Q zQItcU2PutwAGwG!L@CZjZ?%oC(~U;k{>M-kK;KGt=(L`U2G9pIqcIX8rvQ}RN9jFJ z9r-L74bXj*h7ujN(Y<#18#I!t11QTQsp>=7-;mL&918H9LAzWZ>E$$%<&%l;{4G zI|I(oNgn;ICJ2yI`rJhj(C!DR9I(Db5Xi$QtqfrZn=J@S7FM{9*5&6c+U)&4WHF^~ zr2FN!J@6rdfPv}G%~@KCVMN*~0OhWwH1fR!0Tr&HG?aNCL4XoBPWp?-9@FI=HiYM?KR~M|2!K&W z^)YJyNS*+Xa#I?{Zm>O}iqe41^H>?C3}FbZHiQK_1Ps)T|B1TfU35pEYiXci%N`8^ zGXB~r00{4;G>rHMf}k3JQu_!3jQSfYNBVK{1i-qP((o95jzU?k52OFrUK8GD%k!Fm z`nOOT?XIxbgxe_%Pxuf)Q2nEPD?vazTn?kZN1mVzQ-&~v7JGVB>(c{me)9)b+XsJ$ zJEm^^1lj=TU=9LJ51NxCs02`P9aR7XH9elCaww4{C@{W-%Aw3&8w$%K{qFVy2ZY9rv=QP;;@pBt%!FiNMJ9iTl)Mo?G-hP6D`rIG%_*a4g zz1NbwGK`@#+n!OSdj`PW^CPS8uhU&E0cdL=2Zg2w-2HP-0i?fRSL8<|T4zDQ|!1V18Ge`<|Tio)nS2?9Kf+lOkK2?F4; z0jS4o1p2v;+Ea!Qgl&EsLZuD?bvOPOWMRWzx})toXyF8m-5LaB{FPGx9?(H)G{Byr z8p4Qtnmhx>1gISDyPG^ibpT_YBq*vqj4)3ZbjI zpb`M#N2vnx*U_Q^w|kt@Q1V|00!HjRl*aVo9U&V0hAq!)28`tnVSJoC1NZMyIXr@Q zgfNE7VGQpG0gubkZ!N7Em@eEt%0EU>aDRmAE5+Gpdxv;sIgH+ze`KPMmwsyLcGXi> zohn)rFoibdjHYidhjC3#0T>mfG$5QyMq`AppfpD0b}|}D4O1Fbc{-?$0OeOS@_-bh za&*LxOc>QmX+V0K7D}``NNJ3yI&iRpsP7@8(QcVtpA}^z?H%FHGJP+PHlBSNZ2|P} z=nh@ikj}_IhuX^R<>78GI|ZP`uPBWXxQ~p&{Wo?wyEBx2k4llWfbb`(wrcq}jDp0Bf zm4K>%5xa!uAl&9%)Bu$3A|*lmI=kWDk&>u?1En$IY9V5I)e$Rc?ZBp5OZ1~24Ew{g zsEbir^&IXnq(owHa0Lm<)3Q+PQQW7GZrnx|5q4Z)ZhZ0wi(wNXoD2<8# zKcuwk81;E`fex#wTy@M!TRWt*yTUc)nD-c*)jxwMJn?S2gU1ol8H2-5Ck9&zg_NKY zP!-U}qogCi9ij$QMeftukkC`L&h-PA=jytz*WSNyq-I<7e^iZD{I2}=vQX(jN!)!K z3eU*bRI8!80OkyzPca90sa8ubMlk z+EX4bq&@Ho6~J(8Zf@Hjpb$lPEtbK${4z*BZ=Xl``2k&cCxMBXKPXpYfERpS4yI^8JEH-bc3eSy zZRd`)UfZ<7ZF!>!`n-Qr?x_?je2Oar9Lw(J=4Li}dgp5F?2~!-g^{;>+gj~-)x&`C z&Okj^*yu&Ts06V@@o@tq&T&F?#_KckwTKx;hNE9lnuAYhSc}`hNG+s+>7kwOVO-%s zS3C1z>C}!tfS~RCp%-tu0hmVzKKanj5SIX=5=6lbv?+z478?ZwEewe@LW}5OT4=#Ac!CO4sjZF{GJ)|N z)=-MTDD5DP`r4TiYlwE70u=3J0guu))o5SaUqWAP>s7dGp*7ICL2v-$XD>bX{M#+a z>6L)&c-UgVt|Q23gP)a1^L7t+4iYfrrGTsiVeBvH0S`~q0@7GxwAe2^O$(#KbF>H~ z(j44F$9%HD8pHuJz~iSp>T4kz3^IpHlwyFU9po{!_%IE)TpwxeIEVJNlMK?@rXGW- z?RR0awpAqiox8Ha4UYn-`e*3dY|lPh_iQ-aG(pGgqH{peOIwVV|}&R=}Vq?>ZUsRvYqJI%GKNVS)^ucpC|p z93X|xeBjAJR)UyjkI}Y~);8xyG4K@aQx8DaK0v_WXt8&swXifGXc1b}*MgOp30m9^ z`e-36q_yY`+SdXZwB?~QHawWm@F>@gv*?eHl*(|(X@?{XsSWa(w27fc60fjL>5H@Bl5$jX}^NzJR6$KQX!- zNQ8%Q91wRc1cvstXb_Ck0wI_YT1)`TjdomyQ)nkmnhCTVpdKIM3IQ;*%@(xq3V3E+ zes=&}`13a~;DZk8^5<`u4SYCbXp7N<5>x^hnZl2@v`>Z9nu=-0ADECQ(}xf6K>q9i z*o4!2m7LfnaxKn?4mdW45#^Yi>JXmF;VM?rJ`pTg z3MC!x4}iQd!&`Whj5c`P#X#^Ln3bf@#Fd~DDDpJqy$j@cOH#NGR2`^>St%>*Oy_^M z=e;ic$V&(a0U;m+gn$qb0zyCt2mv7=1cZPP_>&PBaaZ`4Z@6Y%@qe&S-|fd=8K2Ik zO%q>Ji@zUrD4QL-aMPxViHVIU9*YfL9UC?`;?D(a%8Z$VEv?O)&dq=6Dc74w;}1@4 zNF_%O)4!l`d%o+!kGzC{5D)@FKnMr{As_^VfDjM@LO=)zfir}_rg8)is^=a%;LrbS zHn{L3FCicVgn$qb0zyCt2mv7=1e^qJ>UEd7Za)uMhMn!+`%=R;yf4}N>dd$HzIv3t z#fn}f$lHi_3-TXA{@GTxs}y-&yw6Ae!^mH6=a(U`9`Cb|{}qRPIr1v-u0{TR$Zxad zk$3(d@qQKgpLgU}BJbCD{|5P=L4KDlUxmD9@%}mT???V#JHHxv-^crh$iLSizW{j; z;SC*GAJt9`^1h5W+TeCn{zBw^8gJ;L^;?U)kKp~!$p0MLe~aC39rE6f_ut#?sC*Cd zZpQmIK-V0%wa6#_@Smd>T{Z~%$EfJU*nRth}uJ&ayyBx9f$v=lBR7`nYO+~q4pgj^WBH>_XXCQ2N=iHpvXx|+{ zjsD&aYM>`%c#HSoHTLfbgp8i9j*Z@-MBHnv+hK$P`|U(~sKaRFBt}de| zZ1hET%nx{Wzqe0fcpE;0h4 zj+ycGjQ8CK=ZUwixbdfox9xSp8|sNLU&4;xUoXfz^22=*i1!7;5gO8Pptq}iR{%MY zo;i)$Tid((1AVrGkn{N972S#C+ng@pBP+UNlX|8lI8aPb%e2OQdjEOWv|2aMac_NX z$Gx?1+;hOB;HcQQOaDvd0GJNw(#+CEN0PlbzqxIuj`Bv@G$%INvxe5Vc`SIUi#PL9HPx}Mvi{&f_tb%G z?8*_)rf*RyPTYF_kHykvGCNnfv(+Q3eP>r-4vTcuYTnzJOvTM)iq`f3?Ie1`!S43( zfU!3);4>^4l2GMMQx_YR^#=~Pr+VgSMmjZ-h@adF7CURcMsO`}Bj1#Yx(T{@O;cOe zR@M&;xTgYhRG;dfTzitLpRe*%>BRi80gM?tyLxsuO>JCLS>MxBHPt;gy-%vLt?XNa z;Yfdbml2tx+jx!szF?@+;Px96ai1}oNKWD!o1|+Zd6<7c+_dAIiu!#QxLy1`VVP@2 z@U>sj*myR@=_r4ZSnjLAGSQZTj1~Bg4Bz;3I|GP4e|ZF^>l^r4Jag`xpT%)=#LSw- jpA2e=nftNNYE3);H>IhO_^e0qX&>H< Date: Tue, 7 Jan 2020 09:03:12 +0100 Subject: [PATCH 32/42] fix buf in new project creation --- plugin.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/plugin.py b/plugin.py index ebd3a71..71f2cc9 100644 --- a/plugin.py +++ b/plugin.py @@ -493,6 +493,9 @@ def __new_project(self): Project.delete(project_name) self.__iface.messageBar().pushInfo("Albion:", "creating project...") Project.create(project_name, srid) + else: + self.__iface.messageBar().pushInfo("Albion:", "creating project...") + Project.create(project_name, srid) if os.path.exists(fil): os.remove(fil) @@ -705,6 +708,7 @@ def __refresh_selected_layers_sections(self): if table.endswith('_section'): table = table[:-8] self.project.refresh_section_geom(table) + self.__refresh_layers(table+'_section') def __compute_mineralization(self): MineralizationDialog(self.project).exec_() From 9666677b419d32a9330cadb2b95c79205a7054ff Mon Sep 17 00:00:00 2001 From: Vincent Mora Date: Tue, 7 Jan 2020 09:03:59 +0100 Subject: [PATCH 33/42] fix bug on postgres 11 GEOMETRYCOLLECTION EMPTY is returned (hex format) by shapely.MultiPolygon when empty, this could not be cast to MULTYPOLYGONZ EMPTY and caused failure to build volumes --- elementary_volume/__init__.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/elementary_volume/__init__.py b/elementary_volume/__init__.py index c5c9134..7f8a892 100644 --- a/elementary_volume/__init__.py +++ b/elementary_volume/__init__.py @@ -629,8 +629,10 @@ def pop_connected(n, graph): face3 = translate(MultiPolygon(face3), translation[0], translation[1], translation[2]) geos.lgeos.GEOSSetSRID(face3._geom, srid_) - - yield res.wkb_hex, face1.wkb_hex, face2.wkb_hex, face3.wkb_hex + + empty_mp = "SRID={} ;MULTIPOLYGONZ EMPTY".format(srid_) + yield (res.wkb_hex if not res.is_empty else empty_mp, face1.wkb_hex if not face1.is_empty else empty_mp, + face2.wkb_hex if not face2.is_empty else empty_mp, face3.wkb_hex if not face3.is_empty else empty_mp) for f in debug_files: os.remove(f) From 30dbfa8fb74ce8eda7ce4906f49511a381292a1c Mon Sep 17 00:00:00 2001 From: Vincent Mora Date: Wed, 8 Jan 2020 10:54:01 +0100 Subject: [PATCH 34/42] fix grade computation fix #97 --- albion.sql | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/albion.sql b/albion.sql index eb6c493..0eef53d 100644 --- a/albion.sql +++ b/albion.sql @@ -801,8 +801,8 @@ $$ ito_ -= OC+IC-1 if ifrom_ >= 0 and ito_ > 0 and c: accu = numpy.sum(AVP[ifrom_:ito_]) - grade = accu/(ito_ - ifrom_) oc = (ito_ - ifrom_)*measure_thickness + grade = accu/oc result.append((cut, ifrom_*measure_thickness + first_from_, ito_*measure_thickness + first_from_, oc, accu, grade)) return result From dfd9f7b51239b9f7ef54653dc4040e70d837efe6 Mon Sep 17 00:00:00 2001 From: Vincent Mora Date: Wed, 15 Jan 2020 11:18:35 +0100 Subject: [PATCH 35/42] removes axis layer fix #102 --- axis_layer.py | 76 --------------------------------------------------- plugin.py | 25 ----------------- 2 files changed, 101 deletions(-) delete mode 100644 axis_layer.py diff --git a/axis_layer.py b/axis_layer.py deleted file mode 100644 index 07e1c48..0000000 --- a/axis_layer.py +++ /dev/null @@ -1,76 +0,0 @@ -# coding: utf-8 -from builtins import range -from qgis.core import (QgsPluginLayerType, - QgsPluginLayer, - QgsRectangle) - -from qgis.PyQt.QtCore import pyqtSignal - -import traceback -import logging - - -class AxisLayerType(QgsPluginLayerType): - def __init__(self): - QgsPluginLayerType.__init__(self, AxisLayer.LAYER_TYPE) - - def createLayer(self): - return AxisLayer() - return True - - def showLayerProperties(self, layer): - return False - - -class AxisLayer(QgsPluginLayer): - - LAYER_TYPE = 'axis' - - __msg = pyqtSignal(str) - __drawException = pyqtSignal(str) - - def __init__(self, crs): - QgsPluginLayer.__init__( - self, - AxisLayer.LAYER_TYPE, - 'axis plugin layer') - self.__msg.connect(self.__print) - self.__drawException.connect(self.__raise) - self.setCrs(crs) - self.setValid(True) - - def extent(self): - return QgsRectangle(-1, -1, 1, 1) - - def __print(self, msg): - logging.info(msg) - - def __raise(self, err): - logging.error(err) - raise Exception(err) - - def draw(self, rendererContext): - try: - painter = rendererContext.painter() - ext = rendererContext.extent() - map_unit_per_pixel = rendererContext.mapToPixel().\ - mapUnitsPerPixel() - width, height = \ - int((ext.xMaximum()-ext.xMinimum())/map_unit_per_pixel),\ - int((ext.yMaximum()-ext.yMinimum())/map_unit_per_pixel) - nb_div = 10 - dw, dh = width/nb_div, height/nb_div - dx, dy = ((ext.xMaximum()-ext.xMinimum())/nb_div, - (ext.yMaximum()-ext.yMinimum())/nb_div) - - for i in range(nb_div+2): - painter.drawText(5, int(i*dh), "%.0f" % (ext.yMaximum()-i*dy)) - painter.drawLine(50, int(i*dh), 60, int(i*dh)) - for i in range(nb_div+2): - painter.drawText(int(i*dw), 20, "%.0f" % (ext.xMinimum()+i*dx)) - painter.drawLine(int(i*dw), 20, int(i*dw), 25) - - return True - except Exception as e: - self.__drawException.emit(traceback.format_exc(e)) - return False diff --git a/plugin.py b/plugin.py index 71f2cc9..585d07b 100644 --- a/plugin.py +++ b/plugin.py @@ -16,7 +16,6 @@ from .project import ProgressBar, Project, find_in_dir from .mineralization import MineralizationDialog -from .axis_layer import AxisLayer, AxisLayerType from .viewer_3d.viewer_3d import Viewer3d from .viewer_3d.viewer_controls import ViewerControls #from .log_strati import BoreHoleWindow @@ -29,13 +28,6 @@ import atexit -AXIS_LAYER_TYPE = AxisLayerType() -QgsApplication.pluginLayerRegistry().addPluginLayerType(AXIS_LAYER_TYPE) -atexit.register( - QgsApplication.pluginLayerRegistry().removePluginLayerType, AxisLayer.LAYER_TYPE -) - - def resource(name): """Return name with prepended `res` directory """ @@ -58,7 +50,6 @@ def __init__(self, iface): self.__current_graph = QComboBox() self.__current_graph.setMinimumWidth(150) self.__toolbar = None - self.__axis_layer = None self.__menu = None self.__log_strati = None @@ -293,10 +284,6 @@ def __create_menu_entries(self): self.__menu.addSeparator() - self.__add_menu_entry("Toggle axis", self.__toggle_axis) - - self.__menu.addSeparator() - self.__menu.addAction("Help").triggered.connect(self.open_help) def __current_graph_changed(self, graph_id): @@ -679,18 +666,6 @@ def __accept_possible_edge(self): assert(self.project) self.project.accept_possible_edge(self.__current_graph.currentText()) - def __toggle_axis(self): - if self.__axis_layer: - pass - QgsProject.instance().removeMapLayer(self.__axis_layer.id()) - self.__axis_layer = None - else: - self.__axis_layer = AxisLayer( - self.__iface.mapCanvas().mapSettings().destinationCrs() - ) - QgsProject.instance().addMapLayer(self.__axis_layer) - self.__refresh_layers() - def __create_cells(self): assert(self.project) self.project.triangulate() From ac91c30c33b0ef2a7d2f6999674719188c86f4b3 Mon Sep 17 00:00:00 2001 From: Vincent Mora Date: Wed, 15 Jan 2020 11:34:10 +0100 Subject: [PATCH 36/42] fix group creation with ctrl+alt+k fix #100 --- project.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project.py b/project.py index c4fccc4..b3304db 100644 --- a/project.py +++ b/project.py @@ -700,7 +700,7 @@ def create_group(self, section, ids): cur = con.cursor() cur.execute( """ - insert into albion.group default values returning id + insert into albion.group(id) values ((select coalesce(max(id)+1, 1) from albion.group)) returning id """ ) group, = cur.fetchone() From baf753fa5412d974373ae13d8a0dbee535fd896f Mon Sep 17 00:00:00 2001 From: Vincent Mora Date: Wed, 15 Jan 2020 12:33:19 +0100 Subject: [PATCH 37/42] replaces end_node_thickness with relative thickness fix #99 --- _albion.sql | 2 +- _albion_v1_to_v2.sql | 4 ++-- albion.sql | 13 +++++++------ elementary_volume/__init__.py | 4 +++- 4 files changed, 13 insertions(+), 10 deletions(-) diff --git a/_albion.sql b/_albion.sql index 33b9912..2e56925 100644 --- a/_albion.sql +++ b/_albion.sql @@ -36,7 +36,7 @@ create table _albion.metadata( correlation_angle real default 5.0, parent_correlation_angle real default 1.0, end_node_relative_distance real default .3, - end_node_thickness real default 1, + end_node_relative_thickness real default .3, version varchar) ; diff --git a/_albion_v1_to_v2.sql b/_albion_v1_to_v2.sql index 5239f7b..2d4456d 100644 --- a/_albion_v1_to_v2.sql +++ b/_albion_v1_to_v2.sql @@ -5,10 +5,10 @@ alter table _albion.metadata drop column end_distance ; alter table _albion.metadata add column end_node_relative_distance real default .3 ; -alter table _albion.metadata add column end_node_thickness real default 1 -; alter table _albion.metadata add column version varchar default '2.0' ; +alter table _albion.metadata add column end_node_relative_thickness real default .3 +; -- add layer table create table _albion.layer( diff --git a/albion.sql b/albion.sql index 0eef53d..ce38662 100644 --- a/albion.sql +++ b/albion.sql @@ -165,7 +165,7 @@ create trigger collar_instead_trig for each row execute procedure albion.collar_instead_fct() ; -create view albion.metadata as select id, srid, close_collar_distance, snap_distance, precision, interpolation, end_node_relative_distance, end_node_thickness, correlation_distance, correlation_angle, parent_correlation_angle, version from _albion.metadata +create view albion.metadata as select id, srid, close_collar_distance, snap_distance, precision, interpolation, end_node_relative_distance, end_node_relative_thickness, correlation_distance, correlation_angle, parent_correlation_angle, version from _albion.metadata ; create view albion.layer as select name, fields_definition from _albion.layer @@ -1044,7 +1044,7 @@ create type albion.volume_row as ( face3 geometry('MULTIPOLYGONZ', $SRID)) ; -create or replace function albion.elementary_volumes(cell_id_ varchar, graph_id_ varchar, geom_ geometry, holes_ varchar[], starts_ varchar[], ends_ varchar[], hole_ids_ varchar[], node_ids_ varchar[], nodes_ geometry[], end_ids_ varchar[], end_geoms_ geometry[], end_holes_ varchar[], end_node_relative_distance real, end_node_thickness real) +create or replace function albion.elementary_volumes(cell_id_ varchar, graph_id_ varchar, geom_ geometry, holes_ varchar[], starts_ varchar[], ends_ varchar[], hole_ids_ varchar[], node_ids_ varchar[], nodes_ geometry[], end_ids_ varchar[], end_geoms_ geometry[], end_holes_ varchar[], end_node_relative_distance real, end_node_relative_thickness real) returns setof albion.volume_row language plpython3u immutable as @@ -1064,7 +1064,7 @@ $$ # ' '.join(end_holes_)+'\n' #) $INCLUDE_ELEMENTARY_VOLUME -for g, f1, f2, f3 in elementary_volumes(holes_, starts_, ends_, hole_ids_, node_ids_, nodes_, end_ids_, end_geoms_, end_holes_, $SRID, end_node_relative_distance, end_node_thickness): +for g, f1, f2, f3 in elementary_volumes(holes_, starts_, ends_, hole_ids_, node_ids_, nodes_, end_ids_, end_geoms_, end_holes_, $SRID, end_node_relative_distance, end_node_relative_thickness): yield g, f1, f2, f3 $$ ; @@ -1310,7 +1310,7 @@ join _albion.hole as hs on hs.id=ns.hole_id join _albion.hole as he on he.id=ne.hole_id ; -create or replace function albion.end_node_geom(node_geom_ geometry, collar_geom_ geometry, rel_distance real default .3, thickness real default 1, nx real default null, ny real default null, nz real default null) +create or replace function albion.end_node_geom(node_geom_ geometry, collar_geom_ geometry, rel_distance real default .3, rel_thickness real default .3, nx real default null, ny real default null, nz real default null) returns geometry language plpython3u as @@ -1327,6 +1327,7 @@ $$ collar_geom = wkb.loads(bytes.fromhex(collar_geom_)) node_coords = array(node_geom.coords) + thickness = rel_thickness*abs(node_coords[0][2] - node_coords[1][2]) center = .5*(node_coords[0] + node_coords[1]) dir = array(collar_geom.coords[0]) - center dir[2] = 0 @@ -1363,7 +1364,7 @@ from nrml create or replace view albion.dynamic_end_node as -select row_number() over() as id, he.graph_id, n.id as node_id, albion.end_node_geom(n.geom, st_startpoint(h.geom), m.end_node_relative_distance, m.end_node_thickness, nrml.nx::real, nrml.ny::real, nrml.nz::real)::geometry('LINESTRINGZ', $SRID) as geom, h.id as hole_id +select row_number() over() as id, he.graph_id, n.id as node_id, albion.end_node_geom(n.geom, st_startpoint(h.geom), m.end_node_relative_distance, m.end_node_relative_thickness, nrml.nx::real, nrml.ny::real, nrml.nz::real)::geometry('LINESTRINGZ', $SRID) as geom, h.id as hole_id from albion.half_edge as he join _albion.node as n on n.id=he.node_id join _albion.hole as h on h.id=he.other @@ -1517,7 +1518,7 @@ select cell_id, graph_id, t.face3::geometry('MULTIPOLYGONZ', $SRID), starts, ends, holes, hole_ids, node_ids, end_ids, end_geoms from res, albion.metadata m -join lateral albion.elementary_volumes(cell_id, graph_id, st_force3d(geom), holes, starts, ends, hole_ids, node_ids, node_geoms, end_ids, end_geoms, end_holes, m.end_node_relative_distance, m.end_node_thickness) as t on true +join lateral albion.elementary_volumes(cell_id, graph_id, st_force3d(geom), holes, starts, ends, hole_ids, node_ids, node_geoms, end_ids, end_geoms, end_holes, m.end_node_relative_distance, m.end_node_relative_thickness) as t on true ; diff --git a/elementary_volume/__init__.py b/elementary_volume/__init__.py index 7f8a892..30983eb 100644 --- a/elementary_volume/__init__.py +++ b/elementary_volume/__init__.py @@ -195,7 +195,7 @@ def offset_coords(offsets, coords): return [offsets[c] if c in offsets else c for c in coords] -def elementary_volumes(holes_, starts_, ends_, hole_ids_, node_ids_, nodes_, end_ids_, end_geoms_, end_holes_, srid_=32632, end_node_relative_distance=0.3, end_node_thickness=1): +def elementary_volumes(holes_, starts_, ends_, hole_ids_, node_ids_, nodes_, end_ids_, end_geoms_, end_holes_, srid_=32632, end_node_relative_distance=0.3, end_node_relative_thickness=.3): DEBUG = False PRECI = 6 @@ -266,6 +266,8 @@ def elementary_volumes(holes_, starts_, ends_, hole_ids_, node_ids_, nodes_, end A, B, C = array(nodes[n].coords[0][:2]), array(nodes[p[0]].coords[0][:2]),array(nodes[p[1]].coords[0][:2]) c = average(array(nodes[n].coords), (0,)) u = .5*(normalized(B-A)+normalized(C-A))*end_node_relative_distance*.5*(norm(B-A)+norm(C-A)) + thickness = abs(nodes[n].coords[0][2] - nodes[n].coords[-1][2]) + end_node_thickness = end_node_relative_thickness*thickness offsets[nodes[n].coords[0]] = tuple(c+array((u[0], u[1], +.5*end_node_thickness))) offsets[nodes[n].coords[-1]] = tuple(c+array((u[0], u[1], -.5*end_node_thickness))) From 570924842d7de60c5768faa0734bc6997c151839 Mon Sep 17 00:00:00 2001 From: Vincent Mora Date: Wed, 15 Jan 2020 14:52:42 +0100 Subject: [PATCH 38/42] allows export of arbitrary albion layer to dxf and vtk formats fix #103 --- plugin.py | 39 +++++++++++++++++++++++++++++++++++---- project.py | 29 +++++++++++++++++++++++++++++ 2 files changed, 64 insertions(+), 4 deletions(-) diff --git a/plugin.py b/plugin.py index 585d07b..6e776e8 100644 --- a/plugin.py +++ b/plugin.py @@ -188,7 +188,7 @@ def __create_menu_entries(self): self.__add_menu_entry( "Export layer", - None, #self.__export_layer, + self.__export_layer, self.project is not None ) @@ -769,10 +769,41 @@ def __export_holes(self): elif fil[-4:] == ".dxf": self.project.export_holes_dxf(fil) else: - self.__iface.messageBar().pushWarning( - "Albion", "unsupported extension for hole export" - ) + self.__iface.messageBar().pushWarning("Albion", "unsupported extension for hole export") + + def __export_layer(self): + assert(self.project) + + table = None + for l in self.__iface.layerTreeView().selectedLayers(): + uri = QgsDataSourceUri(l.dataProvider().dataSourceUri()) + table = uri.table() + if table.endswith('_section'): + table = table[:-8] + break + + if table is None: + self.__iface.messageBar().pushWarning("Albion", "you must select a layer") + return + fil, __ = QFileDialog.getSaveFileName( + None, + u"Export layer", + QgsProject.instance().readEntry("albion", "last_dir", "")[0], + "File formats (*.dxf *.vtk)", + ) + if not fil: + return + + QgsProject.instance().writeEntry("albion", "last_dir", os.path.dirname(fil)) + + + if fil.endswith('.vtk'): + self.project.export_layer_vtk(table, fil) + elif fil.endswith('.dxf'): + self.project.export_layer_dxf(table, fil) + else: + self.__iface.messageBar().pushWarning("Albion", "unsupported extension for hole export") def __import_project(self): fil, __ = QFileDialog.getOpenFileName( diff --git a/project.py b/project.py index b3304db..6d390ac 100644 --- a/project.py +++ b/project.py @@ -887,6 +887,35 @@ def export_holes_dxf(self, filename): ) drawing.save() + def export_layer_vtk(self, table, filename): + with self.connect() as con: + cur = con.cursor() + cur.execute( + """ + select albion.to_vtk(st_collect(albion.hole_piece(from_, to_, hole_id))) + from albion.{} + """.format(table) + ) + open(filename, "w").write(cur.fetchone()[0]) + + def export_layer_dxf(self, table, filename): + with self.connect() as con: + cur = con.cursor() + cur.execute( + """ + select st_collect(albion.hole_piece(from_, to_, hole_id)) + from albion.{} + """.format(table) + ) + drawing = dxf.drawing(filename) + m = wkb.loads(bytes.fromhex(cur.fetchone()[0])) + for l in m: + r = l.coords + drawing.add( + dxf.polyline(list(l.coords)) + ) + drawing.save() + def create_volumes(self, graph_id): with self.connect() as con: cur = con.cursor() From 5b8feedf51236e9b626fa3aba2ddf120cb693af4 Mon Sep 17 00:00:00 2001 From: Vincent Mora Date: Wed, 15 Jan 2020 15:03:59 +0100 Subject: [PATCH 39/42] adds confirmation dialog for cell creation fix #105 --- plugin.py | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/plugin.py b/plugin.py index 6e776e8..8ad4475 100644 --- a/plugin.py +++ b/plugin.py @@ -668,6 +668,19 @@ def __accept_possible_edge(self): def __create_cells(self): assert(self.project) + + if self.project.has_cell: + if ( + QMessageBox.Yes + != QMessageBox( + QMessageBox.Information, + "Creating cells", + "Do you want to replace project cells (your graphs will become invalid) ?", + QMessageBox.Yes | QMessageBox.No, + ).exec_() + ): + return + self.project.triangulate() self.__refresh_layers() From ba6bd215bdfe3194bb9853bb23e82905123aeb4a Mon Sep 17 00:00:00 2001 From: Vincent Mora Date: Wed, 15 Jan 2020 15:13:09 +0100 Subject: [PATCH 40/42] remove version from metadata view and add parent to node_section view fix #106 and fix #107 --- albion.sql | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/albion.sql b/albion.sql index ce38662..9a57fb9 100644 --- a/albion.sql +++ b/albion.sql @@ -165,7 +165,7 @@ create trigger collar_instead_trig for each row execute procedure albion.collar_instead_fct() ; -create view albion.metadata as select id, srid, close_collar_distance, snap_distance, precision, interpolation, end_node_relative_distance, end_node_relative_thickness, correlation_distance, correlation_angle, parent_correlation_angle, version from _albion.metadata +create view albion.metadata as select id, srid, close_collar_distance, snap_distance, precision, interpolation, end_node_relative_distance, end_node_relative_thickness, correlation_distance, correlation_angle, parent_correlation_angle from _albion.metadata ; create view albion.layer as select name, fields_definition from _albion.layer @@ -643,7 +643,7 @@ join _albion.hole as h on s.geom && h.geom and st_intersects(st_startpoint(h.geo create view albion.node_section as select row_number() over() as id, n.id as node_id, h.id as hole_id, n.from_, n.to_, n.graph_id, s.id as section_id, - (albion.to_section(n.geom, s.anchor, s.scale))::geometry('LINESTRING', $SRID) as geom + (albion.to_section(n.geom, s.anchor, s.scale))::geometry('LINESTRING', $SRID) as geom, n.parent from _albion.section as s join _albion.hole as h on s.geom && h.geom and st_intersects(st_startpoint(h.geom), s.geom) join _albion.node as n on n.hole_id = h.id From 9565c570b573b3d139d9db6d3d0159aa4dcbbcc9 Mon Sep 17 00:00:00 2001 From: Vincent Mora Date: Mon, 10 Feb 2020 08:41:49 +0100 Subject: [PATCH 41/42] removes qgeologis config from template project --- res/template_project.qgs | 3571 ++++++++++++++++++++++++++++---------- 1 file changed, 2675 insertions(+), 896 deletions(-) diff --git a/res/template_project.qgs b/res/template_project.qgs index 109d571..c394e96 100644 --- a/res/template_project.qgs +++ b/res/template_project.qgs @@ -19,66 +19,87 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + + + + + + + + + + + + + + + + + + + + + + cell_99e875c2_110e_4f52_a7f4_54ea9cff1367 collar_7e814841_4cc9_495a_8ef6_9229fcfffb5e @@ -96,36 +117,48 @@ close_collar_95b0fcfd_f8c9_476f_9b9d_39d3d8c782f7 section_geom_cbc425ee_c515_4cda_8fec_53f986b4dc2f named_section_geom_d56ae49a_c71c_485f_84ea_2a788ff48e0b + mineralization_ed8c17ee_2398_4fc0_8deb_6db49e2465d7 + radiometry_9d3b823d_d1b6_47a8_a1c2_dd0895a7262e + resistivity_4ed802a8_e512_490c_bf34_cd284ac03506 + facies_047eef51_ef17_438a_b299_7879992c4e6a + formation_8aad2fae_f596_4e4a_b6c4_dea6ae893731 + mineralization_b5620aba_20dd_42f3_8de8_271f443b4578 - + - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + - + meters - 31739170.31633691489696503 - 33490644.32408057525753975 - 31740053.80415702611207962 - 33491232.15907534584403038 + 31738932.63210045173764229 + 33490672.35866895318031311 + 31739689.99440045282244682 + 33491176.27513902634382248 0 @@ -145,104 +178,133 @@ - - - - - - 31739063.62000000104308128 - 33490793.80000000074505806 - 31739514.19000000134110451 - 33491093.58999999985098839 - + cell_99e875c2_110e_4f52_a7f4_54ea9cff1367 dbname='template_project' host=127.0.0.1 port=55432 sslmode=disable key='"id"' srid=32632 type=Polygon checkPrimaryKeyUnicity='1' table="albion"."cell" (geom) sql= @@ -300,10 +362,10 @@ 1 1 - + - - + + @@ -332,7 +394,7 @@ 0 0 1 - + @@ -365,12 +427,20 @@ + + + + + + - - - - + + + + + @@ -379,24 +449,27 @@ + - - - - + + + + + - - - - + + + + + - + - + @@ -416,7 +489,7 @@ - + close_collar_95b0fcfd_f8c9_476f_9b9d_39d3d8c782f7 dbname='template_project' host=127.0.0.1 port=55432 sslmode=disable key='"id"' srid=32632 type=PointZ checkPrimaryKeyUnicity='1' table="albion"."close_collar" (geom) sql= @@ -467,7 +540,7 @@ - + @@ -491,10 +564,10 @@ 1 1 - + - - + + @@ -527,7 +600,7 @@ - + @@ -535,12 +608,12 @@ 0 1 - - - + + + - + - + @@ -563,7 +636,7 @@ - + @@ -571,19 +644,19 @@ - + - + - + - + - @@ -613,16 +686,16 @@ def my_form_open(dialog, layer, feature): 0 generatedlayout - + - + id - + 31739063.62000000104308128 33490793.80000000074505806 @@ -654,6 +727,15 @@ def my_form_open(dialog, layer, feature): dataset + + + + + + + + + @@ -669,7 +751,15 @@ def my_form_open(dialog, layer, feature): false - + + + + + + + + + postgres @@ -686,25 +776,25 @@ def my_form_open(dialog, layer, feature): 1 1 - + - - + + - + - + - + - + @@ -721,38 +811,57 @@ def my_form_open(dialog, layer, feature): - + + + + + 0 0 1 - + + + + + + + + + + + + - + - + - + - + @@ -760,10 +869,10 @@ def my_form_open(dialog, layer, feature): - - - - + + + + @@ -774,23 +883,29 @@ def my_form_open(dialog, layer, feature): - - - - + + + + - - - - + + + + - + - - + + + @@ -800,22 +915,42 @@ def my_form_open(dialog, layer, feature): 0 - + 0 generatedlayout - - + + + + + + + + + + + + - + id - - - 31739088.55057749897241592 - 33490793.3475789986550808 - 31739505.09139769896864891 - 33491092.41476880013942719 - + edge_32c6a82a_82cd_477f_b119_398536a6b6ed dbname='template_project' host=127.0.0.1 port=55432 sslmode=disable key='"id"' srid=32632 type=LineStringZ checkPrimaryKeyUnicity='1' table="albion"."edge" (geom) sql= @@ -873,10 +1008,10 @@ def my_form_open(dialog, layer, feature): 1 1 - + - - + + @@ -910,7 +1045,7 @@ def my_form_open(dialog, layer, feature): 0 0 1 - + @@ -945,10 +1080,10 @@ def my_form_open(dialog, layer, feature): - - - - + + + + @@ -959,22 +1094,22 @@ def my_form_open(dialog, layer, feature): - - - - + + + + - - - - + + + + - + - + @@ -994,13 +1129,7 @@ def my_form_open(dialog, layer, feature): - - - 31739237.11582300066947937 - 33490483.44733380153775215 - 31739828.13419400155544281 - 33491092.31071420013904572 - + edge_section_8b745326_1406_43a8_803e_8ee85be59103 dbname='template_project' host=127.0.0.1 port=55432 sslmode=disable key='"id"' srid=32632 type=LineString checkPrimaryKeyUnicity='1' table="albion"."edge_section" (geom) sql= @@ -1026,6 +1155,15 @@ def my_form_open(dialog, layer, feature): dataset + + + + + + + + + @@ -1041,7 +1179,15 @@ def my_form_open(dialog, layer, feature): false - + + + + + + + + + postgres @@ -1058,10 +1204,10 @@ def my_form_open(dialog, layer, feature): 1 1 - + - - + + @@ -1070,7 +1216,7 @@ def my_form_open(dialog, layer, feature): - + @@ -1091,52 +1237,71 @@ def my_form_open(dialog, layer, feature): - + + + + + 0 0 1 - + + + + + + + + + + + + - + - + - + - + - + - + @@ -1144,12 +1309,12 @@ def my_form_open(dialog, layer, feature): - - - - - - + + + + + + @@ -1162,27 +1327,35 @@ def my_form_open(dialog, layer, feature): - - - - - - + + + + + + - - - - - - + + + + + + - + - - + + + @@ -1192,22 +1365,46 @@ def my_form_open(dialog, layer, feature): 0 - + 0 generatedlayout - - + + + + + + + + + + + + + + + + - + id - - - 31739088.52377190068364143 - 33490480.24929559975862503 - 31739830.13416960090398788 - 33491017.96951229870319366 - + end_node_section_node_geom_f653243c_2e98_4638_b428_1acca01868dc dbname='template_project' host=127.0.0.1 port=55432 sslmode=disable key='"id"' srid=32632 type=LineString checkPrimaryKeyUnicity='1' table="albion"."end_node_section" (node_geom) sql= @@ -1233,6 +1430,15 @@ def my_form_open(dialog, layer, feature): dataset + + + + + + + + + @@ -1248,7 +1454,15 @@ def my_form_open(dialog, layer, feature): false - + + + + + + + + + postgres @@ -1265,19 +1479,19 @@ def my_form_open(dialog, layer, feature): 1 1 - + - - - + + + - + - + @@ -1298,52 +1512,71 @@ def my_form_open(dialog, layer, feature): - + + + + + 0 0 1 - + + + + + + + + + + + + - + - + - + - + - + - + @@ -1351,12 +1584,12 @@ def my_form_open(dialog, layer, feature): - - - - - - + + + + + + @@ -1369,27 +1602,35 @@ def my_form_open(dialog, layer, feature): - - - - - - + + + + + + - - - - - - + + + + + + - + - - + + + @@ -1399,28 +1640,52 @@ def my_form_open(dialog, layer, feature): 0 - - 0 - generatedlayout - - - - - + + 0 + generatedlayout + + + + + + + + + + + + + + + + + + id + - - - 31739104.19999999925494194 - 33490793.80000000074505806 - 31739505.76999999955296516 - 33490839.64999999850988388 - - group_cell_ec51a010_ab41_49d7_ac55_8ce0cfbb8838 - dbname='template_project' host=127.0.0.1 port=55432 sslmode=disable key='id' srid=32632 type=Polygon checkPrimaryKeyUnicity='1' table="albion"."group_cell" (geom) sql=section_id='WE x4' + + facies_047eef51_ef17_438a_b299_7879992c4e6a + dbname='template_project' host=127.0.0.1 port=55432 sslmode=disable key='"id"' srid=32632 type=PointZ checkPrimaryKeyUnicity='1' table="albion"."facies" (geom) sql= - group_cell + facies +proj=utm +zone=32 +datum=WGS84 +units=m +no_defs @@ -1463,8 +1728,8 @@ def my_form_open(dialog, layer, feature): - - + + @@ -1472,21 +1737,28 @@ def my_form_open(dialog, layer, feature): 1 1 - + - - - - + + + + + + - + + - + + + + + - + - 31739063.6191214993596077 - 33490411.37305669859051704 - 31739921.39477939903736115 - 33491092.86334149911999702 + 31739063.62000000104308128 + 33490793.80000000074505806 + 31739514.19000000134110451 + 33491093.58999999985098839 - hole_section_1f8c7d9f_7032_4a97_8033_d7ee1c22ea2a - dbname='template_project' host=127.0.0.1 port=55432 sslmode=disable key='"id"' srid=32632 type=LineString checkPrimaryKeyUnicity='1' table="albion"."hole_section" (geom) sql= + formation_8aad2fae_f596_4e4a_b6c4_dea6ae893731 + dbname='template_project' host=127.0.0.1 port=55432 sslmode=disable key='"id"' srid=32632 type=PointZ checkPrimaryKeyUnicity='1' table="albion"."formation" (geom) sql= - hole_section + formation +proj=utm +zone=32 +datum=WGS84 +units=m +no_defs @@ -1643,8 +1937,8 @@ def my_form_open(dialog, layer, feature): - - + + @@ -1652,26 +1946,28 @@ def my_form_open(dialog, layer, feature): 1 1 - + - - - - - - - + + + + + - - - - - + + - - - + + + + + + + + + + - - - 31739063.62000000104308128 - 33490793.80000000074505806 - 31739514.19000000134110451 - 33491093.58999999985098839 - - named_section_geom_d56ae49a_c71c_485f_84ea_2a788ff48e0b - dbname='template_project' host=127.0.0.1 port=55432 sslmode=disable key='"id"' srid=32632 type=LineString checkPrimaryKeyUnicity='1' table="albion"."named_section" (geom) sql= + + group_cell_ec51a010_ab41_49d7_ac55_8ce0cfbb8838 + dbname='template_project' host=127.0.0.1 port=55432 sslmode=disable key='id' srid=32632 type=Polygon checkPrimaryKeyUnicity='1' table="albion"."group_cell" (geom) sql=section_id='SN x4' - named_section.geom + group_cell +proj=utm +zone=32 +datum=WGS84 +units=m +no_defs @@ -1805,15 +2117,6 @@ def my_form_open(dialog, layer, feature): dataset - - - - - - - - - @@ -1829,15 +2132,7 @@ def my_form_open(dialog, layer, feature): false - - - - - - - - - + postgres @@ -1845,8 +2140,8 @@ def my_form_open(dialog, layer, feature): - - + + @@ -1854,85 +2149,21 @@ def my_form_open(dialog, layer, feature): 1 1 - - - - - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + - - - - - + - - - + + + + + - - - - - - - - - - - - - - - + + + + + 0 + 0 + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 0 + + + 0 + generatedlayout + + + + + + + + hole_section_1f8c7d9f_7032_4a97_8033_d7ee1c22ea2a + dbname='template_project' host=127.0.0.1 port=55432 sslmode=disable key='"id"' srid=32632 type=LineString checkPrimaryKeyUnicity='1' table="albion"."hole_section" (geom) sql= + + + + hole_section + + + +proj=utm +zone=32 +datum=WGS84 +units=m +no_defs + 3116 + 32632 + EPSG:32632 + WGS 84 / UTM zone 32N + utm + WGS84 + false + + + + + + + dataset + + + + + + + + +proj=utm +zone=32 +datum=WGS84 +units=m +no_defs + 3116 + 32632 + EPSG:32632 + WGS 84 / UTM zone 32N + utm + WGS84 + false + + + + + postgres + + + + + + + + + + + 1 + 1 + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 0 + 0 + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 0 + + + 0 + generatedlayout + + + + + + + + metadata_c78c898c_772f_4524_8e45_76de4e0463d3 + dbname='template_project' host=127.0.0.1 port=55432 sslmode=disable key='"id"' checkPrimaryKeyUnicity='1' table="albion"."metadata" sql= + + + + metadata + + + + 0 + 0 + + + + + false + + + + + + + dataset + + + + + + + + + 0 + 0 + + + + + false + + + + + postgres + + + + + + + + + + + 1 + 1 + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 0 + + + 0 + generatedlayout + + + + + + + + + 31739088.89999999850988388 + 33490793.80000000074505806 + 31739505.76999999955296516 + 33491092.85000000149011612 + + mineralization_b5620aba_20dd_42f3_8de8_271f443b4578 + dbname='template_project' host=127.0.0.1 port=55432 sslmode=disable key='"id"' srid=32632 type=PointZ checkPrimaryKeyUnicity='1' table="albion"."mineralization" (geom) sql= + + + + mineralization + + + +proj=utm +zone=32 +datum=WGS84 +units=m +no_defs + 3116 + 32632 + EPSG:32632 + WGS 84 / UTM zone 32N + utm + WGS84 + false + + + + + + + dataset + + + + + + + + +proj=utm +zone=32 +datum=WGS84 +units=m +no_defs + 3116 + 32632 + EPSG:32632 + WGS 84 / UTM zone 32N + utm + WGS84 + false + + + + + postgres + + + + + + + + + + + 1 + 1 + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 0 + 0 + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 0 + + + 0 + generatedlayout + + + + + + + + mineralization_ed8c17ee_2398_4fc0_8deb_6db49e2465d7 + dbname='template_project' host=127.0.0.1 port=55432 sslmode=disable key='"id"' srid=32632 type=PointZ checkPrimaryKeyUnicity='1' table="albion"."mineralization" (geom) sql= + + + + mineralization + + + +proj=utm +zone=32 +datum=WGS84 +units=m +no_defs + 3116 + 32632 + EPSG:32632 + WGS 84 / UTM zone 32N + utm + WGS84 + false + + + + + + + dataset + + + + + + + + +proj=utm +zone=32 +datum=WGS84 +units=m +no_defs + 3116 + 32632 + EPSG:32632 + WGS 84 / UTM zone 32N + utm + WGS84 + false + + + + + postgres + + + + + + + + + + + 1 + 1 + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 0 + 0 + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 0 + + + 0 + generatedlayout + + + + + + + + named_section_geom_d56ae49a_c71c_485f_84ea_2a788ff48e0b + dbname='template_project' host=127.0.0.1 port=55432 sslmode=disable key='"id"' srid=32632 type=LineString checkPrimaryKeyUnicity='1' table="albion"."named_section" (geom) sql= + + + + named_section.geom + + + +proj=utm +zone=32 +datum=WGS84 +units=m +no_defs + 3116 + 32632 + EPSG:32632 + WGS 84 / UTM zone 32N + utm + WGS84 + false + + + + + + + dataset + + + + + + + + + + + + + + + + + +proj=utm +zone=32 +datum=WGS84 +units=m +no_defs + 3116 + 32632 + EPSG:32632 + WGS 84 / UTM zone 32N + utm + WGS84 + false + + + + + + + + + + + + + postgres + + + + + + + + + + + 1 + 1 + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 0 + 0 + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 0 + + + 0 + generatedlayout + + + + + + + + + + + + + + id + + + + node_section_63e3816d_ea42_44c6_937c_65c10a3b3ac4 + dbname='template_project' host=127.0.0.1 port=55432 sslmode=disable key='"id"' srid=32632 type=LineString checkPrimaryKeyUnicity='1' table="albion"."node_section" (geom) sql= + + + + node_section + + + +proj=utm +zone=32 +datum=WGS84 +units=m +no_defs + 3116 + 32632 + EPSG:32632 + WGS 84 / UTM zone 32N + utm + WGS84 + false + + + + + + + dataset + + + + + + + + + + + + + + + + + +proj=utm +zone=32 +datum=WGS84 +units=m +no_defs + 3116 + 32632 + EPSG:32632 + WGS 84 / UTM zone 32N + utm + WGS84 + false + + + + + + + + + + + + + postgres + + + + + + + + + + + 1 + 1 + 1 + + + + + + + + + + + + + + + + + @@ -1971,13 +3581,12 @@ def my_form_open(dialog, layer, feature): - - + - + @@ -1985,11 +3594,12 @@ def my_form_open(dialog, layer, feature): 0 1 - - + + + - + - + @@ -2010,66 +3620,324 @@ def my_form_open(dialog, layer, feature): - + - + - + + + + + + + + + + + + + + + + + + + + + + + + + - - - - + + + + + + + + - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 0 + + + 0 + generatedlayout + + + + + + + + + + + + + + + + + + + + id + + + + possible_edge_a6b83b46_56da_4098_b0fe_e703633800f5 + dbname='template_project' host=127.0.0.1 port=55432 sslmode=disable key='"id"' srid=32632 type=LineStringZ checkPrimaryKeyUnicity='1' table="albion"."possible_edge" (geom) sql= + + + + possible_edge + + + +proj=utm +zone=32 +datum=WGS84 +units=m +no_defs + 3116 + 32632 + EPSG:32632 + WGS 84 / UTM zone 32N + utm + WGS84 + false + + + + + + + dataset + + + + + + + + +proj=utm +zone=32 +datum=WGS84 +units=m +no_defs + 3116 + 32632 + EPSG:32632 + WGS 84 / UTM zone 32N + utm + WGS84 + false + + + + + postgres + + + + + + + + + + + 1 + 1 + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 0 + 0 + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - + + + + - - - - + + + + - + - - - + + @@ -2079,54 +3947,22 @@ def my_form_open(dialog, layer, feature): 0 - + 0 generatedlayout - - - - - - - - - - - - + + - id + - - - 31739088.52377190068364143 - 33490480.24929559975862503 - 31739830.13416960090398788 - 33491092.32762109860777855 - - node_section_63e3816d_ea42_44c6_937c_65c10a3b3ac4 - dbname='template_project' host=127.0.0.1 port=55432 sslmode=disable key='"id"' srid=32632 type=LineString checkPrimaryKeyUnicity='1' table="albion"."node_section" (geom) sql= + + possible_edge_section_04705590_fcdc_4fe9_8309_3d2c648db28f + dbname='template_project' host=127.0.0.1 port=55432 sslmode=disable key='"id"' srid=32632 type=LineString checkPrimaryKeyUnicity='1' table="albion"."possible_edge_section" (geom) sql= - node_section + possible_edge_section +proj=utm +zone=32 +datum=WGS84 +units=m +no_defs @@ -2178,17 +4014,17 @@ def my_form_open(dialog, layer, feature): 1 1 - + - - + + - + @@ -2215,7 +4051,7 @@ def my_form_open(dialog, layer, feature): 0 0 1 - + @@ -2227,28 +4063,14 @@ def my_form_open(dialog, layer, feature): - - - - - - - - - - - - - + - + - - - - - - - + + + + + - - - - + + - - - - - - - + + + + + - - - - - - - + + + + + - + - + @@ -2332,19 +4146,19 @@ def my_form_open(dialog, layer, feature): - + - 31739088.55057749897241592 - 33490793.3475789986550808 - 31739505.09139769896864891 - 33491092.41476880013942719 + 31739063.62000000104308128 + 33490793.80000000074505806 + 31739514.19000000134110451 + 33491093.58999999985098839 - possible_edge_a6b83b46_56da_4098_b0fe_e703633800f5 - dbname='template_project' host=127.0.0.1 port=55432 sslmode=disable key='"id"' srid=32632 type=LineStringZ checkPrimaryKeyUnicity='1' table="albion"."possible_edge" (geom) sql= + radiometry_9d3b823d_d1b6_47a8_a1c2_dd0895a7262e + dbname='template_project' host=127.0.0.1 port=55432 sslmode=disable key='"id"' srid=32632 type=PointZ checkPrimaryKeyUnicity='1' table="albion"."radiometry" (geom) sql= - possible_edge + radiometry +proj=utm +zone=32 +datum=WGS84 +units=m +no_defs @@ -2387,8 +4201,8 @@ def my_form_open(dialog, layer, feature): - - + + @@ -2396,26 +4210,28 @@ def my_form_open(dialog, layer, feature): 1 1 - + - - - - - - - + + + + + - - - - - + + - - - + + + + + + + + + + - + - 31739237.11582300066947937 - 33490483.44733380153775215 - 31739828.13419400155544281 - 33491092.31071420013904572 + 31739063.62000000104308128 + 33490793.80000000074505806 + 31739514.19000000134110451 + 33491093.58999999985098839 - possible_edge_section_04705590_fcdc_4fe9_8309_3d2c648db28f - dbname='template_project' host=127.0.0.1 port=55432 sslmode=disable key='"id"' srid=32632 type=LineString checkPrimaryKeyUnicity='1' table="albion"."possible_edge_section" (geom) sql= + resistivity_4ed802a8_e512_490c_bf34_cd284ac03506 + dbname='template_project' host=127.0.0.1 port=55432 sslmode=disable key='"id"' srid=32632 type=PointZ checkPrimaryKeyUnicity='1' table="albion"."resistivity" (geom) sql= - possible_edge_section + resistivity +proj=utm +zone=32 +datum=WGS84 +units=m +no_defs @@ -2583,8 +4399,8 @@ def my_form_open(dialog, layer, feature): - - + + @@ -2592,26 +4408,28 @@ def my_form_open(dialog, layer, feature): 1 1 - + - - - - - - - + + + + + - - - - - + + - - - + + + + + + + + + + - + 31739063.30036709830164909 33490657.7391928993165493 @@ -2799,10 +4606,10 @@ def my_form_open(dialog, layer, feature): 1 1 - + - - + + @@ -2836,7 +4643,7 @@ def my_form_open(dialog, layer, feature): 0 0 1 - + @@ -2855,13 +4662,6 @@ def my_form_open(dialog, layer, feature): - - - - - - @@ -2871,36 +4671,32 @@ def my_form_open(dialog, layer, feature): - - - - + + + - - - - - + + + - - - - + + + - + - + @@ -2920,13 +4716,7 @@ def my_form_open(dialog, layer, feature): - - - 31739104.19999999925494194 - 33490793.85999999940395355 - 31739505.76999999955296516 - 33491092.85000000149011612 - + section_geom_cbc425ee_c515_4cda_8fec_53f986b4dc2f dbname='template_project' host=127.0.0.1 port=55432 sslmode=disable key='"id"' srid=32632 type=MultiLineString checkPrimaryKeyUnicity='1' table="albion"."section" (geom) sql= @@ -2977,7 +4767,7 @@ def my_form_open(dialog, layer, feature): - + @@ -3001,15 +4791,15 @@ def my_form_open(dialog, layer, feature): 1 1 - + - - - + + + - - + + @@ -3035,8 +4825,8 @@ def my_form_open(dialog, layer, feature): - - + + @@ -3062,8 +4852,8 @@ def my_form_open(dialog, layer, feature): - - + + @@ -3091,8 +4881,8 @@ def my_form_open(dialog, layer, feature): - - + + @@ -3119,12 +4909,11 @@ def my_form_open(dialog, layer, feature): - - + @@ -3132,11 +4921,12 @@ def my_form_open(dialog, layer, feature): 0 1 - - + + + - + - + @@ -3164,13 +4954,6 @@ def my_form_open(dialog, layer, feature): - - - - - - @@ -3180,42 +4963,38 @@ def my_form_open(dialog, layer, feature): - - - - + + + - - - - - + + + - - - - + + + - + - + - @@ -3246,22 +5025,22 @@ def my_form_open(dialog, layer, feature): 0 generatedlayout - - - - + + + + - - - - + + + + id - + section_intersection_13a1d3a9_897b_48fc_9714_e20439ad1ff6 dbname='template_project' host=127.0.0.1 port=55432 sslmode=disable key='"id"' srid=32632 type=Polygon checkPrimaryKeyUnicity='1' table="albion"."section_intersection" (geom) sql= @@ -3312,7 +5091,7 @@ def my_form_open(dialog, layer, feature): - + @@ -3336,10 +5115,10 @@ def my_form_open(dialog, layer, feature): 1 1 - + - - + + @@ -3365,7 +5144,7 @@ def my_form_open(dialog, layer, feature): - + @@ -3373,12 +5152,12 @@ def my_form_open(dialog, layer, feature): 0 1 - - - + + + - + - + @@ -3401,7 +5180,7 @@ def my_form_open(dialog, layer, feature): - + @@ -3409,19 +5188,19 @@ def my_form_open(dialog, layer, feature): - + - + - + - + - @@ -3451,22 +5230,16 @@ def my_form_open(dialog, layer, feature): 0 generatedlayout - + - + id - - - 31739081.25440400093793869 - 33490480.24929559975862503 - 31739830.13419400155544281 - 33491092.32762109860777855 - + section_polygon_f49e48f4_9101_4351_a07c_0a99748eaca2 dbname='template_project' host=127.0.0.1 port=55432 sslmode=disable key='"id"' srid=32632 type=MultiPolygon checkPrimaryKeyUnicity='1' table="albion"."section_polygon" (geom) sql= @@ -3524,10 +5297,10 @@ def my_form_open(dialog, layer, feature): 1 1 - + - - + + @@ -3556,7 +5329,7 @@ def my_form_open(dialog, layer, feature): 0 0 1 - + @@ -3584,9 +5357,9 @@ def my_form_open(dialog, layer, feature): - - - + + + @@ -3596,20 +5369,20 @@ def my_form_open(dialog, layer, feature): - - - + + + - - - + + + - + - + @@ -3647,53 +5420,59 @@ def my_form_open(dialog, layer, feature): + + + + + + - - 1 - + false + true false 16 + 50 30 - 0 - true - false false - 50 0 + 0 - - false - - - meters - m2 - - - 32632 - /home/vmo/albion/nt - template_project - WGS84 - - true - 2 - - - false - - 255 - 0 - 255 - 255 255 + 0 255 + 255 + 255 + 255 255 + + template_project + 32632 + /home/vmo/albion/nt + + + meters + m2 + + + false + + + 1 + + + true + 2 + + + false + From b1b17e54f1b7ca2e28a152c5a1b9c2cea8618cb0 Mon Sep 17 00:00:00 2001 From: Vincent Mora Date: Mon, 10 Feb 2020 09:05:17 +0100 Subject: [PATCH 42/42] adds default id for edge section, fix #109 --- albion.sql | 2 ++ 1 file changed, 2 insertions(+) diff --git a/albion.sql b/albion.sql index 9a57fb9..d04fd1a 100644 --- a/albion.sql +++ b/albion.sql @@ -963,6 +963,8 @@ and cs.section_id=s.id and ce.section_id=s.id ; +alter view albion.edge_section alter column id set default _albion.unique_id(); + create or replace function albion.edge_section_instead_fct() returns trigger language plpgsql