ข้ามไปยังเนื้อหา

บทที่ 5 อ่านข้อมูลโมเดล

Helper สำหรับตรวจ Return Code

ก่อนเริ่มอ่านข้อมูล สร้าง helper function เพื่อตรวจค่า return:

def check(ret: int, method_name: str):
"""ตรวจค่า return จาก API call — ถ้าไม่ใช่ 0 จะ raise exception"""
if ret != 0:
raise Exception(f"{method_name} failed with return code: {ret}")

ใช้งาน:

ret, count, names = sap_model.FrameObj.GetNameList()
check(ret, "FrameObj.GetNameList")

อ่านข้อมูลโมเดลพื้นฐาน

Model Path

C:\Models\MyBuilding.EDB
model_path = sap_model.GetModelFilename()
print(f"📁 Model: {model_path}")

Units ปัจจุบัน

current_units = sap_model.GetPresentUnits()
print(f"📐 Units: {current_units}")
# Output: 📐 Units: 6 (kN_m_C)

อ่านรายชื่อ Elements

Frame Objects (Beam, Column, Brace)

ret, frame_count, frame_names = sap_model.FrameObj.GetNameList()
check(ret, "FrameObj.GetNameList")
print(f"🏗️ Frame count: {frame_count}")
for i in range(min(frame_count, 5)): # แสดง 5 ตัวแรก
print(f" [{i}] {frame_names[i]}")

Output ตัวอย่าง:

🏗️ Frame count: 120
[0] B1
[1] B2
[2] B3
[3] C1
[4] C2

Joint (Point) Objects

ret, joint_count, point_names = sap_model.PointObj.GetNameList()
check(ret, "PointObj.GetNameList")
print(f"📍 Joint count: {joint_count}")

Area Objects (Slab, Wall, Panel)

ret, area_count, area_names = sap_model.AreaObj.GetNameList()
check(ret, "AreaObj.GetNameList")
print(f"🧱 Area count: {area_count}")

อ่านพิกัด Joint

# อ่านพิกัด X, Y, Z ของ joint ชื่อ "1"
ret, x, y, z = sap_model.PointObj.GetCoordCartesian("1")
check(ret, "GetCoordCartesian")
print(f"📍 Joint 1: ({x:.3f}, {y:.3f}, {z:.3f})")
# Output: 📍 Joint 1: (0.000, 0.000, 0.000)

อ่านข้อมูล Section Properties

# อ่าน section ที่ผูกกับ frame
ret, section_name, auto_select = sap_model.FrameObj.GetSection("B1")
check(ret, "FrameObj.GetSection")
print(f"📏 Frame B1 section: {section_name}")
# Output: 📏 Frame B1 section: W12X26

อ่าน Section ทั้งหมดในโมเดล

ret, prop_count, prop_names = sap_model.PropFrame.GetNameList()
check(ret, "PropFrame.GetNameList")
print(f"\n📐 Frame sections ({prop_count}):")
for name in prop_names:
print(f" • {name}")

อ่านข้อมูล Material

ret, mat_count, mat_names = sap_model.PropMaterial.GetNameList()
check(ret, "PropMaterial.GetNameList")
print(f"\n🧪 Materials ({mat_count}):")
for name in mat_names:
print(f" • {name}")

อ่านข้อมูล Story

ret, story_count, story_names, story_elevations, story_heights, \
is_master, similar_to, splice_above, splice_height, colors = \
sap_model.Story.GetStories_2()
check(ret, "Story.GetStories_2")
print(f"\n🏢 Stories ({story_count}):")
for i in range(story_count):
print(f" {story_names[i]:<10} Elev={story_elevations[i]:>8.2f} m "
f"Height={story_heights[i]:>6.2f} m")

Output:

🏢 Stories (5):
Story5 Elev= 15.00 m Height= 3.00 m
Story4 Elev= 12.00 m Height= 3.00 m
Story3 Elev= 9.00 m Height= 3.00 m
Story2 Elev= 6.00 m Height= 3.00 m
Story1 Elev= 3.00 m Height= 3.00 m

อ่าน Load Patterns

ret, lp_count, lp_names, lp_types, lp_self_wt = \
sap_model.LoadPatterns.GetNameList()
check(ret, "LoadPatterns.GetNameList")
print(f"\n📋 Load Patterns ({lp_count}):")
for i in range(lp_count):
print(f" {lp_names[i]:<12} Type={lp_types[i]} SelfWt={lp_self_wt[i]:.1f}")

ตัวอย่าง: Export ข้อมูลโมเดลเป็น CSV ด้วย pandas

import pandas as pd
# Export พิกัด joints ทั้งหมดเป็น CSV
rows = []
for name in point_names:
ret, x, y, z = sap_model.PointObj.GetCoordCartesian(name)
rows.append({"JointName": name, "X": x, "Y": y, "Z": z})
df = pd.DataFrame(rows)
df.to_csv("joints.csv", index=False)
print("✅ Export joints.csv เสร็จ!")
print(df.head())

เขียนข้อมูลกลับ ETABS (Write API)

นอกจากอ่านข้อมูล API ยังเขียนข้อมูลกลับ ETABS ได้:

เปลี่ยน Section ของ Frame

ret = sap_model.FrameObj.SetSection("B1", "W16X40")
check(ret, "FrameObj.SetSection")
print("✅ เปลี่ยน section B1 → W16X40")

เพิ่ม Frame ใหม่

# เพิ่ม frame จากจุด (0,0,0) ถึง (6,0,0) — beam ยาว 6 เมตร
ret, new_frame_name = sap_model.FrameObj.AddByCoord(
0, 0, 0, # จุดเริ่ม (X1, Y1, Z1)
6, 0, 0, # จุดสิ้นสุด (X2, Y2, Z2)
"", # ชื่อ frame (ว่าง = ให้ ETABS ตั้งเอง)
"W12X26", # section name
)
check(ret, "FrameObj.AddByCoord")
print(f"✅ เพิ่ม frame: {new_frame_name}")

เพิ่ม Restraint (Support)

# ตั้ง Pin support ที่ joint "1"
# [UX, UY, UZ, RX, RY, RZ] — True = restraint
pin_restraint = [True, True, True, False, False, False]
ret = sap_model.PointObj.SetRestraint("1", pin_restraint)
check(ret, "PointObj.SetRestraint")
print("✅ เพิ่ม Pin support ที่ joint 1")

เพิ่ม Load Pattern

# เพิ่ม load pattern ใหม่ชื่อ "SDL" (Superimposed Dead Load)
ret = sap_model.LoadPatterns.Add(
"SDL", # ชื่อ
1, # type: 1=Dead
0, # self-weight multiplier
True # add corresponding load case
)
check(ret, "LoadPatterns.Add")

ใส่ Uniform Load บน Frame

# ใส่ distributed load 10 kN/m ลงบน frame "B1" ในแนว Gravity
ret = sap_model.FrameObj.SetLoadDistributed(
"B1", # frame name
"LIVE", # load pattern
1, # myType: 1=Force, 2=Moment
10, # dir: 10=Gravity direction
0, 1, # relative distance start, end (0~1)
-10.0, -10.0, # load value start, end (kN/m)
"Global", # coordinate system
True, True # replace existing
)
check(ret, "FrameObj.SetLoadDistributed")
print("✅ ใส่ load 10 kN/m บน B1")

สรุป API ที่ใช้ในบทนี้

Read API

MethodคำอธิบายPython Return
GetModelFilename()path ของไฟล์โมเดลstr
GetPresentUnits()หน่วยปัจจุบันint
FrameObj.GetNameList()รายชื่อ frame ทั้งหมด(ret, count, names)
PointObj.GetNameList()รายชื่อ joint ทั้งหมด(ret, count, names)
AreaObj.GetNameList()รายชื่อ area ทั้งหมด(ret, count, names)
PointObj.GetCoordCartesian(name)พิกัด X,Y,Z ของ joint(ret, x, y, z)
FrameObj.GetSection(name)section ที่ผูกกับ frame(ret, section, auto)
PropFrame.GetNameList()รายชื่อ section ทั้งหมด(ret, count, names)
PropMaterial.GetNameList()รายชื่อ material ทั้งหมด(ret, count, names)
Story.GetStories_2()ข้อมูล story ทั้งหมด(ret, count, ...)
LoadPatterns.GetNameList()รายชื่อ load pattern(ret, count, ...)

Write API

MethodคำอธิบายPython Return
FrameObj.SetSection(name, section)เปลี่ยน section ของ frameint
FrameObj.AddByCoord(...)เพิ่ม frame ใหม่(ret, name)
PointObj.SetRestraint(name, vals)ตั้ง support/restraintint
LoadPatterns.Add(...)เพิ่ม load patternint
FrameObj.SetLoadDistributed(...)ใส่ distributed loadint