Skip to content

Commit 2e59854

Browse files
committed
initial commit with a semi-working plugin
1 parent 2fd02da commit 2e59854

File tree

15 files changed

+449
-281
lines changed

15 files changed

+449
-281
lines changed

docs/conf.py

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -121,12 +121,8 @@
121121
"author": author,
122122
"date_update": datetime.now().strftime("%d %B %Y"),
123123
"description": description,
124-
"qgis_version_max": __about__.__plugin_md__.get("general").get(
125-
"qgismaximumversion"
126-
),
127-
"qgis_version_min": __about__.__plugin_md__.get("general").get(
128-
"qgisminimumversion"
129-
),
124+
"qgis_version_max": __about__.__plugin_md__.get("general").get("qgismaximumversion"),
125+
"qgis_version_min": __about__.__plugin_md__.get("general").get("qgisminimumversion"),
130126
"repo_url": __about__.__uri__,
131127
"title": project,
132128
"version": version,

loopstructural/__about__.py

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -83,10 +83,7 @@ def plugin_metadata_as_dict() -> dict:
8383

8484
__version__: str = __plugin_md__.get("general").get("version")
8585
__version_info__: tuple = tuple(
86-
[
87-
int(num) if num.isdigit() else num
88-
for num in __version__.replace("-", ".", 1).split(".")
89-
]
86+
[int(num) if num.isdigit() else num for num in __version__.replace("-", ".", 1).split(".")]
9087
)
9188

9289
# #############################################################################

loopstructural/gui/dlg_settings.py

Lines changed: 8 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -32,9 +32,7 @@
3232
# ########## Globals ###############
3333
# ##################################
3434

35-
FORM_CLASS, _ = uic.loadUiType(
36-
Path(__file__).parent / "{}.ui".format(Path(__file__).stem)
37-
)
35+
FORM_CLASS, _ = uic.loadUiType(Path(__file__).parent / "{}.ui".format(Path(__file__).stem))
3836

3937

4038
# ############################################################################
@@ -67,20 +65,15 @@ def __init__(self, parent):
6765

6866
# customization
6967
self.btn_help.setIcon(QIcon(QgsApplication.iconPath("mActionHelpContents.svg")))
70-
self.btn_help.pressed.connect(
71-
partial(QDesktopServices.openUrl, QUrl(__uri_homepage__))
72-
)
73-
68+
self.btn_help.pressed.connect(partial(QDesktopServices.openUrl, QUrl(__uri_homepage__)))
7469

7570
self.btn_report.setIcon(
7671
QIcon(QgsApplication.iconPath("console/iconSyntaxErrorConsole.svg"))
7772
)
78-
73+
7974
self.btn_report.pressed.connect(
8075
partial(QDesktopServices.openUrl, QUrl(f"{__uri_tracker__}new/choose"))
8176
)
82-
83-
8477

8578
self.btn_reset.setIcon(QIcon(QgsApplication.iconPath("mActionUndo.svg")))
8679
self.btn_reset.pressed.connect(self.reset_settings)
@@ -115,7 +108,6 @@ def load_settings(self):
115108
self.opt_debug.setChecked(settings.debug_mode)
116109
self.lbl_version_saved_value.setText(settings.version)
117110

118-
119111
def reset_settings(self):
120112
"""Reset settings to default values (set in preferences.py module)."""
121113
default_settings = PlgSettingsStructure()
@@ -126,19 +118,20 @@ def reset_settings(self):
126118
# update the form
127119
self.load_settings()
128120

121+
129122
class PlgOptionsFactory(QgsOptionsWidgetFactory):
130123
"""Factory for options widget."""
131124

132125
def __init__(self):
133-
"""Constructor."""
126+
"""Constructor."""
134127
super().__init__()
135128

136129
def icon(self) -> QIcon:
137130
"""Returns plugin icon, used to as tab icon in QGIS options tab widget.
138131
139132
:return: _description_
140133
:rtype: QIcon
141-
"""
134+
"""
142135
return QIcon(str(__icon_path__))
143136

144137
def createWidget(self, parent) -> ConfigOptionsPage:
@@ -149,15 +142,15 @@ def createWidget(self, parent) -> ConfigOptionsPage:
149142
150143
:return: options page for tab widget
151144
:rtype: ConfigOptionsPage
152-
"""
145+
"""
153146
return ConfigOptionsPage(parent)
154147

155148
def title(self) -> str:
156149
"""Returns plugin title, used to name the tab in QGIS options tab widget.
157150
158151
:return: plugin title from about module
159152
:rtype: str
160-
"""
153+
"""
161154
return __title__
162155

163156
def helpId(self) -> str:
@@ -167,4 +160,3 @@ def helpId(self) -> str:
167160
:rtype: str
168161
"""
169162
return __uri_homepage__
170-

loopstructural/gui/modelling/modelling_widget.py

Lines changed: 115 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -4,29 +4,44 @@
44

55
from PyQt5.QtCore import QSize
66

7-
from qgis.PyQt.QtWidgets import QWidget, QListWidgetItem, QTableWidgetItem, QLabel, QDoubleSpinBox, QSpinBox
7+
from qgis.PyQt.QtWidgets import (
8+
QWidget,
9+
QListWidgetItem,
10+
QTableWidgetItem,
11+
QLabel,
12+
QDoubleSpinBox,
13+
QSpinBox,
14+
QFileDialog,
15+
)
816

917
import random
1018
import os
1119
from ...main import QgsProcessInputData
20+
21+
# from LoopStructural.visualisation import Loop3DView
1222
# from loopstructural.gui.modelling.stratigraphic_column import StratigraphicColumnWidget
1323
class ModellingWidget(QWidget):
14-
def __init__(self, parent: QWidget = None):
24+
def __init__(self, parent: QWidget = None, mapCanvas=None):
1525
super().__init__(parent)
16-
uic.loadUi(os.path.join(os.path.dirname(__file__),"modelling_widget.ui"), self)
26+
uic.loadUi(os.path.join(os.path.dirname(__file__), "modelling_widget.ui"), self)
27+
self.mapCanvas = mapCanvas
28+
self.rotationDoubleSpinBox.setValue(mapCanvas.rotation())
1729
self.basalContactsLayer.setFilters(QgsMapLayerProxyModel.LineLayer)
1830
self.unitNameField.setLayer(self.basalContactsLayer.currentLayer())
1931
self.faultTraceLayer.setFilters(QgsMapLayerProxyModel.LineLayer)
2032
self.faultTraceLayer.setAllowEmptyLayer(True)
2133
self.DtmLayer.setFilters(QgsMapLayerProxyModel.RasterLayer)
2234
self.DtmLayer.setAllowEmptyLayer(True)
2335
self.structuralDataLayer.setFilters(QgsMapLayerProxyModel.PointLayer)
24-
36+
2537
self._basalContacts = None
2638
self._units = None
2739
self._faults = {}
2840
self._connectSignals()
29-
41+
self.view = None
42+
self.model = None
43+
self.outputPath = ""
44+
3045
def _connectSignals(self):
3146
self.basalContactsLayer.layerChanged.connect(self.onBasalContactsChanged)
3247
self.structuralDataLayer.layerChanged.connect(self.onStructuralDataLayerChanged)
@@ -37,63 +52,98 @@ def _connectSignals(self):
3752
self.faultDisplacementField.fieldChanged.connect(self.onFaultFieldChanged)
3853
self.orientationType.currentIndexChanged.connect(self.onOrientationTypeChanged)
3954
self.orientationField.fieldChanged.connect(self.onOrientationFieldChanged)
40-
self.initModel.clicked.connect(self.initialiseModel)
41-
42-
# self.runModel.clicked.connect(self.runModel)
43-
def initialiseModel(self):
44-
columnmap = {'unitname':self.unitNameField.currentField(),
45-
'faultname':self.faultNameField.currentField(),
46-
'dip':self.dipField.currentField(),
47-
'orientation':self.orientationField.currentField(),
48-
'structure_unitname':self.structuralDataUnitName.currentField()
55+
self.initModel.clicked.connect(self.onInitialiseModel)
56+
self.rotationDoubleSpinBox.valueChanged.connect(self.onRotationChanged)
57+
self.runModelButton.clicked.connect(self.onRunModel)
58+
self.pathButton.clicked.connect(self.onClickPath)
59+
self.saveButton.clicked.connect(self.onSaveModel)
60+
61+
def onInitialiseModel(self):
62+
columnmap = {
63+
'unitname': self.unitNameField.currentField(),
64+
'faultname': self.faultNameField.currentField(),
65+
'dip': self.dipField.currentField(),
66+
'orientation': self.orientationField.currentField(),
67+
'structure_unitname': self.structuralDataUnitName.currentField(),
4968
}
50-
processor = QgsProcessInputData(
51-
basal_contacts=self.basalContactsLayer.currentLayer(),
52-
stratigraphic_column=self._units,
53-
faults=self.faultTraceLayer.currentLayer(),
54-
structural_data=self.structuralDataLayer.currentLayer(),
55-
dtm=self.DtmLayer.currentLayer(),
56-
columnmap=columnmap,
57-
roi=self.roiLayer.currentLayer(),
58-
top=self.heightSpinBox.value(),
59-
bottom=self.depthSpinBox.value(),
60-
dip_direction=self.orientationType.currentIndex()==1
61-
)
62-
self.model = processor.get_model()
63-
# def runModel(self):
64-
# self.model.update()
69+
try:
70+
processor = QgsProcessInputData(
71+
basal_contacts=self.basalContactsLayer.currentLayer(),
72+
stratigraphic_column=self._units,
73+
faults=self.faultTraceLayer.currentLayer(),
74+
structural_data=self.structuralDataLayer.currentLayer(),
75+
dtm=self.DtmLayer.currentLayer(),
76+
columnmap=columnmap,
77+
roi=self.roiLayer.currentLayer(),
78+
top=self.heightSpinBox.value(),
79+
bottom=self.depthSpinBox.value(),
80+
dip_direction=self.orientationType.currentIndex() == 1,
81+
rotation=self.rotationDoubleSpinBox.value(),
82+
)
83+
self.model = processor.get_model()
84+
for feature in self.model.features:
85+
item = QListWidgetItem()
86+
item.setText(feature.name)
87+
item.setBackground(
88+
QColor(random.randint(0, 255), random.randint(0, 255), random.randint(0, 255))
89+
)
90+
self.modelList.addItem(item)
91+
except Exception as e:
92+
print(e)
6593

6694
def onOrientationTypeChanged(self, index):
6795
if index == 0:
6896
self.orientationLabel.setText("Strike")
6997
else:
7098
self.orientationLabel.setText("Dip Direction")
7199

100+
def onRotationChanged(self, rotation):
101+
self.mapCanvas.setRotation(rotation)
102+
72103
def onOrientationFieldChanged(self, field):
73104
pass
105+
74106
def onStructuralDataLayerChanged(self, layer):
75107
self.orientationField.setLayer(layer)
76108
self.dipField.setLayer(layer)
77109
self.structuralDataUnitName.setLayer(layer)
78110
# self.dipField.setValidator(QDoubleValidator(0.0, 360.0, 2))
79111
# self.orientationField.setValidator(QDoubleValidator(0.0, 360.0, 2))
112+
113+
def onRunModel(self):
114+
try:
115+
print('Running model')
116+
self.model.update()
117+
print('Model updated')
118+
except Exception as e:
119+
print(e)
120+
80121
def linkFieldToLayer(self, field, layer):
81122
pass
123+
82124
def onBasalContactsChanged(self, layer):
83125
self.unitNameField.setLayer(layer)
126+
84127
def onFaultTraceLayerChanged(self, layer):
85128
self.faultNameField.setLayer(layer)
86129
self.faultDipField.setLayer(layer)
87130
self.faultDisplacementField.setLayer(layer)
131+
88132
def onUnitFieldChanged(self, field):
89133
unique_values = set()
90134
layer = self.unitNameField.layer()
91135
if layer:
92136
field_index = layer.fields().indexFromName(field)
93137
for feature in layer.getFeatures():
94138
unique_values.add(feature[field_index])
95-
self._units = dict(zip(list(unique_values),[{'thickness':10.,'order':i} for i in range(len(unique_values))]))
139+
self._units = dict(
140+
zip(
141+
list(unique_values),
142+
[{'thickness': 10.0, 'order': i} for i in range(len(unique_values))],
143+
)
144+
)
96145
self._initialiseStratigraphicColumn()
146+
97147
def onFaultFieldChanged(self, field):
98148
name_field = self.faultNameField.currentField()
99149
dip_field = self.faultDipField.currentField()
@@ -102,27 +152,57 @@ def onFaultFieldChanged(self, field):
102152
if name_field and dip_field and displacement_field and layer:
103153
self._faults = {}
104154
for feature in layer.getFeatures():
105-
self._faults[feature[name_field]] = {'dip':feature[dip_field],'displacement':feature[displacement_field]}
155+
self._faults[feature[name_field]] = {
156+
'dip': feature[dip_field],
157+
'displacement': feature[displacement_field],
158+
}
106159
if self._faults:
107160
faults = list(self._faults.keys())
108161
self.faultSelection.clear()
109162
self.faultSelection.addItems(faults)
110-
111163

112-
113164
def _initialiseStratigraphicColumn(self):
114165
while self.stratigraphicColumnContainer.count():
115166
child = self.stratigraphicColumnContainer.takeAt(0)
116167
if child.widget():
117168
child.widget().deleteLater()
118169
for i, (unit, value) in enumerate(self._units.items()):
119170
label = QLabel(unit)
120-
spin_box = QDoubleSpinBox()
171+
spin_box = QDoubleSpinBox(maximum=10000, minimum=0)
121172
spin_box.setValue(value['thickness'])
122173
order = QSpinBox()
123174
order.setValue(value['order'])
124175
self.stratigraphicColumnContainer.addWidget(label, i, 0)
125176
self.stratigraphicColumnContainer.addWidget(spin_box, i, 1)
126177
self.stratigraphicColumnContainer.addWidget(order, i, 2)
127-
128178

179+
def onSaveModel(self):
180+
fileFormat = self.fileFormatCombo.currentText()
181+
path = self.outputPath
182+
name = self.modelNameLineEdit.text()
183+
filename = os.path.join(path, name + "." + fileFormat)
184+
185+
self.model.save(filename=os.path.join(path, name + "." + fileFormat))
186+
self.model.bounding_box.vtk().save(os.path.join(path, name + "_bounding_box." + fileFormat))
187+
# if self.stratigraphicSurfacesCheckBox.isChecked():
188+
# self.model.save_surfaces(
189+
# os.path.join(path, name + "_surfaces." + fileFormat)
190+
# )
191+
# if self.faultSurfacesCheckBox.isChecked():
192+
# self.model.save_faults(os.path.join(path, name + "_faults." + fileFormat))
193+
# if self.blockModelCheckBox.isChecked():
194+
# self.model.save_block_model(os.path.join(path, name + "_block." + fileFormat))
195+
# if self.blockModelCheckBox.isChecked():
196+
# self.model.save_block_model(os.path.join(path, name + "_block." + fileFormat))
197+
# if self.
198+
# pass
199+
200+
def onClickPath(self):
201+
self.outputPath = QFileDialog.getExistingDirectory(None, "Select output path for model")
202+
203+
self.path.setText(self.outputPath)
204+
# if self.path:
205+
# if os.path.exists(self.gridDirectory):
206+
# self.output_directory = os.path.split(
207+
# self.dlg.lineEdit_gridOutputDir.text()
208+
# )[-1]

0 commit comments

Comments
 (0)