|
5 | 5 | from qgis.core import ( |
6 | 6 | QgsCategorizedSymbolRenderer, |
7 | 7 | QgsCoordinateReferenceSystem, |
| 8 | + QgsGraduatedSymbolRenderer, |
8 | 9 | QgsPointXY, |
9 | 10 | QgsProject, |
10 | 11 | QgsRendererCategory, |
| 12 | + QgsRendererRange, |
| 13 | + QgsStyle, |
11 | 14 | QgsSymbol, |
12 | 15 | QgsVectorLayer, |
13 | 16 | ) |
|
17 | 20 | from LoopStructural.datatypes import BoundingBox |
18 | 21 | from LoopStructural.modelling.core.stratigraphic_column import StratigraphicColumnElementType |
19 | 22 |
|
| 23 | +from .m2l_api import paint_stratigraphic_order |
20 | 24 | from .vectorLayerWrapper import qgsLayerToGeoDataFrame |
21 | 25 |
|
22 | 26 |
|
@@ -417,6 +421,81 @@ def apply_stratigraphic_colours_to_layer(self, layer, field_name): |
417 | 421 | self.logger(message=f"Applied stratigraphic column colours to layer '{layer.name()}'.") |
418 | 422 | return True |
419 | 423 |
|
| 424 | + def apply_stratigraphic_age_to_layer(self, layer, field_name, ramp_name=None): |
| 425 | + """Write the stratigraphic order onto a layer and style it with a graduated colour ramp. |
| 426 | +
|
| 427 | + Writes an integer 'strat_order' field to ``layer`` (0 = first unit in |
| 428 | + the stratigraphic column) matched via ``field_name``, then applies a |
| 429 | + graduated renderer over that field. |
| 430 | +
|
| 431 | + Parameters |
| 432 | + ---------- |
| 433 | + layer : QgsVectorLayer |
| 434 | + The layer to update (e.g. the geological units/geology layer). |
| 435 | + field_name : str |
| 436 | + Name of the field on ``layer`` holding the stratigraphic unit name. |
| 437 | + ramp_name : str, optional |
| 438 | + Name of a QGIS colour ramp (from QgsStyle) to use for the |
| 439 | + graduated renderer. Falls back to any available ramp if not found. |
| 440 | +
|
| 441 | + Returns |
| 442 | + ------- |
| 443 | + bool |
| 444 | + True if the field was written and the renderer applied, False otherwise. |
| 445 | + """ |
| 446 | + if layer is None or not field_name: |
| 447 | + self.logger(message="No layer/unit name field set, cannot apply stratigraphic age.") |
| 448 | + return False |
| 449 | + |
| 450 | + unit_names = self.get_stratigraphic_unit_names() |
| 451 | + if not unit_names: |
| 452 | + self.logger(message="Stratigraphic column has no units, cannot apply stratigraphic age.") |
| 453 | + return False |
| 454 | + |
| 455 | + age_field_name = "strat_order" |
| 456 | + try: |
| 457 | + paint_stratigraphic_order(layer, unit_names, field_name) |
| 458 | + except Exception as err: |
| 459 | + self.logger(message=f"Failed to write stratigraphic order onto layer: {err}") |
| 460 | + return False |
| 461 | + |
| 462 | + unique_values = set() |
| 463 | + for feature in layer.getFeatures(): |
| 464 | + value = feature[age_field_name] |
| 465 | + if value is None or (hasattr(value, 'isNull') and value.isNull()): |
| 466 | + continue |
| 467 | + unique_values.add(int(value)) |
| 468 | + unique_values = sorted(unique_values) |
| 469 | + |
| 470 | + if not unique_values: |
| 471 | + self.logger( |
| 472 | + message="No features matched a stratigraphic unit, cannot style layer by age." |
| 473 | + ) |
| 474 | + return False |
| 475 | + |
| 476 | + style = QgsStyle().defaultStyle() |
| 477 | + ramp = style.colorRamp(ramp_name) if ramp_name else None |
| 478 | + if ramp is None: |
| 479 | + ramp_names = style.colorRampNames() |
| 480 | + if ramp_names: |
| 481 | + ramp = style.colorRamp(ramp_names[0]) |
| 482 | + |
| 483 | + n = len(unique_values) |
| 484 | + ranges = [] |
| 485 | + for i, value in enumerate(unique_values): |
| 486 | + symbol = QgsSymbol.defaultSymbol(layer.geometryType()) |
| 487 | + if ramp is not None: |
| 488 | + symbol.setColor(ramp.color(i / (n - 1) if n > 1 else 0)) |
| 489 | + ranges.append(QgsRendererRange(value - 0.5, value + 0.5, symbol, str(value))) |
| 490 | + |
| 491 | + layer.setRenderer(QgsGraduatedSymbolRenderer(age_field_name, ranges)) |
| 492 | + layer.triggerRepaint() |
| 493 | + self.logger( |
| 494 | + message=f"Applied stratigraphic age field '{age_field_name}' and graduated " |
| 495 | + f"styling to layer '{layer.name()}'." |
| 496 | + ) |
| 497 | + return True |
| 498 | + |
420 | 499 | def get_stratigraphic_unit_names(self): |
421 | 500 | """Get the names of the stratigraphic units in the column.""" |
422 | 501 | units = [] |
|
0 commit comments