using SAP2000v1;
using FeMM.Common.Models;
using FeMM.Grasshopper.DataTypes.FeMM;
using FeMM.Grasshopper.Helpers;
using Grasshopper.Kernel;
using Rhino.Geometry;
using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Runtime.Versioning;
using System.Windows.Forms;
namespace FeMM.Grasshopper.Components.SAPExtra
{
#if NETCOREAPP
[SupportedOSPlatform("windows")]
#endif
public class SAPBeamsLoaderResultsComponent : GH_Component
{
private bool _run;
private ComponentAttributes.ComponentOneButtonAttributes _attr;
private List<BeamModel> _output_beam;
private List<string> _dev;
/// <summary>
/// Initializes a new instance of the FeMMBeamsLoaderResults class.
/// </summary>
public SAPBeamsLoaderResultsComponent()
: base("Beams Loader Results", "SAP Beams Loader Results", "Get results after analysis in beams", CategoryNameConstants.CATEGORY_CHECKS, CategoryNameConstants.SUBCATEGORY_SAPEXTRA)
{
_run = false;
_output_beam = [];
_dev = [];
}
public override void CreateAttributes()
{
_attr = new ComponentAttributes.ComponentOneButtonAttributes(this, "Run");
_attr.ButtonPressed += () =>
{
_attr.Text = "Running...";
_output_beam = [];
_run = true;
_dev = [];
ExpireSolution(true);
};
m_attributes = _attr;
}
/// <summary>
/// Registers all the input parameters for this component.
/// </summary>
protected override void RegisterInputParams(GH_InputParamManager pManager)
{
pManager.AddGenericParameter("Beams", "B", "FeMM beam to read results", GH_ParamAccess.list);
pManager.AddTextParameter("SapFile", "SapFile", "Sdb file runned", GH_ParamAccess.item, "");
pManager.AddBooleanParameter("Attach to istance", "A", "If true, attach to the open SAP istance", GH_ParamAccess.item, false);
pManager.AddGenericParameter("Load Cases", "LC", "Load case or Combo to be loaded", GH_ParamAccess.list);
}
/// <summary>
/// Registers all the output parameters for this component.
/// </summary>
protected override void RegisterOutputParams(GH_OutputParamManager pManager)
{
pManager.AddGenericParameter("Beam", "B", "Loaded FeMM beam", GH_ParamAccess.list);
pManager.AddGenericParameter("Log", "L", "Conversion log", GH_ParamAccess.list);
}
/// <summary>
/// This is the method that actually does the work.
/// </summary>
/// <param name="DA">The DA object is used to retrieve from inputs and store in outputs.</param>
///
//var mre = new ManualResetEvent(false);
protected override void SolveInstance(IGH_DataAccess DA)
{
if (_run)
{
if (_output_beam.Count() == 0) //result not yet processed
{
var input_beam = new List<GH_Beam>();
var combo = new List<string>();
string sapfile = "";
bool attach = false;
if (!DA.GetDataList(0, input_beam))
return;
if (!DA.GetData(1, ref sapfile))
return;
if (!DA.GetData(2, ref attach))
return;
if (!DA.GetDataList(3, combo))
return;
var worker = new BackgroundWorker();
var parameters = new Hashtable
{
{ "sapfile", sapfile },
{ "combo", combo },
{ "input_beam", input_beam },
{ "attach", attach }
};
worker.DoWork += Execute;
worker.RunWorkerAsync(parameters);
worker.RunWorkerCompleted += finish;
void finish(object sender, RunWorkerCompletedEventArgs e)
{
ExpireSolution(true);
return;
}
}
else
{
var out_b = new List<GH_Beam>();
for (int i = 0; i < _output_beam.Count; i++)
out_b.Add(new GH_Beam(_output_beam[i]));
if (out_b.Count == 0)
AddRuntimeMessage(GH_RuntimeMessageLevel.Warning, "No beams selected");
DA.SetDataList(0, out_b);
DA.SetDataList(1, _dev);
_run = false;
}
}
}
public void Execute(object sender, DoWorkEventArgs e)
{
Hashtable parameters = e.Argument as Hashtable;
string sapfile = parameters["sapfile"].ToString();
bool attach = (bool)parameters["attach"];
List<string> combo = (List<string>)parameters["combo"];
List<GH_Beam> input_beam = (List<GH_Beam>)parameters["input_beam"];
ExternalProgram.CSIComObjects.InizializeSAPModel(out cSapModel mySapModel, out cOAPI mySapObject, out cHelper myHelper,
attach, sapfile, eUnits.N_mm_C, true);
if (mySapModel == null)
{
MessageBox.Show("Error open SAP2000");
_run = false;
return;
}
bool runned = mySapObject.SapModel.GetModelIsLocked();
if (runned == false)
{
MessageBox.Show("Please run the analysis!");
_run = false;
return;
}
//clear all case and combo output selections
if (mySapObject.SapModel.Results.Setup.DeselectAllCasesAndCombosForOutput() != 0)
{
MessageBox.Show("Error deselect previous combo for output");
_run = false;
return;
}
//set case and combo output selections
for (int i = 0; i < combo.Count; i++)
{
if (mySapObject.SapModel.Results.Setup.SetCaseSelectedForOutput(combo[i]) != 0)
{
if (mySapObject.SapModel.Results.Setup.SetComboSelectedForOutput(combo[i]) != 0)
{
MessageBox.Show("Error set combo/load case of output");
_run = false;
return;
}
}
}
//delete all old results of beam
for (int i = 0; i < input_beam.Count; i++)
{
input_beam[i].Value.Results.Clear();
}
//get all beams
int nr_frame = 0;
string[] name_frame = [];
if (mySapObject.SapModel.FrameObj.GetNameList(ref nr_frame, ref name_frame) != 0)
{
MessageBox.Show("Error get beams");
_run = false;
return;
}
//check if double beams in input or if beams without ID
var unique_label = new HashSet<string>();
//Parallel.For(0, input_beam.Count,
for (int k = 0; k < input_beam.Count; k++)
{
try
{
ElementIdAttributeModel attr = (ElementIdAttributeModel)input_beam[k].Value.Attributes.Where(a => a is ElementIdAttributeModel).First();
unique_label.Add(attr.Value);
if (k >= unique_label.Count)
{
AddRuntimeMessage(GH_RuntimeMessageLevel.Error, "Duplicate beam! " + attr.Value);
_run = false; return;
}
}
catch (Exception)
{
AddRuntimeMessage(GH_RuntimeMessageLevel.Error, "Please add ID to beam");
_run = false; return;
}
}
string[] labels = [.. unique_label];
//get frame forces foreach beam
var _obj = new object();
int iter = 0;
for (int i = 0; i < input_beam.Count; i++)
{
bool found = false;
string label = labels[i];
for (int k = 0; k < nr_frame; k++) //search for the right beam
{
if (label == name_frame[k]) //right beam found!
{
found = true;
var new_beam = new BeamModel(input_beam[i].Value);
_output_beam.Add(new_beam); //Add to output beams
int index = _output_beam.Count - 1;
int number_result = 0;
string[] obj = [];
double[] obj_station = [];
string[] element = [];
double[] element_station = [];
string[] load_case = [];
string[] step_type = [];
double[] step_num = [];
double[] P = [];
double[] V2 = [];
double[] V3 = [];
double[] T = [];
double[] M2 = [];
double[] M3 = [];
if (mySapObject.SapModel.Results.FrameForce(label, eItemTypeElm.ObjectElm, ref number_result, ref obj, ref obj_station, ref element,
ref element_station, ref load_case, ref step_type, ref step_num, ref P, ref V2, ref V3, ref T, ref M2, ref M3) != 0)
{
MessageBox.Show("Error get forces for " + name_frame[k]);
_run = false;
return;
}
for (int j = 0; j < number_result; j++)
{
string dev = string.Empty;
dev = dev + "Obj = " + obj[j] + "\n";
dev = dev + "Element = " + element[j] + "\n";
dev = dev + "Obj station = " + obj_station[j] + "\n";
dev = dev + "El station = " + element_station[j] + "\n";
dev = dev + "Load case = " + load_case[j] + "\n";
var comb = new LoadCaseModel(j, load_case[j]);
ExtraSapHelper.ConvertStressesFromSAP2000(_output_beam[index], ref M2[j], ref M3[j], ref V2[j], ref V3[j]);
var res = new BeamForceResultModel(comb, obj_station[j], step_num[j], step_type[j])
{
AxialForce = P[j],
BendingMoment = new Vector2d(M2[j], M3[j]),
Torque = T[j],
ShearForce = new Vector2d(V2[j], V3[j])
};
_output_beam[index].Results.Add(res);
_dev.Add(dev);
}
k = nr_frame; //beam found -> exit
}
if (k == (nr_frame - 1) && found == false)
{
//BEAM NOT FOUND!!!
AddRuntimeMessage(GH_RuntimeMessageLevel.Warning, "Beam in input not found in model! ID = " + label);
_dev.Add("Beam in input not found in model! ID = " + label + "\n");
}
}
lock (_obj)
{
iter++;
_attr.Text = "Processing element " + iter + " of " + input_beam.Count();
}
}
if (mySapObject.ApplicationExit(false) != 0)
{
MessageBox.Show("Error exit SAP");
_run = false;
return;
}
_attr.Text = "Finish";
}
/// <summary>
/// Provides an Icon for the component.
/// </summary>
protected override System.Drawing.Bitmap Icon => Properties.Resources.SAPBeamResultLoaderIcon;
/// <summary>
/// Gets the unique ID for this component. Do not change this ID after release.
/// </summary>
public override Guid ComponentGuid => new("9e1645eb-0748-472d-8157-4b864b4061a0");
}
}