classdef RC_SRP_Calculator < handle % This application provides a modern, peach-themed interface % to calculate singly reinforced sections step-by-step. % We avoid heavy plots and focus purely on real-time equation updates. properties % Window and main grid UIFigure GridLayout % The three main sections LeftPanel % Sidebar for configurable settings CenterPanel % Main panel for step-by-step equations RightPanel % Right sidebar for our activity log % Left Panel Inputs (using f(c)', f(y), A(s) etc. for UI labels) ModeDropdown TitleFc, FieldFc TitleFy, FieldFy TitleB, FieldB TitleH, FieldH TitleBars, FieldBars TitleArea, FieldArea TitleCover, FieldCover % Extra Inputs for Double Layer TitleBars2, FieldBars2 TitleArea2, FieldArea2 TitleSpacing, FieldSpacing % Center Panel Output EquationHTML % Right Panel Output LogTextArea % Keep track of our log messages LogHistory = {} end methods (Access = public) % Constructor. This runs when we launch the calculator. function app = RC_SRP_Calculator() app.createApp(); app.addLog('Calculator app initialized! Welcome.'); app.updateEquations(); % trigger first calculation end % Clean up when the app is nicely closed function delete(app) if isvalid(app.UIFigure) delete(app.UIFigure); end end end methods (Access = private) % Let's build our user interface step-by-step function createApp(app) % Define our peach color palette (very warm, minimalistic aesthetic) peachBase = [1.00, 0.89, 0.80]; % Main background peachDark = [0.95, 0.76, 0.65]; % Panels peachLight = [1.00, 0.95, 0.90]; % Highlights peachText = [0.20, 0.20, 0.20]; % Text color for readability % Setup the main application window app.UIFigure = uifigure('Name', 'RC-SRP Calculator', 'Position', [100, 100, 1200, 750]); app.UIFigure.Color = peachBase; % Setup a 3-column layout app.GridLayout = uigridlayout(app.UIFigure); app.GridLayout.ColumnWidth = {300, '1x', 280}; app.GridLayout.RowHeight = {'1x'}; app.GridLayout.BackgroundColor = peachBase; % --- 1. LEFT SIDEBAR: Configurable Settings --- app.LeftPanel = uipanel(app.GridLayout); app.LeftPanel.Layout.Row = 1; app.LeftPanel.Layout.Column = 1; app.LeftPanel.BackgroundColor = peachDark; app.LeftPanel.Title = 'Configurable Settings'; app.LeftPanel.ForegroundColor = peachText; app.LeftPanel.FontWeight = 'bold'; % Grid inside the left panel to align our inputs beautifully leftGrid = uigridlayout(app.LeftPanel); leftGrid.ColumnWidth = {'1x', '1x'}; leftGrid.RowHeight = repmat({32}, 1, 15); % 15 rows of 32px height leftGrid.BackgroundColor = peachDark; % Calculation mode dropdown uilabel(leftGrid, 'Text', 'Mode:', 'FontWeight', 'bold', 'FontColor', peachText); app.ModeDropdown = uidropdown(leftGrid, ... 'Items', {'Singly Reinforced', 'Single Layer', 'Double Layer'}, ... 'ValueChangedFcn', @(src, event) app.onInputChanged(), ... 'FontColor', peachText, 'BackgroundColor', peachLight); % f(c)' input (concrete compressive strength) app.TitleFc = uilabel(leftGrid, 'Text', 'f(c)'' (psi):', 'FontColor', peachText, 'FontWeight', 'bold'); app.FieldFc = uieditfield(leftGrid, 'numeric', 'Value', 4000, 'ValueChangedFcn', @(src, event) app.onInputChanged()); % f(y) input (steel yield strength) app.TitleFy = uilabel(leftGrid, 'Text', 'f(y) (psi):', 'FontColor', peachText, 'FontWeight', 'bold'); app.FieldFy = uieditfield(leftGrid, 'numeric', 'Value', 60000, 'ValueChangedFcn', @(src, event) app.onInputChanged()); % Beam width app.TitleB = uilabel(leftGrid, 'Text', 'b (in):', 'FontColor', peachText, 'FontWeight', 'bold'); app.FieldB = uieditfield(leftGrid, 'numeric', 'Value', 12, 'ValueChangedFcn', @(src, event) app.onInputChanged()); % Beam height app.TitleH = uilabel(leftGrid, 'Text', 'h (in):', 'FontColor', peachText, 'FontWeight', 'bold'); app.FieldH = uieditfield(leftGrid, 'numeric', 'Value', 20, 'ValueChangedFcn', @(src, event) app.onInputChanged()); % Bars configuration app.TitleBars = uilabel(leftGrid, 'Text', 'Number of Bars:', 'FontColor', peachText, 'FontWeight', 'bold'); app.FieldBars = uieditfield(leftGrid, 'numeric', 'Value', 4, 'ValueChangedFcn', @(src, event) app.onInputChanged()); app.TitleArea = uilabel(leftGrid, 'Text', 'Area per A(s):', 'FontColor', peachText, 'FontWeight', 'bold'); app.FieldArea = uieditfield(leftGrid, 'numeric', 'Value', 0.79, 'ValueChangedFcn', @(src, event) app.onInputChanged()); app.TitleCover = uilabel(leftGrid, 'Text', 'Cover (in):', 'FontColor', peachText, 'FontWeight', 'bold'); app.FieldCover = uieditfield(leftGrid, 'numeric', 'Value', 2.5, 'ValueChangedFcn', @(src, event) app.onInputChanged()); % Double layer specific fields (hidden by default) app.TitleBars2 = uilabel(leftGrid, 'Text', 'L2 Bars:', 'FontColor', peachText, 'Visible', 'off'); app.FieldBars2 = uieditfield(leftGrid, 'numeric', 'Value', 2, 'Visible', 'off', 'ValueChangedFcn', @(src, event) app.onInputChanged()); app.TitleArea2 = uilabel(leftGrid, 'Text', 'L2 Area A(s):', 'FontColor', peachText, 'Visible', 'off'); app.FieldArea2 = uieditfield(leftGrid, 'numeric', 'Value', 1.00, 'Visible', 'off', 'ValueChangedFcn', @(src, event) app.onInputChanged()); app.TitleSpacing = uilabel(leftGrid, 'Text', 'Spacing (in):', 'FontColor', peachText, 'Visible', 'off'); app.FieldSpacing = uieditfield(leftGrid, 'numeric', 'Value', 2.13, 'Visible', 'off', 'ValueChangedFcn', @(src, event) app.onInputChanged()); % --- 2. CENTER PANEL: Step-by-Step Equations --- app.CenterPanel = uipanel(app.GridLayout); app.CenterPanel.Layout.Row = 1; app.CenterPanel.Layout.Column = 2; app.CenterPanel.BackgroundColor = peachLight; app.CenterPanel.Title = 'Formula & Equations'; app.CenterPanel.ForegroundColor = peachText; app.CenterPanel.FontWeight = 'bold'; % We use an HTML view to render nice Math/LaTeX-like output with CSS animations centerGrid = uigridlayout(app.CenterPanel); centerGrid.ColumnWidth = {'1x'}; centerGrid.RowHeight = {'1x'}; app.EquationHTML = uihtml(centerGrid); % --- 3. RIGHT SIDEBAR: Activity Log --- app.RightPanel = uipanel(app.GridLayout); app.RightPanel.Layout.Row = 1; app.RightPanel.Layout.Column = 3; app.RightPanel.BackgroundColor = peachDark; app.RightPanel.Title = 'Log & Summary'; app.RightPanel.ForegroundColor = peachText; app.RightPanel.FontWeight = 'bold'; rightGrid = uigridlayout(app.RightPanel); rightGrid.ColumnWidth = {'1x'}; rightGrid.RowHeight = {'1x'}; app.LogTextArea = uitextarea(rightGrid); app.LogTextArea.Editable = 'off'; app.LogTextArea.BackgroundColor = peachLight; app.LogTextArea.FontColor = peachText; app.LogTextArea.FontName = 'Courier New'; end % Whenever the user touches a variable, we update instantly function onInputChanged(app) % Gently check if we need to show Double Layer inputs if strcmp(app.ModeDropdown.Value, 'Double Layer') app.TitleBars2.Visible = 'on'; app.FieldBars2.Visible = 'on'; app.TitleArea2.Visible = 'on'; app.FieldArea2.Visible = 'on'; app.TitleSpacing.Visible = 'on'; app.FieldSpacing.Visible = 'on'; else app.TitleBars2.Visible = 'off'; app.FieldBars2.Visible = 'off'; app.TitleArea2.Visible = 'off'; app.FieldArea2.Visible = 'off'; app.TitleSpacing.Visible = 'off'; app.FieldSpacing.Visible = 'off'; end app.addLog('Settings modified, recalculating formulas...'); app.updateEquations(); end % This is the core logic where all the math happens, gracefully formatting results function updateEquations(app) % 1. Grab variables from the visual fields fc = app.FieldFc.Value; fy = app.FieldFy.Value; b = app.FieldB.Value; h = app.FieldH.Value; n_bars = app.FieldBars.Value; a_bar = app.FieldArea.Value; cover = app.FieldCover.Value; mode = app.ModeDropdown.Value; % Convert stress to ksi for smaller, readable numbers fc_ksi = fc / 1000; fy_ksi = fy / 1000; Es_ksi = 29000; E_cu = 0.003; % standard concrete strain parameter % 2. Setup our HTML framework with a lovely peach CSS style and transition animations html = [ ... '
' ... ]; html = [html, 'Tension steel yielded. Assumption confirmed gracefully.
']; else html = [html, 'Assumption failed! Steel did not yield.
']; end % Calculate the raw moment capacity Mn = T * (d - a/2) / 12; html = [html, 'A_s exceeds minimum rules. Wonderful.
']; else html = [html, 'A_s falls short of required minimum!
']; end % Extra steps for single layer reduction factor calculation if strcmp(mode, 'Single Layer') eps_t = eps_s; if eps_t >= 0.005 phi = 0.90; elseif eps_t <= 0.002 phi = 0.65; else phi = 0.65 + (eps_t - 0.002) * (250/3); end phi_Mn = phi * Mn; html = [html, 'Assumption Failed! Solving via Quadratic Exact Match...
']; A_quad = 0.85 * fc_ksi * b * beta1; B_quad = As * Es_ksi * E_cu; C_quad = -1 * As * Es_ksi * E_cu * d; % Find actual real root roots_c = roots([A_quad, B_quad, C_quad]); c_new = max(roots_c(roots_c > 0)); a_new = beta1 * c_new; html = [html, 'Assumption smoothly verified.
']; end % Compute derived raw moment Mn = T * (d - a/2) / 12; html = [html, '