using FeMM.Grasshopper.Helpers;
using Grasshopper.Kernel;
using Grasshopper.Kernel.Data;
using Grasshopper.Kernel.Types;
using St7API;
using System;
using System.Collections.Generic;
using System.Text;
namespace FeMM.Grasshopper.Components.ST2R
{
public class St7ReadBeamForcesWithEnvelopesComponent : GH_Component
{
private bool _run = false;
public St7ReadBeamForcesWithEnvelopesComponent()
: base(
"Read Beam Forces",
"ReadBeamForces",
"Reads beam force from the result file",
CategoryNameConstants.CATEGORY_F2R, CategoryNameConstants.SUBCATEGORY_ST2R_BAKE)
{ }
public override void CreateAttributes()
{
var buttonAttributes = new ComponentAttributes.ComponentOneButtonAttributes(this, "Read");
buttonAttributes.ButtonPressed += () =>
{
_run = true;
ExpireSolution(true);
};
m_attributes = buttonAttributes;
}
protected override void RegisterInputParams(GH_InputParamManager p)
{
p.AddIntegerParameter("uID", "ID", "uID of the opened Straus7 model", GH_ParamAccess.item);
p.AddTextParameter("Result File", "Res", "Path to .NLA / .NLF / .RST result file", GH_ParamAccess.item);
p.AddIntegerParameter("Beam Number", "BeamNum", "Beam number(s)", GH_ParamAccess.list);
p.AddIntegerParameter("Min Stations", "Min", "Minimum number of stations", GH_ParamAccess.item, 5);
p.AddTextParameter("Ref System", "Ref", "Reference system: stBeamLocal, stBeamPrincipal, stBeamGlobal, or UCS ID", GH_ParamAccess.item, "stBeamGlobal");
}
protected override void RegisterOutputParams(GH_OutputParamManager p)
{
p.AddTextParameter("Case Names", "Names", "Result case, combination and envelope names", GH_ParamAccess.tree);
p.AddNumberParameter("Positions", "P", "Station positions", GH_ParamAccess.tree);
p.AddNumberParameter("Fx", "Fx", "Axial force", GH_ParamAccess.tree);
p.AddNumberParameter("Fy", "Fy", "Shear force local Y", GH_ParamAccess.tree);
p.AddNumberParameter("Fz", "Fz", "Shear force local Z", GH_ParamAccess.tree);
p.AddNumberParameter("Mx", "Mx", "Torsion", GH_ParamAccess.tree);
p.AddNumberParameter("My", "My", "Bending moment local Y", GH_ParamAccess.tree);
p.AddNumberParameter("Mz", "Mz", "Bending moment local Z", GH_ParamAccess.tree);
p.AddTextParameter("Log", "Log", "Debug log messages", GH_ParamAccess.list);
}
protected override void SolveInstance(IGH_DataAccess DA)
{
int uID = 0;
string resultFile = "";
List<int> beamNums = [];
int minStations = 5;
string refSystemInput = "stBeamGlobal";
if (!DA.GetData(0, ref uID)) return;
if (!DA.GetData(1, ref resultFile)) return;
if (!DA.GetDataList(2, beamNums)) return;
if (!DA.GetData(3, ref minStations)) return;
if (!DA.GetData(4, ref refSystemInput)) return;
List<string> log = [];
if (!_run)
{
DA.SetDataList(8, log);
return;
}
// --------------------------
// Map reference system input to int
// --------------------------
int refSystem = St7.stBeamGlobal; // default
switch (refSystemInput.Trim())
{
case "BeamLocal":
refSystem = St7.stBeamLocal;
break;
case "BeamPrincipal":
refSystem = St7.stBeamPrincipal;
break;
case "BeamGlobal":
refSystem = St7.stBeamGlobal;
break;
default:
if (int.TryParse(refSystemInput, out int ucsID))
refSystem = ucsID;
else
log.Add($"Invalid Ref System input: {refSystemInput}, using Global.");
break;
}
// --------------------------
// Open result file
// --------------------------
int numPrimary = 0;
int numSecondary = 0;
int err = St7.St7OpenResultFile(
uID,
resultFile,
null,
St7.kUseExistingCombinations,
ref numPrimary,
ref numSecondary);
if (err != 0)
{
log.Add($"Error opening result file: {err}");
DA.SetDataList(8, log);
_run = false;
return;
}
log.Add($"Result file opened. Primary cases: {numPrimary}, Secondary combos: {numSecondary}");
// --------------------------
// Generate envelopes
// --------------------------
int numLimitEnv = 0, numComboEnv = 0, numFactorEnv = 0;
err = St7.St7GenerateEnvelopes(uID, ref numLimitEnv, ref numComboEnv, ref numFactorEnv);
if (err != 0)
log.Add($"Error generating envelopes: {err}");
else
log.Add($"Envelopes generated. Limits={numLimitEnv}, Combinations={numComboEnv}, Factors={numFactorEnv}");
// --------------------------
// Prepare GH trees
// --------------------------
GH_Structure<GH_String> treeNames = new();
GH_Structure<GH_Number> treeN = new();
GH_Structure<GH_Number> treeFx = new();
GH_Structure<GH_Number> treeFy = new();
GH_Structure<GH_Number> treeFz = new();
GH_Structure<GH_Number> treeMx = new();
GH_Structure<GH_Number> treeMy = new();
GH_Structure<GH_Number> treeMz = new();
int beamIndex = 0;
foreach (int beamNum in beamNums)
{
int caseBranchIndex = 0;
void ReadBeamCase(int caseNum, string caseName)
{
int maxStations = 200;
int maxCols = 6;
double[] beamPos = new double[maxStations];
double[] beamResults = new double[maxStations * maxCols];
int numStations = 0;
int numColumns = 0;
int errBeam = St7.St7GetBeamResultArray(
uID,
St7.rtBeamForce,
refSystem,
beamNum,
minStations,
caseNum,
ref numStations,
ref numColumns,
beamPos,
beamResults);
if (errBeam != 0)
{
log.Add($"Error reading beam {beamNum} results for {caseName} (Case {caseNum}): {errBeam}");
return;
}
log.Add($"Read {numStations} stations for beam {beamNum}, case {caseName}");
GH_Path path = new(beamIndex, caseBranchIndex);
for (int i = 0; i < numStations; i++)
{
treeNames.Append(new GH_String(caseName), path);
treeN.Append(new GH_Number(beamPos[i]), path);
treeFx.Append(new GH_Number(beamResults[i * numColumns + 0]), path);
treeFy.Append(new GH_Number(beamResults[i * numColumns + 2]), path);
treeFz.Append(new GH_Number(beamResults[i * numColumns + 4]), path);
treeMx.Append(new GH_Number(beamResults[i * numColumns + 1]), path);
treeMy.Append(new GH_Number(beamResults[i * numColumns + 3]), path);
treeMz.Append(new GH_Number(beamResults[i * numColumns + 5]), path);
}
caseBranchIndex++;
}
// --------------------------
// Primary Cases
// --------------------------
for (int i = 1; i <= numPrimary; i++)
{
StringBuilder name = new(256);
int errCase = St7.St7GetResultCaseName(uID, i, name, name.Capacity);
if (errCase != 0) continue;
ReadBeamCase(i, name.ToString().TrimEnd('\0'));
}
// --------------------------
// Secondary Combinations
// --------------------------
for (int i = 1; i <= numSecondary; i++)
{
StringBuilder name = new(256);
int errCombo = St7.St7GetLSACombinationName(uID, i, name, name.Capacity);
if (errCombo != 0) continue;
ReadBeamCase(i + numPrimary, name.ToString().TrimEnd('\0').Replace("COMBO", "").Trim());
}
// --------------------------
// Envelopes
// --------------------------
for (int i = 1; i <= numLimitEnv + numComboEnv + numFactorEnv; i++)
{
StringBuilder name = new(256);
int errEnv = St7.St7GetResultCaseName(uID, i + numPrimary + numSecondary, name, name.Capacity);
if (errEnv != 0) continue;
ReadBeamCase(i + numPrimary + numSecondary, name.ToString().TrimEnd('\0'));
}
beamIndex++;
}
// --------------------------
// Output
// --------------------------
DA.SetDataTree(0, treeNames);
DA.SetDataTree(1, treeN);
DA.SetDataTree(2, treeFx);
DA.SetDataTree(3, treeFy);
DA.SetDataTree(4, treeFz);
DA.SetDataTree(5, treeMx);
DA.SetDataTree(6, treeMy);
DA.SetDataTree(7, treeMz);
DA.SetDataList(8, log);
_run = false;
}
protected override System.Drawing.Bitmap Icon => Properties.Resources.St7ReadBeamForcesWithEnvelopesIcon;
public override Guid ComponentGuid => new("3a21afc0-ff30-44af-a0f8-58e6aa9b9ab0");
}
}