structuraid_core 0.1.3 → 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (37) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +4 -9
  3. data/lib/structuraid_core/design_codes/aci_318_19/rc/footings/bending_reinforcement_ratio.rb +65 -0
  4. data/lib/structuraid_core/design_codes/aci_318_19/rc/footings/one_way_shear_capacity.rb +29 -0
  5. data/lib/structuraid_core/design_codes/aci_318_19/rc/footings/punching_critical_section_perimeter.rb +105 -0
  6. data/lib/structuraid_core/design_codes/aci_318_19/rc/minimum_steel_cover.rb +55 -0
  7. data/lib/structuraid_core/design_codes/aci_318_19/rc/reduction_factor.rb +88 -0
  8. data/lib/structuraid_core/design_codes/nsr_10/rc/footings/bending_reinforcement_ratio.rb +66 -0
  9. data/lib/structuraid_core/design_codes/nsr_10/rc/footings/one_way_shear_capacity.rb +31 -0
  10. data/lib/structuraid_core/design_codes/nsr_10/rc/footings/punching_critical_section_perimeter.rb +103 -0
  11. data/lib/structuraid_core/design_codes/nsr_10/rc/minimum_steel_cover.rb +57 -0
  12. data/lib/structuraid_core/design_codes/nsr_10/rc/reduction_factor.rb +82 -0
  13. data/lib/structuraid_core/design_codes/schemas/rc/footings/bending_reinforcement_ratio_schema.rb +24 -0
  14. data/lib/structuraid_core/design_codes/schemas/rc/footings/one_way_shear_capacity_schema.rb +22 -0
  15. data/lib/structuraid_core/design_codes/schemas/rc/footings/punching_critical_section_perimeter_schema.rb +23 -0
  16. data/lib/structuraid_core/design_codes/schemas/rc/minimum_steel_cover_schema.rb +32 -0
  17. data/lib/structuraid_core/design_codes/schemas/rc/reduction_factor_schema.rb +17 -0
  18. data/lib/structuraid_core/design_codes/utils/schema_definition.rb +38 -9
  19. data/lib/structuraid_core/elements/column/rectangular.rb +5 -4
  20. data/lib/structuraid_core/elements/footing.rb +69 -2
  21. data/lib/structuraid_core/engineering/analysis/footing/base.rb +17 -0
  22. data/lib/structuraid_core/engineering/analysis/footing/centric_combined_two_columns.rb +99 -0
  23. data/lib/structuraid_core/engineering/analysis/footing/centric_isolated.rb +1 -1
  24. data/lib/structuraid_core/engineering/analysis/footing/utils/basic_geometry.rb +36 -0
  25. data/lib/structuraid_core/engineering/analysis/footing/utils/centroid.rb +33 -0
  26. data/lib/structuraid_core/engineering/analysis/footing/utils/one_way_moment.rb +63 -0
  27. data/lib/structuraid_core/engineering/analysis/footing/utils/one_way_shear.rb +46 -0
  28. data/lib/structuraid_core/engineering/base.rb +1 -1
  29. data/lib/structuraid_core/engineering/locations/absolute.rb +4 -0
  30. data/lib/structuraid_core/engineering/locations/base.rb +1 -0
  31. data/lib/structuraid_core/engineering/locations/collection.rb +51 -0
  32. data/lib/structuraid_core/engineering/locations/coordinates_system.rb +19 -4
  33. data/lib/structuraid_core/engineering/locations/relative.rb +17 -4
  34. data/lib/structuraid_core/errors/engineering/locations/duplicate_label_error.rb +13 -0
  35. data/lib/structuraid_core/loads/point_load.rb +3 -2
  36. data/lib/structuraid_core/version.rb +1 -1
  37. metadata +67 -2
@@ -0,0 +1,82 @@
1
+ module StructuraidCore
2
+ module DesignCodes
3
+ module NSR10
4
+ module RC
5
+ class ReductionFactor
6
+ include DesignCodes::Utils::CodeRequirement
7
+ use_schema DesignCodes::Schemas::RC::ReductionFactorSchema
8
+
9
+ CONTROL_STRENGTH_CASES = %i[
10
+ compression_controlled
11
+ tension_controlled
12
+ transition_controlled
13
+ crushing_controlled
14
+ shear_nonseismic_controlled
15
+ torsion_controlled
16
+ corbel_bracket_controlled
17
+ strud_and_tie_controlled
18
+ ].freeze
19
+
20
+ MAX_STRAIN_BEFORE_TRANSITION = 0.002
21
+ MIN_STRAIN_AFTER_TRANSITION = 0.005
22
+
23
+ CODE_REFERENCE = 'NSR-10 C.9.3.2'.freeze
24
+
25
+ def call
26
+ unless CONTROL_STRENGTH_CASES.include?(strength_controlling_behaviour)
27
+ raise UnrecognizedValueError.new(strength_controlling_behaviour, :strength_controlling_behaviour)
28
+ end
29
+
30
+ return tension_controlled_factor if strength_controlling_behaviour == :tension_controlled
31
+ return compression_controlled_factor if strength_controlling_behaviour == :compression_controlled
32
+ return crushing_controlled_factor if strength_controlling_behaviour == :crushing_controlled
33
+ if %i[
34
+ shear_nonseismic_controlled
35
+ torsion_controlled
36
+ corbel_bracket_controlled
37
+ strud_and_tie_controlled
38
+ ].include?(strength_controlling_behaviour)
39
+ return shear_nonseismic_controlled_factor
40
+ end
41
+
42
+ transition_controlled_factor
43
+ end
44
+
45
+ private
46
+
47
+ def shear_nonseismic_controlled_factor
48
+ 0.75
49
+ end
50
+
51
+ def crushing_controlled_factor
52
+ 0.65
53
+ end
54
+
55
+ def tension_controlled_factor
56
+ 0.90
57
+ end
58
+
59
+ def compression_controlled_factor
60
+ return 0.75 if is_coil_rebar
61
+
62
+ 0.65
63
+ end
64
+
65
+ def transition_controlled_factor
66
+ raise MissingParamError, :strain unless strain
67
+
68
+ transition_controlled_by_strain
69
+ end
70
+
71
+ def transition_controlled_by_strain
72
+ return compression_controlled_factor if strain < MAX_STRAIN_BEFORE_TRANSITION
73
+ return tension_controlled_factor if strain > MIN_STRAIN_AFTER_TRANSITION
74
+
75
+ transition_rate = is_coil_rebar ? 50 : 250 / 3
76
+ compression_controlled_factor + (strain - MAX_STRAIN_BEFORE_TRANSITION) * transition_rate
77
+ end
78
+ end
79
+ end
80
+ end
81
+ end
82
+ end
@@ -0,0 +1,24 @@
1
+ module StructuraidCore
2
+ module DesignCodes
3
+ module Schemas
4
+ module RC
5
+ module Footings
6
+ class BendingReinforcementRatioSchema
7
+ include DesignCodes::Utils::SchemaDefinition
8
+
9
+ required_params %i[
10
+ design_compression_strength
11
+ design_steel_yield_strength
12
+ width
13
+ effective_height
14
+ flexural_moment
15
+ capacity_reduction_factor
16
+ ]
17
+
18
+ optional_params []
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,22 @@
1
+ module StructuraidCore
2
+ module DesignCodes
3
+ module Schemas
4
+ module RC
5
+ module Footings
6
+ class OneWayShearCapacitySchema
7
+ include DesignCodes::Utils::SchemaDefinition
8
+
9
+ required_params %i[
10
+ design_compression_strength
11
+ width
12
+ effective_height
13
+ light_concrete_modification_factor
14
+ ]
15
+
16
+ optional_params []
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,23 @@
1
+ module StructuraidCore
2
+ module DesignCodes
3
+ module Schemas
4
+ module RC
5
+ module Footings
6
+ class PunchingCriticalSectionPerimeterSchema
7
+ include DesignCodes::Utils::SchemaDefinition
8
+
9
+ required_params %i[
10
+ column_section_length_1
11
+ column_section_length_2
12
+ column_absolute_location
13
+ column_label
14
+ footing
15
+ ]
16
+
17
+ optional_params []
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,32 @@
1
+ module StructuraidCore
2
+ module DesignCodes
3
+ module Schemas
4
+ module RC
5
+ class MinimumSteelCoverSchema
6
+ include DesignCodes::Utils::SchemaDefinition
7
+
8
+ required_params %i[
9
+ concrete_casting_against_soil
10
+ environment_exposure
11
+ ]
12
+
13
+ optional_params %i[
14
+ maximum_rebar_diameter
15
+ structural_element
16
+ ]
17
+
18
+ enum :structural_element, %i[
19
+ slab
20
+ wall
21
+ joist
22
+ beam
23
+ column
24
+ shell thin_shell
25
+ tensor_joint
26
+ pedestal
27
+ ]
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,17 @@
1
+ module StructuraidCore
2
+ module DesignCodes
3
+ module Schemas
4
+ module RC
5
+ class ReductionFactorSchema
6
+ include DesignCodes::Utils::SchemaDefinition
7
+
8
+ required_params %i[strength_controlling_behaviour]
9
+ optional_params %i[
10
+ strain
11
+ is_coil_rebar
12
+ ]
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
@@ -10,15 +10,9 @@ module StructuraidCore
10
10
 
11
11
  module ClassMethods
12
12
  def validate!(params)
13
- required.each do |required_param|
14
- raise DesignCodes::MissingParamError, required_param if params[required_param].nil?
15
- end
16
-
17
- optional.each do |optional_param|
18
- raise DesignCodes::MissingParamError, optional_param if params[optional_param].nil?
19
- rescue DesignCodes::MissingParamError => e
20
- Warning.warn(e.message)
21
- end
13
+ validate_required_params!(params)
14
+ validate_optional_params!(params)
15
+ validate_enum_params!(params)
22
16
 
23
17
  true
24
18
  end
@@ -40,8 +34,38 @@ module StructuraidCore
40
34
  @optional
41
35
  end
42
36
 
37
+ def enum_params
38
+ @enum_params
39
+ end
40
+
43
41
  private
44
42
 
43
+ def validate_required_params!(params)
44
+ required.each do |required_param|
45
+ raise DesignCodes::MissingParamError, required_param if params[required_param].nil?
46
+ end
47
+ end
48
+
49
+ def validate_optional_params!(params)
50
+ optional.each do |optional_param|
51
+ raise DesignCodes::MissingParamError, optional_param if params[optional_param].nil?
52
+ rescue DesignCodes::MissingParamError => e
53
+ Warning.warn(e.message)
54
+ end
55
+ end
56
+
57
+ def validate_enum_params!(params)
58
+ enum_params&.each do |enum_param|
59
+ param_name = enum_param[:name]
60
+ param_value = params[param_name]
61
+ next if param_value.nil? && optional.include?(param_name)
62
+
63
+ if enum_param[:values].none?(param_value)
64
+ raise DesignCodes::UnrecognizedValueError.new(param_name, param_value)
65
+ end
66
+ end
67
+ end
68
+
45
69
  def required_params(params)
46
70
  @required = params
47
71
  end
@@ -49,6 +73,11 @@ module StructuraidCore
49
73
  def optional_params(params)
50
74
  @optional = params
51
75
  end
76
+
77
+ def enum(param_name, values)
78
+ @enum_params = []
79
+ @enum_params << { name: param_name, values: }
80
+ end
52
81
  end
53
82
  end
54
83
  end
@@ -2,13 +2,14 @@ module StructuraidCore
2
2
  module Elements
3
3
  module Column
4
4
  class Rectangular < Base
5
- attr_reader :length_x, :length_y, :height, :material
5
+ attr_reader :length_1, :length_2, :height, :material, :label
6
6
 
7
- def initialize(length_x:, length_y:, height:, material:)
8
- @length_x = length_x.to_f
9
- @length_y = length_y.to_f
7
+ def initialize(length_1:, length_2:, height:, material:, label: nil)
8
+ @length_1 = length_1.to_f
9
+ @length_2 = length_2.to_f
10
10
  @height = height.to_f
11
11
  @material = material
12
+ @label = label&.to_sym
12
13
  end
13
14
  end
14
15
  end
@@ -1,14 +1,29 @@
1
1
  module StructuraidCore
2
2
  module Elements
3
+ # A footing is a structural element that transfers load from a column to the soil.
3
4
  class Footing < Base
4
5
  attr_accessor :length_1, :length_2, :height, :material, :cover_lateral, :cover_top, :cover_bottom
5
6
  attr_reader :longitudinal_top_reinforcement_length_1,
6
7
  :longitudinal_bottom_reinforcement_length_1,
7
8
  :longitudinal_top_reinforcement_length_2,
8
- :longitudinal_bottom_reinforcement_length_2
9
+ :longitudinal_bottom_reinforcement_length_2,
10
+ :coordinates_system
9
11
 
10
12
  VALID_SECTIONS = %i[length_1 length_2].freeze
11
13
 
14
+ # @param length_1 [Float] The length of the footing in the direction of the main section
15
+ # @param length_2 [Float] The length of the footing in the direction perpendicular to the main section
16
+ # @param height [Float] The height of the footing
17
+ # @param material [Materials::Concrete] The material of the footing. It must be concrete
18
+ # @param cover_lateral [Float] The lateral cover of the footing
19
+ # @param cover_top [Float] The top cover of the footing
20
+ # @param cover_bottom [Float] The bottom cover of the footing
21
+ # @param longitudinal_top_reinforcement_length_1 [Reinforcement::StraightLongitudinal] The longitudinal reinforcement in the direction of the main section
22
+ # @param longitudinal_bottom_reinforcement_length_1 [Reinforcement::StraightLongitudinal] The longitudinal reinforcement in the direction of the main section
23
+ # @param longitudinal_top_reinforcement_length_2 [Reinforcement::StraightLongitudinal] The longitudinal reinforcement in the direction perpendicular to the main section
24
+ # @param longitudinal_bottom_reinforcement_length_2 [Reinforcement::StraightLongitudinal] The longitudinal reinforcement in the direction perpendicular to the main section
25
+ #
26
+ # @return [Footing] the footing
12
27
  def initialize(
13
28
  length_1:,
14
29
  length_2:,
@@ -36,10 +51,16 @@ module StructuraidCore
36
51
  @main_section = :length_1
37
52
  end
38
53
 
54
+ # Computes the horizontal area of the footing
55
+ # @return [Float] The horizontal area of the footing
39
56
  def horizontal_area
40
- @length_1 * @length_2
57
+ length_1 * length_2
41
58
  end
42
59
 
60
+ # Computes the effective height of the footing for each direction and for either top or bottom reinforcement
61
+ # @param section_direction [Symbol] The direction of the section. See VALID_SECTIONS
62
+ # @param above_middle [Boolean] Whether the reinforcement is above the middle of the footing
63
+ # @return [Float] The effective height of the footing
43
64
  def effective_height(section_direction:, above_middle:)
44
65
  case section_direction
45
66
  when :length_1
@@ -49,8 +70,54 @@ module StructuraidCore
49
70
  end
50
71
  end
51
72
 
73
+ # Sets the coordinates system of the footing
74
+ # @param coordinates_system [Engineering::Locations::CoordinatesSystem] A coordinates system instance
75
+ # @return [Engineering::Locations::CoordinatesSystem] The coordinates system of the footing
76
+ def add_coordinates_system(coordinates_system)
77
+ @coordinates_system = coordinates_system
78
+ end
79
+
80
+ # Adds a column's location to the footing. If the column's location is already in the footing's coordinates system, it returns the existing location.
81
+ # @param column_location [Engineering::Locations::Absolute] The column's absolute location
82
+ # @param column_label [String, Symbol] The column's label
83
+ # @return [Engineering::Locations::Relative] The column's relative location
84
+ def find_or_add_column_location(column_location, column_label)
85
+ label = "column_#{column_label}"
86
+ relative_location_vector = column_location.to_vector - coordinates_system.anchor_location.to_vector
87
+ coordinates_system.find_or_add_location_from_vector(relative_location_vector, label:)
88
+ end
89
+
90
+ # Computes the vertices location of the footing's perimeter horizontally and adds them to the footing's coordinates system
91
+ def add_vertices_location
92
+ vertices_locations_vectors.each do |label, vector|
93
+ coordinates_system.find_or_add_location_from_vector(vector, label:)
94
+ end
95
+ end
96
+
97
+ # Evaluates if a relative location is inside the footing's perimeter. It works only for horizontal locations (z = 0)
98
+ # @param location [Engineering::Locations::Relative] The relative location to evaluate
99
+ # @return [Boolean] Whether the location is inside the footing's perimeter
100
+ def inside_me?(location)
101
+ inside_axis_2 = location.value_2 >= -0.5 * length_2 && location.value_2 <= 0.5 * length_2
102
+ inside_axis_1 = location.value_1 >= -0.5 * length_1 && location.value_1 <= 0.5 * length_1
103
+
104
+ inside_axis_1 && inside_axis_2
105
+ end
106
+
52
107
  private
53
108
 
109
+ def vertices_locations_vectors
110
+ half_length_1 = 0.5 * length_1
111
+ half_length_2 = 0.5 * length_2
112
+
113
+ {
114
+ 'vertex_top_right' => Vector[half_length_1, half_length_2, 0],
115
+ 'vertex_top_left' => Vector[-half_length_1, half_length_2, 0],
116
+ 'vertex_bottom_left' => Vector[-half_length_1, -half_length_2, 0],
117
+ 'vertex_bottom_right' => Vector[half_length_1, -half_length_2, 0]
118
+ }
119
+ end
120
+
54
121
  def aspect_ratio
55
122
  @length_1 / @length_2
56
123
  end
@@ -0,0 +1,17 @@
1
+ module StructuraidCore
2
+ module Engineering
3
+ module Analysis
4
+ module Footing
5
+ class Base
6
+ end
7
+ end
8
+ end
9
+ end
10
+ end
11
+
12
+ require_relative 'utils/basic_geometry'
13
+ require_relative 'utils/centroid'
14
+ require_relative 'utils/one_way_shear'
15
+ require_relative 'utils/one_way_moment'
16
+ require_relative 'centric_isolated'
17
+ require_relative 'centric_combined_two_columns'
@@ -0,0 +1,99 @@
1
+ require 'byebug'
2
+
3
+ module StructuraidCore
4
+ module Engineering
5
+ module Analysis
6
+ module Footing
7
+ class CentricCombinedTwoColumns < Base
8
+ include Utils::BasicGeometry
9
+ include Utils::Centroid
10
+ include Utils::OneWayShear
11
+ include Utils::OneWayMoment
12
+
13
+ def initialize(footing:, loads_from_columns:, section_direction:)
14
+ if ORTHOGONALITIES.none?(section_direction)
15
+ raise Engineering::Analysis::SectionDirectionError.new(section_direction, ORTHOGONALITIES)
16
+ end
17
+
18
+ @footing = footing
19
+ @loads_from_columns = loads_from_columns
20
+ @section_direction = section_direction
21
+ end
22
+
23
+ def build_geometry
24
+ add_loads_to_coordinates_system
25
+ align_coordinates_system_with_loads
26
+ add_vertices_location_to_coordinates_system
27
+ end
28
+
29
+ def reaction_at_first_column
30
+ -(solicitation * @footing.horizontal_area + reaction_at_second_column)
31
+ end
32
+
33
+ def reaction_at_second_column
34
+ local_length_1 = length_border_to_first_column
35
+ local_length_2 = length_first_column_to_second_column
36
+ local_length_3 = length_second_column_to_border
37
+
38
+ (solicitation_load / 2 / local_length_2) * (local_length_1**2 - (local_length_2 + local_length_3)**2)
39
+ end
40
+
41
+ private
42
+
43
+ attr_reader :footing, :section_direction, :loads_from_columns
44
+
45
+ def coordinates_system
46
+ footing.coordinates_system
47
+ end
48
+
49
+ def align_coordinates_system_with_loads
50
+ last_load_location_label = "load_#{loads_from_columns.last.label}"
51
+ aligner_vector = coordinates_system.find_location(last_load_location_label).to_vector
52
+ coordinates_system.align_axis_1_with(vector: aligner_vector)
53
+ end
54
+
55
+ def add_loads_to_coordinates_system
56
+ centroid = absolute_centroid
57
+
58
+ loads_from_columns.each do |load_from_column|
59
+ coordinates_system.find_or_add_location_from_vector(
60
+ load_from_column.location.to_vector - centroid.to_vector,
61
+ label: "load_#{load_from_column.label}"
62
+ )
63
+ end
64
+ end
65
+
66
+ def add_vertices_location_to_coordinates_system
67
+ footing.add_vertices_location
68
+ end
69
+
70
+ def length_border_to_first_column
71
+ load_location_label = "load_#{loads_from_columns.first.label}"
72
+ load_location_vector = coordinates_system.find_location(load_location_label).to_vector
73
+ vertex_location_vector = coordinates_system.find_location('vertex_top_left').to_vector
74
+
75
+ (load_location_vector - vertex_location_vector)[0].abs
76
+ end
77
+
78
+ def length_first_column_to_second_column
79
+ first_load_location_label = "load_#{loads_from_columns.first.label}"
80
+ first_load_location_vector = coordinates_system.find_location(first_load_location_label).to_vector
81
+
82
+ last_load_location_label = "load_#{loads_from_columns.last.label}"
83
+ last_load_location_vector = coordinates_system.find_location(last_load_location_label).to_vector
84
+
85
+ (last_load_location_vector - first_load_location_vector)[0].abs
86
+ end
87
+
88
+ def length_second_column_to_border
89
+ load_location_label = "load_#{loads_from_columns.last.label}"
90
+ load_location_vector = coordinates_system.find_location(load_location_label).to_vector
91
+ vertex_location_vector = coordinates_system.find_location('vertex_top_right').to_vector
92
+
93
+ (vertex_location_vector - load_location_vector)[0].abs
94
+ end
95
+ end
96
+ end
97
+ end
98
+ end
99
+ end
@@ -2,7 +2,7 @@ module StructuraidCore
2
2
  module Engineering
3
3
  module Analysis
4
4
  module Footing
5
- class CentricIsolated
5
+ class CentricIsolated < Base
6
6
  ORTHOGONALITIES = %i[length_1 length_2].freeze
7
7
 
8
8
  def initialize(footing:, load_from_column:, section_direction:)
@@ -0,0 +1,36 @@
1
+ module StructuraidCore
2
+ module Engineering
3
+ module Analysis
4
+ module Footing
5
+ module Utils
6
+ module BasicGeometry
7
+ ORTHOGONALITIES = %i[length_1 length_2].freeze
8
+
9
+ def solicitation_load
10
+ solicitation * orthogonal_length
11
+ end
12
+
13
+ private
14
+
15
+ def section_length
16
+ footing.public_send(section_direction)
17
+ end
18
+
19
+ def orthogonal_length
20
+ footing.public_send(orthogonal_direction)
21
+ end
22
+
23
+ def orthogonal_direction
24
+ orthogonal = ORTHOGONALITIES - [@cut_direction]
25
+ orthogonal.last
26
+ end
27
+
28
+ def solicitation
29
+ -loads_from_columns.sum(&:value) / @footing.horizontal_area
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,33 @@
1
+ module StructuraidCore
2
+ module Engineering
3
+ module Analysis
4
+ module Footing
5
+ module Utils
6
+ module Centroid
7
+ def absolute_centroid
8
+ Engineering::Locations::Absolute.new(
9
+ value_x: moment_yy / total_load,
10
+ value_y: moment_xx / total_load,
11
+ value_z: loads_from_columns.first.location.value_z
12
+ )
13
+ end
14
+
15
+ private
16
+
17
+ def moment_yy
18
+ loads_from_columns.sum { |load| load.value * load.location.value_x }
19
+ end
20
+
21
+ def moment_xx
22
+ loads_from_columns.sum { |load| load.value * load.location.value_y }
23
+ end
24
+
25
+ def total_load
26
+ loads_from_columns.sum(&:value)
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,63 @@
1
+ module StructuraidCore
2
+ module Engineering
3
+ module Analysis
4
+ module Footing
5
+ module Utils
6
+ module OneWayMoment
7
+ def moment_at(x_distance)
8
+ return [] if x_distance > section_length
9
+
10
+ moment = [
11
+ moment_stretch_1(x_distance),
12
+ moment_stretch_2(x_distance),
13
+ moment_stretch_3(x_distance)
14
+ ].select(&:nonzero?)
15
+ return [0] if moment.empty?
16
+
17
+ moment
18
+ end
19
+
20
+ def maximum_moment
21
+ moment_at(moment_inflection_point)
22
+ end
23
+
24
+ def moment_inflection_point
25
+ -reaction_at_first_column / solicitation_load
26
+ end
27
+
28
+ private
29
+
30
+ def moment_stretch_1(x_distance)
31
+ return 0.0 if x_distance > length_border_to_first_column
32
+
33
+ 0.5 * solicitation_load * x_distance**2
34
+ end
35
+
36
+ def moment_stretch_2(x_distance)
37
+ local_length_1 = length_border_to_first_column
38
+ local_length_2 = length_first_column_to_second_column
39
+ return 0.0 if x_distance < local_length_1 || x_distance > local_length_1 + local_length_2
40
+
41
+ 0.5 * solicitation_load * x_distance**2 + reaction_at_first_column * (x_distance - local_length_1)
42
+ end
43
+
44
+ def moment_stretch_3(x_distance)
45
+ return 0.0 if x_distance < length_border_to_first_column + length_first_column_to_second_column
46
+
47
+ 0.5 * solicitation_load * x_distance**2 + reaction_1_moment(x_distance) + reaction_2_moment(x_distance)
48
+ end
49
+
50
+ def reaction_1_moment(x_distance)
51
+ reaction_at_first_column * (x_distance - length_border_to_first_column)
52
+ end
53
+
54
+ def reaction_2_moment(x_distance)
55
+ local_length_2 = length_first_column_to_second_column
56
+ reaction_at_second_column * (x_distance - length_border_to_first_column - local_length_2)
57
+ end
58
+ end
59
+ end
60
+ end
61
+ end
62
+ end
63
+ end