using FeMM.Common.Helpers;
using FeMM.Common.Models;
using FeMM.Grasshopper.Components.Parameters;
using FeMM.Grasshopper.DataTypes;
using FeMM.Grasshopper.DataTypes.FeMM;
using FeMM.Grasshopper.DataTypes.MeCheck2;
using FeMM.Grasshopper.Helpers;
using Grasshopper.Kernel;
using Grasshopper.Kernel.Data;
using Grasshopper.Kernel.Parameters;
using Maffeis.Checkers.Concrete.Results;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Imaging;
using System.Linq;
namespace FeMM.Grasshopper.Components.MeCheck2
{
public abstract class PrintCheckImageMeCheckResultComponentBase : GH_Component
{
protected bool _run;
protected const double FROMNTOKN = 0.001;
protected const double FROMNMTOKNM = 0.000001;
protected Color[] ComboColors =
[
Color.Red,
Color.Green,
Color.Blue,
Color.Orange,
Color.Magenta,
Color.Yellow,
Color.Purple,
Color.Orchid,
Color.Aquamarine,
];
protected readonly List<string> _forceComponent =
[
"σ1 concrete",
"σ2 rebar",
"σ3 rebar",
"σ4 concrete",
"σ5 steel",
"σ6 steel",
"σ7 steel",
"σ8 steel",
"τ6",
"τ7",
"σ6 id",
"σ7 id",
"ε1 concrete",
"ε8 steel",
];
/// <summary>
/// Initializes a new instance of the MyComponent1 class.
/// </summary>
public PrintCheckImageMeCheckResultComponentBase()
: base("Print MeCheck Results", "PI", "Create the check image of super element check", CategoryNameConstants.CATEGORY_CHECKS, CategoryNameConstants.SUBCATEGORY_MECHECK2)
{
}
public override void CreateAttributes()
{
var attr = new ComponentAttributes.ComponentOneButtonAttributes(this, "Run");
attr.ButtonPressed += () =>
{
_run = true;
ExpireSolution(true);
};
m_attributes = attr;
}
protected abstract void RegisterInputMarks(GH_InputParamManager pManager);
protected abstract void GetInputMarks(IGH_DataAccess DA, ref int nnn, ref bool showMarks, List<double> customMarks);
/// <summary>
/// Registers all the input parameters for this component.
/// </summary>
protected override void RegisterInputParams(GH_InputParamManager pManager)
{
pManager.AddGenericParameter("FeMM Model", "FM", "The FEM models (more than one for stages)", GH_ParamAccess.item);
pManager.AddGenericParameter("Super-Element Beam", "SE", "The Super-Element Beam", GH_ParamAccess.list);
pManager.AddParameter(new StressAnalysisResultMeCheckParam(), "Results", "R", "The MeCheck Results", GH_ParamAccess.tree);
pManager.AddIntegerParameter("Result component", "FC", "The force component to print", GH_ParamAccess.item, 4);
Param_Integer param = (Param_Integer)pManager[pManager.ParamCount - 1];
for (int i = 0; i < _forceComponent.Count; i++)
param.AddNamedValue(_forceComponent[i], i);
pManager.AddTextParameter("Combinations", "C", "The list of the combinations to draw", GH_ParamAccess.list);
pManager[pManager.ParamCount - 1].Optional = true;
pManager.AddBooleanParameter("Show Min/Max Combo", "SMM", "If true, show the combinations that maximize and minimize the envelop", GH_ParamAccess.item, true);
pManager.AddGenericParameter("Additional values", "AV", "List of curves to add to the graph", GH_ParamAccess.list);
pManager[pManager.ParamCount - 1].Optional = true;
pManager.AddNumberParameter("Reference Values", "RV", "List of reference values to add to the graph", GH_ParamAccess.list);
pManager[pManager.ParamCount - 1].Optional = true;
pManager.AddTextParameter("File Path", "P", "The path of the file", GH_ParamAccess.item);
pManager.AddTextParameter("Graphic Title", "T", "The title of the graphic", GH_ParamAccess.item, "");
pManager.AddIntegerParameter("Significant digits", "SD", "Significant digits of ascissas", GH_ParamAccess.item, 2);
pManager.AddBooleanParameter("Keep Running", "KR", "Run", GH_ParamAccess.item, false);
RegisterInputMarks(pManager);
}
/// <summary>
/// Registers all the output parameters for this component.
/// </summary>
protected override void RegisterOutputParams(GH_OutputParamManager pManager)
{
}
/// <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>
protected override void SolveInstance(IGH_DataAccess DA)
{
Message = "";
var model = new GH_Model();
var beams = new List<GH_CompositeBeam>();
var comboToDraw = new List<string>();
int resultComponent = 0;
bool showMinMax = true;
var additionalValue = new List<GraphicCreator.Curve>();
var referenceValues = new List<double>();
string savePath = "";
string title = "";
int significantDigits = 0;
bool keepRunning = false;
int nnn = 0;
if (!DA.GetData(nnn++, ref model))
return;
if (!DA.GetDataList(nnn++, beams))
return;
if (!DA.GetDataTree(nnn++, out GH_Structure<GH_StressAnalysisResultMeCheck> inputTree))
return;
if (!DA.GetData(nnn++, ref resultComponent))
return;
DA.GetDataList(nnn++, comboToDraw);
DA.GetData(nnn++, ref showMinMax);
DA.GetDataList(nnn++, additionalValue);
DA.GetDataList(nnn++, referenceValues);
DA.GetData(nnn++, ref savePath);
DA.GetData(nnn++, ref title);
DA.GetData(nnn++, ref significantDigits);
if (!DA.GetData(nnn++, ref keepRunning))
return;
bool showMarks = true;
var customMarks = new List<double>();
GetInputMarks(DA, ref nnn, ref showMarks, customMarks);
if (_run || keepRunning)
{
if (model.Value == null)
{
AddRuntimeMessage(GH_RuntimeMessageLevel.Error, "Null model");
Message = "Error";
_run = false;
return;
}
try
{
var map = new Dictionary<int, Dictionary<int, List<StressAnalysisResultMeCheck>>>();
foreach (var path in inputTree.Paths)
{
if (path.Indices.Length != 2)
continue;
int beam = path.Indices[0];
int section = path.Indices[1];
if (!map.TryGetValue(beam, out var sectionMap))
{
sectionMap = [];
map[beam] = sectionMap;
}
if (!sectionMap.TryGetValue(section, out var list))
{
list = [];
sectionMap[section] = list;
}
foreach (var goo in inputTree.get_Branch(path))
{
if (goo is GH_StressAnalysisResultMeCheck meCheck)
if (meCheck.IsValid)
list.Add(meCheck.Value);
}
}
int beamCount = beams.Count;
var meCheckResults = new StressAnalysisResultMeCheck[beamCount][][];
for (int i = 0; i < beamCount; i++)
{
if (!map.TryGetValue(i, out var sections))
{
meCheckResults[i] = [];
continue;
}
int maxSection = sections.Keys.Max() + 1;
meCheckResults[i] = new StressAnalysisResultMeCheck[maxSection][];
foreach (var kv in sections)
meCheckResults[i][kv.Key] = [.. kv.Value];
}
var gc = new GraphicCreator(1500.0F, 900.0F, true)
{
Title = title,
CustomMarkPositions = customMarks
};
List<string> comboName = [.. model.Value.Combinations.Select(j => j.Name)];
double x = 0;
int absoluteMinIndex = 0;
int absoluteMaxIndex = 0;
double absoluteMinValue = 0;
double absoluteMaxValue = 0;
x = 0;
// Set the minimum/maximum values
for (int i = 0; i < beams.Count; i++)
{
var stationBuffer = new HashSet<double>();
for (int k = 0; k < beams[i].Value.Results.Count; k++)
{
BeamForceResultModel force = (BeamForceResultModel)beams[i].Value.Results[k];
double dist = Math.Round(force.NormalizedLength ? force.Station * beams[i].Value.Length : force.Station, 15);
stationBuffer.Add(dist);
}
double[] dists = [.. stationBuffer];
var v = new List<(double dist, double max, double min)>();
for (int n = 0; n < dists.Length; n++)
{
StressAnalysisResultMeCheck[] fff = meCheckResults[i][n];
double min = 0;
double max = 0;
switch (resultComponent)
{
case 0:
for (int j = 0; j < fff.Length; j++)
{
double combonentBuffer = fff[j].Point1_ConcreteSigma;
GraphicCreator.MinMax(j, combonentBuffer, true, ref absoluteMaxValue, ref absoluteMinValue, ref absoluteMaxIndex, ref absoluteMinIndex, ref max, ref min);
}
break;
case 1:
for (int j = 0; j < fff.Length; j++)
{
double combonentBuffer = fff[j].Point2_RebarSigma;
GraphicCreator.MinMax(j, combonentBuffer, true, ref absoluteMaxValue, ref absoluteMinValue, ref absoluteMaxIndex, ref absoluteMinIndex, ref max, ref min);
}
break;
case 2:
for (int j = 0; j < fff.Length; j++)
{
double combonentBuffer = fff[j].Point3_RebarSigma;
GraphicCreator.MinMax(j, combonentBuffer, true, ref absoluteMaxValue, ref absoluteMinValue, ref absoluteMaxIndex, ref absoluteMinIndex, ref max, ref min);
}
break;
case 3:
for (int j = 0; j < fff.Length; j++)
{
double combonentBuffer = fff[j].Point4_ConcreteSigma;
GraphicCreator.MinMax(j, combonentBuffer, true, ref absoluteMaxValue, ref absoluteMinValue, ref absoluteMaxIndex, ref absoluteMinIndex, ref max, ref min);
}
break;
case 4:
for (int j = 0; j < fff.Length; j++)
{
double combonentBuffer = fff[j].Point5_SteelSigma;
GraphicCreator.MinMax(j, combonentBuffer, true, ref absoluteMaxValue, ref absoluteMinValue, ref absoluteMaxIndex, ref absoluteMinIndex, ref max, ref min);
}
break;
case 5:
for (int j = 0; j < fff.Length; j++)
{
double combonentBuffer = fff[j].Point6_SteelSigma;
GraphicCreator.MinMax(j, combonentBuffer, true, ref absoluteMaxValue, ref absoluteMinValue, ref absoluteMaxIndex, ref absoluteMinIndex, ref max, ref min);
}
break;
case 6:
for (int j = 0; j < fff.Length; j++)
{
double combonentBuffer = fff[j].Point7_SteelSigma;
GraphicCreator.MinMax(j, combonentBuffer, true, ref absoluteMaxValue, ref absoluteMinValue, ref absoluteMaxIndex, ref absoluteMinIndex, ref max, ref min);
}
break;
case 7:
for (int j = 0; j < fff.Length; j++)
{
double combonentBuffer = fff[j].Point8_SteelSigma;
GraphicCreator.MinMax(j, combonentBuffer, true, ref absoluteMaxValue, ref absoluteMinValue, ref absoluteMaxIndex, ref absoluteMinIndex, ref max, ref min);
}
break;
case 8:
for (int j = 0; j < fff.Length; j++)
{
double combonentBuffer = fff[j].Point6_SteelTau;
GraphicCreator.MinMax(j, combonentBuffer, true, ref absoluteMaxValue, ref absoluteMinValue, ref absoluteMaxIndex, ref absoluteMinIndex, ref max, ref min);
}
break;
case 9:
for (int j = 0; j < fff.Length; j++)
{
double combonentBuffer = fff[j].Point7_SteelTau;
GraphicCreator.MinMax(j, combonentBuffer, true, ref absoluteMaxValue, ref absoluteMinValue, ref absoluteMaxIndex, ref absoluteMinIndex, ref max, ref min);
}
break;
case 10:
for (int j = 0; j < fff.Length; j++)
{
double combonentBuffer = fff[j].Point6_SteelSigmaId;
GraphicCreator.MinMax(j, combonentBuffer, true, ref absoluteMaxValue, ref absoluteMinValue, ref absoluteMaxIndex, ref absoluteMinIndex, ref max, ref min);
}
break;
case 11:
for (int j = 0; j < fff.Length; j++)
{
double combonentBuffer = fff[j].Point7_SteelSigmaId;
GraphicCreator.MinMax(j, combonentBuffer, true, ref absoluteMaxValue, ref absoluteMinValue, ref absoluteMaxIndex, ref absoluteMinIndex, ref max, ref min);
}
break;
case 12:
for (int j = 0; j < fff.Length; j++)
{
double combonentBuffer = fff[j].Point1_ConcreteEpsilon;
GraphicCreator.MinMax(j, combonentBuffer, true, ref absoluteMaxValue, ref absoluteMinValue, ref absoluteMaxIndex, ref absoluteMinIndex, ref max, ref min);
}
break;
case 13:
for (int j = 0; j < fff.Length; j++)
{
double combonentBuffer = fff[j].Point8_SteelEpsilon;
GraphicCreator.MinMax(j, combonentBuffer, true, ref absoluteMaxValue, ref absoluteMinValue, ref absoluteMaxIndex, ref absoluteMinIndex, ref max, ref min);
}
break;
}
double mod = 0;
if (n == dists.Length - 1)
mod = -1;
v.Add((x + dists[n] - mod, max, min));
}
var sorted = v.OrderBy(a => a.dist).ToList();
for (int k = 0; k < sorted.Count; k++)
gc.AddMaximumValues(sorted[k].dist, sorted[k].min, sorted[k].max);
x += dists.Max();
gc.FrameLenths.Add(dists.Max());
}
if (referenceValues.Count > 0)
{
for (int i = 0; i < referenceValues.Count; i++)
{
gc.AddReferenceLine(referenceValues[i], Color.FromArgb(100, 100, 100));
gc.AddMaxValue(referenceValues[i]);
gc.AddMinValue(referenceValues[i]);
}
}
if (additionalValue.Count > 0)
{
for (int i = 0; i < additionalValue.Count; i++)
{
gc.AddCurve(additionalValue[i].Name, additionalValue[i].Color, additionalValue[i].Thickness);
for (int j = 0; j < additionalValue[i].Values.Count; j++)
gc.AddCurveValue(additionalValue[i].Name, additionalValue[i].Values[j][0], additionalValue[i].Values[j][1]);
}
}
if (showMinMax)
{
comboToDraw.Insert(0, comboName[absoluteMaxIndex]);
comboToDraw.Insert(1, comboName[absoluteMinIndex]);
}
if (comboToDraw.Count > 0)
{
for (int c = 0; c < comboToDraw.Count; c++)
{
int comboIndex = comboName.IndexOf(comboToDraw[c]);
Color color = ComboColors[c % ComboColors.Length];
gc.AddCurve(comboToDraw[c], color);
x = 0;
for (int i = 0; i < beams.Count; i++)
{
var stationBuffer = new HashSet<double>();
var cc = new List<(string combo, double delta, double value)>();
for (int k = 0; k < beams[i].Value.Results.Count; k++)
{
BeamForceResultModel force = (BeamForceResultModel)beams[i].Value.Results[k];
double dist = Math.Round(force.NormalizedLength ? force.Station * beams[i].Value.Length : force.Station, 15);
stationBuffer.Add(dist);
}
double[] dists = [.. stationBuffer];
for (int n = 0; n < dists.Length; n++)
{
StressAnalysisResultMeCheck[] fff = meCheckResults[i][n];
double vv = 0;
switch (resultComponent)
{
case 0:
vv = fff[comboIndex].Point1_ConcreteSigma;
break;
case 1:
vv = fff[comboIndex].Point2_RebarSigma;
break;
case 2:
vv = fff[comboIndex].Point3_RebarSigma;
break;
case 3:
vv = fff[comboIndex].Point4_ConcreteSigma;
break;
case 4:
vv = fff[comboIndex].Point5_SteelSigma;
break;
case 5:
vv = fff[comboIndex].Point6_SteelSigma;
break;
case 6:
vv = fff[comboIndex].Point7_SteelSigma;
break;
case 7:
vv = fff[comboIndex].Point8_SteelSigma;
break;
case 8:
vv = fff[comboIndex].Point6_SteelTau;
break;
case 9:
vv = fff[comboIndex].Point7_SteelTau;
break;
case 10:
vv = fff[comboIndex].Point6_SteelSigmaId;
break;
case 11:
vv = fff[comboIndex].Point7_SteelSigmaId;
break;
case 12:
vv = fff[comboIndex].Point1_ConcreteEpsilon;
break;
case 13:
vv = fff[comboIndex].Point8_SteelEpsilon;
break;
}
double mod = 0;
if (n == dists.Length - 1)
mod = -1;
cc.Add((comboToDraw[c], x + dists[n] - mod, vv));
}
var sorted = cc.OrderBy(a => a.delta).ToList();
for (int k = 0; k < sorted.Count; k++)
gc.AddCurveValue(sorted[k].combo, sorted[k].delta, sorted[k].value);
x += dists.Max();
}
}
}
switch (resultComponent)
{
case 0:
case 1:
case 2:
case 3:
case 4:
case 5:
case 6:
case 7:
case 8:
case 9:
case 10:
case 11:
gc.YAxisTitle = "MPa";
break;
case 12:
case 13:
gc.YAxisTitle = "";
break;
}
gc.XAxisTitle = "m";
double _valuesScaleRatio = 1.0;
Bitmap _graphicImage = gc.Create(true, (float)_valuesScaleRatio, significantDigits, showMarks);
_graphicImage.Save(savePath, ImageFormat.Png);
_run = false;
}
catch (Exception e)
{
AddRuntimeMessage(GH_RuntimeMessageLevel.Error, $"Fail to create the image: {e}");
_run = false;
}
}
}
/// <summary>
/// Provides an Icon for the component.
/// </summary>
protected override Bitmap Icon => Properties.Resources.PrintCompositeSectionResultsIcon;
}
}