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.Generic;
using System.Linq;
using System.Runtime.Versioning;
// In order to load the result of this wizard, you will also need to
// add the output bin/ folder of this project to the list of loaded
// folder in Grasshopper.
// You can use the _GrasshopperDeveloperSettings Rhino command for that.
namespace FeMM.Grasshopper.Components.SAPExtra
{
#if NETCOREAPP
[SupportedOSPlatform("windows")]
#endif
public class SAPBeamLoaderComponent : GH_Component
{
/// <summary>
/// Each implementation of GH_Component must provide a public
/// constructor without any arguments.
/// Category represents the Tab in which the component will appear,
/// Subcategory the panel. If you use non-existing tab or panel names,
/// new tabs/panels will automatically be created.
/// </summary>
public SAPBeamLoaderComponent()
: base("Beam Loader", "BLC", "SAP Beam Loader", CategoryNameConstants.CATEGORY_CHECKS, CategoryNameConstants.SUBCATEGORY_SAPEXTRA)
{
_run = false;
}
bool _run;
public override void CreateAttributes()
{
var attr = new ComponentAttributes.ComponentOneButtonAttributes(this, "Run");
attr.ButtonPressed += () =>
{
_run = true;
ExpireSolution(true);
};
m_attributes = attr;
}
/// <summary>
/// Registers all the input parameters for this component.
/// </summary>
protected override void RegisterInputParams(GH_Component.GH_InputParamManager pManager)
{
pManager.AddGenericParameter("Beams", "B", "Beams", GH_ParamAccess.list);
pManager.AddTextParameter("Path SAP Model", "P", "", GH_ParamAccess.item);
int j = pManager.AddTextParameter("Load Pattern", "LP", "Load Patterns to copy. If is empty, copy all load patterns", GH_ParamAccess.list);
pManager[j].Optional = true;
int i = pManager.AddTextParameter("SapExe", "S", "sap2000 exe fullpath", GH_ParamAccess.item);
pManager[i].Optional = true;
}
/// <summary>
/// Registers all the output parameters for this component.
/// </summary>
protected override void RegisterOutputParams(GH_Component.GH_OutputParamManager pManager)
{
pManager.AddGenericParameter("Beams", "Loaded Beams", "", GH_ParamAccess.list);
pManager.AddTextParameter("dev", "dev", "", GH_ParamAccess.item);
}
/// <summary>
/// This is the method that actually does the work.
/// </summary>
/// <param name="DA">The DA object can be used to retrieve data from input parameters and
/// to store data in output parameters.</param>
protected override void SolveInstance(IGH_DataAccess DA)
{
var beams = new List<GH_Beam>();
string path = "";
var load_patterns = new List<string>();
string sapExe = "";
if (!DA.GetDataList(0, beams))
return;
if (!DA.GetData(1, ref path))
return;
DA.GetDataList(2, load_patterns);
DA.GetData(3, ref sapExe);
if (_run)
{
var new_beams = new List<GH_Beam>();
for (int i = 0; i < beams.Count; i++)
{
new_beams.Add(new GH_Beam(beams[i]));
}
string dev = "";
LoadBeams(sapExe, path, load_patterns, ref new_beams, ref dev);
DA.SetDataList(0, new_beams);
DA.SetData(1, dev);
}
_run = false;
}
/// <summary>
/// Provides an Icon for every component that will be visible in the User Interface.
/// Icons need to be 24x24 pixels.
/// </summary>
protected override System.Drawing.Bitmap Icon => Properties.Resources.SAPBeamLoaderIcon;
/// <summary>
/// Each component must have a unique Guid to identify it.
/// It is vital this Guid doesn't change otherwise old ghx files
/// that use the old ID will partially fail during loading.
/// </summary>
public override Guid ComponentGuid => new("1ab542c9-585b-4186-9055-e8a4bfe01f60");
protected void LoadBeams(string sapExe, string path_model, List<string> load_patterns, ref List<GH_Beam> new_beams, ref string dev)
{
bool AttachToInstance = false;
ExtraSapHelper.InitializeModel(!AttachToInstance, sapExe, path_model, out cOAPI mySapObject, out cSapModel mySapModel, out cHelper myHelper);
bool exportAll = false;
if (load_patterns == null || load_patterns.Count == 0)
exportAll = true;
int beams_nr = -1;
string[] beams_name = [];
mySapObject.SapModel.FrameObj.GetNameList(ref beams_nr, ref beams_name);
var beams_name_list = new List<string>(beams_name);
int tot = mySapObject.SapModel.FrameObj.Count();
if (tot != beams_nr || tot != beams_name_list.Distinct().ToList().Count)
{
AddRuntimeMessage(GH_RuntimeMessageLevel.Error, "Plese add unique ID to all beams!");
return;
}
for (int i = 0; i < beams_nr; i++)
{
//search in selected beam if have same name
//ElementIdAttributeModel attr = (ElementIdAttributeModel)el.Attributes.FirstOrDefault(a => a is ElementIdAttributeModel);
int j_iter = -1;
for (int j = 0; j < new_beams.Count; j++)
{
ElementIdAttributeModel attr;
try
{
attr = (ElementIdAttributeModel)new_beams[j].Value.Attributes.Where(a => a is ElementIdAttributeModel).First();
}
catch (Exception)
{
AddRuntimeMessage(GH_RuntimeMessageLevel.Error, "Please add ID to beam");
return;
}
if (attr.Value == beams_name[i])
{
j_iter = j;
j = new_beams.Count(); //exit
}
}
if (j_iter >= 0) //I have found
{
#region distribuited_load
//dev = dev + " " + beams_name[i] + "\n";
int nr_load = -1;
string[] frame_name = [];
string[] load_pat = [];
int[] my_type = [];
string[] c_sys = [];
int[] dir = [];
double[] rd1 = [];
double[] rd2 = [];
double[] dist1 = [];
double[] dist2 = [];
double[] val1 = [];
double[] val2 = [];
if (mySapObject.SapModel.FrameObj.GetLoadDistributed(beams_name[i], ref nr_load, ref frame_name, ref load_pat, ref my_type, ref c_sys, ref dir,
ref rd1, ref rd2, ref dist1, ref dist2, ref val1, ref val2) != 0)
return;
for (int j = 0; j < nr_load; j++)
{
if (load_patterns.Contains(load_pat[j]) || exportAll)
{
dev = dev + " name = " + frame_name[j] + "\n";
dev = dev + " load pattern = " + load_pat[j] + "\n";
dev = dev + " type = " + my_type[j] + "\n";
dev = dev + " c sys = " + c_sys[j] + "\n";
dev = dev + " dir = " + dir[j] + "\n";
dev = dev + " rd1 = " + rd1[j] + "\n";
dev = dev + " rd2 = " + rd2[j] + "\n";
dev = dev + " dist1 = " + dist1[j] + "\n";
dev = dev + " dist2 = " + dist2[j] + "\n";
dev = dev + " val1 = " + val1[j] + "\n";
dev = dev + " val2 = " + val2[j] + "\n \n";
//Add load to new beam
string id = load_pat[j];
string name = load_pat[j];
var loadCase = new LoadCaseModel(-1, name);
var loadData = new BeamDistributedLoadModel.LoadData
{
A = rd1[j],
B = rd2[j] - 1.0
};
if (c_sys[j] == "Local")
{
loadData.CoordinateSystem = null;
}
else
{
loadData.CoordinateSystem = new CoordinateSystemModel(c_sys[j]);
}
if (dir[j] == 1) //direcion 1 for sap
{
loadData.LoadDirection = (BeamDistributedLoadModel.LoadDirection)(3 - 1); //Local axis 3 for Straus == local axis 1 for Sap
}
else if (dir[j] == 2) //direction 2 for sap
{
loadData.LoadDirection = (BeamDistributedLoadModel.LoadDirection)(2 - 1); //Local axis 2 Straus == Local axis 2 for sap
}
else if (dir[j] == 3) //direction 3 for sap
{
val1[j] = -val1[j]; //opposite sign of local axis between SAP and Straus
val2[j] = -val2[j]; //opposite sign of local axis between SAP and Straus
loadData.LoadDirection = (BeamDistributedLoadModel.LoadDirection)(1 - 1); //Local 1 axis for Sap == local axis 3 for sap but opposite signe!!!!
}
else if (dir[j] == 4)
{
loadData.LoadDirection = BeamDistributedLoadModel.LoadDirection.X;
}
else if (dir[j] == 5)
{
loadData.LoadDirection = BeamDistributedLoadModel.LoadDirection.Y;
}
else if (dir[j] == 6)
{
loadData.LoadDirection = BeamDistributedLoadModel.LoadDirection.Z;
}
else if (dir[j] == 7)
{
loadData.LoadDirection = BeamDistributedLoadModel.LoadDirection.X_Projected;
}
else if (dir[j] == 8)
{
loadData.LoadDirection = BeamDistributedLoadModel.LoadDirection.Y_Projected;
}
else if (dir[j] == 9)
{
loadData.LoadDirection = BeamDistributedLoadModel.LoadDirection.Z_Projected;
}
else if (dir[j] == 10)
{
loadData.LoadDirection = BeamDistributedLoadModel.LoadDirection.Gravity;
}
else if (dir[j] == 11)
{
loadData.LoadDirection = BeamDistributedLoadModel.LoadDirection.Z_Projected;
}
loadData.LoadSchema = BeamDistributedLoadModel.LoadSchema.Uniform;
loadData.P1 = val1[j];
loadData.P2 = val2[j];
loadData.PA = val1[j];
loadData.PB = val2[j];
BeamDistributedLoadModel.LoadType loadType;
if (my_type[j] == 1)
{
loadType = BeamDistributedLoadModel.LoadType.Force;
}
else
{
loadType = BeamDistributedLoadModel.LoadType.Moment;
}
var load = new BeamDistributedLoadModel(loadCase, loadData, loadType);
//new_beams[i].Value.Loads.Add(load);
new_beams[j_iter].Value.Loads.Add(load);
}
}
#endregion
#region point_load
nr_load = -1;
frame_name = [];
load_pat = [];
my_type = [];
c_sys = [];
dir = [];
/**
dir:
1 = Local 1 axis (only applies when CSys is Local
2 = Local 2 axis (only applies when CSys is Local)
3 = Local 3 axis (only applies when CSys is Local)
4 = X direction (does not apply when CSys is Local)
5 = Y direction (does not apply when CSys is Local)
6 = Z direction (does not apply when CSys is Local)
7 = Projected X direction (does not apply when CSys is Local)
8 = Projected Y direction (does not apply when CSys is Local)
9 = Projected Z direction (does not apply when CSys is Local)
10 = Gravity direction (only applies when CSys is Global)
11 = Projected Gravity direction (only applies when CSys is Global)
**/
double[] rel_dist = [];
double[] dist = [];
double[] val = [];
if (mySapObject.SapModel.FrameObj.GetLoadPoint(beams_name[i], ref nr_load, ref frame_name, ref load_pat, ref my_type, ref c_sys, ref dir, ref rel_dist, ref dist, ref val) != 0)
return;
for (int j = 0; j < nr_load; j++)
{
if (load_patterns.Contains(load_pat[j]) || exportAll)
{
dev = dev + " name = " + frame_name[j] + "\n"; //array?
dev = dev + " load pattern = " + load_pat[j] + "\n"; //array?
dev = dev + " type = " + my_type[j] + "\n"; //array?
dev = dev + " c sys = " + c_sys[j] + "\n"; //array?
dev = dev + " dir = " + dir[j] + "\n"; //array?
dev = dev + " rel_dist = " + rel_dist[j] + "\n"; //array?
dev = dev + " dist = " + dist[j] + "\n"; //array?
dev = dev + " val = " + val[j] + "\n \n"; //array?
//Add load to new beam
string id = load_pat[j];
string name = load_pat[j];
var loadCase = new LoadCaseModel(-1, name);
if (my_type[j] == 1) //Force
{
var load_model = new BeamPointLoadModel();
var load_value = new BeamPointLoadModel.LoadData { A = rel_dist[j] };
if (c_sys[j] == "Local")
{
load_value.CoordinateSystem = null;
}
else
{
load_value.CoordinateSystem = new CoordinateSystemModel(c_sys[j]);
}
if (dir[j] == 1) //1 = Local 1 SAP axis
{
load_value.P = new Vector3d(0, 0, val[j]);
}
else if (dir[j] == 2) //2 = Local 2 axis SAP
{
load_value.P = new Vector3d(0, val[j], 0);
}
else if (dir[j] == 3) //3 = Local 3 axis SAP
{
load_value.P = new Vector3d(-1.0 * val[j], 0, 0);
}
else if (dir[j] == 4) //Global X direction
{
load_value.P = new Vector3d(val[j], 0, 0);
}
else if (dir[j] == 5) //Global Y direction
{
load_value.P = new Vector3d(0, val[j], 0);
}
else if (dir[j] == 6) //Global Z direction
{
load_value.P = new Vector3d(0, 0, val[j]);
}
else
{
AddRuntimeMessage(GH_RuntimeMessageLevel.Warning, $"Force Point load on frame {beams_name[i]} case {load_pat[j]} - GetPointLoad type " + dir[j] + " - Direction not supported");
}
var load = new BeamPointLoadModel(loadCase, load_value, BeamPointLoadModel.LoadType.Force);
new_beams[j_iter].Value.Loads.Add(load);
}
else //Moments
{
var load_model = new BeamPointLoadModel();
var load_value = new BeamPointLoadModel.LoadData { A = rel_dist[j] };
if (c_sys[j] == "Local")
{
load_value.CoordinateSystem = null;
}
else
{
load_value.CoordinateSystem = new CoordinateSystemModel(c_sys[j]);
}
if (dir[j] == 1 || dir[j] == 4)
{
load_value.P = new Vector3d(val[j], 0, 0);
}
else if (dir[j] == 2 || dir[j] == 5)
{
load_value.P = new Vector3d(0, val[j], 0);
}
else if (dir[j] == 3 || dir[j] == 6)
{
load_value.P = new Vector3d(0, 0, val[j]);
}
else
{
AddRuntimeMessage(GH_RuntimeMessageLevel.Warning, $"Moment Point load on frame {beams_name[i]} case {load_pat[j]} - GetPointLoad type " + dir[j] + " - Direction not supported");
}
var load = new BeamPointLoadModel(loadCase, load_value, BeamPointLoadModel.LoadType.Moment);
new_beams[j_iter].Value.Loads.Add(load);
}
}
}
#endregion
}
}
mySapObject.ApplicationExit(false);
}
}
}