midas-civil 0.1.5__py3-none-any.whl → 0.1.7__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of midas-civil might be problematic. Click here for more details.

midas_civil/_element.py CHANGED
@@ -1,9 +1,15 @@
1
1
  from ._mapi import *
2
2
  from ._node import *
3
3
  from ._group import _add_elem_2_stGroup
4
+ from ._group import _add_node_2_stGroup
4
5
 
5
6
  import numpy as np
6
7
 
8
+
9
+
10
+
11
+
12
+
7
13
  def _ADD(self):
8
14
  """
9
15
  Adds an element to the main list. If the ID is 0, it auto-increments.
@@ -37,8 +43,12 @@ def _ADD(self):
37
43
  elif isinstance(self._GROUP, list):
38
44
  for gpName in self._GROUP:
39
45
  _add_elem_2_stGroup(self.ID,gpName)
46
+ for nd in self.NODE:
47
+ _add_node_2_stGroup(nd,gpName)
40
48
  elif isinstance(self._GROUP, str):
41
49
  _add_elem_2_stGroup(self.ID,self._GROUP)
50
+ for nd in self.NODE:
51
+ _add_node_2_stGroup(nd,self._GROUP)
42
52
 
43
53
 
44
54
 
@@ -516,10 +526,179 @@ class Element:
516
526
  _ADD(self)
517
527
 
518
528
 
529
+ #-----------------------------------------------Stiffness Scale Factor------------------------------
519
530
 
531
+ class StiffnessScaleFactor:
532
+
533
+ data = []
534
+
535
+ def __init__(self,
536
+ element_id,
537
+ area_sf: float = 1.0,
538
+ asy_sf: float = 1.0,
539
+ asz_sf: float = 1.0,
540
+ ixx_sf: float = 1.0,
541
+ iyy_sf: float = 1.0,
542
+ izz_sf: float = 1.0,
543
+ wgt_sf: float = 1.0,
544
+ group: str = "",
545
+ id: int = None):
546
+ """
547
+ element_id: Element ID(s) where scale factor is applied (can be int or list)
548
+ area_sf: Cross-sectional area scale factor
549
+ asy_sf: Effective Shear Area scale factor (y-axis)
550
+ asz_sf: Effective Shear Area scale factor (z-axis)
551
+ ixx_sf: Torsional Resistance scale factor (x-axis)
552
+ iyy_sf: Area Moment of Inertia scale factor (y-axis)
553
+ izz_sf: Area Moment of Inertia scale factor (z-axis)
554
+ wgt_sf: Weight scale factor
555
+ group: Group name (default "")
556
+ id: Scale factor ID (optional, auto-assigned if None)
557
+
558
+ Examples:
559
+ StiffnessScaleFactor(908, area_sf=0.5, asy_sf=0.6, asz_sf=0.7,
560
+ ixx_sf=0.8, iyy_sf=0.8, izz_sf=0.9, wgt_sf=0.95)
561
+
562
+ """
563
+
564
+ # Check if group exists, create if not
565
+ if group != "":
566
+ chk = 0
567
+ a = [v['NAME'] for v in Group.Boundary.json()["Assign"].values()]
568
+ if group in a:
569
+ chk = 1
570
+ if chk == 0:
571
+ Group.Boundary(group)
572
+
573
+ # Handle element_id as single int or list
574
+ if isinstance(element_id, (list, tuple)):
575
+ self.ELEMENT_IDS = list(element_id)
576
+ else:
577
+ self.ELEMENT_IDS = [element_id]
578
+
579
+ self.AREA_SF = area_sf
580
+ self.ASY_SF = asy_sf
581
+ self.ASZ_SF = asz_sf
582
+ self.IXX_SF = ixx_sf
583
+ self.IYY_SF = iyy_sf
584
+ self.IZZ_SF = izz_sf
585
+ self.WGT_SF = wgt_sf
586
+ self.GROUP_NAME = group
587
+
588
+ # Auto-assign ID if not provided
589
+ if id is None:
590
+ self.ID = len(Element.StiffnessScaleFactor.data) + 1
591
+ else:
592
+ self.ID = id
593
+
594
+ # Add to static list
595
+ Element.StiffnessScaleFactor.data.append(self)
596
+
597
+ @classmethod
598
+ def json(cls):
599
+ """
600
+ Converts StiffnessScaleFactor data to JSON format
601
+ """
602
+ json_data = {"Assign": {}}
603
+
604
+ for scale_factor in cls.data:
605
+ # Create scale factor item
606
+ scale_factor_item = {
607
+ "ID": scale_factor.ID,
608
+ "AREA_SF": scale_factor.AREA_SF,
609
+ "ASY_SF": scale_factor.ASY_SF,
610
+ "ASZ_SF": scale_factor.ASZ_SF,
611
+ "IXX_SF": scale_factor.IXX_SF,
612
+ "IYY_SF": scale_factor.IYY_SF,
613
+ "IZZ_SF": scale_factor.IZZ_SF,
614
+ "WGT_SF": scale_factor.WGT_SF,
615
+ "GROUP_NAME": scale_factor.GROUP_NAME
616
+ }
617
+
618
+ # Assign to each element ID
619
+ for element_id in scale_factor.ELEMENT_IDS:
620
+ if str(element_id) not in json_data["Assign"]:
621
+ json_data["Assign"][str(element_id)] = {"ITEMS": []}
622
+
623
+ json_data["Assign"][str(element_id)]["ITEMS"].append(scale_factor_item)
624
+
625
+ return json_data
626
+
627
+ @classmethod
628
+ def create(cls):
629
+ """
630
+ Sends all StiffnessScaleFactor data to the API
631
+ """
632
+ MidasAPI("PUT", "/db/essf", cls.json())
633
+
634
+ @classmethod
635
+ def get(cls):
636
+ """
637
+ Retrieves StiffnessScaleFactor data from the API
638
+ """
639
+ return MidasAPI("GET", "/db/essf")
640
+
641
+ @classmethod
642
+ def sync(cls):
643
+ """
644
+ Updates the StiffnessScaleFactor class with data from the API
645
+ """
646
+ cls.data = []
647
+ response = cls.get()
648
+
649
+ if response != {'message': ''}:
650
+ processed_ids = set() # To avoid duplicate processing
651
+
652
+ for element_data in response.get("ESSF", {}).items():
653
+ for item in element_data.get("ITEMS", []):
654
+ scale_factor_id = item.get("ID", 1)
655
+
656
+ # Skip if already processed (for multi-element scale factors)
657
+ if scale_factor_id in processed_ids:
658
+ continue
659
+
660
+ # Find all elements with the same scale factor ID
661
+ element_ids = []
662
+ for eid, edata in response.get("ESSF", {}).items():
663
+ for eitem in edata.get("ITEMS", []):
664
+ if eitem.get("ID") == scale_factor_id:
665
+ element_ids.append(int(eid))
666
+
667
+ # Create StiffnessScaleFactor object
668
+ Element.StiffnessScaleFactor(
669
+ element_id=element_ids if len(element_ids) > 1 else element_ids[0],
670
+ area_sf=item.get("AREA_SF", 1.0),
671
+ asy_sf=item.get("ASY_SF", 1.0),
672
+ asz_sf=item.get("ASZ_SF", 1.0),
673
+ ixx_sf=item.get("IXX_SF", 1.0),
674
+ iyy_sf=item.get("IYY_SF", 1.0),
675
+ izz_sf=item.get("IZZ_SF", 1.0),
676
+ wgt_sf=item.get("WGT_SF", 1.0),
677
+ group=item.get("GROUP_NAME", ""),
678
+ id=scale_factor_id
679
+ )
680
+
681
+ processed_ids.add(scale_factor_id)
682
+
683
+ @classmethod
684
+ def delete(cls):
685
+ """
686
+ Deletes all stiffness scale factors from the database and resets the class.
687
+ """
688
+ cls.data = []
689
+ return MidasAPI("DELETE", "/db/essf")
520
690
 
521
691
 
522
692
 
523
693
 
694
+ # ---- GET ELEMENT OBJECT FROM ID ----------
524
695
 
696
+ def elemByID(elemID:int) -> Element:
697
+ ''' Return Element object with the input ID '''
698
+ for elem in Element.elements:
699
+ if elem.ID == elemID:
700
+ return elem
701
+
702
+ print(f'There is no element with ID {elemID}')
703
+ return None
525
704
 
midas_civil/_group.py CHANGED
@@ -8,18 +8,21 @@ from ._mapi import *
8
8
  # ----------- HELPER FUNCTION -----------
9
9
  # -------- RETRIEVE NODE / ELEMENT FROM STRUCTURE GROUP -------
10
10
 
11
- def getNode(groupName):
11
+ def nodesInGroup(groupName:str) -> list | int:
12
12
  ''' Returns Node ID list in a Structure Group '''
13
13
  for i in Group.Structure.Groups:
14
14
  if i.NAME == groupName:
15
15
  return i.NLIST
16
+ print('⚠️ Structure group not found !')
16
17
  return []
17
18
 
18
- def getElement(groupName):
19
+
20
+ def elemsInGroup(groupName:str) -> list:
19
21
  ''' Returns Element ID list in a Structure Group '''
20
22
  for i in Group.Structure.Groups:
21
23
  if i.NAME == groupName:
22
24
  return i.ELIST
25
+ print('⚠️ Structure group not found !')
23
26
  return []
24
27
 
25
28
 
midas_civil/_load.py CHANGED
@@ -2,6 +2,28 @@ from ._mapi import *
2
2
  from ._model import *
3
3
  from ._group import *
4
4
 
5
+
6
+
7
+ # ----- Extend for list of nodes/elems -----
8
+
9
+ def _ADD_NodalLoad(self):
10
+ if isinstance(self.NODE,int):
11
+ Load.Nodal.data.append(self)
12
+ elif isinstance(self.NODE,list):
13
+ for nID in self.NODE:
14
+ Load.Nodal(nID,self.LCN,self.LDGR,self.FX,self.FY,self.FZ,self.MX,self.MY,self.MZ,self.ID)
15
+
16
+
17
+ def _ADD_BeamLoad(self):
18
+ if isinstance(self.ELEMENT,int):
19
+ Load.Beam.data.append(self)
20
+ elif isinstance(self.ELEMENT,list):
21
+ for eID in self.ELEMENT:
22
+ Load.Beam(eID,self.LCN,self.LDGR,self.VALUE,self.DIRECTION,self.ID,self.D,self.P,self.CMD,self.TYPE,self.USE_ECCEN,self.USE_PROJECTION,
23
+ self.ECCEN_DIR,self.ECCEN_TYPE,self.IECC,self.JECC,self.USE_H,self.I_H,self.J_H)
24
+
25
+
26
+
5
27
  #11 Class to define Load Cases:
6
28
  class Load_Case:
7
29
  """Type symbol (Refer Static Load Case section in the Onine API Manual, Load Case names.
@@ -74,10 +96,12 @@ class Load:
74
96
  Sample: Load_SW("Self-Weight", "Z", -1, "DL")"""
75
97
  data = []
76
98
  def __init__(self, load_case, dir = "Z", value = -1, load_group = ""):
99
+
77
100
  chk = 0
78
101
  for i in Load_Case.cases:
79
102
  if load_case in i.NAME: chk = 1
80
103
  if chk == 0: Load_Case("D", load_case)
104
+
81
105
  if load_group != "":
82
106
  chk = 0
83
107
  a = [v['NAME'] for v in Group.Load.json()["Assign"].values()]
@@ -177,7 +201,9 @@ class Load:
177
201
  self.MZ = MZ
178
202
  if id == "": id = len(Load.Nodal.data) + 1
179
203
  self.ID = id
180
- Load.Nodal.data.append(self)
204
+
205
+ _ADD_NodalLoad(self)
206
+ # Load.Nodal.data.append(self)
181
207
 
182
208
  @classmethod
183
209
  def json(cls):
@@ -228,9 +254,9 @@ class Load:
228
254
  #19 Class to define Beam Loads:
229
255
  class Beam:
230
256
  data = []
231
- def __init__(self, element: int, load_case: str, value: float, load_group: str = "", direction: str = "GZ",
257
+ def __init__(self, element, load_case: str, load_group: str = "", value: float=0, direction: str = "GZ",
232
258
  id = "", D = [0, 1, 0, 0], P = [0, 0, 0, 0], cmd = "BEAM", typ = "UNILOAD", use_ecc = False, use_proj = False,
233
- eccn_dir = "LZ", eccn_type = 1, ieccn = 0, jeccn = 0.0000195, adnl_h = False, adnl_h_i = 0, adnl_h_j = 0.0000195):
259
+ eccn_dir = "LZ", eccn_type = 1, ieccn = 0, jeccn = 0, adnl_h = False, adnl_h_i = 0, adnl_h_j = 0):
234
260
  """
235
261
  element: Element Number
236
262
  load_case (str): Load case name
@@ -276,7 +302,7 @@ class Load:
276
302
  if cmd not in ("BEAM", "LINE", "TYPICAL"): cmd = "BEAM"
277
303
  if typ not in ("CONLOAD", "CONMOMENT", "UNILOAD", "UNIMOMENT","PRESSURE"): typ = "UNILOAD"
278
304
  if use_ecc == False:
279
- if ieccn != 0 or jeccn != 0.0000195: use_ecc = True
305
+ if ieccn != 0 or jeccn != 0: use_ecc = True
280
306
  self.ELEMENT = element
281
307
  self.LCN = load_case
282
308
  self.LDGR = load_group
@@ -289,7 +315,7 @@ class Load:
289
315
  self.ECCEN_TYPE = eccn_type
290
316
  self.ECCEN_DIR = eccn_dir
291
317
  self.IECC = ieccn
292
- if jeccn == 0.0000195:
318
+ if jeccn == 0:
293
319
  self.JECC = 0
294
320
  self.USE_JECC = False
295
321
  else:
@@ -299,7 +325,7 @@ class Load:
299
325
  self.P = P
300
326
  self.USE_H = adnl_h
301
327
  self.I_H = adnl_h_i
302
- if adnl_h == 0.0000195:
328
+ if adnl_h == 0:
303
329
  self.USE_JH = False
304
330
  self.J_H = 0
305
331
  else:
@@ -309,7 +335,8 @@ class Load:
309
335
  if id == "":
310
336
  id = len(Load.Beam.data) + 1
311
337
  self.ID = id
312
- Load.Beam.data.append(self)
338
+ _ADD_BeamLoad(self)
339
+ # Load.Beam.data.append(self)
313
340
 
314
341
  @classmethod
315
342
  def json(cls):
@@ -368,23 +395,23 @@ class Load:
368
395
  for i in a['BMLD'].keys():
369
396
  for j in range(len(a['BMLD'][i]['ITEMS'])):
370
397
  if a['BMLD'][i]['ITEMS'][j]['USE_ECCEN'] == True and a['BMLD'][i]['ITEMS'][j]['USE_ADDITIONAL'] == True:
371
- Load.Beam(i,a['BMLD'][i]['ITEMS'][j]['LCNAME'], a['BMLD'][i]['ITEMS'][j]['P'][0], a['BMLD'][i]['ITEMS'][j]['GROUP_NAME'],
398
+ Load.Beam(i,a['BMLD'][i]['ITEMS'][j]['LCNAME'], a['BMLD'][i]['ITEMS'][j]['GROUP_NAME'], a['BMLD'][i]['ITEMS'][j]['P'][0],
372
399
  a['BMLD'][i]['ITEMS'][j]['DIRECTION'], a['BMLD'][i]['ITEMS'][j]['ID'], a['BMLD'][i]['ITEMS'][j]['D'], a['BMLD'][i]['ITEMS'][j]['P'],
373
400
  a['BMLD'][i]['ITEMS'][j]['CMD'], a['BMLD'][i]['ITEMS'][j]['TYPE'], a['BMLD'][i]['ITEMS'][j]['USE_ECCEN'], a['BMLD'][i]['ITEMS'][j]['USE_PROJECTION'],
374
401
  a['BMLD'][i]['ITEMS'][j]['ECCEN_DIR'], a['BMLD'][i]['ITEMS'][j]['ECCEN_TYPE'], a['BMLD'][i]['ITEMS'][j]['I_END'], a['BMLD'][i]['ITEMS'][j]['J_END'],
375
402
  a['BMLD'][i]['ITEMS'][j]['USE_ADDITIONAL'], a['BMLD'][i]['ITEMS'][j]['ADDITIONAL_I_END'], a['BMLD'][i]['ITEMS'][j]['ADDITIONAL_J_END'])
376
403
  elif a['BMLD'][i]['ITEMS'][j]['USE_ECCEN'] == False and a['BMLD'][i]['ITEMS'][j]['USE_ADDITIONAL'] == True:
377
- Load.Beam(i,a['BMLD'][i]['ITEMS'][j]['LCNAME'], a['BMLD'][i]['ITEMS'][j]['P'][0], a['BMLD'][i]['ITEMS'][j]['GROUP_NAME'],
404
+ Load.Beam(i,a['BMLD'][i]['ITEMS'][j]['LCNAME'], a['BMLD'][i]['ITEMS'][j]['GROUP_NAME'], a['BMLD'][i]['ITEMS'][j]['P'][0],
378
405
  a['BMLD'][i]['ITEMS'][j]['DIRECTION'], a['BMLD'][i]['ITEMS'][j]['ID'], a['BMLD'][i]['ITEMS'][j]['D'], a['BMLD'][i]['ITEMS'][j]['P'],
379
406
  a['BMLD'][i]['ITEMS'][j]['CMD'], a['BMLD'][i]['ITEMS'][j]['TYPE'], a['BMLD'][i]['ITEMS'][j]['USE_ECCEN'], a['BMLD'][i]['ITEMS'][j]['USE_PROJECTION'],
380
407
  adnl_h = a['BMLD'][i]['ITEMS'][j]['USE_ADDITIONAL'], adnl_h_i = a['BMLD'][i]['ITEMS'][j]['ADDITIONAL_I_END'], adnl_h_j = a['BMLD'][i]['ITEMS'][j]['ADDITIONAL_J_END'])
381
408
  elif a['BMLD'][i]['ITEMS'][j]['USE_ECCEN'] == True and a['BMLD'][i]['ITEMS'][j]['USE_ADDITIONAL'] == False:
382
- Load.Beam(i,a['BMLD'][i]['ITEMS'][j]['LCNAME'], a['BMLD'][i]['ITEMS'][j]['P'][0], a['BMLD'][i]['ITEMS'][j]['GROUP_NAME'],
409
+ Load.Beam(i,a['BMLD'][i]['ITEMS'][j]['LCNAME'], a['BMLD'][i]['ITEMS'][j]['GROUP_NAME'], a['BMLD'][i]['ITEMS'][j]['P'][0],
383
410
  a['BMLD'][i]['ITEMS'][j]['DIRECTION'], a['BMLD'][i]['ITEMS'][j]['ID'], a['BMLD'][i]['ITEMS'][j]['D'], a['BMLD'][i]['ITEMS'][j]['P'],
384
411
  a['BMLD'][i]['ITEMS'][j]['CMD'], a['BMLD'][i]['ITEMS'][j]['TYPE'], a['BMLD'][i]['ITEMS'][j]['USE_ECCEN'], a['BMLD'][i]['ITEMS'][j]['USE_PROJECTION'],
385
412
  a['BMLD'][i]['ITEMS'][j]['ECCEN_DIR'], a['BMLD'][i]['ITEMS'][j]['ECCEN_TYPE'], a['BMLD'][i]['ITEMS'][j]['I_END'], a['BMLD'][i]['ITEMS'][j]['J_END'])
386
413
  else:
387
- Load.Beam(i,a['BMLD'][i]['ITEMS'][j]['LCNAME'], a['BMLD'][i]['ITEMS'][j]['P'][0], a['BMLD'][i]['ITEMS'][j]['GROUP_NAME'],
414
+ Load.Beam(i,a['BMLD'][i]['ITEMS'][j]['LCNAME'], a['BMLD'][i]['ITEMS'][j]['GROUP_NAME'],a['BMLD'][i]['ITEMS'][j]['P'][0],
388
415
  a['BMLD'][i]['ITEMS'][j]['DIRECTION'], a['BMLD'][i]['ITEMS'][j]['ID'], a['BMLD'][i]['ITEMS'][j]['D'], a['BMLD'][i]['ITEMS'][j]['P'],
389
416
  a['BMLD'][i]['ITEMS'][j]['CMD'], a['BMLD'][i]['ITEMS'][j]['TYPE'], a['BMLD'][i]['ITEMS'][j]['USE_ECCEN'], a['BMLD'][i]['ITEMS'][j]['USE_PROJECTION'])
390
417
 
@@ -521,12 +548,13 @@ class Load:
521
548
 
522
549
  class NodalMass:
523
550
  """Creates nodal mass and converts to JSON format.
524
- Example: NodalMass(1.5, 2.0, 3.0, 0.1, 0.2, 0.3)
551
+ Example: NodalMass(1, 1.5, 2.0, 3.0, 0.1, 0.2, 0.3)
525
552
  """
526
553
  data = []
527
-
528
- def __init__(self, mX, mY=0, mZ=0, rmX=0, rmY=0, rmZ=0):
554
+
555
+ def __init__(self, node_id, mX, mY=0, mZ=0, rmX=0, rmY=0, rmZ=0):
529
556
  """
557
+ node_id (int): Node ID where the mass is applied (Required)
530
558
  mX (float): Translational Lumped Mass in GCS X-direction (Required)
531
559
  mY (float): Translational Lumped Mass in GCS Y-direction. Defaults to 0
532
560
  mZ (float): Translational Lumped Mass in GCS Z-direction. Defaults to 0
@@ -534,6 +562,7 @@ class Load:
534
562
  rmY (float): Rotational Mass Moment of Inertia about GCS Y-axis. Defaults to 0
535
563
  rmZ (float): Rotational Mass Moment of Inertia about GCS Z-axis. Defaults to 0
536
564
  """
565
+ self.NODE_ID = node_id
537
566
  self.MX = mX
538
567
  self.MY = mY
539
568
  self.MZ = mZ
@@ -547,10 +576,8 @@ class Load:
547
576
  def json(cls):
548
577
  json_data = {"Assign": {}}
549
578
 
550
- # Use the last added mass data (or first if only one exists)
551
- if cls.data:
552
- mass_obj = cls.data[-1] # Get the most recent mass object
553
- json_data["Assign"]["1"] = {
579
+ for mass_obj in cls.data:
580
+ json_data["Assign"][mass_obj.NODE_ID] = {
554
581
  "mX": mass_obj.MX,
555
582
  "mY": mass_obj.MY,
556
583
  "mZ": mass_obj.MZ,
@@ -567,23 +594,24 @@ class Load:
567
594
 
568
595
  @classmethod
569
596
  def get(cls):
570
- return MidasAPI("GET", "/db/nmas")
597
+ MidasAPI("GET", "/db/nmas")
571
598
 
572
599
  @classmethod
573
600
  def delete(cls):
574
601
  cls.data = []
575
- return MidasAPI("DELETE", "/db/nmas")
602
+ MidasAPI("DELETE", "/db/nmas")
576
603
 
577
604
  @classmethod
578
605
  def sync(cls):
579
606
  cls.data = []
580
607
  response = cls.get()
581
608
 
582
- if response != {'message': ''}:
609
+ if response and response != {'message': ''}:
583
610
  nmas_data = response.get('NMAS', {})
584
- if "1" in nmas_data:
585
- item_data = nmas_data["1"]
611
+
612
+ for node_id, item_data in nmas_data.items():
586
613
  Load.NodalMass(
614
+ node_id=int(node_id),
587
615
  mX=item_data.get('mX'),
588
616
  mY=item_data.get('mY'),
589
617
  mZ=item_data.get('mZ'),
midas_civil/_mapi.py CHANGED
@@ -11,17 +11,63 @@ def Midas_help():
11
11
 
12
12
 
13
13
 
14
- class MAPI_PRODUCT:
15
- product = "civil"
14
+ class MAPI_COUNTRY:
15
+
16
+ country = "US"
17
+
18
+ def __init__(self,country:str):
19
+ ''' Define Civil NX country to automatically set Base URL and MAPI Key from registry.
20
+ ```
21
+ MAPI_COUNTRY('US')
22
+ MAPI_COUNTRY('CN')
23
+
24
+ ```
25
+ '''
26
+ if country.lower() == 'cn':
27
+ MAPI_COUNTRY.country = 'CN'
28
+ else:
29
+ MAPI_COUNTRY.country = 'US'
30
+
31
+ MAPI_BASEURL.set_url()
32
+ MAPI_KEY.get_key()
33
+
34
+
35
+ class MAPI_BASEURL:
36
+ baseURL = "https://moa-engineers.midasit.com:443/civil"
37
+
38
+ def __init__(self, baseURL:str):
39
+ ''' Define the Base URL for API connection.
40
+ ```
41
+ MAPI_BASEURL('https://moa-engineers.midasit.com:443/civil')
42
+ ```
43
+ '''
44
+ MAPI_BASEURL.baseURL = baseURL
45
+
46
+ @classmethod
47
+ def get_url(cls):
48
+ return MAPI_BASEURL.baseURL
49
+
50
+ @classmethod
51
+ def set_url(cls):
52
+ try:
53
+ key_path = f"Software\\MIDAS\\CVLwNX_{MAPI_COUNTRY.country}\\CONNECTION"
54
+ registry_key = winreg.OpenKey(winreg.HKEY_CURRENT_USER, key_path, 0, winreg.KEY_READ)
55
+ url_reg = winreg.QueryValueEx(registry_key, "URI")
56
+ url_reg_key = url_reg[0]
57
+
58
+ port_reg = winreg.QueryValueEx(registry_key, "PORT")
59
+ port_reg_key = port_reg[0]
16
60
 
17
- def __init__(self,product:str):
18
- """Product 'civil' or 'gen'"""
19
- if product.lower() == 'gen':
20
- MAPI_PRODUCT.product = 'gen'
61
+ url_comb = f'https://{url_reg_key}:{port_reg_key}/civil'
21
62
 
63
+ print(f' 🌐 BASE URL is taken from Registry entry. >> {url_comb}')
64
+ MAPI_BASEURL(url_comb)
65
+ except:
66
+ print(" 🌐 BASE URL is not defined. Click on Apps > API Settings to copy the BASE URL Key.\nDefine it using MAPI_BASEURL('https://moa-engineers.midasit.com:443/civil')")
67
+ sys.exit(0)
22
68
 
23
69
  class MAPI_KEY:
24
- """MAPI key from Civil NX.\n\nEg: MAPI_Key("eadsfjaks568wqehhf.ajkgj345")"""
70
+ """MAPI key from Civil NX.\n\nEg: MAPI_Key("eadsfjaks568wqehhf.ajkgj345qfhh")"""
25
71
  data = ""
26
72
 
27
73
  def __init__(self, mapi_key:str):
@@ -31,14 +77,14 @@ class MAPI_KEY:
31
77
  def get_key(cls):
32
78
  if MAPI_KEY.data == "":
33
79
  try:
34
- key_path = r"Software\\MIDAS\\CVLwNX_US\\CONNECTION"
80
+ key_path = f"Software\\MIDAS\\CVLwNX_{MAPI_COUNTRY.country}\\CONNECTION"
35
81
  registry_key = winreg.OpenKey(winreg.HKEY_CURRENT_USER, key_path, 0, winreg.KEY_READ)
36
82
  value = winreg.QueryValueEx(registry_key, "Key")
37
83
  my_key = value[0]
38
- print(' 🔑 MAPI KEY is not defined. MAPI-KEY is taken from Registry entry.')
84
+ print(f' 🔑 MAPI-KEY is taken from Registry entry. >> {my_key[:35]}...')
39
85
  MAPI_KEY(my_key)
40
86
  except:
41
- print(f"🔑 MAPI KEY is not defined. Click on Apps > API Settings to copy the MAPI Key.")
87
+ print(f"🔑 MAPI KEY is not defined. Click on Apps > API Settings to copy the MAPI Key.\n Define it using MAPI_KEY('xxxx')")
42
88
  sys.exit(0)
43
89
  else:
44
90
  my_key = MAPI_KEY.data
@@ -57,7 +103,7 @@ def MidasAPI(method:str, command:str, body:dict={})->dict:
57
103
  # Create a node
58
104
  MidasAPI("PUT","/db/NODE",{{"Assign":{{"1":{{'X':0, 'Y':0, 'Z':0}}}}}})"""
59
105
 
60
- base_url = f"https://moa-engineers.midasit.com:443/{MAPI_PRODUCT.product}"
106
+ base_url = MAPI_BASEURL.baseURL
61
107
  mapi_key = MAPI_KEY.get_key()
62
108
 
63
109
  url = base_url + command
midas_civil/_model.py CHANGED
@@ -11,6 +11,7 @@ from ._material import *
11
11
  from ._thickness import *
12
12
 
13
13
  from ._tendon import *
14
+ from ._result import *
14
15
 
15
16
  class Model:
16
17
 
@@ -242,6 +243,8 @@ class Model:
242
243
  Load.create()
243
244
  Tendon.create()
244
245
 
246
+ LoadCombination.create()
247
+
245
248
 
246
249
 
247
250
 
midas_civil/_node.py CHANGED
@@ -12,7 +12,10 @@ def dist_tol(a,b):
12
12
  def cell(point,size=1): #SIZE OF GRID
13
13
  return (int(point.X//size),int(point.Y//size),int(point.Z//size))
14
14
 
15
- #-- NEW SYSTEM
15
+
16
+ # -------- FUNCTIONS ARE DEFINED BELOW TO RECOGNISE NODE CLASS ----------------
17
+
18
+
16
19
 
17
20
  #5 Class to create nodes
18
21
  class Node:
@@ -161,6 +164,16 @@ class Node:
161
164
 
162
165
 
163
166
 
167
+ # ---- GET NODE OBJECT FROM ID ----------
168
+
169
+ def nodeByID(nodeID:int) -> Node:
170
+ ''' Return Node object with the input ID '''
171
+ for node in Node.nodes:
172
+ if node.ID == nodeID:
173
+ return node
174
+
175
+ print(f'There is no node with ID {nodeID}')
176
+ return None
164
177
 
165
178
 
166
179
 
midas_civil/_result.py CHANGED
@@ -111,7 +111,7 @@ class LoadCombination:
111
111
  @classmethod
112
112
  def create(cls, classification = "All"):
113
113
  if len(LoadCombination.data) == 0:
114
- print("No Load Combinations defined! Define the load combination using the 'LoadCombination' class before creating these in the model.")
114
+ # print("No Load Combinations defined! Define the load combination using the 'LoadCombination' class before creating these in the model.")
115
115
  return
116
116
  if classification not in LoadCombination.valid:
117
117
  print(f'"{classification}" is not a valid input. It is changed to "General".')