Skip to content

Commit 12ce2a3

Browse files
committed
Add anchor rerouting for cables, other small updates
1 parent 183df6a commit 12ce2a3

File tree

4 files changed

+83
-6
lines changed

4 files changed

+83
-6
lines changed

famodel/anchors/anchor.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
from famodel.famodel_base import Node
77
from famodel.mooring.mooring import Mooring
88
import famodel.platform.platform
9+
import shapely as sh
910

1011

1112
class Anchor(Node):
@@ -81,6 +82,8 @@ def __init__(self, dd=None, ms=None, r=[0,0,0], aNum=None, id=None,
8182
# Dictionaries for additional information
8283
# anchor capacity
8384
self.anchorCapacity = {}
85+
self.safety_factors = {} # calculated safety factor
86+
self.safety_factors_required = {} # minimum allowable safety factor
8487

8588
# anchor costs
8689
self.cost = {}
@@ -676,7 +679,10 @@ def getFS(self, loads=None, acceptance_crit=None):
676679
else:
677680
return(FS)
678681

679-
682+
def makeBuffer(self, buff_rad=50):
683+
point = sh.Point(self.r[:2])
684+
buff = point.buffer(buff_rad)
685+
return buff
680686

681687
def getCost(self,costDict='default'):
682688
'''find costs of anchor and store in design dictionary

famodel/cables/cable.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
from copy import deepcopy
55
from moorpy.subsystem import Subsystem
66
from moorpy import helpers
7+
import shapely as sh
78

89
from famodel.cables.dynamic_cable import DynamicCable
910
from famodel.cables.static_cable import StaticCable
@@ -233,6 +234,24 @@ def getL(self):
233234
L += cab.L
234235

235236
self.L = L
237+
238+
def makeLine(self,buff_rad=20,include_dc=True):
239+
240+
coords = []
241+
for sub in self.subcomponents:
242+
if isinstance(sub,Joint):
243+
coords.append(sub['r'][:2])
244+
elif isinstance(sub,DynamicCable) and include_dc:
245+
coords.append(sub.rA[:2])
246+
coords.append(sub.rB[:2])
247+
pass
248+
elif isinstance(sub, StaticCable):
249+
if len(sub.x)>0:
250+
for i in range(len(sub.x)):
251+
coords.append([sub.x[i],sub.y[i]])
252+
line = sh.LineString(coords)
253+
254+
return(line)
236255

237256
def updateSpan(self,newSpan):
238257
'''

famodel/helpers.py

Lines changed: 52 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
import ruamel.yaml
1010
import moorpy as mp
1111
from moorpy.helpers import loadPointProps, getPointProps
12+
import shapely as sh
1213

1314

1415
def cart2pol(x, y):
@@ -211,7 +212,6 @@ def check_headings(m_headings,c_heading,rad_buff):
211212
# convert negative headings to positive headings
212213
for i,mh in enumerate(m_headings):
213214
if mh<0:
214-
#breakpoint()
215215
m_headings[i] = 2*np.pi + mh
216216
elif mh>2*np.pi:
217217
m_headings[i] = mh - 2*np.pi
@@ -249,7 +249,6 @@ def head_adjust(att,heading,rad_buff=np.radians(30),endA_dir=1):
249249
headnew = np.pi*2 + heading
250250
else:
251251
headnew = heading
252-
#breakpoint()
253252
attheadings = []
254253
flipheads = False # whether to flip headings ( for if you are looking at mooring headings of platform on the other end)
255254
for at in att:
@@ -849,6 +848,57 @@ def getAnchors(lineAnch, arrayAnchor, proj):
849848

850849
return(ad, mass)
851850

851+
def route_around_anchors(proj, anchor=True, cable=True, padding=50):
852+
853+
# make anchor buffers with 50m radius
854+
if anchor:
855+
anchor_buffs = []
856+
for anch in proj.anchorList.values():
857+
anchor_buffs.append(anch.makeBuffer())
858+
859+
# make cable linestrings including joint locs and static cable (no dynamic cable for simplicity)
860+
if cable:
861+
cable_line = {}
862+
for name, cab in proj.cableList.items():
863+
cable_line[name] = cab.makeLine(include_dc=False)
864+
865+
# Function to calculate angle of a point relative to a center
866+
def angle(pt):
867+
return np.arctan2(pt[1] - center[1], pt[0] - center[0])
868+
869+
# Loop through each cable linestring and anchor buffer
870+
for name,cab in cable_line.items():
871+
for anch in anchor_buffs:
872+
if cab.intersects(anch):
873+
# Get the start and end of the detour (the two closest points to the buffer)
874+
segments = []
875+
# make additional points on the line on either side of anchor
876+
dist_to_anch = cab.line_locate_point(anch.centroid)
877+
if dist_to_anch > 100:
878+
segments.append(cab.interpolate(dist_to_anch - 100))
879+
if cab.length - dist_to_anch > 100:
880+
segments.append(cab.interpolate(dist_to_anch + 100))
881+
882+
start = np.array(segments[0].coords[-1])
883+
884+
# Get buffer center and radius
885+
center = np.array(anch.centroid.coords[0])
886+
radius = anch.boundary.distance(sh.Point(center))+padding
887+
888+
# Calculate angle for start point relative to center
889+
angle_start = angle(start)
890+
891+
# Generate point along the arc (detour)
892+
arc_point = [center[0] + radius * np.cos(angle_start+np.pi/2), center[1] + radius * np.sin(angle_start+np.pi/2)]
893+
894+
# add new routing point in cable object
895+
proj.cableList[name].subcomponents[2].updateRouting([list(segments[0].coords[1:]) + arc_point + list(segments[1].coords[:-1])])
896+
897+
898+
899+
900+
901+
852902
def configureAdjuster(mooring, adjuster=None, method='horizontal',
853903
i_line=0, span=None, project=None, target=None):
854904
'''Configures adjuster function for mooring object

famodel/project.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,8 @@
3434
# Import select required helper functions
3535
from famodel.helpers import (check_headings, head_adjust, getCableDD, getDynamicCables,
3636
getMoorings, getAnchors, getFromDict, cleanDataTypes,
37-
getStaticCables, getCableDesign,m2nm, loadYAML, configureAdjuster)
37+
getStaticCables, getCableDesign, m2nm, loadYAML,
38+
configureAdjuster, route_around_anchors)
3839

3940

4041
class Project():
@@ -1900,7 +1901,7 @@ def addCablesConnections(self,connDict,cableType_def='dynamic_cable_66',oss=Fals
19001901
heads = [headingA,headingB]
19011902
# reposition cable
19021903
cab.reposition(project=self,headings=heads,rad_fair=[5,5])
1903-
1904+
19041905
coords = []
19051906
if cableConfig:
19061907
ref_cables = None
@@ -1930,6 +1931,7 @@ def addCablesConnections(self,connDict,cableType_def='dynamic_cable_66',oss=Fals
19301931
# update routing
19311932
cab.subcomponents[cs].updateRouting(coords) # also updates static and general cable lengths
19321933

1934+
route_around_anchors(self)
19331935

19341936

19351937
def updatePositions(self):
@@ -2538,7 +2540,7 @@ def getMoorPyArray(self, plt=0, pristineLines=True, cables=True):
25382540
pass
25392541
elif isinstance(comp,DynamicCable):
25402542
# create subsystem for dynamic cable
2541-
comp.createSubsystem(pristine=pristineLines)
2543+
comp.createSubsystem(pristine=pristineLines)
25422544

25432545
if pristineLines:
25442546
ssloc = comp.ss

0 commit comments

Comments
 (0)