Compare commits

..

4 Commits

10 changed files with 194 additions and 0 deletions

View File

@ -213,6 +213,17 @@ class Friction(SQLSubModel):
return new return new
def cloned_for(self, reach):
new = Friction(reach=reach, status=self._status)
new.reach = reach
new.begin_rk = self._begin_rk
new.end_rk = self._end_rk
new.begin_strickler = self._begin_strickler
new.end_strickler = self._begin_strickler
return new
def must_be_saved(self): def must_be_saved(self):
ssi = self._status.scenario_id ssi = self._status.scenario_id

View File

@ -20,6 +20,7 @@ import logging
from copy import copy from copy import copy
from tools import trace, timer from tools import trace, timer
from functools import reduce
from Model.Tools.PamhyrDB import SQLSubModel from Model.Tools.PamhyrDB import SQLSubModel
from Model.Tools.PamhyrListExt import PamhyrModelList from Model.Tools.PamhyrListExt import PamhyrModelList
@ -95,3 +96,29 @@ class FrictionList(PamhyrModelList):
self._lst.insert(index, n) self._lst.insert(index, n)
self._status.modified() self._status.modified()
return n return n
def _splited_for(self, reach):
new = FrictionList(status=self._status)
rk_min, rk_max = reduce(
lambda mm, p: (
min(mm[0], p.rk),
max(mm[1], p.rk)
),
reach.reach.profiles,
((999 ** 100), -(999 ** 100))
)
frictions = list(
filter(
lambda f: ((rk_min <= f.begin_rk <= rk_max) or
(rk_min <= f.end_rk <= rk_max)),
self._lst))
for ind, friction in enumerate(frictions):
n = friction.cloned_for(reach)
new._lst.insert(ind, n)
new._status.modified()
return new

View File

@ -289,6 +289,22 @@ class PointXYZ(Point):
new_p.modified() new_p.modified()
return new_p return new_p
def cloned_for(self, new_profile):
new_p = PointXYZ(
id=-1,
name=self.name,
x=self.x, y=self.y, z=self.z,
profile=new_profile,
status=self._status
)
if self.is_deleted():
new_p.set_as_deleted()
new_p._sl = self.sl
new_p.modified()
return new_p
def __repr__(self): def __repr__(self):
return f"({self._x}, {self._y}, {self._z}, {self._name})" return f"({self._x}, {self._y}, {self._z}, {self._name})"

View File

@ -402,6 +402,26 @@ class ProfileXYZ(Profile, SQLSubModel):
new_p.modified() new_p.modified()
return new_p return new_p
def cloned_for(self, new_reach):
new_p = ProfileXYZ(
id=-1,
name=self.name,
rk=self.rk,
reach=new_reach,
status=self._status
)
if self.is_deleted():
new_p.set_as_deleted()
new_p._sl = self.sl
for point in self._points:
p = point.cloned_for(new_p)
new_p._points.append(p)
new_p.modified()
return new_p
def point_from_data(self, header, data): def point_from_data(self, header, data):
def float_format(s: str): def float_format(s: str):
return float( return float(

View File

@ -892,3 +892,20 @@ class Reach(SQLSubModel):
profile.rk = previous.rk + dist profile.rk = previous.rk + dist
previous = profile previous = profile
def _split(self, profile, reach1, reach2):
if profile is None:
return
nr1 = Reach(status=self._status, parent=reach1)
nr2 = Reach(status=self._status, parent=reach2)
ind = self.profiles.index(profile)
nr1_profiles = self.profiles[:ind+1]
nr2_profiles = self.profiles[ind:]
nr1._profiles = list(map(lambda p: p.cloned_for(nr1), nr1_profiles))
nr2._profiles = list(map(lambda p: p.cloned_for(nr2), nr2_profiles))
return nr1, nr2

View File

@ -417,6 +417,34 @@ class RiverReach(Edge):
def frictions(self): def frictions(self):
return self._frictions return self._frictions
def _split(self, profile, new_node):
name = self.name
node1 = self.node1
node2 = self.node2
new_reach1 = RiverReach(
id=-1, name=name + "(part 1)",
node1=node1, node2=new_node,
status=self._status,
)
new_reach2 = RiverReach(
id=-1, name=name + "(part 2)",
node1=new_node, node2=node2,
status=self._status,
)
nr1, nr2 = self._reach._split(profile, new_reach1, new_reach2)
new_reach1._reach = nr1
new_reach1._frictions = self._frictions._splited_for(new_reach1)
new_reach2._reach = nr2
new_reach2._frictions = self._frictions._splited_for(new_reach2)
self.disable()
return new_reach1, new_reach2
class River(Graph): class River(Graph):
_sub_classes = [ _sub_classes = [
@ -874,3 +902,22 @@ Last export at: @date."""
@results.setter @results.setter
def results(self, results): def results(self, results):
self._results = results self._results = results
def _split_reach(self, reach, profile):
node1 = reach.node1
node2 = reach.node2
x1, y1 = node1.x, node1.y
x2, y2 = node2.x, node2.y
center_x = (x1 + x2) / 2
center_y = (y1 + y2) / 2
new_node = self.add_node(center_x, center_y)
r1, r2 = reach._split(profile, new_node)
self._add_edge(r1)
self._add_edge(r2)
return r1, r2

View File

@ -96,6 +96,7 @@ class EdgeMenu(AbstractMenu):
reverse = self._menu.addAction(self._trad["menu_rev_edge"]) reverse = self._menu.addAction(self._trad["menu_rev_edge"])
delete = self._menu.addAction(self._trad["menu_del_edge"]) delete = self._menu.addAction(self._trad["menu_del_edge"])
split = self._menu.addAction(self._trad["menu_split_edge"])
if self._parent.graph.is_enable_edge(it.edge): if self._parent.graph.is_enable_edge(it.edge):
enable = self._menu.addAction(self._trad["menu_dis_edge"]) enable = self._menu.addAction(self._trad["menu_dis_edge"])
is_enable = True is_enable = True
@ -110,3 +111,5 @@ class EdgeMenu(AbstractMenu):
self._parent.enable_edge(it, is_enable) self._parent.enable_edge(it, is_enable)
elif action == reverse: elif action == reverse:
self._parent.reverse_edge(it) self._parent.reverse_edge(it)
elif action == split:
self._parent.split_edge(it)

View File

@ -38,6 +38,7 @@ from Model.Network.Node import Node
from Model.Network.Edge import Edge from Model.Network.Edge import Edge
from Model.Network.Graph import Graph from Model.Network.Graph import Graph
from View.Network.ProfileDialog import SelectProfileDialog
from View.Network.UndoCommand import * from View.Network.UndoCommand import *
from View.Network.ContextMenu import ( from View.Network.ContextMenu import (
DefaultMenu, NodeMenu, EdgeMenu, DefaultMenu, NodeMenu, EdgeMenu,
@ -720,6 +721,31 @@ class GraphWidget(QGraphicsView):
self.changeNode.emit(self.sender()) self.changeNode.emit(self.sender())
self.changeEdge.emit(self.sender()) self.changeEdge.emit(self.sender())
def split_edge(self, item):
edge = item.edge
dlg = SelectProfileDialog(
study=self.parent._study,
reach=edge,
trad=self._trad,
parent=self.parent,
)
if not dlg.exec():
return
profile = dlg._profile
self._undo.push(
SplitEdgeCommand(
self.graph, edge, profile
)
)
self.scene().clear()
self.create_items()
self.changeNode.emit(self.sender())
self.changeEdge.emit(self.sender())
def update_edges(self, node): def update_edges(self, node):
"""Update display of all edges linked with the node """Update display of all edges linked with the node

View File

@ -117,6 +117,27 @@ class DelEdgeCommand(QUndoCommand):
def redo(self): def redo(self):
self._graph.remove_edge(self._edge) self._graph.remove_edge(self._edge)
class SplitEdgeCommand(QUndoCommand):
def __init__(self, graph, edge, profile):
QUndoCommand.__init__(self)
self._graph = graph
self._edge = edge
self._profile = profile
self._new_r1 = None
self._new_r2 = None
def undo(self):
self._new_r1.set_as_deleted()
self._new_r2.set_as_deleted()
def redo(self):
if self._new_r1 is None:
self._new_r1, self._new_r2 = self._graph._split_reach(
self._edge, self._profile)
else:
self._new_r1.set_as_not_deleted()
self._new_r2.set_as_not_deleted()
class SetCommand(QUndoCommand): class SetCommand(QUndoCommand):
def __init__(self, element, column, new_value): def __init__(self, element, column, new_value):

View File

@ -47,6 +47,7 @@ class NetworkTranslate(MainTranslate):
) )
self._dict["menu_del_edge"] = _translate("Network", "Delete the reach") self._dict["menu_del_edge"] = _translate("Network", "Delete the reach")
self._dict["menu_split_edge"] = _translate("Network", "Split the reach")
self._dict["menu_ena_edge"] = _translate("Network", "Enable the reach") self._dict["menu_ena_edge"] = _translate("Network", "Enable the reach")
self._dict["menu_dis_edge"] = _translate("Network", self._dict["menu_dis_edge"] = _translate("Network",
"Disable the reach") "Disable the reach")
@ -54,6 +55,11 @@ class NetworkTranslate(MainTranslate):
"Network", "Reverse the reach orientation" "Network", "Reverse the reach orientation"
) )
self._dict["dialog_select_profile_title"] = _translate(
"Network",
"Select profile"
)
self._sub_dict["table_headers_node"] = { self._sub_dict["table_headers_node"] = {
"name": self._dict['name'], "name": self._dict['name'],
"type": self._dict['type'], "type": self._dict['type'],