civilpy.structural.odot package
Designers built around ODOT standard bridge drawings: prestressed box beams, bridge railing, guardrail, headwalls, and rocker bolsters.
Submodules
civilpy.structural.odot.approach_slab module
ODOT AS-1-15 Reinforced Concrete Approach Slab.
Transcribed from Ohio DOT Standard Construction Drawing AS-1-15
(revised 01-20-2023, 2 sheets). The drawing remains the controlling
document; this module encodes its reinforcing-steel table, bar-count and
bar-length formulas, section geometry, and the sheet-2 joint/seat detail
catalog so the Grasshopper component (Notebooks/Rhino Components/AS-1-15.py) and
downstream quantity takeoffs can be driven from tested Python.
Design basis printed on the sheet: AASHTO LRFD Bridge Design Specifications (2014) and ODOT BDM (2007); dead load 60 lb/ft^2 (FWS), live load HL-93; concrete f’c = 4,500 psi; reinforcing steel fy = 60,000 psi (pay item: ITEM 526 - REINFORCED CONCRETE APPROACH SLABS, anchor bars paid separately under ITEM 509).
Conventions match civilpy.structural.bridge_layout: plan frame with
X along stations (increasing away from the bridge), Y transverse, Z up,
Z = 0 at the top of the approach slab; plan lengths in feet, section
dimensions in inches (_in suffixes). Positive skew rotates the
support (bridge-limit) line counterclockwise in plan, so points at +Y
shift toward +X.
- class civilpy.structural.odot.approach_slab.ApproachSlabDesign(length_ft: float, thickness_in: float, a_bar_spacing_in: float, a_bar_mark: str, a_bar_length_ft: float, a_bar_dimension_ft: float, b501_bottom_spacing_in: float, b501_bottom_count: int, b501_top_count: int, c_bar_mark: str, c_bar_length_ft: float)[source]
Bases:
objectOne row of the AS-1-15 reinforcing steel table.
Lengths in feet, spacings/thicknesses in inches. Bar counts that depend on the slab width W are computed by the module-level functions, matching the tabulated formulas (e.g.
12(W-0.5)/K + 1).
- class civilpy.structural.odot.approach_slab.ApproachSlabInput(length_ft: float, width_ft: float, skew_deg: float = 0.0, end_thickness_in: float | None = None, seat_length_in: float = 9.0, backwall_thickness_in: float = 14.0)[source]
Bases:
objectThe design choices an engineer makes on the project plans.
length_ftmust be one of the tabulated L values.width_ftis the approach slab width W per the sheet’s width-dimension figure (out-to-out without curbs, toe-to-toe of curbs, or toe-to-toe of barrier).end_thickness_inis X (thickness at the abutment end); the sheet requires X >= T and expresses X in feet in its formulas.seat_length_inis the bearing length on the seat/backwall (6 in to 1’-0” per section B-B).backwall_thickness_inselects the anchor bar (D801 needs >= 14 in; D802 covers the 11 in PS box beam case).
- class civilpy.structural.odot.approach_slab.ApproachSlabLayout(inputs: ~civilpy.structural.odot.approach_slab.ApproachSlabInput, design: ~civilpy.structural.odot.approach_slab.ApproachSlabDesign, outline: tuple[tuple[float, float, float], tuple[float, float, float], tuple[float, float, float], tuple[float, float, float]], profile: tuple[tuple[float, float], ...], bars: tuple[~civilpy.structural.odot.approach_slab.BarRun, ...], anchor_mark: str, anchor_length_ft: float, pay_area_sy: float, notes: tuple[str, ...] = <factory>)[source]
Bases:
objectEverything the Grasshopper component draws.
outlineis the counterclockwise plan parallelogram at z = 0 (top of slab), starting at the bridge-limit / y = 0 corner.profileis the longitudinal section polyline in (u, z) feet, u measured from the bridge limit along the roadway; it is swept transversely (with the skew shear) to form the solid.- design: ApproachSlabDesign
- inputs: ApproachSlabInput
- class civilpy.structural.odot.approach_slab.BarRun(mark: str, size: int, points: tuple[tuple[float, float, float], ...])[source]
Bases:
objectOne physical bar as a polyline of plan-frame points (feet).
- class civilpy.structural.odot.approach_slab.SeatConfiguration(support: str, wearing_surface: str, details: tuple[str, ...])[source]
Bases:
objectOne sheet-2 configuration: which joint details apply at the bridge limit for a support type + wearing surface combination.
- civilpy.structural.odot.approach_slab.a_bar_count(width_ft: float, design: ApproachSlabDesign) int[source]
A-bar count per slab:
[12(W-0.5)/K] + 1.
- civilpy.structural.odot.approach_slab.anchor_bar_mark(backwall_thickness_in: float) str[source]
Which anchor bar the sheet permits for a given backwall thickness.
D801 cannot be used on backwalls less than 14 in thick; D802 is for prestressed box beam bridges with 11 in backwalls.
- civilpy.structural.odot.approach_slab.approach_slab_design(length_ft: float) ApproachSlabDesign[source]
The standard design for an approach slab length L (ft).
- civilpy.structural.odot.approach_slab.b501_length_ft(width_ft: float, skew_deg: float = 0.0) float[source]
B501 bar length
(W - 0.5) sec(theta)(ft).
- civilpy.structural.odot.approach_slab.c_bar_count(width_ft: float) int[source]
C-bar count per slab:
[12(W-0.5)/6] + 1.
- civilpy.structural.odot.approach_slab.d801_length_ft(end_thickness_ft: float, skew_deg: float = 0.0) float[source]
D801 anchor bar length (ft): 1’-0” leg +
(1.414X + 0.823)sec (theta)diagonal (X = slab thickness at the abutment end, ft). The 180-degree hook at the free end is included in the diagonal term as tabulated.
- civilpy.structural.odot.approach_slab.d802_length_ft(end_thickness_ft: float, skew_deg: float = 0.0) float[source]
D802 anchor bar length (ft): 1’-0” +
(1.414X + 0.202)sec(theta)+ 1’-0”.
- civilpy.structural.odot.approach_slab.d_bar_count(width_ft: float) int[source]
D801/D802 anchor-bar count:
[12(W-0.5)/18] + 1.
- civilpy.structural.odot.approach_slab.layout_approach_slab(inp: ApproachSlabInput) ApproachSlabLayout[source]
Generate the AS-1-15 approach slab layout.
Raises
ValueErrorwhen inputs leave the drawing’s assumptions (untabulated length, X < T, seat length outside 6-12 in, skew >= 60 degrees, or a backwall too thin for either anchor bar).
civilpy.structural.odot.bikeway_railing module
Ohio DOT bikeway railing (SCD RM-5.2): a treated-wood post-and-rail fence along bicycle paths.
Transcribed from Standard Roadway Construction Drawing RM-5.2, “Bikeway Railing” (rev. 07-21-2023, 1 sheet). A wood system — 6x6 posts with a 2x8 top rail and two 2x12 face rails — not a crashworthy barrier; it pairs with the structures-side BR-2-15 sidewalk railing only in role, not in section. The drawing remains the controlling document.
Lengths in inches unless a name says otherwise.
- class civilpy.structural.odot.bikeway_railing.BikewayRailingInput(length_ft: float, flared_ends: bool = True, low_shoulder: bool = False)[source]
Bases:
objectOne straight bikeway railing run.
length_ftis the fence length between flares (as shown on plans); flared ends addFLARED_END_LENGTH_FTeach whenflared_ends.
- class civilpy.structural.odot.bikeway_railing.BikewayRailingLayout(inputs: BikewayRailingInput, post_stations_ft: tuple[float, ...], midspan_stations_ft: tuple[float, ...], post_length_in: float, embedment_in: float, n_rail_pieces: int, total_length_ft: float, notes: tuple[str, ...] = ())[source]
Bases:
objectMembers of one bikeway railing run.
post_stations_ftare full-post centers from the run start;midspan_stations_ftthe 18 in rail-stiffener posts centered in each bay. Rails run the full length in <= 20 ft pieces butt- jointed on posts (top rail and lower face rail staggered to alternate posts, note 6).- inputs: BikewayRailingInput
- civilpy.structural.odot.bikeway_railing.FLARED_END_LENGTH_FT = 20.0
each end, turned away from the path
- civilpy.structural.odot.bikeway_railing.LOWER_FACE_RAIL_GAP_IN = 6.0
lower face rail clears grade by 6 in
- civilpy.structural.odot.bikeway_railing.LOW_SHOULDER_EMBEDMENT_IN = 60.0
1 or flatter), use longer posts giving 5 ft-0 in embedment (note 4).
- Type:
With less than 1 ft of graded shoulder beyond the rail face (10
- civilpy.structural.odot.bikeway_railing.MIDSPAN_POST_LENGTH_IN = 18.0
1 ft-6 in, 45 deg top cut, rails only
- civilpy.structural.odot.bikeway_railing.OFFSET_PREFERRED_IN = 24.0
face of rail to edge of pavement
- civilpy.structural.odot.bikeway_railing.POST_EMBEDMENT_MIN_IN = 36.0
3 ft-0 in min (see LOW_SHOULDER note)
- civilpy.structural.odot.bikeway_railing.POST_LENGTH_IN = 78.0
6 ft-6 in standard post
- civilpy.structural.odot.bikeway_railing.POST_REVEAL_IN = 36.0
grade to underside of the top rail zone
- civilpy.structural.odot.bikeway_railing.POST_SPACING_MAX_IN = 120.0
10 ft-0 in max
- civilpy.structural.odot.bikeway_railing.RAILING_HEIGHT_IN = 42.0
Rail top height above grade (3 ft reveal + top-rail zone).
- civilpy.structural.odot.bikeway_railing.RAIL_LENGTH_MAX_FT = 20.0
max piece length, butt joints on posts
- civilpy.structural.odot.bikeway_railing.layout_bikeway_railing(inp: BikewayRailingInput) BikewayRailingLayout[source]
Lay out posts and rails for one RM-5.2 bikeway railing run.
Full posts at up to 10 ft centers with a mid-span stiffener post in each bay; each flared end (20 ft at 30 degrees away from the path) is treated as additional railing length with the same spacing. Raises
ValueErrorfor a non-positive length.
civilpy.structural.odot.box_beam module
Ohio DOT prestressed concrete box beam construction details (PSBD-1-25).
Transcribed from the Ohio DOT Standard Bridge Drawing PSBD-1-25, “Prestressed Concrete Box Beam Details” (Office of Structural Engineering, 2025-07-18, rev. 2026-01-16, 6 sheets). Captured here: design-stress and material specs, transverse tie rod and anchor dowel details, shear-key grouting, intermediate-diaphragm placement rules, the available beam depths, and the standard steel-reinforced elastomeric bearing pads (B1/B2) with their design data.
The standard box-beam strand patterns, eccentricities, camber, and load
ratings live on the companion design data sheet PSBDD-1-25
(DESIGN_DATA_SHEET); those are carried in
civilpy.structural.odot.box_beam_design.
Lengths are in inches, forces in kips, stresses/moduli in ksi unless a field name says otherwise. Values are spot-checked against the drawing in the test suite; the drawing remains the controlling document.
- civilpy.structural.odot.box_beam.ANCHOR_DOWEL = AnchorDowelDetail(diameter=1.0, beam_hole_diameter=2.0, beam_hole_diameter_compression_seal=2.5, fixed_substructure_hole_min=1.0625, expansion_substructure_hole_min=1.25)
Anchor dowel detail (PSBD-1-25).
- class civilpy.structural.odot.box_beam.AnchorDowelDetail(diameter: float = 1.0, beam_hole_diameter: float = 2.0, beam_hole_diameter_compression_seal: float = 2.5, fixed_substructure_hole_min: float = 1.0625, expansion_substructure_hole_min: float = 1.25)[source]
Bases:
objectAnchor dowel details (PSBD-1-25 sheets 1 & 5).
- civilpy.structural.odot.box_beam.BDM_ASPHALT_MIN_IN = 3.0
Asphalt concrete wearing surface on NON-composite box beams, inches: 3 in minimum (BDM 309.1.B, two 1.5 in lifts of Item 441), 8 in maximum (BDM 308.2.3.3). The first lift is placed at variable thickness to take up camber and grade, so the mean is often thicker than 3 in – use the computed topping depth (BDM 308.2.3.3.e) for a real design.
- civilpy.structural.odot.box_beam.BDM_ASPHALT_PCF = 145.0
Unit weights, pcf, from BDM 909 (“assumptions … while performing the load rating analysis unless more accurate site information is available”). Note asphalt is 145 pcf, not the 140 pcf of LRFD Table 3.5.1-1.
- civilpy.structural.odot.box_beam.BDM_COMPOSITE_DECK_MIN_IN = 6.0
Minimum composite deck slab on prestressed box beams, inches (BDM 308.2.3.3.c, “#6 bars, longitudinal at 18-in max, transverse at 9-in max”).
- civilpy.structural.odot.box_beam.BDM_FUTURE_WEARING_SURFACE_KSF = 0.06
“Design all new bridges that carry highway traffic for a future wearing surface (FWS) of 0.060-ksf.” Unqualified – it applies whether or not the bridge also carries an asphalt wearing surface today. Two exceptions in the manual: temporary structures take 0.0 ksf (BDM 501), and FWS is excluded from the dead load used for shop camber (BDM 308.2.2.1.f).
- Type:
Future wearing surface allowance, ksf. BDM 303.1.2
- civilpy.structural.odot.box_beam.BEARING_DESIGN_DATA = BearingDesignData(durometer=50, allowable_compressive_stress=1.25, shear_modulus_compressive=0.095, shear_modulus_horizontal=0.13, creep_deflection_percent=25.0, bearings_per_beam=4, spec_edition='AASHTO LRFD BDS 10th Edition (2024)')
Elastomeric bearing design data (PSBD-1-25 sheet 6/6).
- civilpy.structural.odot.box_beam.BEARING_PADS: dict[str, BearingPad] = {'B1': BearingPad(name='B1', length=7.0, width=11.0, total_thickness=1.409, t_external=0.35, t_internal=0.5, t_steel=0.1046, n_laminates=2, max_total_load=36.0, max_expansion_length=92.0, max_movement=0.53, rotation_capacity=0.024), 'B2': BearingPad(name='B2', length=9.0, width=14.0, total_thickness=2.014, t_external=0.35, t_internal=0.5, t_steel=0.1046, n_laminates=3, max_total_load=74.0, max_expansion_length=147.0, max_movement=0.847, rotation_capacity=0.024)}
Standard elastomeric bearing pads B1 and B2 (PSBD-1-25 sheet 6/6).
- civilpy.structural.odot.box_beam.BEVELED_LOAD_PLATE = BeveledLoadPlate(min_thickness=1.5, plate_grade='ASTM A709 Gr 50', anchor_rod_diameter=0.75, plate_washer='3 x 3 x 1/2', expansion_anchor_hole=1.25, stud_yield=50.0)
Beveled load plate detail (BD-1-11).
- civilpy.structural.odot.box_beam.BOX_BEAM_DEPTHS: tuple[int, ...] = (17, 21, 27, 33, 42)
Standard box-beam depths, inches (PSBD-1-25 sheet 4/6).
- civilpy.structural.odot.box_beam.BOX_BOTTOM_CHAMFER_IN = 0.75
3/4 in x 3/4 in chamfer at each bottom (soffit) corner (ODOT’s standard chamfer), so the soffit is 46.5 in wide on a 48 in beam. The top corners are square. Not dimensioned on sheet 2/6 – recovered from the published areas, which it reproduces to +-0.01% at all five depths (1 in gives -0.07%, 1 1/2 in gives -0.25%).
- civilpy.structural.odot.box_beam.BOX_FLANGE_THICKNESS_IN = 5.5
Top/bottom flange thickness, inches – PSBD-1-25 sheet 2/6 LEFT dimension chain (5 1/2” | void | 5 1/2”), identical at every depth, so the void is centred on the beam. Verified: this geometry reproduces the sheet 4/6 published Ab, Yb and Ib to 0.2% at all five depths.
- civilpy.structural.odot.box_beam.BOX_SECTION_PROPERTIES: dict[int, BoxSectionProperties] = {17: BoxSectionProperties(depth=17, width=48.0, area=580.8, i=18652, yb=8.42, zt=2175, zb=2214, ic=39506, ybc=11.59, ztc=7302, zbc=3409), 21: BoxSectionProperties(depth=21, width=48.0, area=632.3, i=33551, yb=10.4, zt=3165, zb=3226, ic=63190, ybc=13.92, ztc=8925, zbc=4540), 27: BoxSectionProperties(depth=27, width=48.0, area=689.3, i=65398, yb=13.38, zt=4802, zb=4888, ic=111083, ybc=17.44, ztc=11620, zbc=6369), 33: BoxSectionProperties(depth=33, width=48.0, area=746.2, i=109652, yb=16.5, zt=6646, zb=6646, ic=175131, ybc=20.9, ztc=14474, zbc=8379), 42: BoxSectionProperties(depth=42, width=48.0, area=831.8, i=201537, yb=20.82, zt=9515, zb=9680, ic=303890, ybc=26.0, ztc=18993, zbc=11688)}
48 in wide box-beam section properties by depth, as published on PSBD-1-25 sheet 4/6.
VERIFIED (2026-07-28) against the section dimensioned on sheet 2/6: recomputing Ab, Yb and Ib from that geometry reproduces every value in this table to within 0.2% (the residual is the small exterior corner chamfers, which the polygon does not draw). The table is internally self-consistent as well – S = I/c closes both beam-only and composite.
- civilpy.structural.odot.box_beam.BOX_VOID_FILLET_IN = 3.0
Void corner fillet, inches (square). Only the 17 in beam uses 1 1/2” x 1 1/2”; every deeper beam uses 3” x 3”.
- civilpy.structural.odot.box_beam.BOX_WEB_THICKNESS_IN = 6.0
6” | 3’-0” | 6” bottom chain).
- Type:
Side web thickness, inches (sheet 2/6
- civilpy.structural.odot.box_beam.BOX_WIDTH_IN = 48.0
Standard (and only current) box-beam width, inches. Earlier editions of this drawing (PSBD-2-07) also cataloged a 36 in wide beam; PSBD-1-25 carries 48 in wide adjacent box beams only.
- class civilpy.structural.odot.box_beam.BearingDesignData(durometer: int = 50, allowable_compressive_stress: float = 1.25, shear_modulus_compressive: float = 0.095, shear_modulus_horizontal: float = 0.13, creep_deflection_percent: float = 25.0, bearings_per_beam: int = 4, spec_edition: str = 'AASHTO LRFD BDS 10th Edition (2024)')[source]
Bases:
objectElastomeric bearing design data (PSBD-1-25 sheet 6/6).
- creep_deflection_percent: float = 25.0
25-year creep deflection / instantaneous deflection, percent.
- class civilpy.structural.odot.box_beam.BearingPad(name: str, length: float, width: float, total_thickness: float, t_external: float, t_internal: float, t_steel: float, n_laminates: int, max_total_load: float, max_expansion_length: float, max_movement: float, rotation_capacity: float = 0.024)[source]
Bases:
objectA standard steel-reinforced elastomeric bearing pad (PSBD-1-25 sheet 6/6 table). Lengths in inches, load in kips, expansion length in feet.
- class civilpy.structural.odot.box_beam.BeveledLoadPlate(min_thickness: float = 1.5, plate_grade: str = 'ASTM A709 Gr 50', anchor_rod_diameter: float = 0.75, plate_washer: str = '3 x 3 x 1/2', expansion_anchor_hole: float = 1.25, stud_yield: float = 50.0)[source]
Bases:
objectBeveled steel load plate detail (BD-1-11).
- class civilpy.structural.odot.box_beam.BoxBeamDesignSpec(fc_28day_range: tuple[float, float] = (5.5, 7.0), fci_release_range: tuple[float, float] = (4.0, 5.0), fc_cast_in_place: float = 4.5, fy_reinforcing: float = 60.0, strand_grade: int = 270, strand_diameter: float = 0.5, strand_area_options: tuple[float, ...] = (0.153, 0.167))[source]
Bases:
objectDesign-stress and material specifications (PSBD-1-25 sheet 1/6).
Concrete strengths are designer-selected ranges; the strand and reinforcing values are fixed by the standard. Stresses in ksi.
- fc_28day_range: tuple[float, float] = (5.5, 7.0)
Designer-selected 28-day concrete strength range, ksi.
- class civilpy.structural.odot.box_beam.BoxSectionProperties(depth: int, width: float = 48.0, area: float = 0.0, i: float = 0.0, yb: float = 0.0, zt: float = 0.0, zb: float = 0.0, ic: float = 0.0, ybc: float = 0.0, ztc: float = 0.0, zbc: float = 0.0)[source]
Bases:
objectNon-composite (“beam only”) and composite section properties for one standard box-beam depth (PSBD-1-25 sheet 4/6 tables). Lengths in inches;
areain in^2,i/icin in^4,zt/zb/ztc/zbcin in^3. The composite values assume the standardCOMPOSITE_SLAB_STRUCTURAL_THICKNESS_INtopping atCOMPOSITE_MODULAR_RATIO; they apply to any beam of this depth when a CIP composite slab is cast, independent of which design table (composite vs. non-composite strand pattern) governs the beam itself.
- civilpy.structural.odot.box_beam.COMPOSITE_MODULAR_RATIO = 0.9
E_slab / E_beam used to compute the tabulated composite section properties (PSBD-1-25 sheet 4/6 note).
- civilpy.structural.odot.box_beam.COMPOSITE_SLAB_STRUCTURAL_THICKNESS_IN = 5.0
structural thickness carried in the composite section properties, plus a non-structural monolithic wearing surface on top of it (PSBD-1-25 sheet 4/6 section-properties note).
- Type:
Composite (CIP) topping
- civilpy.structural.odot.box_beam.DESIGN_DATA_SHEET = 'PSBDD-1-25'
Companion design data sheet (strand tables, camber, load ratings), transcribed in
civilpy.structural.odot.box_beam_design.
- civilpy.structural.odot.box_beam.DESIGN_SPEC = BoxBeamDesignSpec(fc_28day_range=(5.5, 7.0), fci_release_range=(4.0, 5.0), fc_cast_in_place=4.5, fy_reinforcing=60.0, strand_grade=270, strand_diameter=0.5, strand_area_options=(0.153, 0.167))
Box-beam design/material specification (PSBD-1-25 sheet 1/6).
- civilpy.structural.odot.box_beam.KEYWAY_BOTTOM_BAND_IN = 5.0
Height of the full-width band at the soffit, inches.
- civilpy.structural.odot.box_beam.KEYWAY_LOWER_CHAMFER_IN = 1.25
Lower chamfer leg into the keyway recess, inches.
- civilpy.structural.odot.box_beam.KEYWAY_RECESS_DEPTH_IN = 1.25
Depth of the keyway recess from the nominal face, inches.
- civilpy.structural.odot.box_beam.KEYWAY_TOP_BAND_IN = 5.0
Height of the top band, inches, and how far it is set in per side.
- civilpy.structural.odot.box_beam.KEYWAY_UPPER_CHAMFER_IN = 0.5
Upper chamfer leg out of the keyway recess, inches.
- class civilpy.structural.odot.box_beam.LoadPlateLayout(bevel_plate: BeveledLoadPlate, bottom_face: tuple[tuple[float, float, float], tuple[float, float, float], tuple[float, float, float], tuple[float, float, float]], top_face: tuple[tuple[float, float, float], tuple[float, float, float], tuple[float, float, float], tuple[float, float, float]], notes: tuple[str, ...] = ())[source]
Bases:
objectThe generated BD-1-11 beveled load plate, sized to a bearing pad’s plan footprint (
bearing_pad(name).lengthx.width).top_facecarries the bevel: each corner’s Z is offset by its (x, y) distance from plate center times the transverse/longitudinal bevel slope, so the plate top is a single tilted plane (not warped).- bevel_plate: BeveledLoadPlate
- civilpy.structural.odot.box_beam.MAX_SKEW_DEG = 30.0
Maximum structure skew this standard applies to, degrees.
- civilpy.structural.odot.box_beam.PSBD_2_07_SECTION_PROPERTIES: dict[int, BoxSectionProperties] = {17: BoxSectionProperties(depth=17, width=48.0, area=590.3, i=18819, yb=8.44, zt=2198, zb=2230, ic=38620, ybc=11.4, ztc=6898, zbc=3387), 21: BoxSectionProperties(depth=21, width=48.0, area=647.8, i=33884, yb=10.42, zt=3202, zb=3253, ic=62057, ybc=13.69, ztc=8489, zbc=4533), 27: BoxSectionProperties(depth=27, width=48.0, area=713.8, i=66222, yb=13.39, zt=4866, zb=4945, ic=109704, ybc=17.13, ztc=11119, zbc=6403), 33: BoxSectionProperties(depth=33, width=48.0, area=774.5, i=111342, yb=16.33, zt=6681, zb=6816, ic=173831, ybc=20.51, ztc=13922, zbc=8474), 42: BoxSectionProperties(depth=42, width=48.0, area=873.5, i=205459, yb=20.78, zt=9684, zb=9886, ic=303315, ybc=25.49, ztc=18367, zbc=11901)}
The superseded PSBD-2-07 (2007) sheet 4/4 “48 in wide box beam” table. That standard’s section is geometrically DIFFERENT from PSBD-1-25: 5 1/2 in uniform walls and a 37 in wide void. Use these when rating existing bridges built under PSBD-2-07 and earlier; the 12 in depth of that table is omitted because PSBD-1-25 dropped it.
- civilpy.structural.odot.box_beam.SHEAR_KEY = ShearKeyDetail(grout_depth_from_top=5.0, composite_backer_rod_min=2.0, end_shear_key_depth=1.0, end_shear_key_width=38.0)
Shear-key detail (PSBD-1-25).
- civilpy.structural.odot.box_beam.SOLID_DIAPHRAGM_BLOCK_IN = 18.0
Longitudinal length of the solid block at an intermediate diaphragm, inches, at zero skew (PSBD-1-25 sheet 4). Skewed beams widen it to
X/2 + 6whereX = width * tan(theta).
- civilpy.structural.odot.box_beam.SOLID_END_BLOCK_IN = 39.0
3’-3” on the 27/33/42 in beams, 2’-9” on the 17/21 in beams (PSBD-1-25 sheet 3).
- Type:
Length of the solid block at each beam end, inches
- class civilpy.structural.odot.box_beam.ShearKeyDetail(grout_depth_from_top: float = 5.0, composite_backer_rod_min: float = 2.0, end_shear_key_depth: float = 1.0, end_shear_key_width: float = 38.0)[source]
Bases:
objectShear-key details between adjacent box beams (PSBD-1-25 sheets 1 & 5).
- civilpy.structural.odot.box_beam.TIE_ROD = TieRodDetail(diameter=1.0, thread_root_min_diameter=0.838, torque_ft_lb=250.0, plate_washer='4 x 4 x 1/2', hole_min_diameter=2.0, hole_max_diameter=3.0, max_beams_per_rod=3)
Transverse tie rod detail (PSBD-1-25).
- class civilpy.structural.odot.box_beam.TieRodDetail(diameter: float = 1.0, thread_root_min_diameter: float = 0.838, torque_ft_lb: float = 250.0, plate_washer: str = '4 x 4 x 1/2', hole_min_diameter: float = 2.0, hole_max_diameter: float = 3.0, max_beams_per_rod: int = 3)[source]
Bases:
objectTransverse tie rod details (PSBD-1-25 sheets 1 & 4).
- civilpy.structural.odot.box_beam.bearing_pad(name: str) BearingPad[source]
Look up a standard bearing pad by name (
"B1"or"B2").
- civilpy.structural.odot.box_beam.box_section_properties(depth_in: int) BoxSectionProperties[source]
Look up the 48 in wide box-beam section properties for a standard depth (17/21/27/33/42 in).
- civilpy.structural.odot.box_beam.box_void_dimensions(depth_in: float, width_in: float = 48.0) tuple[float, float][source]
Void
(width, height)in inches for a box beam ofdepth_in/width_in:BOX_WEB_THICKNESS_INwebs each side,BOX_FLANGE_THICKNESS_INflanges top and bottom (PSBD-1-25 sheet 2/6 dimension chains).
- civilpy.structural.odot.box_beam.diaphragm_count(span_ft: float) int[source]
Number of intermediate diaphragms for a span, per PSBD-1-25 sheet 4/6: 1 for spans <= 50 ft, 2 for 50 ft < span <= 75 ft, 3 for spans > 75 ft.
- civilpy.structural.odot.box_beam.diaphragm_end_offset(beam_depth: int) float[source]
Distance from beam end to the end diaphragm, inches (PSBD-1-25 sheet 4/6): 24 in for 17/21 in deep beams, 30 in for 27/33/42 in deep beams.
- civilpy.structural.odot.box_beam.diaphragm_stations_ft(span_ft: float, beam_depth: int) tuple[float, ...][source]
Station (ft, from the beam start) of every diaphragm, sorted: the two end diaphragms plus
diaphragm_count()intermediate ones.A 70 ft CB27-48 therefore has four – ends at 2.5 and 67.5 ft, intermediates at 24.17 and 45.83 – which is what PSBD-1-25 sheet 4/6 details and what the beam is cast solid at.
- civilpy.structural.odot.box_beam.end_diaphragm_stations_ft(span_ft: float, beam_depth: int) tuple[float, float][source]
Station (ft) of the two end diaphragms, one
diaphragm_end_offset()in from each beam end (PSBD-1-25 sheet 4/6). These are cast inside the solid end blocks – seesolid_end_block_in()– not in the voided length.
- civilpy.structural.odot.box_beam.intermediate_diaphragm_stations_ft(span_ft: float, beam_depth: int) tuple[float, ...][source]
Station (ft) of each intermediate diaphragm.
diaphragm_count()of them, dividing the length between the two end diaphragms into equal bays: one lands at midspan, two at the third points of that length, three at the quarter points. The drawing states the count and the end offset but not an explicit multi-diaphragm spacing rule; equal bays is the standard detailing assumption.Note
This used to be folded into
diaphragm_stations_ftwith ank / (n - 1)interpolation, which for two diaphragms returned the two end stations and so produced no intermediate diaphragms at all – a 70 ft span came back as(2.5, 67.5). A model built on that had its tie rods buried in the end blocks and no diaphragm anywhere in the span.
- civilpy.structural.odot.box_beam.layout_load_plate(bearing_pad_name: str, longitudinal_grade: float = 0.0, skew_deg: float = 0.0, plate: BeveledLoadPlate = BeveledLoadPlate(min_thickness=1.5, plate_grade='ASTM A709 Gr 50', anchor_rod_diameter=0.75, plate_washer='3 x 3 x 1/2', expansion_anchor_hole=1.25, stud_yield=50.0)) LoadPlateLayout[source]
Generate the BD-1-11 beveled load plate sized to
bearing_pad_name("B1"or"B2",bearing_pad()), tilted perload_plate_bevel(). Origin at plate-bottom center, z = 0 at the bottom face; x = bearing length (beam axis), y = bearing width.
- civilpy.structural.odot.box_beam.load_plate_bevel(longitudinal_grade: float, skew_deg: float) tuple[float, float][source]
Transverse and longitudinal bevels of the BD-1-11 load plate.
The plate top is beveled to match the roadway grade resolved into the bearing’s local axes (BD-1-11 bevel notes): the component across the bearing width is
grade * sin(skew)and the component along the bearing length isgrade * cos(skew).longitudinal_gradeis the roadway grade (rise/run, e.g. 0.04 for 4%);skew_degis the structure skew angle in degrees. Returns(transverse, longitudinal)bevel slopes in the same rise/run units as the grade.
- civilpy.structural.odot.box_beam.solid_diaphragm_block_in(skew_deg: float = 0.0, width_in: float = 48.0) float[source]
Longitudinal length of an intermediate diaphragm’s solid block.
Zero skew gives
SOLID_DIAPHRAGM_BLOCK_IN; a skewed beam needsX/2 + 6inches,X = width * tan(skew), so the block still contains the full diaphragm once it runs on the bias.
civilpy.structural.odot.box_beam_design module
Ohio DOT prestressed box beam standard designs and load ratings (PSBDD-1-25).
Design data and load ratings transcribed from the Ohio DOT Design Data
Sheet PSBDD-1-25, “Prestressed Concrete Composite / Non-Composite Adjacent
Box Beams” (Office of Structural Engineering, 2025-07-18, rev. 2026-01-16,
4 sheets). This is the companion to the construction-detail drawing
PSBD-1-25 (see civilpy.structural.odot.box_beam).
The drawing covers two families – composite (CB, sheets 1-2) and non-composite (B, sheets 3-4) – of 48 in wide adjacent box beams at five depths (17, 21, 27, 33, 42 in). Two tables are carried here:
design(PSBDD-1-25 sheets 1 & 3)Per box and span: strand eccentricity (beam, and for composite the composite section), number of strands and their placement (rows at 2, 4, 6 in from the bottom), stirrup-zone layout, camber at release (D0) and erection (D30), residual deflection, and the bearing pad type. The tensile-bar schedule and debonding lengths on the drawing are not carried here.
load rating(PSBDD-1-25 sheets 2 & 4)LRFR rating factors (adjusted load factors, mainline interstate) for each box, span, and bridge width (24/28/32 ft = 6/7/8 beams), across the 16 rating vehicles tabulated on the sheet: HL-93 inventory and operating, the emergency (EV2/EV3) and specialized-hauling (SU4-SU7) vehicles, the AASHTO legal types (Type 3, 3-3, 3S2), and the Ohio permit/legal trucks (S-2F1, S-3F1, S-5C1, S-PL60T, S-PL65T).
Lengths in inches, spans in feet. The values were extracted from the drawing’s text layer and validated (strand placement sums to the strand count; operating exceeds inventory on every line); the drawing remains the controlling document.
Design assumptions (per the sheet’s design notes): AASHTO LRFD BDS 10th Ed. (2024) + ODOT BDM, HL-93, skew <= 30 deg, roadway width 24-32 ft, f’c = 7 ksi (f’ci = 5 ksi), Grade 60 reinforcing, 0.5 in 270 ksi low-relaxation strand (0.167 sq in).
- civilpy.structural.odot.box_beam_design.BOX_BEAM_DESIGNS: list[BoxBeamDesign] = [BoxBeamDesign(beam_type='composite', box='CB17-48', depth=17, width=48, span=20, e_beam=5.78, e_composite=8.07, n_strands=12, strands_2in=8, strands_4in=4, strands_6in=0, stirrup_w_pairs=9, stirrup_zone_x=32.0, stirrup_y=12.0, stirrup_z=12.0, camber_d0=0.125, camber_d30=0.25, deflection=0.0, bearing_type='B1'), BoxBeamDesign(beam_type='composite', box='CB17-48', depth=17, width=48, span=25, e_beam=5.88, e_composite=8.17, n_strands=14, strands_2in=10, strands_4in=4, strands_6in=0, stirrup_w_pairs=9, stirrup_zone_x=32.0, stirrup_y=12.0, stirrup_z=12.0, camber_d0=0.25, camber_d30=0.375, deflection=0.0, bearing_type='B1'), BoxBeamDesign(beam_type='composite', box='CB17-48', depth=17, width=48, span=30, e_beam=5.45, e_composite=7.74, n_strands=16, strands_2in=10, strands_4in=6, strands_6in=0, stirrup_w_pairs=9, stirrup_zone_x=32.0, stirrup_y=12.0, stirrup_z=12.0, camber_d0=0.5, camber_d30=0.875, deflection=0.125, bearing_type='B1'), BoxBeamDesign(beam_type='composite', box='CB17-48', depth=17, width=48, span=35, e_beam=5.78, e_composite=8.07, n_strands=18, strands_2in=12, strands_4in=6, strands_6in=0, stirrup_w_pairs=9, stirrup_zone_x=32.0, stirrup_y=12.0, stirrup_z=12.0, camber_d0=0.625, camber_d30=1.0, deflection=0.125, bearing_type='B1'), BoxBeamDesign(beam_type='composite', box='CB17-48', depth=17, width=48, span=40, e_beam=5.54, e_composite=7.83, n_strands=22, strands_2in=12, strands_4in=10, strands_6in=0, stirrup_w_pairs=16, stirrup_zone_x=60.0, stirrup_y=12.0, stirrup_z=12.0, camber_d0=0.875, camber_d30=1.5, deflection=0.25, bearing_type='B1'), BoxBeamDesign(beam_type='composite', box='CB17-48', depth=17, width=48, span=45, e_beam=5.45, e_composite=7.74, n_strands=24, strands_2in=12, strands_4in=12, strands_6in=0, stirrup_w_pairs=16, stirrup_zone_x=60.0, stirrup_y=12.0, stirrup_z=12.0, camber_d0=1.125, camber_d30=1.875, deflection=0.375, bearing_type='B1'), BoxBeamDesign(beam_type='composite', box='CB21-48', depth=21, width=48, span=30, e_beam=7.67, e_composite=10.94, n_strands=16, strands_2in=10, strands_4in=6, strands_6in=0, stirrup_w_pairs=9, stirrup_zone_x=32.0, stirrup_y=12.0, stirrup_z=12.0, camber_d0=0.375, camber_d30=0.625, deflection=0.125, bearing_type='B1'), BoxBeamDesign(beam_type='composite', box='CB21-48', depth=21, width=48, span=35, e_beam=7.53, e_composite=10.8, n_strands=18, strands_2in=10, strands_4in=8, strands_6in=0, stirrup_w_pairs=9, stirrup_zone_x=32.0, stirrup_y=12.0, stirrup_z=12.0, camber_d0=0.5, camber_d30=0.875, deflection=0.125, bearing_type='B1'), BoxBeamDesign(beam_type='composite', box='CB21-48', depth=21, width=48, span=40, e_beam=7.75, e_composite=11.02, n_strands=18, strands_2in=12, strands_4in=6, strands_6in=0, stirrup_w_pairs=9, stirrup_zone_x=32.0, stirrup_y=12.0, stirrup_z=12.0, camber_d0=0.5, camber_d30=0.875, deflection=0.125, bearing_type='B1'), BoxBeamDesign(beam_type='composite', box='CB21-48', depth=21, width=48, span=45, e_beam=7.75, e_composite=11.02, n_strands=18, strands_2in=12, strands_4in=6, strands_6in=0, stirrup_w_pairs=9, stirrup_zone_x=32.0, stirrup_y=12.0, stirrup_z=12.0, camber_d0=0.625, camber_d30=1.0, deflection=0.25, bearing_type='B1'), BoxBeamDesign(beam_type='composite', box='CB21-48', depth=21, width=48, span=50, e_beam=7.69, e_composite=10.96, n_strands=22, strands_2in=14, strands_4in=8, strands_6in=0, stirrup_w_pairs=9, stirrup_zone_x=32.0, stirrup_y=12.0, stirrup_z=12.0, camber_d0=1.375, camber_d30=2.375, deflection=0.5, bearing_type='B1'), BoxBeamDesign(beam_type='composite', box='CB21-48', depth=21, width=48, span=55, e_beam=7.65, e_composite=10.92, n_strands=26, strands_2in=16, strands_4in=10, strands_6in=0, stirrup_w_pairs=9, stirrup_zone_x=32.0, stirrup_y=12.0, stirrup_z=12.0, camber_d0=1.375, camber_d30=2.375, deflection=0.5, bearing_type='B2'), BoxBeamDesign(beam_type='composite', box='CB21-48', depth=21, width=48, span=60, e_beam=7.49, e_composite=10.76, n_strands=30, strands_2in=16, strands_4in=14, strands_6in=0, stirrup_w_pairs=16, stirrup_zone_x=60.0, stirrup_y=12.0, stirrup_z=12.0, camber_d0=1.75, camber_d30=3.0, deflection=0.75, bearing_type='B2'), BoxBeamDesign(beam_type='composite', box='CB27-48', depth=27, width=48, span=40, e_beam=10.88, e_composite=14.61, n_strands=16, strands_2in=12, strands_4in=4, strands_6in=0, stirrup_w_pairs=9, stirrup_zone_x=32.0, stirrup_y=9.0, stirrup_z=18.0, camber_d0=0.375, camber_d30=0.625, deflection=0.125, bearing_type='B1'), BoxBeamDesign(beam_type='composite', box='CB27-48', depth=27, width=48, span=45, e_beam=10.88, e_composite=14.61, n_strands=16, strands_2in=12, strands_4in=4, strands_6in=0, stirrup_w_pairs=9, stirrup_zone_x=32.0, stirrup_y=9.0, stirrup_z=18.0, camber_d0=0.5, camber_d30=0.875, deflection=0.125, bearing_type='B1'), BoxBeamDesign(beam_type='composite', box='CB27-48', depth=27, width=48, span=50, e_beam=10.71, e_composite=14.44, n_strands=18, strands_2in=12, strands_4in=6, strands_6in=0, stirrup_w_pairs=9, stirrup_zone_x=32.0, stirrup_y=9.0, stirrup_z=18.0, camber_d0=0.625, camber_d30=1.0, deflection=0.25, bearing_type='B1'), BoxBeamDesign(beam_type='composite', box='CB27-48', depth=27, width=48, span=55, e_beam=10.78, e_composite=14.51, n_strands=20, strands_2in=14, strands_4in=6, strands_6in=0, stirrup_w_pairs=9, stirrup_zone_x=32.0, stirrup_y=9.0, stirrup_z=18.0, camber_d0=0.75, camber_d30=1.25, deflection=0.25, bearing_type='B2'), BoxBeamDesign(beam_type='composite', box='CB27-48', depth=27, width=48, span=60, e_beam=10.83, e_composite=14.56, n_strands=24, strands_2in=16, strands_4in=8, strands_6in=0, stirrup_w_pairs=16, stirrup_zone_x=60.0, stirrup_y=9.0, stirrup_z=18.0, camber_d0=1.125, camber_d30=1.875, deflection=0.375, bearing_type='B2'), BoxBeamDesign(beam_type='composite', box='CB27-48', depth=27, width=48, span=65, e_beam=10.52, e_composite=14.25, n_strands=28, strands_2in=16, strands_4in=12, strands_6in=0, stirrup_w_pairs=16, stirrup_zone_x=60.0, stirrup_y=9.0, stirrup_z=18.0, camber_d0=1.375, camber_d30=2.375, deflection=0.625, bearing_type='B2'), BoxBeamDesign(beam_type='composite', box='CB27-48', depth=27, width=48, span=70, e_beam=10.38, e_composite=14.11, n_strands=32, strands_2in=16, strands_4in=16, strands_6in=0, stirrup_w_pairs=16, stirrup_zone_x=60.0, stirrup_y=9.0, stirrup_z=18.0, camber_d0=1.75, camber_d30=3.0, deflection=0.75, bearing_type='B2'), BoxBeamDesign(beam_type='composite', box='CB33-48', depth=33, width=48, span=50, e_beam=13.73, e_composite=17.99, n_strands=14, strands_2in=10, strands_4in=4, strands_6in=0, stirrup_w_pairs=9, stirrup_zone_x=32.0, stirrup_y=9.0, stirrup_z=18.0, camber_d0=0.375, camber_d30=0.625, deflection=0.125, bearing_type='B2'), BoxBeamDesign(beam_type='composite', box='CB33-48', depth=33, width=48, span=55, e_beam=13.55, e_composite=17.81, n_strands=16, strands_2in=10, strands_4in=6, strands_6in=0, stirrup_w_pairs=9, stirrup_zone_x=32.0, stirrup_y=9.0, stirrup_z=18.0, camber_d0=0.5, camber_d30=0.875, deflection=0.25, bearing_type='B2'), BoxBeamDesign(beam_type='composite', box='CB33-48', depth=33, width=48, span=60, e_beam=13.63, e_composite=17.89, n_strands=18, strands_2in=12, strands_4in=6, strands_6in=0, stirrup_w_pairs=9, stirrup_zone_x=32.0, stirrup_y=9.0, stirrup_z=18.0, camber_d0=0.625, camber_d30=1.0, deflection=0.25, bearing_type='B2'), BoxBeamDesign(beam_type='composite', box='CB33-48', depth=33, width=48, span=65, e_beam=13.57, e_composite=17.83, n_strands=22, strands_2in=14, strands_4in=8, strands_6in=0, stirrup_w_pairs=16, stirrup_zone_x=60.0, stirrup_y=9.0, stirrup_z=18.0, camber_d0=0.875, camber_d30=1.5, deflection=0.375, bearing_type='B2'), BoxBeamDesign(beam_type='composite', box='CB33-48', depth=33, width=48, span=70, e_beam=13.38, e_composite=17.64, n_strands=26, strands_2in=14, strands_4in=12, strands_6in=0, stirrup_w_pairs=16, stirrup_zone_x=60.0, stirrup_y=9.0, stirrup_z=18.0, camber_d0=1.125, camber_d30=1.875, deflection=0.5, bearing_type='B2'), BoxBeamDesign(beam_type='composite', box='CB33-48', depth=33, width=48, span=75, e_beam=13.37, e_composite=17.63, n_strands=30, strands_2in=16, strands_4in=14, strands_6in=0, stirrup_w_pairs=16, stirrup_zone_x=60.0, stirrup_y=9.0, stirrup_z=18.0, camber_d0=1.5, camber_d30=2.5, deflection=0.625, bearing_type='B2'), BoxBeamDesign(beam_type='composite', box='CB33-48', depth=33, width=48, span=80, e_beam=13.24, e_composite=17.5, n_strands=34, strands_2in=16, strands_4in=18, strands_6in=0, stirrup_w_pairs=16, stirrup_zone_x=60.0, stirrup_y=9.0, stirrup_z=18.0, camber_d0=1.75, camber_d30=3.0, deflection=0.875, bearing_type='B2'), BoxBeamDesign(beam_type='composite', box='CB33-48', depth=33, width=48, span=85, e_beam=13.08, e_composite=17.34, n_strands=36, strands_2in=16, strands_4in=18, strands_6in=2, stirrup_w_pairs=16, stirrup_zone_x=60.0, stirrup_y=9.0, stirrup_z=18.0, camber_d0=2.0, camber_d30=3.375, deflection=1.125, bearing_type='B2'), BoxBeamDesign(beam_type='composite', box='CB42-48', depth=42, width=48, span=65, e_beam=18.32, e_composite=23.05, n_strands=16, strands_2in=12, strands_4in=4, strands_6in=0, stirrup_w_pairs=16, stirrup_zone_x=60.0, stirrup_y=9.0, stirrup_z=18.0, camber_d0=0.375, camber_d30=0.625, deflection=0.25, bearing_type='B2'), BoxBeamDesign(beam_type='composite', box='CB42-48', depth=42, width=48, span=70, e_beam=18.22, e_composite=22.95, n_strands=20, strands_2in=14, strands_4in=6, strands_6in=0, stirrup_w_pairs=16, stirrup_zone_x=60.0, stirrup_y=9.0, stirrup_z=18.0, camber_d0=0.625, camber_d30=1.0, deflection=0.25, bearing_type='B2'), BoxBeamDesign(beam_type='composite', box='CB42-48', depth=42, width=48, span=75, e_beam=18.09, e_composite=22.82, n_strands=22, strands_2in=14, strands_4in=8, strands_6in=0, stirrup_w_pairs=16, stirrup_zone_x=60.0, stirrup_y=9.0, stirrup_z=18.0, camber_d0=0.75, camber_d30=1.25, deflection=0.375, bearing_type='B2'), BoxBeamDesign(beam_type='composite', box='CB42-48', depth=42, width=48, span=80, e_beam=17.82, e_composite=22.55, n_strands=28, strands_2in=14, strands_4in=14, strands_6in=0, stirrup_w_pairs=16, stirrup_zone_x=60.0, stirrup_y=9.0, stirrup_z=18.0, camber_d0=1.125, camber_d30=1.875, deflection=0.5, bearing_type='B2'), BoxBeamDesign(beam_type='composite', box='CB42-48', depth=42, width=48, span=85, e_beam=17.82, e_composite=22.55, n_strands=32, strands_2in=16, strands_4in=16, strands_6in=0, stirrup_w_pairs=16, stirrup_zone_x=60.0, stirrup_y=9.0, stirrup_z=18.0, camber_d0=1.375, camber_d30=2.375, deflection=0.625, bearing_type='B2'), BoxBeamDesign(beam_type='composite', box='CB42-48', depth=42, width=48, span=90, e_beam=17.76, e_composite=22.49, n_strands=34, strands_2in=16, strands_4in=18, strands_6in=0, stirrup_w_pairs=16, stirrup_zone_x=60.0, stirrup_y=9.0, stirrup_z=18.0, camber_d0=1.625, camber_d30=2.75, deflection=0.75, bearing_type='B2'), BoxBeamDesign(beam_type='composite', box='CB42-48', depth=42, width=48, span=95, e_beam=17.6, e_composite=22.33, n_strands=36, strands_2in=16, strands_4in=18, strands_6in=2, stirrup_w_pairs=16, stirrup_zone_x=60.0, stirrup_y=9.0, stirrup_z=18.0, camber_d0=1.75, camber_d30=3.0, deflection=1.0, bearing_type='B2'), BoxBeamDesign(beam_type='non_composite', box='B17-48', depth=17, width=48, span=20, e_beam=6.45, e_composite=None, n_strands=12, strands_2in=12, strands_4in=0, strands_6in=0, stirrup_w_pairs=9, stirrup_zone_x=32.0, stirrup_y=10.0, stirrup_z=10.0, camber_d0=0.25, camber_d30=0.375, deflection=0.0, bearing_type='B1'), BoxBeamDesign(beam_type='non_composite', box='B17-48', depth=17, width=48, span=25, e_beam=6.45, e_composite=None, n_strands=14, strands_2in=14, strands_4in=0, strands_6in=0, stirrup_w_pairs=9, stirrup_zone_x=32.0, stirrup_y=10.0, stirrup_z=10.0, camber_d0=0.375, camber_d30=0.625, deflection=0.0, bearing_type='B1'), BoxBeamDesign(beam_type='non_composite', box='B17-48', depth=17, width=48, span=30, e_beam=5.85, e_composite=None, n_strands=20, strands_2in=14, strands_4in=6, strands_6in=0, stirrup_w_pairs=16, stirrup_zone_x=60.0, stirrup_y=10.0, stirrup_z=10.0, camber_d0=0.625, camber_d30=1.0, deflection=0.0, bearing_type='B1'), BoxBeamDesign(beam_type='non_composite', box='B17-48', depth=17, width=48, span=35, e_beam=6.05, e_composite=None, n_strands=20, strands_2in=16, strands_4in=4, strands_6in=0, stirrup_w_pairs=16, stirrup_zone_x=60.0, stirrup_y=10.0, stirrup_z=10.0, camber_d0=0.75, camber_d30=1.25, deflection=0.125, bearing_type='B1'), BoxBeamDesign(beam_type='non_composite', box='B21-48', depth=21, width=48, span=30, e_beam=7.62, e_composite=None, n_strands=16, strands_2in=12, strands_4in=4, strands_6in=0, stirrup_w_pairs=9, stirrup_zone_x=32.0, stirrup_y=12.0, stirrup_z=12.0, camber_d0=0.375, camber_d30=0.625, deflection=0.0, bearing_type='B1'), BoxBeamDesign(beam_type='non_composite', box='B21-48', depth=21, width=48, span=35, e_beam=7.98, e_composite=None, n_strands=18, strands_2in=14, strands_4in=4, strands_6in=0, stirrup_w_pairs=9, stirrup_zone_x=32.0, stirrup_y=12.0, stirrup_z=12.0, camber_d0=0.625, camber_d30=1.0, deflection=0.125, bearing_type='B1'), BoxBeamDesign(beam_type='non_composite', box='B21-48', depth=21, width=48, span=40, e_beam=7.98, e_composite=None, n_strands=18, strands_2in=14, strands_4in=4, strands_6in=0, stirrup_w_pairs=9, stirrup_zone_x=32.0, stirrup_y=12.0, stirrup_z=12.0, camber_d0=0.625, camber_d30=1.0, deflection=0.125, bearing_type='B1'), BoxBeamDesign(beam_type='non_composite', box='B21-48', depth=21, width=48, span=45, e_beam=7.82, e_composite=None, n_strands=22, strands_2in=14, strands_4in=8, strands_6in=0, stirrup_w_pairs=16, stirrup_zone_x=60.0, stirrup_y=12.0, stirrup_z=12.0, camber_d0=0.875, camber_d30=1.5, deflection=0.125, bearing_type='B1'), BoxBeamDesign(beam_type='non_composite', box='B21-48', depth=21, width=48, span=50, e_beam=7.87, e_composite=None, n_strands=22, strands_2in=16, strands_4in=6, strands_6in=0, stirrup_w_pairs=16, stirrup_zone_x=60.0, stirrup_y=12.0, stirrup_z=12.0, camber_d0=1.0, camber_d30=1.75, deflection=0.25, bearing_type='B2'), BoxBeamDesign(beam_type='non_composite', box='B27-48', depth=27, width=48, span=40, e_beam=10.49, e_composite=None, n_strands=14, strands_2in=10, strands_4in=4, strands_6in=0, stirrup_w_pairs=9, stirrup_zone_x=32.0, stirrup_y=12.0, stirrup_z=12.0, camber_d0=0.5, camber_d30=0.875, deflection=0.0, bearing_type='B1'), BoxBeamDesign(beam_type='non_composite', box='B27-48', depth=27, width=48, span=45, e_beam=10.88, e_composite=None, n_strands=16, strands_2in=12, strands_4in=4, strands_6in=0, stirrup_w_pairs=9, stirrup_zone_x=32.0, stirrup_y=12.0, stirrup_z=12.0, camber_d0=0.5, camber_d30=0.875, deflection=0.125, bearing_type='B1'), BoxBeamDesign(beam_type='non_composite', box='B27-48', depth=27, width=48, span=50, e_beam=10.71, e_composite=None, n_strands=18, strands_2in=12, strands_4in=6, strands_6in=0, stirrup_w_pairs=9, stirrup_zone_x=32.0, stirrup_y=12.0, stirrup_z=12.0, camber_d0=0.625, camber_d30=1.0, deflection=0.125, bearing_type='B1'), BoxBeamDesign(beam_type='non_composite', box='B27-48', depth=27, width=48, span=55, e_beam=10.78, e_composite=None, n_strands=20, strands_2in=14, strands_4in=6, strands_6in=0, stirrup_w_pairs=16, stirrup_zone_x=60.0, stirrup_y=12.0, stirrup_z=12.0, camber_d0=0.625, camber_d30=1.0, deflection=0.25, bearing_type='B2'), BoxBeamDesign(beam_type='non_composite', box='B27-48', depth=27, width=48, span=60, e_beam=10.71, e_composite=None, n_strands=24, strands_2in=16, strands_4in=8, strands_6in=0, stirrup_w_pairs=16, stirrup_zone_x=60.0, stirrup_y=12.0, stirrup_z=12.0, camber_d0=1.125, camber_d30=1.875, deflection=0.375, bearing_type='B2'), BoxBeamDesign(beam_type='non_composite', box='B27-48', depth=27, width=48, span=65, e_beam=10.45, e_composite=None, n_strands=30, strands_2in=16, strands_4in=14, strands_6in=0, stirrup_w_pairs=16, stirrup_zone_x=60.0, stirrup_y=12.0, stirrup_z=12.0, camber_d0=1.5, camber_d30=2.5, deflection=0.5, bearing_type='B2'), BoxBeamDesign(beam_type='non_composite', box='B33-48', depth=33, width=48, span=50, e_beam=13.73, e_composite=None, n_strands=14, strands_2in=10, strands_4in=4, strands_6in=0, stirrup_w_pairs=9, stirrup_zone_x=32.0, stirrup_y=12.0, stirrup_z=18.0, camber_d0=0.375, camber_d30=0.625, deflection=0.125, bearing_type='B1'), BoxBeamDesign(beam_type='non_composite', box='B33-48', depth=33, width=48, span=55, e_beam=13.55, e_composite=None, n_strands=16, strands_2in=10, strands_4in=6, strands_6in=0, stirrup_w_pairs=16, stirrup_zone_x=60.0, stirrup_y=12.0, stirrup_z=18.0, camber_d0=0.5, camber_d30=0.875, deflection=0.125, bearing_type='B2'), BoxBeamDesign(beam_type='non_composite', box='B33-48', depth=33, width=48, span=60, e_beam=13.39, e_composite=None, n_strands=22, strands_2in=12, strands_4in=10, strands_6in=0, stirrup_w_pairs=16, stirrup_zone_x=60.0, stirrup_y=12.0, stirrup_z=18.0, camber_d0=0.75, camber_d30=1.25, deflection=0.25, bearing_type='B2'), BoxBeamDesign(beam_type='non_composite', box='B33-48', depth=33, width=48, span=65, e_beam=13.57, e_composite=None, n_strands=22, strands_2in=14, strands_4in=8, strands_6in=0, stirrup_w_pairs=16, stirrup_zone_x=60.0, stirrup_y=12.0, stirrup_z=18.0, camber_d0=0.875, camber_d30=1.5, deflection=0.25, bearing_type='B2'), BoxBeamDesign(beam_type='non_composite', box='B33-48', depth=33, width=48, span=70, e_beam=13.53, e_composite=None, n_strands=26, strands_2in=16, strands_4in=10, strands_6in=0, stirrup_w_pairs=16, stirrup_zone_x=60.0, stirrup_y=12.0, stirrup_z=18.0, camber_d0=1.125, camber_d30=1.875, deflection=0.375, bearing_type='B2'), BoxBeamDesign(beam_type='non_composite', box='B33-48', depth=33, width=48, span=75, e_beam=13.37, e_composite=None, n_strands=30, strands_2in=16, strands_4in=14, strands_6in=0, stirrup_w_pairs=16, stirrup_zone_x=60.0, stirrup_y=12.0, stirrup_z=18.0, camber_d0=1.5, camber_d30=2.5, deflection=0.5, bearing_type='B2'), BoxBeamDesign(beam_type='non_composite', box='B33-48', depth=33, width=48, span=80, e_beam=13.24, e_composite=None, n_strands=34, strands_2in=16, strands_4in=18, strands_6in=0, stirrup_w_pairs=16, stirrup_zone_x=60.0, stirrup_y=12.0, stirrup_z=18.0, camber_d0=1.875, camber_d30=3.125, deflection=0.625, bearing_type='B2'), BoxBeamDesign(beam_type='non_composite', box='B42-48', depth=42, width=48, span=65, e_beam=18.15, e_composite=None, n_strands=18, strands_2in=12, strands_4in=6, strands_6in=0, stirrup_w_pairs=16, stirrup_zone_x=60.0, stirrup_y=12.0, stirrup_z=18.0, camber_d0=0.5, camber_d30=0.875, deflection=0.125, bearing_type='B2'), BoxBeamDesign(beam_type='non_composite', box='B42-48', depth=42, width=48, span=70, e_beam=18.22, e_composite=None, n_strands=20, strands_2in=14, strands_4in=6, strands_6in=0, stirrup_w_pairs=16, stirrup_zone_x=60.0, stirrup_y=12.0, stirrup_z=18.0, camber_d0=0.625, camber_d30=1.0, deflection=0.25, bearing_type='B2'), BoxBeamDesign(beam_type='non_composite', box='B42-48', depth=42, width=48, span=75, e_beam=18.09, e_composite=None, n_strands=22, strands_2in=14, strands_4in=8, strands_6in=0, stirrup_w_pairs=16, stirrup_zone_x=60.0, stirrup_y=12.0, stirrup_z=18.0, camber_d0=0.75, camber_d30=1.25, deflection=0.25, bearing_type='B2'), BoxBeamDesign(beam_type='non_composite', box='B42-48', depth=42, width=48, span=80, e_beam=17.9, e_composite=None, n_strands=26, strands_2in=14, strands_4in=12, strands_6in=0, stirrup_w_pairs=16, stirrup_zone_x=60.0, stirrup_y=12.0, stirrup_z=18.0, camber_d0=1.0, camber_d30=1.75, deflection=0.375, bearing_type='B2'), BoxBeamDesign(beam_type='non_composite', box='B42-48', depth=42, width=48, span=85, e_beam=17.89, e_composite=None, n_strands=30, strands_2in=16, strands_4in=14, strands_6in=0, stirrup_w_pairs=16, stirrup_zone_x=60.0, stirrup_y=12.0, stirrup_z=18.0, camber_d0=1.25, camber_d30=2.125, deflection=0.5, bearing_type='B2'), BoxBeamDesign(beam_type='non_composite', box='B42-48', depth=42, width=48, span=90, e_beam=17.76, e_composite=None, n_strands=34, strands_2in=16, strands_4in=18, strands_6in=0, stirrup_w_pairs=16, stirrup_zone_x=60.0, stirrup_y=12.0, stirrup_z=18.0, camber_d0=1.625, camber_d30=2.75, deflection=0.625, bearing_type='B2')]
All standard box-beam designs (PSBDD-1-25 sheets 1 & 3).
- civilpy.structural.odot.box_beam_design.BOX_BEAM_RATINGS: list[BoxBeamRating] = [BoxBeamRating(beam_type='composite', box='CB17-48', width_ft=24, n_beams=6, span=20, rating_factors={'inv': 2.3, 'op': 2.98, 'ev2': 3.78, 'ev3': 2.94, 's2f1': 5.57, 's3f1': 4.23, 's5c1': 4.44, 'spl60t': 4.18, 'spl65t': 3.91, 'su4': 3.92, 'su5': 3.7, 'su6': 3.7, 'su7': 3.7, 'type3': 4.44, 'type33': 5.4, 'type3s2': 4.76}), BoxBeamRating(beam_type='composite', box='CB17-48', width_ft=28, n_beams=7, span=20, rating_factors={'inv': 2.3, 'op': 2.98, 'ev2': 3.78, 'ev3': 2.95, 's2f1': 5.57, 's3f1': 4.23, 's5c1': 4.44, 'spl60t': 4.18, 'spl65t': 3.91, 'su4': 3.92, 'su5': 3.7, 'su6': 3.7, 'su7': 3.7, 'type3': 4.44, 'type33': 5.4, 'type3s2': 4.77}), BoxBeamRating(beam_type='composite', box='CB17-48', width_ft=24, n_beams=6, span=25, rating_factors={'inv': 2.06, 'op': 2.67, 'ev2': 3.14, 'ev3': 2.63, 's2f1': 4.95, 's3f1': 3.62, 's5c1': 3.75, 'spl60t': 3.59, 'spl65t': 3.33, 'su4': 3.38, 'su5': 3.21, 'su6': 3.24, 'su7': 3.24, 'type3': 3.94, 'type33': 4.91, 'type3s2': 4.07}), BoxBeamRating(beam_type='composite', box='CB17-48', width_ft=28, n_beams=7, span=25, rating_factors={'inv': 2.06, 'op': 2.67, 'ev2': 3.14, 'ev3': 2.63, 's2f1': 4.96, 's3f1': 3.62, 's5c1': 3.75, 'spl60t': 3.6, 'spl65t': 3.33, 'su4': 3.38, 'su5': 3.21, 'su6': 3.24, 'su7': 3.24, 'type3': 3.95, 'type33': 4.92, 'type3s2': 4.08}), BoxBeamRating(beam_type='composite', box='CB17-48', width_ft=24, n_beams=6, span=30, rating_factors={'inv': 1.94, 'op': 2.51, 'ev2': 2.84, 'ev3': 2.36, 's2f1': 4.67, 's3f1': 3.34, 's5c1': 3.43, 'spl60t': 3.31, 'spl65t': 3.0, 'su4': 3.06, 'su5': 2.91, 'su6': 2.96, 'su7': 2.96, 'type3': 3.5, 'type33': 4.26, 'type3s2': 3.75}), BoxBeamRating(beam_type='composite', box='CB17-48', width_ft=28, n_beams=7, span=30, rating_factors={'inv': 1.94, 'op': 2.51, 'ev2': 2.84, 'ev3': 2.36, 's2f1': 4.67, 's3f1': 3.34, 's5c1': 3.43, 'spl60t': 3.31, 'spl65t': 3.0, 'su4': 3.06, 'su5': 2.91, 'su6': 2.96, 'su7': 2.96, 'type3': 3.5, 'type33': 4.26, 'type3s2': 3.75}), BoxBeamRating(beam_type='composite', box='CB17-48', width_ft=24, n_beams=6, span=35, rating_factors={'inv': 1.56, 'op': 2.02, 'ev2': 2.38, 'ev3': 1.96, 's2f1': 4.08, 's3f1': 2.84, 's5c1': 2.9, 'spl60t': 2.81, 'spl65t': 2.5, 'su4': 2.55, 'su5': 2.36, 'su6': 2.36, 'su7': 2.36, 'type3': 2.87, 'type33': 3.42, 'type3s2': 3.2}), BoxBeamRating(beam_type='composite', box='CB17-48', width_ft=28, n_beams=7, span=35, rating_factors={'inv': 1.56, 'op': 2.02, 'ev2': 2.38, 'ev3': 1.96, 's2f1': 4.08, 's3f1': 2.85, 's5c1': 2.9, 'spl60t': 2.81, 'spl65t': 2.5, 'su4': 2.55, 'su5': 2.36, 'su6': 2.36, 'su7': 2.36, 'type3': 2.87, 'type33': 3.42, 'type3s2': 3.2}), BoxBeamRating(beam_type='composite', box='CB17-48', width_ft=24, n_beams=6, span=40, rating_factors={'inv': 1.65, 'op': 2.14, 'ev2': 2.53, 'ev3': 2.08, 's2f1': 4.35, 's3f1': 3.03, 's5c1': 3.09, 'spl60t': 2.97, 'spl65t': 2.64, 'su4': 2.71, 'su5': 2.51, 'su6': 2.5, 'su7': 2.54, 'type3': 3.05, 'type33': 3.63, 'type3s2': 3.4}), BoxBeamRating(beam_type='composite', box='CB17-48', width_ft=28, n_beams=7, span=40, rating_factors={'inv': 1.65, 'op': 2.14, 'ev2': 2.53, 'ev3': 2.08, 's2f1': 4.36, 's3f1': 3.03, 's5c1': 3.09, 'spl60t': 2.97, 'spl65t': 2.65, 'su4': 2.71, 'su5': 2.51, 'su6': 2.5, 'su7': 2.54, 'type3': 3.05, 'type33': 3.63, 'type3s2': 3.41}), BoxBeamRating(beam_type='composite', box='CB17-48', width_ft=24, n_beams=6, span=45, rating_factors={'inv': 1.51, 'op': 1.99, 'ev2': 2.42, 'ev3': 1.99, 's2f1': 4.23, 's3f1': 2.92, 's5c1': 2.97, 'spl60t': 2.72, 'spl65t': 2.42, 'su4': 2.6, 'su5': 2.38, 'su6': 2.33, 'su7': 2.32, 'type3': 2.9, 'type33': 3.4, 'type3s2': 3.18}), BoxBeamRating(beam_type='composite', box='CB17-48', width_ft=28, n_beams=7, span=45, rating_factors={'inv': 1.54, 'op': 2.0, 'ev2': 2.42, 'ev3': 1.99, 's2f1': 4.23, 's3f1': 2.92, 's5c1': 2.97, 'spl60t': 2.72, 'spl65t': 2.42, 'su4': 2.6, 'su5': 2.38, 'su6': 2.34, 'su7': 2.32, 'type3': 2.9, 'type33': 3.4, 'type3s2': 3.18}), BoxBeamRating(beam_type='composite', box='CB21-48', width_ft=24, n_beams=6, span=30, rating_factors={'inv': 1.94, 'op': 2.51, 'ev2': 2.84, 'ev3': 2.36, 's2f1': 4.67, 's3f1': 3.34, 's5c1': 3.43, 'spl60t': 3.31, 'spl65t': 3.0, 'su4': 3.06, 'su5': 2.91, 'su6': 2.96, 'su7': 2.96, 'type3': 3.5, 'type33': 4.26, 'type3s2': 3.75}), BoxBeamRating(beam_type='composite', box='CB21-48', width_ft=28, n_beams=7, span=30, rating_factors={'inv': 1.94, 'op': 2.51, 'ev2': 2.84, 'ev3': 2.36, 's2f1': 4.67, 's3f1': 3.34, 's5c1': 3.43, 'spl60t': 3.31, 'spl65t': 3.0, 'su4': 3.06, 'su5': 2.91, 'su6': 2.96, 'su7': 2.96, 'type3': 3.5, 'type33': 4.26, 'type3s2': 3.75}), BoxBeamRating(beam_type='composite', box='CB21-48', width_ft=24, n_beams=6, span=35, rating_factors={'inv': 2.07, 'op': 2.68, 'ev2': 3.15, 'ev3': 2.6, 's2f1': 5.41, 's3f1': 3.77, 's5c1': 3.85, 'spl60t': 3.72, 'spl65t': 3.32, 'su4': 3.38, 'su5': 3.13, 'su6': 3.13, 'su7': 3.13, 'type3': 3.8, 'type33': 4.53, 'type3s2': 4.24}), BoxBeamRating(beam_type='composite', box='CB21-48', width_ft=28, n_beams=7, span=35, rating_factors={'inv': 2.07, 'op': 2.68, 'ev2': 3.15, 'ev3': 2.6, 's2f1': 5.42, 's3f1': 3.77, 's5c1': 3.85, 'spl60t': 3.72, 'spl65t': 3.32, 'su4': 3.38, 'su5': 3.13, 'su6': 3.13, 'su7': 3.13, 'type3': 3.8, 'type33': 4.53, 'type3s2': 4.24}), BoxBeamRating(beam_type='composite', box='CB21-48', width_ft=24, n_beams=6, span=40, rating_factors={'inv': 1.69, 'op': 2.19, 'ev2': 2.67, 'ev3': 2.19, 's2f1': 4.65, 's3f1': 3.21, 's5c1': 3.26, 'spl60t': 3.14, 'spl65t': 2.79, 'su4': 2.86, 'su5': 2.62, 'su6': 2.57, 'su7': 2.55, 'type3': 3.19, 'type33': 3.74, 'type3s2': 3.5}), BoxBeamRating(beam_type='composite', box='CB21-48', width_ft=28, n_beams=7, span=40, rating_factors={'inv': 1.69, 'op': 2.19, 'ev2': 2.67, 'ev3': 2.19, 's2f1': 4.65, 's3f1': 3.21, 's5c1': 3.27, 'spl60t': 3.14, 'spl65t': 2.79, 'su4': 2.86, 'su5': 2.62, 'su6': 2.57, 'su7': 2.55, 'type3': 3.19, 'type33': 3.74, 'type3s2': 3.5}), BoxBeamRating(beam_type='composite', box='CB21-48', width_ft=24, n_beams=6, span=45, rating_factors={'inv': 1.57, 'op': 2.03, 'ev2': 2.53, 'ev3': 2.08, 's2f1': 4.47, 's3f1': 3.07, 's5c1': 3.11, 'spl60t': 2.85, 'spl65t': 2.37, 'su4': 2.71, 'su5': 2.47, 'su6': 2.39, 'su7': 2.34, 'type3': 3.02, 'type33': 3.35, 'type3s2': 3.15}), BoxBeamRating(beam_type='composite', box='CB21-48', width_ft=28, n_beams=7, span=45, rating_factors={'inv': 1.57, 'op': 2.03, 'ev2': 2.54, 'ev3': 2.08, 's2f1': 4.48, 's3f1': 3.07, 's5c1': 3.11, 'spl60t': 2.85, 'spl65t': 2.37, 'su4': 2.71, 'su5': 2.47, 'su6': 2.39, 'su7': 2.34, 'type3': 3.02, 'type33': 3.35, 'type3s2': 3.16}), BoxBeamRating(beam_type='composite', box='CB21-48', width_ft=24, n_beams=6, span=50, rating_factors={'inv': 1.44, 'op': 1.87, 'ev2': 2.4, 'ev3': 1.96, 's2f1': 4.27, 's3f1': 2.91, 's5c1': 2.95, 'spl60t': 2.68, 'spl65t': 2.07, 'su4': 2.56, 'su5': 2.32, 'su6': 2.22, 'su7': 2.14, 'type3': 2.84, 'type33': 2.95, 'type3s2': 2.79}), BoxBeamRating(beam_type='composite', box='CB21-48', width_ft=28, n_beams=7, span=50, rating_factors={'inv': 1.45, 'op': 1.88, 'ev2': 2.4, 'ev3': 1.96, 's2f1': 4.27, 's3f1': 2.91, 's5c1': 2.95, 'spl60t': 2.69, 'spl65t': 2.07, 'su4': 2.57, 'su5': 2.33, 'su6': 2.22, 'su7': 2.15, 'type3': 2.85, 'type33': 2.96, 'type3s2': 2.8}), BoxBeamRating(beam_type='composite', box='CB21-48', width_ft=24, n_beams=6, span=55, rating_factors={'inv': 1.31, 'op': 1.69, 'ev2': 2.22, 'ev3': 1.81, 's2f1': 3.98, 's3f1': 2.7, 's5c1': 2.67, 'spl60t': 2.45, 'spl65t': 1.8, 'su4': 2.37, 'su5': 2.14, 'su6': 2.03, 'su7': 1.94, 'type3': 2.62, 'type33': 2.6, 'type3s2': 2.45}), BoxBeamRating(beam_type='composite', box='CB21-48', width_ft=28, n_beams=7, span=55, rating_factors={'inv': 1.3, 'op': 1.69, 'ev2': 2.21, 'ev3': 1.8, 's2f1': 3.97, 's3f1': 2.69, 's5c1': 2.66, 'spl60t': 2.44, 'spl65t': 1.79, 'su4': 2.36, 'su5': 2.13, 'su6': 2.02, 'su7': 1.93, 'type3': 2.61, 'type33': 2.59, 'type3s2': 2.44}), BoxBeamRating(beam_type='composite', box='CB21-48', width_ft=24, n_beams=6, span=60, rating_factors={'inv': 1.32, 'op': 1.71, 'ev2': 2.26, 'ev3': 1.84, 's2f1': 4.07, 's3f1': 2.75, 's5c1': 2.63, 'spl60t': 2.4, 'spl65t': 1.77, 'su4': 2.41, 'su5': 2.17, 'su6': 2.05, 'su7': 1.95, 'type3': 2.66, 'type33': 2.59, 'type3s2': 2.45}), BoxBeamRating(beam_type='composite', box='CB21-48', width_ft=28, n_beams=7, span=60, rating_factors={'inv': 1.32, 'op': 1.71, 'ev2': 2.26, 'ev3': 1.84, 's2f1': 4.07, 's3f1': 2.76, 's5c1': 2.64, 'spl60t': 2.21, 'spl65t': 1.78, 'su4': 2.41, 'su5': 2.17, 'su6': 2.05, 'su7': 1.96, 'type3': 2.66, 'type33': 2.59, 'type3s2': 2.45}), BoxBeamRating(beam_type='composite', box='CB27-48', width_ft=24, n_beams=6, span=40, rating_factors={'inv': 2.2, 'op': 2.85, 'ev2': 3.47, 'ev3': 2.85, 's2f1': 6.05, 's3f1': 4.17, 's5c1': 4.24, 'spl60t': 4.08, 'spl65t': 3.63, 'su4': 3.71, 'su5': 3.41, 'su6': 3.34, 'su7': 3.32, 'type3': 4.15, 'type33': 4.86, 'type3s2': 4.55}), BoxBeamRating(beam_type='composite', box='CB27-48', width_ft=28, n_beams=7, span=40, rating_factors={'inv': 2.2, 'op': 2.85, 'ev2': 3.47, 'ev3': 2.85, 's2f1': 6.05, 's3f1': 4.18, 's5c1': 4.25, 'spl60t': 4.08, 'spl65t': 3.63, 'su4': 3.71, 'su5': 3.41, 'su6': 3.34, 'su7': 3.32, 'type3': 4.15, 'type33': 4.86, 'type3s2': 4.55}), BoxBeamRating(beam_type='composite', box='CB27-48', width_ft=24, n_beams=6, span=45, rating_factors={'inv': 1.79, 'op': 2.32, 'ev2': 2.9, 'ev3': 2.38, 's2f1': 5.12, 's3f1': 3.51, 's5c1': 3.56, 'spl60t': 3.26, 'spl65t': 2.71, 'su4': 3.11, 'su5': 2.83, 'su6': 2.74, 'su7': 2.68, 'type3': 3.45, 'type33': 3.83, 'type3s2': 3.61}), BoxBeamRating(beam_type='composite', box='CB27-48', width_ft=28, n_beams=7, span=45, rating_factors={'inv': 1.79, 'op': 2.33, 'ev2': 2.9, 'ev3': 2.38, 's2f1': 5.12, 's3f1': 3.51, 's5c1': 3.56, 'spl60t': 3.26, 'spl65t': 2.71, 'su4': 3.11, 'su5': 2.83, 'su6': 2.74, 'su7': 2.68, 'type3': 3.46, 'type33': 3.84, 'type3s2': 3.61}), BoxBeamRating(beam_type='composite', box='CB27-48', width_ft=24, n_beams=6, span=50, rating_factors={'inv': 1.67, 'op': 2.16, 'ev2': 2.76, 'ev3': 2.26, 's2f1': 4.92, 's3f1': 3.35, 's5c1': 3.39, 'spl60t': 3.09, 'spl65t': 2.4, 'su4': 2.95, 'su5': 2.67, 'su6': 2.56, 'su7': 2.48, 'type3': 3.27, 'type33': 3.42, 'type3s2': 3.23}), BoxBeamRating(beam_type='composite', box='CB27-48', width_ft=28, n_beams=7, span=50, rating_factors={'inv': 1.67, 'op': 2.16, 'ev2': 2.76, 'ev3': 2.26, 's2f1': 4.92, 's3f1': 3.35, 's5c1': 3.4, 'spl60t': 3.09, 'spl65t': 2.4, 'su4': 2.95, 'su5': 2.68, 'su6': 2.56, 'su7': 2.48, 'type3': 3.27, 'type33': 3.42, 'type3s2': 3.24}), BoxBeamRating(beam_type='composite', box='CB27-48', width_ft=24, n_beams=6, span=55, rating_factors={'inv': 1.52, 'op': 1.97, 'ev2': 2.57, 'ev3': 2.1, 's2f1': 4.63, 's3f1': 3.14, 's5c1': 3.11, 'spl60t': 2.84, 'spl65t': 2.09, 'su4': 2.75, 'su5': 2.48, 'su6': 2.35, 'su7': 2.25, 'type3': 3.04, 'type33': 3.02, 'type3s2': 2.85}), BoxBeamRating(beam_type='composite', box='CB27-48', width_ft=28, n_beams=7, span=55, rating_factors={'inv': 1.52, 'op': 1.97, 'ev2': 2.58, 'ev3': 2.1, 's2f1': 4.63, 's3f1': 3.14, 's5c1': 3.11, 'spl60t': 2.84, 'spl65t': 2.09, 'su4': 2.75, 'su5': 2.48, 'su6': 2.35, 'su7': 2.25, 'type3': 3.04, 'type33': 3.02, 'type3s2': 2.85}), BoxBeamRating(beam_type='composite', box='CB27-48', width_ft=24, n_beams=6, span=60, rating_factors={'inv': 1.64, 'op': 2.41, 'ev2': 3.12, 'ev3': 2.55, 's2f1': 5.58, 's3f1': 3.79, 's5c1': 3.74, 'spl60t': 3.14, 'spl65t': 2.52, 'su4': 3.33, 'su5': 3.01, 'su6': 2.87, 'su7': 2.75, 'type3': 3.69, 'type33': 3.69, 'type3s2': 3.49}), BoxBeamRating(beam_type='composite', box='CB27-48', width_ft=28, n_beams=7, span=60, rating_factors={'inv': 1.69, 'op': 2.41, 'ev2': 3.12, 'ev3': 2.55, 's2f1': 5.58, 's3f1': 3.79, 's5c1': 3.74, 'spl60t': 3.14, 'spl65t': 2.53, 'su4': 3.34, 'su5': 3.01, 'su6': 2.87, 'su7': 2.76, 'type3': 3.69, 'type33': 3.7, 'type3s2': 3.49}), BoxBeamRating(beam_type='composite', box='CB27-48', width_ft=24, n_beams=6, span=65, rating_factors={'inv': 1.55, 'op': 2.05, 'ev2': 2.77, 'ev3': 2.26, 's2f1': 5.02, 's3f1': 3.38, 's5c1': 3.03, 'spl60t': 2.54, 'spl65t': 2.07, 'su4': 2.96, 'su5': 2.65, 'su6': 2.49, 'su7': 2.35, 'type3': 3.25, 'type33': 3.0, 'type3s2': 2.89}), BoxBeamRating(beam_type='composite', box='CB27-48', width_ft=28, n_beams=7, span=65, rating_factors={'inv': 1.58, 'op': 2.05, 'ev2': 2.77, 'ev3': 2.26, 's2f1': 5.03, 's3f1': 3.39, 's5c1': 3.03, 'spl60t': 2.54, 'spl65t': 2.07, 'su4': 2.96, 'su5': 2.65, 'su6': 2.49, 'su7': 2.36, 'type3': 3.26, 'type33': 3.0, 'type3s2': 2.9}), BoxBeamRating(beam_type='composite', box='CB27-48', width_ft=24, n_beams=6, span=70, rating_factors={'inv': 1.3, 'op': 1.68, 'ev2': 2.31, 'ev3': 1.88, 's2f1': 4.21, 's3f1': 2.83, 's5c1': 2.43, 'spl60t': 2.04, 'spl65t': 1.68, 'su4': 2.47, 'su5': 2.21, 'su6': 2.07, 'su7': 1.95, 'type3': 2.72, 'type33': 2.41, 'type3s2': 2.36}), BoxBeamRating(beam_type='composite', box='CB27-48', width_ft=28, n_beams=7, span=70, rating_factors={'inv': 1.3, 'op': 1.68, 'ev2': 2.32, 'ev3': 1.89, 's2f1': 4.22, 's3f1': 2.84, 's5c1': 2.43, 'spl60t': 2.04, 'spl65t': 1.68, 'su4': 2.47, 'su5': 2.21, 'su6': 2.07, 'su7': 1.95, 'type3': 2.72, 'type33': 2.41, 'type3s2': 2.36}), BoxBeamRating(beam_type='composite', box='CB33-48', width_ft=24, n_beams=6, span=50, rating_factors={'inv': 1.88, 'op': 2.75, 'ev2': 3.51, 'ev3': 2.87, 's2f1': 6.08, 's3f1': 4.11, 's5c1': 4.22, 'spl60t': 3.71, 'spl65t': 3.05, 'su4': 3.66, 'su5': 3.38, 'su6': 3.04, 'su7': 2.81, 'type3': 4.16, 'type33': 4.35, 'type3s2': 4.11}), BoxBeamRating(beam_type='composite', box='CB33-48', width_ft=28, n_beams=7, span=50, rating_factors={'inv': 1.94, 'op': 2.85, 'ev2': 3.79, 'ev3': 2.96, 's2f1': 6.28, 's3f1': 4.25, 's5c1': 4.36, 'spl60t': 3.84, 'spl65t': 3.4, 'su4': 3.78, 'su5': 3.49, 'su6': 3.14, 'su7': 2.9, 'type3': 4.34, 'type33': 5.18, 'type3s2': 4.74}), BoxBeamRating(beam_type='composite', box='CB33-48', width_ft=24, n_beams=6, span=55, rating_factors={'inv': 1.64, 'op': 2.58, 'ev2': 3.4, 'ev3': 2.75, 's2f1': 5.91, 's3f1': 3.98, 's5c1': 4.07, 'spl60t': 3.61, 'spl65t': 2.79, 'su4': 3.52, 'su5': 3.23, 'su6': 2.9, 'su7': 2.68, 'type3': 4.01, 'type33': 4.02, 'type3s2': 3.8}), BoxBeamRating(beam_type='composite', box='CB33-48', width_ft=28, n_beams=7, span=55, rating_factors={'inv': 1.69, 'op': 2.61, 'ev2': 3.4, 'ev3': 2.78, 's2f1': 6.1, 's3f1': 4.11, 's5c1': 4.14, 'spl60t': 3.73, 'spl65t': 2.79, 'su4': 3.63, 'su5': 3.28, 'su6': 3.0, 'su7': 2.76, 'type3': 4.02, 'type33': 4.02, 'type3s2': 3.8}), BoxBeamRating(beam_type='composite', box='CB33-48', width_ft=24, n_beams=6, span=60, rating_factors={'inv': 1.48, 'op': 2.45, 'ev2': 3.26, 'ev3': 2.66, 's2f1': 5.82, 's3f1': 3.91, 's5c1': 3.75, 'spl60t': 3.15, 'spl65t': 2.54, 'su4': 3.44, 'su5': 3.13, 'su6': 2.82, 'su7': 2.6, 'type3': 3.84, 'type33': 3.71, 'type3s2': 3.51}), BoxBeamRating(beam_type='composite', box='CB33-48', width_ft=28, n_beams=7, span=60, rating_factors={'inv': 1.54, 'op': 2.45, 'ev2': 3.26, 'ev3': 2.66, 's2f1': 5.88, 's3f1': 3.98, 's5c1': 3.76, 'spl60t': 3.15, 'spl65t': 2.54, 'su4': 3.48, 'su5': 3.13, 'su6': 2.92, 'su7': 2.68, 'type3': 3.84, 'type33': 3.71, 'type3s2': 3.51}), BoxBeamRating(beam_type='composite', box='CB33-48', width_ft=24, n_beams=6, span=65, rating_factors={'inv': 1.58, 'op': 2.62, 'ev2': 3.7, 'ev3': 2.92, 's2f1': 6.38, 's3f1': 4.27, 's5c1': 4.3, 'spl60t': 3.61, 'spl65t': 2.94, 'su4': 3.76, 'su5': 3.42, 'su6': 3.06, 'su7': 2.81, 'type3': 4.24, 'type33': 4.26, 'type3s2': 4.03}), BoxBeamRating(beam_type='composite', box='CB33-48', width_ft=28, n_beams=7, span=65, rating_factors={'inv': 1.64, 'op': 2.71, 'ev2': 3.82, 'ev3': 3.02, 's2f1': 6.59, 's3f1': 4.41, 's5c1': 4.31, 'spl60t': 3.61, 'spl65t': 2.95, 'su4': 3.88, 'su5': 3.53, 'su6': 3.16, 'su7': 2.9, 'type3': 4.38, 'type33': 4.27, 'type3s2': 4.11}), BoxBeamRating(beam_type='composite', box='CB33-48', width_ft=24, n_beams=6, span=70, rating_factors={'inv': 1.62, 'op': 2.52, 'ev2': 3.46, 'ev3': 2.82, 's2f1': 6.3, 's3f1': 4.24, 's5c1': 3.64, 'spl60t': 3.05, 'spl65t': 2.51, 'su4': 3.69, 'su5': 3.31, 'su6': 3.09, 'su7': 2.91, 'type3': 4.06, 'type33': 3.61, 'type3s2': 3.53}), BoxBeamRating(beam_type='composite', box='CB33-48', width_ft=28, n_beams=7, span=70, rating_factors={'inv': 1.67, 'op': 2.52, 'ev2': 3.46, 'ev3': 2.82, 's2f1': 6.31, 's3f1': 4.24, 's5c1': 3.64, 'spl60t': 3.05, 'spl65t': 2.51, 'su4': 3.7, 'su5': 3.31, 'su6': 3.09, 'su7': 2.91, 'type3': 4.07, 'type33': 3.61, 'type3s2': 3.53}), BoxBeamRating(beam_type='composite', box='CB33-48', width_ft=24, n_beams=6, span=75, rating_factors={'inv': 1.56, 'op': 2.07, 'ev2': 2.9, 'ev3': 2.36, 's2f1': 5.3, 's3f1': 3.55, 's5c1': 2.94, 'spl60t': 2.45, 'spl65t': 2.05, 'su4': 3.09, 'su5': 2.76, 'su6': 2.57, 'su7': 2.41, 'type3': 3.39, 'type33': 2.92, 'type3s2': 2.9}), BoxBeamRating(beam_type='composite', box='CB33-48', width_ft=28, n_beams=7, span=75, rating_factors={'inv': 1.6, 'op': 2.07, 'ev2': 2.9, 'ev3': 2.36, 's2f1': 5.3, 's3f1': 3.56, 's5c1': 2.95, 'spl60t': 2.45, 'spl65t': 2.05, 'su4': 3.1, 'su5': 2.76, 'su6': 2.57, 'su7': 2.41, 'type3': 3.4, 'type33': 2.93, 'type3s2': 2.9}), BoxBeamRating(beam_type='composite', box='CB33-48', width_ft=24, n_beams=6, span=80, rating_factors={'inv': 1.45, 'op': 1.94, 'ev2': 2.75, 'ev3': 2.24, 's2f1': 5.05, 's3f1': 3.38, 's5c1': 2.72, 'spl60t': 2.24, 'spl65t': 1.9, 'su4': 2.94, 'su5': 2.62, 'su6': 2.43, 'su7': 2.27, 'type3': 3.22, 'type33': 2.7, 'type3s2': 2.7}), BoxBeamRating(beam_type='composite', box='CB33-48', width_ft=28, n_beams=7, span=80, rating_factors={'inv': 1.5, 'op': 1.94, 'ev2': 2.75, 'ev3': 2.24, 's2f1': 5.05, 's3f1': 3.38, 's5c1': 2.72, 'spl60t': 2.24, 'spl65t': 1.91, 'su4': 2.94, 'su5': 2.62, 'su6': 2.43, 'su7': 2.27, 'type3': 3.22, 'type33': 2.7, 'type3s2': 2.71}), BoxBeamRating(beam_type='composite', box='CB33-48', width_ft=24, n_beams=6, span=85, rating_factors={'inv': 1.4, 'op': 1.82, 'ev2': 2.62, 'ev3': 2.13, 's2f1': 4.81, 's3f1': 3.22, 's5c1': 2.53, 'spl60t': 2.06, 'spl65t': 1.78, 'su4': 2.79, 'su5': 2.48, 'su6': 2.3, 'su7': 2.15, 'type3': 3.06, 'type33': 2.51, 'type3s2': 2.53}), BoxBeamRating(beam_type='composite', box='CB33-48', width_ft=28, n_beams=7, span=85, rating_factors={'inv': 1.4, 'op': 1.82, 'ev2': 2.62, 'ev3': 2.13, 's2f1': 4.82, 's3f1': 3.22, 's5c1': 2.53, 'spl60t': 2.06, 'spl65t': 1.78, 'su4': 2.8, 'su5': 2.49, 'su6': 2.31, 'su7': 2.15, 'type3': 3.06, 'type33': 2.51, 'type3s2': 2.54}), BoxBeamRating(beam_type='composite', box='CB42-48', width_ft=24, n_beams=6, span=65, rating_factors={'inv': 1.45, 'op': 2.4, 'ev2': 3.39, 'ev3': 2.67, 's2f1': 5.84, 's3f1': 3.91, 's5c1': 3.98, 'spl60t': 3.3, 'spl65t': 2.73, 'su4': 3.43, 'su5': 3.12, 'su6': 2.8, 'su7': 2.57, 'type3': 3.88, 'type33': 3.93, 'type3s2': 3.69}), BoxBeamRating(beam_type='composite', box='CB42-48', width_ft=28, n_beams=7, span=65, rating_factors={'inv': 1.5, 'op': 2.48, 'ev2': 3.5, 'ev3': 2.76, 's2f1': 6.03, 's3f1': 4.04, 's5c1': 4.11, 'spl60t': 3.41, 'spl65t': 2.83, 'su4': 3.55, 'su5': 3.23, 'su6': 2.89, 'su7': 2.66, 'type3': 4.01, 'type33': 4.07, 'type3s2': 3.81}), BoxBeamRating(beam_type='composite', box='CB42-48', width_ft=24, n_beams=6, span=70, rating_factors={'inv': 1.62, 'op': 2.7, 'ev2': 3.87, 'ev3': 3.06, 's2f1': 6.74, 's3f1': 4.5, 's5c1': 4.41, 'spl60t': 3.81, 'spl65t': 3.01, 'su4': 3.95, 'su5': 3.58, 'su6': 3.2, 'su7': 2.93, 'type3': 4.44, 'type33': 4.32, 'type3s2': 4.09}), BoxBeamRating(beam_type='composite', box='CB42-48', width_ft=28, n_beams=7, span=70, rating_factors={'inv': 1.67, 'op': 2.79, 'ev2': 4.0, 'ev3': 3.16, 's2f1': 6.96, 's3f1': 4.65, 's5c1': 4.56, 'spl60t': 3.94, 'spl65t': 3.11, 'su4': 4.08, 'su5': 3.69, 'su6': 3.31, 'su7': 3.03, 'type3': 4.59, 'type33': 4.47, 'type3s2': 4.23}), BoxBeamRating(beam_type='composite', box='CB42-48', width_ft=24, n_beams=6, span=75, rating_factors={'inv': 1.47, 'op': 2.57, 'ev2': 3.76, 'ev3': 2.97, 's2f1': 6.58, 's3f1': 4.39, 's5c1': 4.13, 'spl60t': 3.57, 'spl65t': 2.82, 'su4': 3.84, 'su5': 3.47, 'su6': 3.11, 'su7': 2.84, 'type3': 4.31, 'type33': 4.02, 'type3s2': 3.87}), BoxBeamRating(beam_type='composite', box='CB42-48', width_ft=28, n_beams=7, span=75, rating_factors={'inv': 1.49, 'op': 2.66, 'ev2': 3.88, 'ev3': 3.07, 's2f1': 6.8, 's3f1': 4.54, 's5c1': 4.27, 'spl60t': 3.57, 'spl65t': 2.91, 'su4': 3.97, 'su5': 3.58, 'su6': 3.21, 'su7': 2.94, 'type3': 4.45, 'type33': 4.15, 'type3s2': 4.0}), BoxBeamRating(beam_type='composite', box='CB42-48', width_ft=24, n_beams=6, span=80, rating_factors={'inv': 1.66, 'op': 2.73, 'ev2': 3.87, 'ev3': 3.15, 's2f1': 7.11, 's3f1': 4.76, 's5c1': 3.83, 'spl60t': 3.15, 'spl65t': 2.68, 'su4': 4.14, 'su5': 3.69, 'su6': 3.42, 'su7': 3.2, 'type3': 4.54, 'type33': 3.81, 'type3s2': 3.81}), BoxBeamRating(beam_type='composite', box='CB42-48', width_ft=28, n_beams=7, span=80, rating_factors={'inv': 1.72, 'op': 2.73, 'ev2': 3.88, 'ev3': 3.16, 's2f1': 7.12, 's3f1': 4.77, 's5c1': 3.84, 'spl60t': 3.16, 'spl65t': 2.68, 'su4': 4.14, 'su5': 3.69, 'su6': 3.43, 'su7': 3.2, 'type3': 4.54, 'type33': 3.81, 'type3s2': 3.81}), BoxBeamRating(beam_type='composite', box='CB42-48', width_ft=24, n_beams=6, span=85, rating_factors={'inv': 1.7, 'op': 2.52, 'ev2': 3.63, 'ev3': 2.95, 's2f1': 6.67, 's3f1': 4.46, 's5c1': 3.5, 'spl60t': 2.86, 'spl65t': 2.46, 'su4': 3.87, 'su5': 3.44, 'su6': 3.19, 'su7': 2.97, 'type3': 4.24, 'type33': 3.48, 'type3s2': 3.51}), BoxBeamRating(beam_type='composite', box='CB42-48', width_ft=28, n_beams=7, span=85, rating_factors={'inv': 1.77, 'op': 2.52, 'ev2': 3.63, 'ev3': 2.95, 's2f1': 6.68, 's3f1': 4.46, 's5c1': 3.5, 'spl60t': 2.86, 'spl65t': 2.47, 'su4': 3.87, 'su5': 3.45, 'su6': 3.19, 'su7': 2.98, 'type3': 4.24, 'type33': 3.48, 'type3s2': 3.52}), BoxBeamRating(beam_type='composite', box='CB42-48', width_ft=24, n_beams=6, span=90, rating_factors={'inv': 1.51, 'op': 2.42, 'ev2': 3.54, 'ev3': 2.88, 's2f1': 6.53, 's3f1': 4.36, 's5c1': 3.35, 'spl60t': 2.71, 'spl65t': 2.36, 'su4': 3.78, 'su5': 3.36, 'su6': 3.1, 'su7': 2.88, 'type3': 4.13, 'type33': 3.33, 'type3s2': 3.39}), BoxBeamRating(beam_type='composite', box='CB42-48', width_ft=28, n_beams=7, span=90, rating_factors={'inv': 1.57, 'op': 2.43, 'ev2': 3.54, 'ev3': 2.88, 's2f1': 6.53, 's3f1': 4.36, 's5c1': 3.35, 'spl60t': 2.71, 'spl65t': 2.37, 'su4': 3.78, 'su5': 3.36, 'su6': 3.1, 'su7': 2.89, 'type3': 4.14, 'type33': 3.33, 'type3s2': 3.39}), BoxBeamRating(beam_type='composite', box='CB42-48', width_ft=24, n_beams=6, span=95, rating_factors={'inv': 1.5, 'op': 2.32, 'ev2': 3.44, 'ev3': 2.79, 's2f1': 6.35, 's3f1': 4.24, 's5c1': 3.2, 'spl60t': 2.57, 'spl65t': 2.27, 'su4': 3.67, 'su5': 3.26, 'su6': 3.0, 'su7': 2.79, 'type3': 4.01, 'type33': 3.18, 'type3s2': 3.25}), BoxBeamRating(beam_type='composite', box='CB42-48', width_ft=28, n_beams=7, span=95, rating_factors={'inv': 1.55, 'op': 2.33, 'ev2': 3.44, 'ev3': 2.8, 's2f1': 6.36, 's3f1': 4.24, 's5c1': 3.2, 'spl60t': 2.57, 'spl65t': 2.27, 'su4': 3.67, 'su5': 3.26, 'su6': 3.01, 'su7': 2.79, 'type3': 4.02, 'type33': 3.18, 'type3s2': 3.26}), BoxBeamRating(beam_type='composite', box='CB17-48', width_ft=32, n_beams=8, span=20, rating_factors={'inv': 2.3, 'op': 2.98, 'ev2': 3.78, 'ev3': 2.95, 's2f1': 5.57, 's3f1': 4.23, 's5c1': 4.45, 'spl60t': 4.18, 'spl65t': 3.91, 'su4': 3.92, 'su5': 3.7, 'su6': 3.7, 'su7': 3.7, 'type3': 4.45, 'type33': 5.4, 'type3s2': 4.77}), BoxBeamRating(beam_type='composite', box='CB17-48', width_ft=32, n_beams=8, span=25, rating_factors={'inv': 2.06, 'op': 2.67, 'ev2': 3.14, 'ev3': 2.63, 's2f1': 4.96, 's3f1': 3.62, 's5c1': 3.76, 'spl60t': 3.6, 'spl65t': 3.33, 'su4': 3.39, 'su5': 3.21, 'su6': 3.24, 'su7': 3.24, 'type3': 3.95, 'type33': 4.92, 'type3s2': 4.08}), BoxBeamRating(beam_type='composite', box='CB17-48', width_ft=32, n_beams=8, span=30, rating_factors={'inv': 1.94, 'op': 2.51, 'ev2': 2.84, 'ev3': 2.36, 's2f1': 4.67, 's3f1': 3.34, 's5c1': 3.43, 'spl60t': 3.31, 'spl65t': 3.0, 'su4': 3.06, 'su5': 2.91, 'su6': 2.96, 'su7': 2.96, 'type3': 3.5, 'type33': 4.26, 'type3s2': 3.75}), BoxBeamRating(beam_type='composite', box='CB17-48', width_ft=32, n_beams=8, span=35, rating_factors={'inv': 1.56, 'op': 2.02, 'ev2': 2.38, 'ev3': 1.96, 's2f1': 4.09, 's3f1': 2.85, 's5c1': 2.91, 'spl60t': 2.81, 'spl65t': 2.5, 'su4': 2.55, 'su5': 2.36, 'su6': 2.36, 'su7': 2.36, 'type3': 2.87, 'type33': 3.42, 'type3s2': 3.2}), BoxBeamRating(beam_type='composite', box='CB17-48', width_ft=32, n_beams=8, span=40, rating_factors={'inv': 1.65, 'op': 2.14, 'ev2': 2.53, 'ev3': 2.08, 's2f1': 4.36, 's3f1': 3.03, 's5c1': 3.09, 'spl60t': 2.97, 'spl65t': 2.65, 'su4': 2.72, 'su5': 2.51, 'su6': 2.5, 'su7': 2.54, 'type3': 3.05, 'type33': 3.63, 'type3s2': 3.41}), BoxBeamRating(beam_type='composite', box='CB17-48', width_ft=32, n_beams=8, span=45, rating_factors={'inv': 1.54, 'op': 2.0, 'ev2': 2.43, 'ev3': 1.99, 's2f1': 4.23, 's3f1': 2.92, 's5c1': 2.97, 'spl60t': 2.72, 'spl65t': 2.42, 'su4': 2.6, 'su5': 2.38, 'su6': 2.34, 'su7': 2.32, 'type3': 2.9, 'type33': 3.4, 'type3s2': 3.19}), BoxBeamRating(beam_type='composite', box='CB21-48', width_ft=32, n_beams=8, span=30, rating_factors={'inv': 1.94, 'op': 2.51, 'ev2': 2.84, 'ev3': 2.36, 's2f1': 4.67, 's3f1': 3.34, 's5c1': 3.43, 'spl60t': 3.31, 'spl65t': 3.0, 'su4': 3.06, 'su5': 2.91, 'su6': 2.96, 'su7': 2.96, 'type3': 3.5, 'type33': 4.26, 'type3s2': 3.75}), BoxBeamRating(beam_type='composite', box='CB21-48', width_ft=32, n_beams=8, span=35, rating_factors={'inv': 2.07, 'op': 2.68, 'ev2': 3.15, 'ev3': 2.6, 's2f1': 5.42, 's3f1': 3.77, 's5c1': 3.85, 'spl60t': 3.72, 'spl65t': 3.32, 'su4': 3.38, 'su5': 3.13, 'su6': 3.13, 'su7': 3.13, 'type3': 3.81, 'type33': 4.53, 'type3s2': 4.24}), BoxBeamRating(beam_type='composite', box='CB21-48', width_ft=32, n_beams=8, span=40, rating_factors={'inv': 1.69, 'op': 2.2, 'ev2': 2.67, 'ev3': 2.19, 's2f1': 4.66, 's3f1': 3.21, 's5c1': 3.27, 'spl60t': 3.14, 'spl65t': 2.79, 'su4': 2.86, 'su5': 2.62, 'su6': 2.57, 'su7': 2.56, 'type3': 3.19, 'type33': 3.74, 'type3s2': 3.5}), BoxBeamRating(beam_type='composite', box='CB21-48', width_ft=32, n_beams=8, span=45, rating_factors={'inv': 1.57, 'op': 2.03, 'ev2': 2.54, 'ev3': 2.08, 's2f1': 4.48, 's3f1': 3.07, 's5c1': 3.12, 'spl60t': 2.85, 'spl65t': 2.37, 'su4': 2.72, 'su5': 2.47, 'su6': 2.39, 'su7': 2.34, 'type3': 3.02, 'type33': 3.35, 'type3s2': 3.16}), BoxBeamRating(beam_type='composite', box='CB21-48', width_ft=32, n_beams=8, span=50, rating_factors={'inv': 1.45, 'op': 1.88, 'ev2': 2.4, 'ev3': 1.96, 's2f1': 4.28, 's3f1': 2.92, 's5c1': 2.95, 'spl60t': 2.69, 'spl65t': 2.08, 'su4': 2.57, 'su5': 2.33, 'su6': 2.23, 'su7': 2.15, 'type3': 2.85, 'type33': 2.96, 'type3s2': 2.8}), BoxBeamRating(beam_type='composite', box='CB21-48', width_ft=32, n_beams=8, span=55, rating_factors={'inv': 1.3, 'op': 1.69, 'ev2': 2.21, 'ev3': 1.8, 's2f1': 3.97, 's3f1': 2.69, 's5c1': 2.66, 'spl60t': 2.44, 'spl65t': 1.79, 'su4': 2.36, 'su5': 2.13, 'su6': 2.02, 'su7': 1.93, 'type3': 2.61, 'type33': 2.59, 'type3s2': 2.45}), BoxBeamRating(beam_type='composite', box='CB21-48', width_ft=32, n_beams=8, span=60, rating_factors={'inv': 1.32, 'op': 1.71, 'ev2': 2.26, 'ev3': 1.85, 's2f1': 4.08, 's3f1': 2.76, 's5c1': 2.64, 'spl60t': 2.22, 'spl65t': 1.78, 'su4': 2.42, 'su5': 2.17, 'su6': 2.05, 'su7': 1.96, 'type3': 2.67, 'type33': 2.6, 'type3s2': 2.45}), BoxBeamRating(beam_type='composite', box='CB27-48', width_ft=32, n_beams=8, span=40, rating_factors={'inv': 2.2, 'op': 2.85, 'ev2': 3.47, 'ev3': 2.85, 's2f1': 6.05, 's3f1': 4.18, 's5c1': 4.25, 'spl60t': 4.08, 'spl65t': 3.63, 'su4': 3.72, 'su5': 3.41, 'su6': 3.34, 'su7': 3.32, 'type3': 4.15, 'type33': 4.86, 'type3s2': 4.56}), BoxBeamRating(beam_type='composite', box='CB27-48', width_ft=32, n_beams=8, span=45, rating_factors={'inv': 1.8, 'op': 2.33, 'ev2': 2.9, 'ev3': 2.38, 's2f1': 5.13, 's3f1': 3.51, 's5c1': 3.57, 'spl60t': 3.27, 'spl65t': 2.71, 'su4': 3.11, 'su5': 2.83, 'su6': 2.74, 'su7': 2.68, 'type3': 3.46, 'type33': 3.84, 'type3s2': 3.62}), BoxBeamRating(beam_type='composite', box='CB27-48', width_ft=32, n_beams=8, span=50, rating_factors={'inv': 1.67, 'op': 2.16, 'ev2': 2.76, 'ev3': 2.26, 's2f1': 4.92, 's3f1': 3.35, 's5c1': 3.4, 'spl60t': 3.1, 'spl65t': 2.4, 'su4': 2.96, 'su5': 2.68, 'su6': 2.56, 'su7': 2.48, 'type3': 3.28, 'type33': 3.43, 'type3s2': 3.24}), BoxBeamRating(beam_type='composite', box='CB27-48', width_ft=32, n_beams=8, span=55, rating_factors={'inv': 1.52, 'op': 1.97, 'ev2': 2.58, 'ev3': 2.11, 's2f1': 4.63, 's3f1': 3.14, 's5c1': 3.11, 'spl60t': 2.85, 'spl65t': 2.09, 'su4': 2.76, 'su5': 2.48, 'su6': 2.36, 'su7': 2.25, 'type3': 3.04, 'type33': 3.02, 'type3s2': 2.86}), BoxBeamRating(beam_type='composite', box='CB27-48', width_ft=32, n_beams=8, span=60, rating_factors={'inv': 1.74, 'op': 2.41, 'ev2': 3.12, 'ev3': 2.55, 's2f1': 5.59, 's3f1': 3.8, 's5c1': 3.74, 'spl60t': 3.14, 'spl65t': 2.53, 'su4': 3.34, 'su5': 3.01, 'su6': 2.87, 'su7': 2.76, 'type3': 3.69, 'type33': 3.7, 'type3s2': 3.5}), BoxBeamRating(beam_type='composite', box='CB27-48', width_ft=32, n_beams=8, span=65, rating_factors={'inv': 1.58, 'op': 2.05, 'ev2': 2.77, 'ev3': 2.26, 's2f1': 5.03, 's3f1': 3.39, 's5c1': 3.04, 'spl60t': 2.55, 'spl65t': 2.08, 'su4': 2.96, 'su5': 2.65, 'su6': 2.49, 'su7': 2.36, 'type3': 3.26, 'type33': 3.01, 'type3s2': 2.9}), BoxBeamRating(beam_type='composite', box='CB27-48', width_ft=32, n_beams=8, span=70, rating_factors={'inv': 1.3, 'op': 1.69, 'ev2': 2.32, 'ev3': 1.89, 's2f1': 4.22, 's3f1': 2.84, 's5c1': 2.44, 'spl60t': 2.04, 'spl65t': 1.68, 'su4': 2.48, 'su5': 2.21, 'su6': 2.07, 'su7': 1.95, 'type3': 2.72, 'type33': 2.42, 'type3s2': 2.37}), BoxBeamRating(beam_type='composite', box='CB33-48', width_ft=32, n_beams=8, span=50, rating_factors={'inv': 2.0, 'op': 2.93, 'ev2': 3.9, 'ev3': 3.05, 's2f1': 6.46, 's3f1': 4.37, 's5c1': 4.48, 'spl60t': 3.94, 'spl65t': 3.5, 'su4': 3.88, 'su5': 3.59, 'su6': 3.23, 'su7': 2.99, 'type3': 4.46, 'type33': 5.33, 'type3s2': 4.88}), BoxBeamRating(beam_type='composite', box='CB33-48', width_ft=32, n_beams=8, span=55, rating_factors={'inv': 1.74, 'op': 2.61, 'ev2': 3.4, 'ev3': 2.78, 's2f1': 6.1, 's3f1': 4.14, 's5c1': 4.14, 'spl60t': 3.78, 'spl65t': 2.79, 'su4': 3.64, 'su5': 3.28, 'su6': 3.08, 'su7': 2.84, 'type3': 4.02, 'type33': 4.02, 'type3s2': 3.8}), BoxBeamRating(beam_type='composite', box='CB33-48', width_ft=32, n_beams=8, span=60, rating_factors={'inv': 1.58, 'op': 2.45, 'ev2': 3.26, 'ev3': 2.66, 's2f1': 5.89, 's3f1': 3.98, 's5c1': 3.76, 'spl60t': 3.15, 'spl65t': 2.54, 'su4': 3.49, 'su5': 3.13, 'su6': 2.96, 'su7': 2.76, 'type3': 3.84, 'type33': 3.72, 'type3s2': 3.51}), BoxBeamRating(beam_type='composite', box='CB33-48', width_ft=32, n_beams=8, span=65, rating_factors={'inv': 1.69, 'op': 2.79, 'ev2': 3.84, 'ev3': 3.1, 's2f1': 6.78, 's3f1': 4.54, 's5c1': 4.31, 'spl60t': 3.62, 'spl65t': 2.95, 'su4': 3.99, 'su5': 3.63, 'su6': 3.25, 'su7': 2.99, 'type3': 4.51, 'type33': 4.27, 'type3s2': 4.11}), BoxBeamRating(beam_type='composite', box='CB33-48', width_ft=32, n_beams=8, span=70, rating_factors={'inv': 1.72, 'op': 2.52, 'ev2': 3.46, 'ev3': 2.82, 's2f1': 6.31, 's3f1': 4.24, 's5c1': 3.64, 'spl60t': 3.05, 'spl65t': 2.51, 'su4': 3.7, 'su5': 3.31, 'su6': 3.09, 'su7': 2.91, 'type3': 4.07, 'type33': 3.61, 'type3s2': 3.54}), BoxBeamRating(beam_type='composite', box='CB33-48', width_ft=32, n_beams=8, span=75, rating_factors={'inv': 1.6, 'op': 2.08, 'ev2': 2.9, 'ev3': 2.36, 's2f1': 5.31, 's3f1': 3.56, 's5c1': 2.95, 'spl60t': 2.45, 'spl65t': 2.05, 'su4': 3.1, 'su5': 2.77, 'su6': 2.58, 'su7': 2.42, 'type3': 3.4, 'type33': 2.93, 'type3s2': 2.9}), BoxBeamRating(beam_type='composite', box='CB33-48', width_ft=32, n_beams=8, span=80, rating_factors={'inv': 1.5, 'op': 1.94, 'ev2': 2.76, 'ev3': 2.24, 's2f1': 5.06, 's3f1': 3.39, 's5c1': 2.73, 'spl60t': 2.24, 'spl65t': 1.91, 'su4': 2.94, 'su5': 2.62, 'su6': 2.44, 'su7': 2.28, 'type3': 3.23, 'type33': 2.71, 'type3s2': 2.71}), BoxBeamRating(beam_type='composite', box='CB33-48', width_ft=32, n_beams=8, span=85, rating_factors={'inv': 1.41, 'op': 1.82, 'ev2': 2.62, 'ev3': 2.13, 's2f1': 4.82, 's3f1': 3.23, 's5c1': 2.53, 'spl60t': 2.06, 'spl65t': 1.78, 'su4': 2.8, 'su5': 2.49, 'su6': 2.31, 'su7': 2.15, 'type3': 3.07, 'type33': 2.52, 'type3s2': 2.54}), BoxBeamRating(beam_type='composite', box='CB42-48', width_ft=32, n_beams=8, span=65, rating_factors={'inv': 1.55, 'op': 2.55, 'ev2': 3.6, 'ev3': 2.84, 's2f1': 6.2, 's3f1': 4.15, 's5c1': 4.23, 'spl60t': 3.51, 'spl65t': 2.91, 'su4': 3.65, 'su5': 3.32, 'su6': 2.98, 'su7': 2.73, 'type3': 4.12, 'type33': 4.18, 'type3s2': 3.92}), BoxBeamRating(beam_type='composite', box='CB42-48', width_ft=32, n_beams=8, span=70, rating_factors={'inv': 1.72, 'op': 2.87, 'ev2': 4.12, 'ev3': 3.25, 's2f1': 7.16, 's3f1': 4.78, 's5c1': 4.69, 'spl60t': 3.94, 'spl65t': 3.2, 'su4': 4.19, 'su5': 3.8, 'su6': 3.41, 'su7': 3.12, 'type3': 4.72, 'type33': 4.6, 'type3s2': 4.35}), BoxBeamRating(beam_type='composite', box='CB42-48', width_ft=32, n_beams=8, span=75, rating_factors={'inv': 1.53, 'op': 2.74, 'ev2': 3.99, 'ev3': 3.16, 's2f1': 7.0, 's3f1': 4.67, 's5c1': 4.29, 'spl60t': 3.58, 'spl65t': 2.97, 'su4': 4.08, 'su5': 3.69, 'su6': 3.3, 'su7': 3.02, 'type3': 4.58, 'type33': 4.26, 'type3s2': 4.11}), BoxBeamRating(beam_type='composite', box='CB42-48', width_ft=32, n_beams=8, span=80, rating_factors={'inv': 1.77, 'op': 2.74, 'ev2': 3.88, 'ev3': 3.16, 's2f1': 7.12, 's3f1': 4.77, 's5c1': 3.84, 'spl60t': 3.16, 'spl65t': 2.69, 'su4': 4.14, 'su5': 3.69, 'su6': 3.43, 'su7': 3.21, 'type3': 4.54, 'type33': 3.81, 'type3s2': 3.82}), BoxBeamRating(beam_type='composite', box='CB42-48', width_ft=32, n_beams=8, span=85, rating_factors={'inv': 1.82, 'op': 2.52, 'ev2': 3.63, 'ev3': 2.95, 's2f1': 6.68, 's3f1': 4.47, 's5c1': 3.51, 'spl60t': 2.86, 'spl65t': 2.47, 'su4': 3.88, 'su5': 3.45, 'su6': 3.2, 'su7': 2.98, 'type3': 4.25, 'type33': 3.49, 'type3s2': 3.52}), BoxBeamRating(beam_type='composite', box='CB42-48', width_ft=32, n_beams=8, span=90, rating_factors={'inv': 1.62, 'op': 2.43, 'ev2': 3.54, 'ev3': 2.88, 's2f1': 6.54, 's3f1': 4.36, 's5c1': 3.35, 'spl60t': 2.71, 'spl65t': 2.37, 'su4': 3.78, 'su5': 3.36, 'su6': 3.11, 'su7': 2.89, 'type3': 4.14, 'type33': 3.33, 'type3s2': 3.39}), BoxBeamRating(beam_type='composite', box='CB42-48', width_ft=32, n_beams=8, span=95, rating_factors={'inv': 1.6, 'op': 2.33, 'ev2': 3.44, 'ev3': 2.8, 's2f1': 6.37, 's3f1': 4.25, 's5c1': 3.2, 'spl60t': 2.57, 'spl65t': 2.27, 'su4': 3.68, 'su5': 3.26, 'su6': 3.01, 'su7': 2.79, 'type3': 4.02, 'type33': 3.19, 'type3s2': 3.26}), BoxBeamRating(beam_type='non_composite', box='B17-48', width_ft=24, n_beams=6, span=20, rating_factors={'inv': 1.94, 'op': 2.52, 'ev2': 3.19, 'ev3': 2.49, 's2f1': 4.7, 's3f1': 3.57, 's5c1': 3.75, 'spl60t': 4.02, 'spl65t': 3.75, 'su4': 3.31, 'su5': 3.12, 'su6': 3.12, 'su7': 3.12, 'type3': 3.75, 'type33': 4.56, 'type3s2': 4.02}), BoxBeamRating(beam_type='non_composite', box='B17-48', width_ft=28, n_beams=7, span=20, rating_factors={'inv': 1.94, 'op': 2.52, 'ev2': 3.19, 'ev3': 2.49, 's2f1': 4.7, 's3f1': 3.57, 's5c1': 3.75, 'spl60t': 4.02, 'spl65t': 3.75, 'su4': 3.31, 'su5': 3.12, 'su6': 3.12, 'su7': 3.12, 'type3': 3.75, 'type33': 4.56, 'type3s2': 4.02}), BoxBeamRating(beam_type='non_composite', box='B17-48', width_ft=24, n_beams=6, span=25, rating_factors={'inv': 1.79, 'op': 2.31, 'ev2': 2.72, 'ev3': 2.28, 's2f1': 4.29, 's3f1': 3.14, 's5c1': 3.25, 'spl60t': 3.58, 'spl65t': 3.31, 'su4': 2.93, 'su5': 2.78, 'su6': 2.81, 'su7': 2.81, 'type3': 3.42, 'type33': 4.26, 'type3s2': 3.53}), BoxBeamRating(beam_type='non_composite', box='B17-48', width_ft=28, n_beams=7, span=25, rating_factors={'inv': 1.79, 'op': 2.32, 'ev2': 2.72, 'ev3': 2.28, 's2f1': 4.29, 's3f1': 3.14, 's5c1': 3.25, 'spl60t': 3.58, 'spl65t': 3.32, 'su4': 2.93, 'su5': 2.78, 'su6': 2.81, 'su7': 2.81, 'type3': 3.42, 'type33': 4.26, 'type3s2': 3.53}), BoxBeamRating(beam_type='non_composite', box='B17-48', width_ft=24, n_beams=6, span=30, rating_factors={'inv': 1.54, 'op': 1.99, 'ev2': 2.25, 'ev3': 1.87, 's2f1': 3.71, 's3f1': 2.65, 's5c1': 2.73, 'spl60t': 3.05, 'spl65t': 2.76, 'su4': 2.43, 'su5': 2.31, 'su6': 2.35, 'su7': 2.35, 'type3': 2.78, 'type33': 3.38, 'type3s2': 2.98}), BoxBeamRating(beam_type='non_composite', box='B17-48', width_ft=28, n_beams=7, span=30, rating_factors={'inv': 1.54, 'op': 2.0, 'ev2': 2.26, 'ev3': 1.87, 's2f1': 3.71, 's3f1': 2.65, 's5c1': 2.73, 'spl60t': 3.05, 'spl65t': 2.76, 'su4': 2.43, 'su5': 2.31, 'su6': 2.35, 'su7': 2.35, 'type3': 2.78, 'type33': 3.38, 'type3s2': 2.98}), BoxBeamRating(beam_type='non_composite', box='B17-48', width_ft=24, n_beams=6, span=35, rating_factors={'inv': 1.43, 'op': 1.85, 'ev2': 2.11, 'ev3': 1.74, 's2f1': 3.57, 's3f1': 2.51, 's5c1': 2.57, 'spl60t': 2.9, 'spl65t': 2.59, 'su4': 2.27, 'su5': 2.12, 'su6': 2.16, 'su7': 2.17, 'type3': 2.57, 'type33': 3.08, 'type3s2': 2.82}), BoxBeamRating(beam_type='non_composite', box='B17-48', width_ft=28, n_beams=7, span=35, rating_factors={'inv': 1.41, 'op': 1.83, 'ev2': 2.09, 'ev3': 1.72, 's2f1': 3.53, 's3f1': 2.48, 's5c1': 2.54, 'spl60t': 2.87, 'spl65t': 2.56, 'su4': 2.24, 'su5': 2.1, 'su6': 2.14, 'su7': 2.14, 'type3': 2.54, 'type33': 3.05, 'type3s2': 2.79}), BoxBeamRating(beam_type='non_composite', box='B21-48', width_ft=24, n_beams=6, span=30, rating_factors={'inv': 1.94, 'op': 2.51, 'ev2': 2.84, 'ev3': 2.36, 's2f1': 4.67, 's3f1': 3.34, 's5c1': 3.43, 'spl60t': 3.84, 'spl65t': 3.48, 'su4': 3.06, 'su5': 2.91, 'su6': 2.96, 'su7': 2.96, 'type3': 3.5, 'type33': 4.26, 'type3s2': 3.75}), BoxBeamRating(beam_type='non_composite', box='B21-48', width_ft=28, n_beams=7, span=30, rating_factors={'inv': 1.94, 'op': 2.51, 'ev2': 2.84, 'ev3': 2.36, 's2f1': 4.68, 's3f1': 3.34, 's5c1': 3.43, 'spl60t': 3.85, 'spl65t': 3.48, 'su4': 3.06, 'su5': 2.91, 'su6': 2.96, 'su7': 2.96, 'type3': 3.5, 'type33': 4.26, 'type3s2': 3.76}), BoxBeamRating(beam_type='non_composite', box='B21-48', width_ft=24, n_beams=6, span=35, rating_factors={'inv': 1.5, 'op': 1.94, 'ev2': 2.29, 'ev3': 1.89, 's2f1': 3.93, 's3f1': 2.74, 's5c1': 2.79, 'spl60t': 3.16, 'spl65t': 2.82, 'su4': 2.45, 'su5': 2.27, 'su6': 2.27, 'su7': 2.27, 'type3': 2.76, 'type33': 3.29, 'type3s2': 3.08}), BoxBeamRating(beam_type='non_composite', box='B21-48', width_ft=28, n_beams=7, span=35, rating_factors={'inv': 1.5, 'op': 1.95, 'ev2': 2.29, 'ev3': 1.89, 's2f1': 3.93, 's3f1': 2.74, 's5c1': 2.8, 'spl60t': 3.16, 'spl65t': 2.82, 'su4': 2.46, 'su5': 2.27, 'su6': 2.27, 'su7': 2.27, 'type3': 2.76, 'type33': 3.29, 'type3s2': 3.08}), BoxBeamRating(beam_type='non_composite', box='B21-48', width_ft=24, n_beams=6, span=40, rating_factors={'inv': 1.29, 'op': 1.67, 'ev2': 2.03, 'ev3': 1.66, 's2f1': 3.53, 's3f1': 2.44, 's5c1': 2.48, 'spl60t': 2.81, 'spl65t': 2.5, 'su4': 2.17, 'su5': 1.99, 'su6': 1.95, 'su7': 1.94, 'type3': 2.43, 'type33': 2.84, 'type3s2': 2.66}), BoxBeamRating(beam_type='non_composite', box='B21-48', width_ft=28, n_beams=7, span=40, rating_factors={'inv': 1.29, 'op': 1.67, 'ev2': 2.03, 'ev3': 1.67, 's2f1': 3.54, 's3f1': 2.44, 's5c1': 2.48, 'spl60t': 2.81, 'spl65t': 2.5, 'su4': 2.17, 'su5': 1.99, 'su6': 1.95, 'su7': 1.94, 'type3': 2.43, 'type33': 2.84, 'type3s2': 2.66}), BoxBeamRating(beam_type='non_composite', box='B21-48', width_ft=24, n_beams=6, span=45, rating_factors={'inv': 1.44, 'op': 1.86, 'ev2': 2.26, 'ev3': 1.86, 's2f1': 3.95, 's3f1': 2.72, 's5c1': 2.77, 'spl60t': 3.0, 'spl65t': 2.67, 'su4': 2.42, 'su5': 2.22, 'su6': 2.18, 'su7': 2.17, 'type3': 2.71, 'type33': 3.17, 'type3s2': 2.97}), BoxBeamRating(beam_type='non_composite', box='B21-48', width_ft=28, n_beams=7, span=45, rating_factors={'inv': 1.44, 'op': 1.86, 'ev2': 2.26, 'ev3': 1.86, 's2f1': 3.95, 's3f1': 2.72, 's5c1': 2.77, 'spl60t': 3.0, 'spl65t': 2.67, 'su4': 2.42, 'su5': 2.22, 'su6': 2.18, 'su7': 2.17, 'type3': 2.71, 'type33': 3.17, 'type3s2': 2.97}), BoxBeamRating(beam_type='non_composite', box='B21-48', width_ft=24, n_beams=6, span=50, rating_factors={'inv': 1.25, 'op': 1.75, 'ev2': 2.18, 'ev3': 1.79, 's2f1': 3.85, 's3f1': 2.64, 's5c1': 2.68, 'spl60t': 2.58, 'spl65t': 2.29, 'su4': 2.34, 'su5': 2.13, 'su6': 2.06, 'su7': 1.96, 'type3': 2.6, 'type33': 2.91, 'type3s2': 2.73}), BoxBeamRating(beam_type='non_composite', box='B21-48', width_ft=28, n_beams=7, span=50, rating_factors={'inv': 1.3, 'op': 1.75, 'ev2': 2.18, 'ev3': 1.79, 's2f1': 3.85, 's3f1': 2.64, 's5c1': 2.68, 'spl60t': 2.67, 'spl65t': 2.37, 'su4': 2.34, 'su5': 2.13, 'su6': 2.06, 'su7': 2.02, 'type3': 2.6, 'type33': 2.91, 'type3s2': 2.73}), BoxBeamRating(beam_type='non_composite', box='B27-48', width_ft=24, n_beams=6, span=40, rating_factors={'inv': 1.89, 'op': 2.45, 'ev2': 2.98, 'ev3': 2.45, 's2f1': 5.2, 's3f1': 3.59, 's5c1': 3.65, 'spl60t': 3.46, 'spl65t': 3.12, 'su4': 3.19, 'su5': 2.93, 'su6': 2.86, 'su7': 2.68, 'type3': 3.57, 'type33': 4.18, 'type3s2': 3.91}), BoxBeamRating(beam_type='non_composite', box='B27-48', width_ft=28, n_beams=7, span=40, rating_factors={'inv': 1.89, 'op': 2.45, 'ev2': 2.98, 'ev3': 2.45, 's2f1': 5.2, 's3f1': 3.59, 's5c1': 3.65, 'spl60t': 3.51, 'spl65t': 3.12, 'su4': 3.2, 'su5': 2.93, 'su6': 2.87, 'su7': 2.77, 'type3': 3.57, 'type33': 4.18, 'type3s2': 3.92}), BoxBeamRating(beam_type='non_composite', box='B27-48', width_ft=24, n_beams=6, span=45, rating_factors={'inv': 1.76, 'op': 2.28, 'ev2': 2.85, 'ev3': 2.34, 's2f1': 5.03, 's3f1': 3.45, 's5c1': 3.5, 'spl60t': 3.2, 'spl65t': 2.66, 'su4': 3.05, 'su5': 2.78, 'su6': 2.67, 'su7': 2.49, 'type3': 3.4, 'type33': 3.77, 'type3s2': 3.55}), BoxBeamRating(beam_type='non_composite', box='B27-48', width_ft=28, n_beams=7, span=45, rating_factors={'inv': 1.76, 'op': 2.29, 'ev2': 2.85, 'ev3': 2.34, 's2f1': 5.04, 's3f1': 3.45, 's5c1': 3.5, 'spl60t': 3.21, 'spl65t': 2.67, 'su4': 3.05, 'su5': 2.78, 'su6': 2.69, 'su7': 2.57, 'type3': 3.4, 'type33': 3.77, 'type3s2': 3.55}), BoxBeamRating(beam_type='non_composite', box='B27-48', width_ft=24, n_beams=6, span=50, rating_factors={'inv': 1.55, 'op': 2.08, 'ev2': 2.65, 'ev3': 2.17, 's2f1': 4.73, 's3f1': 3.22, 's5c1': 3.26, 'spl60t': 2.97, 'spl65t': 2.31, 'su4': 2.84, 'su5': 2.57, 'su6': 2.46, 'su7': 2.29, 'type3': 3.15, 'type33': 3.29, 'type3s2': 3.11}), BoxBeamRating(beam_type='non_composite', box='B27-48', width_ft=28, n_beams=7, span=50, rating_factors={'inv': 1.62, 'op': 2.1, 'ev2': 2.68, 'ev3': 2.19, 's2f1': 4.77, 's3f1': 3.25, 's5c1': 3.29, 'spl60t': 3.0, 'spl65t': 2.33, 'su4': 2.86, 'su5': 2.59, 'su6': 2.48, 'su7': 2.39, 'type3': 3.17, 'type33': 3.32, 'type3s2': 3.14}), BoxBeamRating(beam_type='non_composite', box='B27-48', width_ft=24, n_beams=6, span=55, rating_factors={'inv': 1.38, 'op': 2.08, 'ev2': 2.83, 'ev3': 2.22, 's2f1': 4.77, 's3f1': 3.21, 's5c1': 3.29, 'spl60t': 2.92, 'spl65t': 2.53, 'su4': 2.84, 'su5': 2.61, 'su6': 2.34, 'su7': 2.16, 'type3': 3.24, 'type33': 3.61, 'type3s2': 3.35}), BoxBeamRating(beam_type='non_composite', box='B27-48', width_ft=28, n_beams=7, span=55, rating_factors={'inv': 1.43, 'op': 2.15, 'ev2': 2.93, 'ev3': 2.3, 's2f1': 4.93, 's3f1': 3.32, 's5c1': 3.4, 'spl60t': 3.02, 'spl65t': 2.61, 'su4': 2.94, 'su5': 2.7, 'su6': 2.42, 'su7': 2.24, 'type3': 3.35, 'type33': 3.73, 'type3s2': 3.46}), BoxBeamRating(beam_type='non_composite', box='B27-48', width_ft=24, n_beams=6, span=60, rating_factors={'inv': 1.4, 'op': 2.14, 'ev2': 2.97, 'ev3': 2.34, 's2f1': 5.07, 's3f1': 3.4, 's5c1': 3.45, 'spl60t': 2.86, 'spl65t': 2.33, 'su4': 3.0, 'su5': 2.74, 'su6': 2.46, 'su7': 2.26, 'type3': 3.4, 'type33': 3.41, 'type3s2': 3.23}), BoxBeamRating(beam_type='non_composite', box='B27-48', width_ft=28, n_beams=7, span=60, rating_factors={'inv': 1.45, 'op': 2.21, 'ev2': 3.0, 'ev3': 2.42, 's2f1': 5.24, 's3f1': 3.52, 's5c1': 3.45, 'spl60t': 2.9, 'spl65t': 2.33, 'su4': 3.1, 'su5': 2.83, 'su6': 2.54, 'su7': 2.34, 'type3': 3.52, 'type33': 3.42, 'type3s2': 3.23}), BoxBeamRating(beam_type='non_composite', box='B27-48', width_ft=24, n_beams=6, span=65, rating_factors={'inv': 1.39, 'op': 1.8, 'ev2': 2.44, 'ev3': 1.99, 's2f1': 4.42, 's3f1': 2.98, 's5c1': 2.67, 'spl60t': 2.24, 'spl65t': 1.82, 'su4': 2.6, 'su5': 2.33, 'su6': 2.19, 'su7': 2.07, 'type3': 2.87, 'type33': 2.64, 'type3s2': 2.55}), BoxBeamRating(beam_type='non_composite', box='B27-48', width_ft=28, n_beams=7, span=65, rating_factors={'inv': 1.39, 'op': 1.8, 'ev2': 2.44, 'ev3': 1.99, 's2f1': 4.43, 's3f1': 2.98, 's5c1': 2.67, 'spl60t': 2.24, 'spl65t': 1.83, 'su4': 2.61, 'su5': 2.34, 'su6': 2.19, 'su7': 2.08, 'type3': 2.87, 'type33': 2.65, 'type3s2': 2.55}), BoxBeamRating(beam_type='non_composite', box='B33-48', width_ft=24, n_beams=6, span=50, rating_factors={'inv': 1.63, 'op': 2.25, 'ev2': 2.96, 'ev3': 2.34, 's2f1': 4.97, 's3f1': 3.36, 's5c1': 3.44, 'spl60t': 3.03, 'spl65t': 2.57, 'su4': 2.99, 'su5': 2.76, 'su6': 2.48, 'su7': 2.3, 'type3': 3.43, 'type33': 3.67, 'type3s2': 3.47}), BoxBeamRating(beam_type='non_composite', box='B33-48', width_ft=28, n_beams=7, span=50, rating_factors={'inv': 1.69, 'op': 2.32, 'ev2': 2.96, 'ev3': 2.42, 's2f1': 5.14, 's3f1': 3.47, 's5c1': 3.56, 'spl60t': 3.13, 'spl65t': 2.57, 'su4': 3.09, 'su5': 2.85, 'su6': 2.56, 'su7': 2.37, 'type3': 3.51, 'type33': 3.67, 'type3s2': 3.47}), BoxBeamRating(beam_type='non_composite', box='B33-48', width_ft=24, n_beams=6, span=55, rating_factors={'inv': 1.45, 'op': 2.12, 'ev2': 2.88, 'ev3': 2.26, 's2f1': 4.86, 's3f1': 3.27, 's5c1': 3.34, 'spl60t': 2.97, 'spl65t': 2.57, 'su4': 2.89, 'su5': 2.66, 'su6': 2.39, 'su7': 2.2, 'type3': 3.3, 'type33': 3.68, 'type3s2': 3.41}), BoxBeamRating(beam_type='non_composite', box='B33-48', width_ft=28, n_beams=7, span=55, rating_factors={'inv': 1.5, 'op': 2.19, 'ev2': 2.98, 'ev3': 2.34, 's2f1': 5.02, 's3f1': 3.38, 's5c1': 3.46, 'spl60t': 3.07, 'spl65t': 2.66, 'su4': 2.99, 'su5': 2.75, 'su6': 2.47, 'su7': 2.27, 'type3': 3.41, 'type33': 3.8, 'type3s2': 3.52}), BoxBeamRating(beam_type='non_composite', box='B33-48', width_ft=24, n_beams=6, span=60, rating_factors={'inv': 1.63, 'op': 2.12, 'ev2': 2.8, 'ev3': 2.29, 's2f1': 5.05, 's3f1': 3.42, 's5c1': 3.27, 'spl60t': 2.75, 'spl65t': 2.2, 'su4': 2.99, 'su5': 2.69, 'su6': 2.55, 'su7': 2.43, 'type3': 3.31, 'type33': 3.22, 'type3s2': 3.04}), BoxBeamRating(beam_type='non_composite', box='B33-48', width_ft=28, n_beams=7, span=60, rating_factors={'inv': 1.63, 'op': 2.12, 'ev2': 2.8, 'ev3': 2.29, 's2f1': 5.06, 's3f1': 3.42, 's5c1': 3.27, 'spl60t': 2.75, 'spl65t': 2.2, 'su4': 3.0, 'su5': 2.7, 'su6': 2.55, 'su7': 2.43, 'type3': 3.31, 'type33': 3.22, 'type3s2': 3.04}), BoxBeamRating(beam_type='non_composite', box='B33-48', width_ft=24, n_beams=6, span=65, rating_factors={'inv': 1.43, 'op': 2.16, 'ev2': 2.89, 'ev3': 2.36, 's2f1': 5.23, 's3f1': 3.53, 's5c1': 3.27, 'spl60t': 2.75, 'spl65t': 2.22, 'su4': 3.09, 'su5': 2.78, 'su6': 2.58, 'su7': 2.36, 'type3': 3.41, 'type33': 3.23, 'type3s2': 3.08}), BoxBeamRating(beam_type='non_composite', box='B33-48', width_ft=28, n_beams=7, span=65, rating_factors={'inv': 1.47, 'op': 2.15, 'ev2': 2.87, 'ev3': 2.34, 's2f1': 5.19, 's3f1': 3.51, 's5c1': 3.25, 'spl60t': 2.73, 'spl65t': 2.21, 'su4': 3.07, 'su5': 2.76, 'su6': 2.6, 'su7': 2.42, 'type3': 3.38, 'type33': 3.2, 'type3s2': 3.06}), BoxBeamRating(beam_type='non_composite', box='B33-48', width_ft=24, n_beams=6, span=70, rating_factors={'inv': 1.48, 'op': 1.94, 'ev2': 2.67, 'ev3': 2.18, 's2f1': 4.87, 's3f1': 3.27, 's5c1': 2.81, 'spl60t': 2.35, 'spl65t': 1.94, 'su4': 2.85, 'su5': 2.55, 'su6': 2.39, 'su7': 2.25, 'type3': 3.14, 'type33': 2.79, 'type3s2': 2.73}), BoxBeamRating(beam_type='non_composite', box='B33-48', width_ft=28, n_beams=7, span=70, rating_factors={'inv': 1.5, 'op': 1.94, 'ev2': 2.67, 'ev3': 2.18, 's2f1': 4.87, 's3f1': 3.28, 's5c1': 2.81, 'spl60t': 2.36, 'spl65t': 1.94, 'su4': 2.86, 'su5': 2.55, 'su6': 2.39, 'su7': 2.25, 'type3': 3.14, 'type33': 2.79, 'type3s2': 2.73}), BoxBeamRating(beam_type='non_composite', box='B33-48', width_ft=24, n_beams=6, span=75, rating_factors={'inv': 1.34, 'op': 1.73, 'ev2': 2.42, 'ev3': 1.97, 's2f1': 4.43, 's3f1': 2.97, 's5c1': 2.46, 'spl60t': 2.04, 'spl65t': 1.71, 'su4': 2.59, 'su5': 2.31, 'su6': 2.15, 'su7': 2.02, 'type3': 2.84, 'type33': 2.44, 'type3s2': 2.42}), BoxBeamRating(beam_type='non_composite', box='B33-48', width_ft=28, n_beams=7, span=75, rating_factors={'inv': 1.34, 'op': 1.73, 'ev2': 2.43, 'ev3': 1.97, 's2f1': 4.44, 's3f1': 2.98, 's5c1': 2.46, 'spl60t': 2.04, 'spl65t': 1.71, 'su4': 2.59, 'su5': 2.31, 'su6': 2.15, 'su7': 2.02, 'type3': 2.84, 'type33': 2.44, 'type3s2': 2.42}), BoxBeamRating(beam_type='non_composite', box='B33-48', width_ft=24, n_beams=6, span=80, rating_factors={'inv': 1.24, 'op': 1.61, 'ev2': 2.28, 'ev3': 1.85, 's2f1': 4.18, 's3f1': 2.8, 's5c1': 2.25, 'spl60t': 1.85, 'spl65t': 1.58, 'su4': 2.43, 'su5': 2.17, 'su6': 2.01, 'su7': 1.88, 'type3': 2.67, 'type33': 2.24, 'type3s2': 2.24}), BoxBeamRating(beam_type='non_composite', box='B33-48', width_ft=28, n_beams=7, span=80, rating_factors={'inv': 1.24, 'op': 1.61, 'ev2': 2.28, 'ev3': 1.86, 's2f1': 4.18, 's3f1': 2.8, 's5c1': 2.25, 'spl60t': 1.86, 'spl65t': 1.58, 'su4': 2.43, 'su5': 2.17, 'su6': 2.01, 'su7': 1.88, 'type3': 2.67, 'type33': 2.24, 'type3s2': 2.24}), BoxBeamRating(beam_type='non_composite', box='B42-48', width_ft=24, n_beams=6, span=65, rating_factors={'inv': 1.64, 'op': 2.43, 'ev2': 3.43, 'ev3': 2.71, 's2f1': 5.92, 's3f1': 3.96, 's5c1': 4.03, 'spl60t': 3.35, 'spl65t': 2.77, 'su4': 3.48, 'su5': 3.17, 'su6': 2.84, 'su7': 2.6, 'type3': 3.93, 'type33': 3.99, 'type3s2': 3.74}), BoxBeamRating(beam_type='non_composite', box='B42-48', width_ft=28, n_beams=7, span=65, rating_factors={'inv': 1.7, 'op': 2.51, 'ev2': 3.55, 'ev3': 2.8, 's2f1': 6.11, 's3f1': 4.09, 's5c1': 4.17, 'spl60t': 3.46, 'spl65t': 2.86, 'su4': 3.6, 'su5': 3.27, 'su6': 2.93, 'su7': 2.69, 'type3': 4.06, 'type33': 4.12, 'type3s2': 3.87}), BoxBeamRating(beam_type='non_composite', box='B42-48', width_ft=24, n_beams=6, span=70, rating_factors={'inv': 1.54, 'op': 2.37, 'ev2': 3.41, 'ev3': 2.7, 's2f1': 5.93, 's3f1': 3.96, 's5c1': 3.89, 'spl60t': 3.36, 'spl65t': 2.65, 'su4': 3.47, 'su5': 3.15, 'su6': 2.82, 'su7': 2.58, 'type3': 3.91, 'type33': 3.81, 'type3s2': 3.6}), BoxBeamRating(beam_type='non_composite', box='B42-48', width_ft=28, n_beams=7, span=70, rating_factors={'inv': 1.58, 'op': 2.43, 'ev2': 3.49, 'ev3': 2.76, 's2f1': 6.07, 's3f1': 4.06, 's5c1': 3.98, 'spl60t': 3.44, 'spl65t': 2.71, 'su4': 3.56, 'su5': 3.22, 'su6': 2.89, 'su7': 2.65, 'type3': 4.0, 'type33': 3.9, 'type3s2': 3.69}), BoxBeamRating(beam_type='non_composite', box='B42-48', width_ft=24, n_beams=6, span=75, rating_factors={'inv': 1.43, 'op': 2.29, 'ev2': 3.35, 'ev3': 2.65, 's2f1': 5.86, 's3f1': 3.91, 's5c1': 3.59, 'spl60t': 2.99, 'spl65t': 2.5, 'su4': 3.42, 'su5': 3.09, 'su6': 2.77, 'su7': 2.53, 'type3': 3.83, 'type33': 3.56, 'type3s2': 3.45}), BoxBeamRating(beam_type='non_composite', box='B42-48', width_ft=28, n_beams=7, span=75, rating_factors={'inv': 1.49, 'op': 2.37, 'ev2': 3.46, 'ev3': 2.74, 's2f1': 6.06, 's3f1': 4.04, 's5c1': 3.59, 'spl60t': 2.99, 'spl65t': 2.5, 'su4': 3.54, 'su5': 3.19, 'su6': 2.86, 'su7': 2.62, 'type3': 3.96, 'type33': 3.56, 'type3s2': 3.53}), BoxBeamRating(beam_type='non_composite', box='B42-48', width_ft=24, n_beams=6, span=80, rating_factors={'inv': 1.43, 'op': 2.38, 'ev2': 3.38, 'ev3': 2.75, 's2f1': 6.2, 's3f1': 4.15, 's5c1': 3.34, 'spl60t': 2.75, 'spl65t': 2.34, 'su4': 3.61, 'su5': 3.21, 'su6': 2.94, 'su7': 2.68, 'type3': 3.95, 'type33': 3.32, 'type3s2': 3.32}), BoxBeamRating(beam_type='non_composite', box='B42-48', width_ft=28, n_beams=7, span=80, rating_factors={'inv': 1.48, 'op': 2.38, 'ev2': 3.38, 'ev3': 2.75, 's2f1': 6.2, 's3f1': 4.15, 's5c1': 3.34, 'spl60t': 2.75, 'spl65t': 2.34, 'su4': 3.61, 'su5': 3.22, 'su6': 2.99, 'su7': 2.78, 'type3': 3.96, 'type33': 3.32, 'type3s2': 3.32}), BoxBeamRating(beam_type='non_composite', box='B42-48', width_ft=24, n_beams=6, span=85, rating_factors={'inv': 1.51, 'op': 2.24, 'ev2': 3.22, 'ev3': 2.62, 's2f1': 5.92, 's3f1': 3.96, 's5c1': 3.11, 'spl60t': 2.53, 'spl65t': 2.19, 'su4': 3.43, 'su5': 3.06, 'su6': 2.83, 'su7': 2.64, 'type3': 3.76, 'type33': 3.09, 'type3s2': 3.12}), BoxBeamRating(beam_type='non_composite', box='B42-48', width_ft=28, n_beams=7, span=85, rating_factors={'inv': 1.56, 'op': 2.24, 'ev2': 3.22, 'ev3': 2.62, 's2f1': 5.93, 's3f1': 3.96, 's5c1': 3.11, 'spl60t': 2.54, 'spl65t': 2.19, 'su4': 3.44, 'su5': 3.06, 'su6': 2.83, 'su7': 2.64, 'type3': 3.77, 'type33': 3.09, 'type3s2': 3.12}), BoxBeamRating(beam_type='non_composite', box='B42-48', width_ft=24, n_beams=6, span=90, rating_factors={'inv': 1.54, 'op': 2.13, 'ev2': 3.1, 'ev3': 2.52, 's2f1': 5.72, 's3f1': 3.82, 's5c1': 2.94, 'spl60t': 2.38, 'spl65t': 2.07, 'su4': 3.31, 'su5': 2.94, 'su6': 2.72, 'su7': 2.53, 'type3': 3.63, 'type33': 2.92, 'type3s2': 2.97}), BoxBeamRating(beam_type='non_composite', box='B42-48', width_ft=28, n_beams=7, span=90, rating_factors={'inv': 1.6, 'op': 2.13, 'ev2': 2.92, 'ev3': 2.38, 's2f1': 5.39, 's3f1': 3.6, 's5c1': 2.76, 'spl60t': 2.24, 'spl65t': 1.95, 'su4': 3.12, 'su5': 2.77, 'su6': 2.56, 'su7': 2.38, 'type3': 3.41, 'type33': 2.75, 'type3s2': 2.79}), BoxBeamRating(beam_type='non_composite', box='B17-48', width_ft=32, n_beams=8, span=20, rating_factors={'inv': 1.94, 'op': 2.52, 'ev2': 3.19, 'ev3': 2.49, 's2f1': 4.7, 's3f1': 3.57, 's5c1': 3.75, 'spl60t': 4.02, 'spl65t': 3.76, 'su4': 3.31, 'su5': 3.12, 'su6': 3.12, 'su7': 3.12, 'type3': 3.75, 'type33': 4.56, 'type3s2': 4.02}), BoxBeamRating(beam_type='non_composite', box='B17-48', width_ft=32, n_beams=8, span=25, rating_factors={'inv': 1.79, 'op': 2.32, 'ev2': 2.72, 'ev3': 2.28, 's2f1': 4.3, 's3f1': 3.14, 's5c1': 3.25, 'spl60t': 3.58, 'spl65t': 3.32, 'su4': 2.93, 'su5': 2.78, 'su6': 2.81, 'su7': 2.81, 'type3': 3.42, 'type33': 4.26, 'type3s2': 3.53}), BoxBeamRating(beam_type='non_composite', box='B17-48', width_ft=32, n_beams=8, span=30, rating_factors={'inv': 1.54, 'op': 2.0, 'ev2': 2.26, 'ev3': 1.87, 's2f1': 3.71, 's3f1': 2.65, 's5c1': 2.73, 'spl60t': 3.05, 'spl65t': 2.76, 'su4': 2.43, 'su5': 2.31, 'su6': 2.35, 'su7': 2.35, 'type3': 2.78, 'type33': 3.39, 'type3s2': 2.98}), BoxBeamRating(beam_type='non_composite', box='B17-48', width_ft=32, n_beams=8, span=35, rating_factors={'inv': 1.41, 'op': 1.83, 'ev2': 2.09, 'ev3': 1.73, 's2f1': 3.53, 's3f1': 2.48, 's5c1': 2.54, 'spl60t': 2.87, 'spl65t': 2.56, 'su4': 2.24, 'su5': 2.1, 'su6': 2.14, 'su7': 2.15, 'type3': 2.54, 'type33': 3.05, 'type3s2': 2.79}), BoxBeamRating(beam_type='non_composite', box='B21-48', width_ft=32, n_beams=8, span=30, rating_factors={'inv': 1.94, 'op': 2.51, 'ev2': 2.84, 'ev3': 2.36, 's2f1': 4.68, 's3f1': 3.34, 's5c1': 3.44, 'spl60t': 3.85, 'spl65t': 3.48, 'su4': 3.06, 'su5': 2.91, 'su6': 2.96, 'su7': 2.96, 'type3': 3.5, 'type33': 4.26, 'type3s2': 3.76}), BoxBeamRating(beam_type='non_composite', box='B21-48', width_ft=32, n_beams=8, span=35, rating_factors={'inv': 1.5, 'op': 1.95, 'ev2': 2.29, 'ev3': 1.89, 's2f1': 3.94, 's3f1': 2.74, 's5c1': 2.8, 'spl60t': 3.16, 'spl65t': 2.82, 'su4': 2.46, 'su5': 2.28, 'su6': 2.27, 'su7': 2.27, 'type3': 2.76, 'type33': 3.29, 'type3s2': 3.08}), BoxBeamRating(beam_type='non_composite', box='B21-48', width_ft=32, n_beams=8, span=40, rating_factors={'inv': 1.29, 'op': 1.67, 'ev2': 3.54, 'ev3': 2.44, 's2f1': 2.49, 's3f1': 2.81, 's5c1': 2.5, 'spl60t': 2.81, 'spl65t': 2.5, 'su4': 2.17, 'su5': 1.99, 'su6': 1.95, 'su7': 1.94, 'type3': 2.43, 'type33': 2.84, 'type3s2': 2.66}), BoxBeamRating(beam_type='non_composite', box='B21-48', width_ft=32, n_beams=8, span=45, rating_factors={'inv': 1.44, 'op': 1.86, 'ev2': 2.26, 'ev3': 1.86, 's2f1': 3.95, 's3f1': 2.73, 's5c1': 2.77, 'spl60t': 3.01, 'spl65t': 2.67, 'su4': 2.43, 'su5': 2.23, 'su6': 2.18, 'su7': 2.17, 'type3': 2.71, 'type33': 3.17, 'type3s2': 2.97}), BoxBeamRating(beam_type='non_composite', box='B21-48', width_ft=32, n_beams=8, span=50, rating_factors={'inv': 1.34, 'op': 1.76, 'ev2': 2.18, 'ev3': 1.79, 's2f1': 3.85, 's3f1': 2.64, 's5c1': 2.68, 'spl60t': 2.75, 'spl65t': 2.44, 'su4': 2.34, 'su5': 2.13, 'su6': 2.06, 'su7': 2.02, 'type3': 2.6, 'type33': 2.91, 'type3s2': 2.73}), BoxBeamRating(beam_type='non_composite', box='B27-48', width_ft=32, n_beams=8, span=40, rating_factors={'inv': 1.89, 'op': 2.46, 'ev2': 2.98, 'ev3': 2.45, 's2f1': 5.21, 's3f1': 3.59, 's5c1': 3.66, 'spl60t': 3.51, 'spl65t': 3.12, 'su4': 3.2, 'su5': 2.93, 'su6': 2.87, 'su7': 2.85, 'type3': 3.57, 'type33': 4.18, 'type3s2': 3.92}), BoxBeamRating(beam_type='non_composite', box='B27-48', width_ft=32, n_beams=8, span=45, rating_factors={'inv': 1.76, 'op': 2.29, 'ev2': 2.85, 'ev3': 2.34, 's2f1': 5.04, 's3f1': 3.45, 's5c1': 3.51, 'spl60t': 3.21, 'spl65t': 2.67, 'su4': 3.06, 'su5': 2.78, 'su6': 2.69, 'su7': 2.63, 'type3': 3.4, 'type33': 3.77, 'type3s2': 3.55}), BoxBeamRating(beam_type='non_composite', box='B27-48', width_ft=32, n_beams=8, span=50, rating_factors={'inv': 1.62, 'op': 2.1, 'ev2': 2.68, 'ev3': 2.19, 's2f1': 4.77, 's3f1': 3.25, 's5c1': 3.29, 'spl60t': 3.0, 'spl65t': 2.33, 'su4': 2.86, 'su5': 2.59, 'su6': 2.48, 'su7': 2.4, 'type3': 3.17, 'type33': 3.32, 'type3s2': 3.14}), BoxBeamRating(beam_type='non_composite', box='B27-48', width_ft=32, n_beams=8, span=55, rating_factors={'inv': 1.47, 'op': 2.22, 'ev2': 3.01, 'ev3': 2.36, 's2f1': 5.07, 's3f1': 3.42, 's5c1': 3.49, 'spl60t': 3.1, 'spl65t': 2.69, 'su4': 3.02, 'su5': 2.78, 'su6': 2.49, 'su7': 2.3, 'type3': 3.45, 'type33': 3.84, 'type3s2': 3.56}), BoxBeamRating(beam_type='non_composite', box='B27-48', width_ft=32, n_beams=8, span=60, rating_factors={'inv': 1.49, 'op': 2.26, 'ev2': 3.0, 'ev3': 2.45, 's2f1': 5.39, 's3f1': 3.62, 's5c1': 3.46, 'spl60t': 2.9, 'spl65t': 2.34, 'su4': 3.19, 'su5': 2.88, 'su6': 2.61, 'su7': 2.4, 'type3': 3.54, 'type33': 3.42, 'type3s2': 3.23}), BoxBeamRating(beam_type='non_composite', box='B27-48', width_ft=32, n_beams=8, span=65, rating_factors={'inv': 1.39, 'op': 1.8, 'ev2': 2.44, 'ev3': 1.99, 's2f1': 4.43, 's3f1': 2.99, 's5c1': 2.67, 'spl60t': 2.24, 'spl65t': 1.83, 'su4': 2.61, 'su5': 2.34, 'su6': 2.2, 'su7': 2.08, 'type3': 2.87, 'type33': 2.65, 'type3s2': 2.55}), BoxBeamRating(beam_type='non_composite', box='B33-48', width_ft=32, n_beams=8, span=50, rating_factors={'inv': 1.74, 'op': 2.32, 'ev2': 2.96, 'ev3': 2.42, 's2f1': 5.28, 's3f1': 3.57, 's5c1': 3.65, 'spl60t': 3.22, 'spl65t': 2.58, 'su4': 3.17, 'su5': 2.87, 'su6': 2.64, 'su7': 2.44, 'type3': 3.51, 'type33': 3.67, 'type3s2': 3.47}), BoxBeamRating(beam_type='non_composite', box='B33-48', width_ft=32, n_beams=8, span=55, rating_factors={'inv': 1.54, 'op': 2.25, 'ev2': 3.07, 'ev3': 2.41, 's2f1': 5.16, 's3f1': 3.48, 's5c1': 3.56, 'spl60t': 3.16, 'spl65t': 2.73, 'su4': 3.08, 'su5': 2.83, 'su6': 2.54, 'su7': 2.34, 'type3': 3.51, 'type33': 3.91, 'type3s2': 3.62}), BoxBeamRating(beam_type='non_composite', box='B33-48', width_ft=32, n_beams=8, span=60, rating_factors={'inv': 1.64, 'op': 2.12, 'ev2': 2.81, 'ev3': 2.29, 's2f1': 5.06, 's3f1': 3.42, 's5c1': 3.28, 'spl60t': 2.75, 'spl65t': 2.21, 'su4': 3.0, 'su5': 2.7, 'su6': 2.55, 'su7': 2.43, 'type3': 3.31, 'type33': 3.22, 'type3s2': 3.05}), BoxBeamRating(beam_type='non_composite', box='B33-48', width_ft=32, n_beams=8, span=65, rating_factors={'inv': 1.53, 'op': 2.17, 'ev2': 2.89, 'ev3': 2.36, 's2f1': 5.24, 's3f1': 3.54, 's5c1': 3.28, 'spl60t': 2.75, 'spl65t': 2.23, 'su4': 3.09, 'su5': 2.78, 'su6': 2.62, 'su7': 2.49, 'type3': 3.41, 'type33': 3.23, 'type3s2': 3.09}), BoxBeamRating(beam_type='non_composite', box='B33-48', width_ft=32, n_beams=8, span=70, rating_factors={'inv': 1.5, 'op': 1.95, 'ev2': 2.68, 'ev3': 2.18, 's2f1': 4.88, 's3f1': 3.28, 's5c1': 2.81, 'spl60t': 2.36, 'spl65t': 1.94, 'su4': 2.86, 'su5': 2.56, 'su6': 2.39, 'su7': 2.25, 'type3': 3.14, 'type33': 2.79, 'type3s2': 2.73}), BoxBeamRating(beam_type='non_composite', box='B33-48', width_ft=32, n_beams=8, span=75, rating_factors={'inv': 1.59, 'op': 2.5, 'ev2': 3.49, 'ev3': 2.84, 's2f1': 6.39, 's3f1': 4.28, 's5c1': 3.54, 'spl60t': 2.94, 'spl65t': 2.46, 'su4': 3.73, 'su5': 3.33, 'su6': 3.03, 'su7': 2.77, 'type3': 4.1, 'type33': 3.51, 'type3s2': 3.49}), BoxBeamRating(beam_type='non_composite', box='B33-48', width_ft=32, n_beams=8, span=80, rating_factors={'inv': 1.24, 'op': 1.61, 'ev2': 2.28, 'ev3': 1.86, 's2f1': 4.19, 's3f1': 2.8, 's5c1': 2.26, 'spl60t': 1.86, 'spl65t': 1.58, 'su4': 2.44, 'su5': 2.17, 'su6': 2.02, 'su7': 1.89, 'type3': 2.67, 'type33': 2.24, 'type3s2': 2.24}), BoxBeamRating(beam_type='non_composite', box='B42-48', width_ft=32, n_beams=8, span=65, rating_factors={'inv': 1.75, 'op': 2.58, 'ev2': 3.65, 'ev3': 2.88, 's2f1': 6.29, 's3f1': 4.21, 's5c1': 4.29, 'spl60t': 3.56, 'spl65t': 2.94, 'su4': 3.7, 'su5': 3.37, 'su6': 3.02, 'su7': 2.77, 'type3': 4.18, 'type33': 4.24, 'type3s2': 3.98}), BoxBeamRating(beam_type='non_composite', box='B42-48', width_ft=32, n_beams=8, span=70, rating_factors={'inv': 1.65, 'op': 2.52, 'ev2': 3.63, 'ev3': 2.87, 's2f1': 6.31, 's3f1': 4.21, 's5c1': 4.14, 'spl60t': 3.48, 'spl65t': 2.82, 'su4': 3.69, 'su5': 3.35, 'su6': 3.0, 'su7': 2.75, 'type3': 4.16, 'type33': 4.05, 'type3s2': 3.83}), BoxBeamRating(beam_type='non_composite', box='B42-48', width_ft=32, n_beams=8, span=75, rating_factors={'inv': 1.53, 'op': 2.44, 'ev2': 3.53, 'ev3': 2.82, 's2f1': 6.24, 's3f1': 4.16, 's5c1': 3.59, 'spl60t': 2.99, 'spl65t': 2.5, 'su4': 3.64, 'su5': 3.29, 'su6': 2.94, 'su7': 2.69, 'type3': 4.08, 'type33': 3.57, 'type3s2': 3.53}), BoxBeamRating(beam_type='non_composite', box='B42-48', width_ft=32, n_beams=8, span=80, rating_factors={'inv': 1.53, 'op': 2.39, 'ev2': 3.38, 'ev3': 2.75, 's2f1': 6.21, 's3f1': 4.16, 's5c1': 3.35, 'spl60t': 2.75, 'spl65t': 2.34, 'su4': 3.61, 'su5': 3.22, 'su6': 2.99, 'su7': 2.8, 'type3': 3.96, 'type33': 3.32, 'type3s2': 3.33}), BoxBeamRating(beam_type='non_composite', box='B42-48', width_ft=32, n_beams=8, span=85, rating_factors={'inv': 1.61, 'op': 2.24, 'ev2': 3.22, 'ev3': 2.62, 's2f1': 5.93, 's3f1': 3.97, 's5c1': 3.11, 'spl60t': 2.54, 'spl65t': 2.19, 'su4': 3.44, 'su5': 3.06, 'su6': 2.84, 'su7': 2.64, 'type3': 3.77, 'type33': 3.09, 'type3s2': 3.12}), BoxBeamRating(beam_type='non_composite', box='B42-48', width_ft=32, n_beams=8, span=90, rating_factors={'inv': 1.64, 'op': 2.13, 'ev2': 3.11, 'ev3': 2.53, 's2f1': 5.74, 's3f1': 3.83, 's5c1': 2.94, 'spl60t': 2.38, 'spl65t': 2.08, 'su4': 3.32, 'su5': 2.95, 'su6': 2.73, 'su7': 2.53, 'type3': 3.63, 'type33': 2.93, 'type3s2': 2.98})]
All box-beam load ratings (PSBDD-1-25 sheets 2 & 4).
- civilpy.structural.odot.box_beam_design.BOX_DESIGNATIONS: tuple[str, ...] = ('CB17-48', 'CB21-48', 'CB27-48', 'CB33-48', 'CB42-48', 'B17-48', 'B21-48', 'B27-48', 'B33-48', 'B42-48')
Standard box designations (e.g.
"CB27-48","B27-48").
- class civilpy.structural.odot.box_beam_design.BoxBeamDesign(beam_type: str, box: str, depth: int, width: int, span: int, e_beam: float, e_composite: float | None, n_strands: int, strands_2in: int, strands_4in: int, strands_6in: int, stirrup_w_pairs: int, stirrup_zone_x: float, stirrup_y: float, stirrup_z: float, camber_d0: float, camber_d30: float, deflection: float, bearing_type: str)[source]
Bases:
objectOne standard box-beam design line (PSBDD-1-25 sheets 1 & 3).
e_compositeisNonefor non-composite beams.strands_2in/strands_4in/strands_6inare the strand counts in the rows 2, 4, and 6 in above the soffit (their sum isn_strands). Camber values are at release (camber_d0) and erection (camber_d30);deflectionis the residual midspan deflection under remaining dead load. All lengths in inches.
- class civilpy.structural.odot.box_beam_design.BoxBeamRating(beam_type: str, box: str, width_ft: int, n_beams: int, span: int, rating_factors: dict[str, float]=<factory>)[source]
Bases:
objectLRFR rating factors for one box / span / bridge width (PSBDD-1-25 sheets 2 & 4).
rating_factorsis keyed byRATING_VEHICLES.
- civilpy.structural.odot.box_beam_design.RATING_VEHICLES: tuple[str, ...] = ('inv', 'op', 'ev2', 'ev3', 's2f1', 's3f1', 's5c1', 'spl60t', 'spl65t', 'su4', 'su5', 'su6', 'su7', 'type3', 'type33', 'type3s2')
Rating vehicles in the order tabulated on PSBDD-1-25 (keys into
BoxBeamRating.rating_factors).
- civilpy.structural.odot.box_beam_design.STRAND_ROW_HEIGHTS_IN: tuple[float, float, float] = (2.0, 4.0, 6.0)
Strand row heights above the soffit, inches (PSBDD-1-25 sheets 1 & 3).
- civilpy.structural.odot.box_beam_design.box_beam_design(box: str, span: int) BoxBeamDesign[source]
The design line for a box designation and span in feet.
- civilpy.structural.odot.box_beam_design.box_beam_rating(box: str, span: int, width_ft: int) BoxBeamRating[source]
The load rating for a box, span (ft), and bridge width (24/28/32 ft).
- civilpy.structural.odot.box_beam_design.designs_for_box(box: str) list[BoxBeamDesign][source]
All span designs for one box designation, shortest span first.
- civilpy.structural.odot.box_beam_design.strand_group_height_in(design: BoxBeamDesign) float[source]
Height of the strand-group centroid above the soffit (in), the strand-count-weighted average of the 2/4/6 in row heights. A schematic single-height tendon path uses this; it is consistent with (Yb of the matching
BoxSectionProperties) minusdesign.e_beamto within drawing rounding.
civilpy.structural.odot.box_culvert_headwall module
Ohio DOT precast box culvert headwall / wingwall plan insert (BCHW).
Transcribed from the Ohio DOT “BCHW” plan insert (rev. 01-21-2022, 8 sheets: culvert & wingwall layout, wingwall elevation + foreslope wall + footing plan + sections, and several “SUBSET” sheets of alternate wingwall corner configurations). The drawing remains the controlling document.
BCHW is a detailing template, not a dimensioned standard. Unlike every
other SCD this package catalogs, none of its geometry is tabulated: every
dimension on the sheet (wall height H, footing offsets a/b/c,
foreslope-wall height hf, cutoff-wall height hcw, footing width
Wf, box wall thickness t box, wingwall length L, bar spacings)
is drawn as * or a blank @ _ c/c for the project engineer to fill
in from the actual box culvert design – the sheet says so explicitly
(“INSERT ODOT BOX CULVERT REINFORCING DESIGN HERE IF SPAN > 12’.”). There
is therefore no guarded catalog lookup here: layout_wingwall() takes
every dimension as a required input (no defaults, nothing to look up) and
only performs the geometry the sheet’s own sections make unambiguous
(civilpy.structural.odot’s ASTM C1577 precast box section catalog,
if/when encoded, is a separate concern – BCHW is the cast-in-place
wingwall/foreslope-wall wrap-around, not the precast box itself).
What is cataloged here: the general notes (payment items, waterproofing,
porous backfill, weepholes, PEJF, lap splice lengths, epoxy coating) and
the eight standard rebar bend shapes (TYPE-1 .. TYPE-8) the bar
list (WW5xx wingwall, FS5xx foreslope wall, F6xx footing, Z/V/W/X/Y series)
references – bend_shape() turns a type + the project-supplied leg
lengths into a bend polyline, the same “shape template, project-supplied
legs” split as the sheet itself.
- civilpy.structural.odot.box_culvert_headwall.BOX_SPAN_RANGE_FT = (8.0, 20.0)
precast spans 8-20 ft in 2 ft increments, rises 4-10 ft in 1 ft increments; ASTM C1433 covers spans to 12 ft, larger spans need an OSE box design.
- Type:
Culvert size limits (sheet 1/6)
- civilpy.structural.odot.box_culvert_headwall.CUTOFF_WALL_WIDTH_FT = 1.5
1’-6” cutoff wall (Section B-B)
- civilpy.structural.odot.box_culvert_headwall.FOOTING_EXTENSION_FT = 4.0
“4’-0” (MIN.)” footing run past the wall
- civilpy.structural.odot.box_culvert_headwall.FOOTING_REINFORCING = {1: ((5, 18.0), (5, 18.0)), 2: ((5, 15.0), (5, 18.0)), 3: ((5, 12.0), (5, 18.0)), 4: ((5, 18.0), (5, 12.0)), 5: ((5, 15.0), (5, 9.0)), 6: ((6, 18.0), (6, 18.0)), 7: ((6, 18.0), (6, 18.0)), 8: ((6, 9.0), (6, 12.0))}
“V” transverse bars and “W”/”Z” longitudinal / cutoff bars per footing design number.
- Type:
Footing reinforcing (sheet 6/6)
- civilpy.structural.odot.box_culvert_headwall.FORESLOPE_WALL_HEIGHTS_IN = (6.0, 18.0)
Foreslope wall height above the top of the culvert (sheet 1/6): 6 in or 1’-6” only.
- civilpy.structural.odot.box_culvert_headwall.FORESLOPE_WALL_QUANTITIES = {(1.0, 6.0): (6.7, 0.02), (1.0, 18.0): (10.87, 0.06), (1.25, 6.0): (7.22, 0.03), (1.25, 18.0): (11.39, 0.07)}
(width b ft, height in) -> (reinf lbs/ft, conc cy/ft); multiply by box span + 2 (t box, wall).
- Type:
Foreslope wall quantities (sheet 6/6)
- class civilpy.structural.odot.box_culvert_headwall.HeadwallDesign(inputs: HeadwallInput, H: float, H_required: float, t_wall_in: float, row: HeadwallRow, v_bar: tuple[int, float], wz_bar: tuple[int, float], foreslope_lbs_per_ft: float, foreslope_cy_per_ft: float)[source]
Bases:
objectThe resolved design: the table row plus the derived dimensions.
- inputs: HeadwallInput
- row: HeadwallRow
- class civilpy.structural.odot.box_culvert_headwall.HeadwallInput(headwall_type: Literal['A', 'B', 'C'], box_span_ft: float, box_rise_ft: float, box_slab_thickness_in: float = 10.0, roadway_skew_deg: float = 0.0, foreslope_wall_height_in: float = 6.0)[source]
Bases:
objectDesign inputs for one culvert-end headwall assembly (Design Data sheets), resolved against the tables by
design_headwall().- box_slab_thickness_in: float = 10.0
Box top/bottom slab thickness, in (from the box design); feeds
H = rise + 2 slab + foreslope height.
- box_span_ft: float
Box clear span, ft — tabulated 8-20 in 2 ft increments (
BOX_SPAN_RANGE_FT).
- foreslope_wall_height_in: float = 6.0
Foreslope wall height above the top of the culvert, in — the sheet allows 6 or 18 only (
FORESLOPE_WALL_HEIGHTS_IN).
- class civilpy.structural.odot.box_culvert_headwall.HeadwallRow(H: float, footing_design: int, L1: float, L2: float, h1: float, h2: float, footing_w: float, footing_t: float, hcw: float, a: float, b: float, x_bar: int, x_spa_in: float, y_bar: int, y_spa_in: float, c: float, wingwall_conc_cy: float, wingwall_reinf_lbs: float, footing_conc_cy: float, footing_reinf_lbs: float, culvert_footing_cy_per_ft: float, culvert_footing_lbs_per_ft: float)[source]
Bases:
objectOne design-height row of a Type A/B/C table (sheets 2/6-5/6).
Lengths and heights in feet, bar spacings in inches, quantities as printed: wingwall/footing concrete in cy and reinforcing in lbs are whole-assembly (both wingwalls); culvert-footing values are per lineal foot, to be multiplied by
box span + 2 (t box, wall).
- civilpy.structural.odot.box_culvert_headwall.PAY_ITEMS = {'sealing_concrete_surfaces': ('512', '46000', 'SQ. YD.'), 'structure_removed': ('202', '11000', 'LUMP'), 'unclassified_excavation': ('503', '21100', 'LUMP'), 'unclassified_excavation_wingwall_footing': ('503', '11100', 'LUMP')}
Payment items (note block, “TOTALS CARRIED TO GENERAL SUMMARY SHEET”).
- civilpy.structural.odot.box_culvert_headwall.TYPE_A_TABLE = (HeadwallRow(H=6.5, footing_design=1, L1=7.25, L2=7.25, h1=4.0, h2=4.0, footing_w=4.5, footing_t=1.5, hcw=2.5, a=1.1666666666666667, b=1.0, x_bar=5, x_spa_in=18.0, y_bar=5, y_spa_in=18.0, c=2.4166666666666665, wingwall_conc_cy=3.02, wingwall_reinf_lbs=446, footing_conc_cy=6.0, footing_reinf_lbs=598, culvert_footing_cy_per_ft=0.43, culvert_footing_lbs_per_ft=24.55), HeadwallRow(H=7.5, footing_design=1, L1=8.5, L2=8.5, h1=4.5, h2=4.5, footing_w=5.0, footing_t=1.5, hcw=2.5, a=1.5, b=1.0, x_bar=5, x_spa_in=18.0, y_bar=5, y_spa_in=18.0, c=2.4166666666666665, wingwall_conc_cy=4.01, wingwall_reinf_lbs=533, footing_conc_cy=7.38, footing_reinf_lbs=733, culvert_footing_cy_per_ft=0.48, culvert_footing_lbs_per_ft=27.58), HeadwallRow(H=8.5, footing_design=1, L1=10.0, L2=10.0, h1=5.0, h2=5.0, footing_w=5.5, footing_t=1.5, hcw=2.5, a=1.9166666666666665, b=1.0, x_bar=5, x_spa_in=16.5, y_bar=5, y_spa_in=16.5, c=2.4166666666666665, wingwall_conc_cy=5.27, wingwall_reinf_lbs=726, footing_conc_cy=9.05, footing_reinf_lbs=830, culvert_footing_cy_per_ft=0.52, culvert_footing_lbs_per_ft=28.61), HeadwallRow(H=9.5, footing_design=1, L1=11.5, L2=11.5, h1=5.5, h2=5.5, footing_w=6.25, footing_t=1.5, hcw=2.5, a=2.25, b=1.0, x_bar=5, x_spa_in=18.0, y_bar=5, y_spa_in=9.0, c=3.8333333333333335, wingwall_conc_cy=6.69, wingwall_reinf_lbs=934, footing_conc_cy=11.35, footing_reinf_lbs=911, culvert_footing_cy_per_ft=0.57, culvert_footing_lbs_per_ft=29.9), HeadwallRow(H=10.5, footing_design=1, L1=12.75, L2=12.75, h1=6.0, h2=6.0, footing_w=7.0, footing_t=2.0, hcw=2.0, a=2.9166666666666665, b=1.25, x_bar=5, x_spa_in=18.0, y_bar=5, y_spa_in=9.0, c=4.166666666666667, wingwall_conc_cy=10.25, wingwall_reinf_lbs=1104, footing_conc_cy=16.19, footing_reinf_lbs=1087, culvert_footing_cy_per_ft=0.74, culvert_footing_lbs_per_ft=33.95), HeadwallRow(H=11.5, footing_design=1, L1=14.25, L2=14.25, h1=6.5, h2=6.5, footing_w=7.5, footing_t=2.0, hcw=2.0, a=3.4166666666666665, b=1.25, x_bar=5, x_spa_in=17.0, y_bar=5, y_spa_in=8.5, c=5.0, wingwall_conc_cy=12.43, wingwall_reinf_lbs=1404, footing_conc_cy=18.87, footing_reinf_lbs=1205, culvert_footing_cy_per_ft=0.8, culvert_footing_lbs_per_ft=35.06), HeadwallRow(H=12.5, footing_design=2, L1=15.75, L2=15.75, h1=7.0, h2=7.0, footing_w=8.75, footing_t=2.0, hcw=2.0, a=3.5, b=1.25, x_bar=5, x_spa_in=17.0, y_bar=5, y_spa_in=8.5, c=5.25, wingwall_conc_cy=14.82, wingwall_reinf_lbs=1580, footing_conc_cy=24.41, footing_reinf_lbs=1511, culvert_footing_cy_per_ft=0.89, culvert_footing_lbs_per_ft=40.14), HeadwallRow(H=13.5, footing_design=6, L1=17.0, L2=17.0, h1=7.5, h2=7.5, footing_w=9.5, footing_t=2.0, hcw=2.0, a=3.9166666666666665, b=1.25, x_bar=6, x_spa_in=18.0, y_bar=6, y_spa_in=9.0, c=6.166666666666667, wingwall_conc_cy=17.18, wingwall_reinf_lbs=2139, footing_conc_cy=28.17, footing_reinf_lbs=2024, culvert_footing_cy_per_ft=0.97, culvert_footing_lbs_per_ft=50.56))
culvert normal to the roadway, both wingwalls skewed 45 degrees from the culvert centerline.
- Type:
Type A headwall (sheet 2/6)
- civilpy.structural.odot.box_culvert_headwall.TYPE_C_TABLE = (HeadwallRow(H=6.5, footing_design=1, L1=10.0, L2=10.0, h1=6.5, h2=6.5, footing_w=5.25, footing_t=1.5, hcw=2.5, a=1.4166666666666667, b=1.0, x_bar=5, x_spa_in=17.5, y_bar=5, y_spa_in=17.5, c=2.4166666666666665, wingwall_conc_cy=4.82, wingwall_reinf_lbs=528, footing_conc_cy=8.62, footing_reinf_lbs=587, culvert_footing_cy_per_ft=0.49, culvert_footing_lbs_per_ft=27.84), HeadwallRow(H=7.5, footing_design=1, L1=12.0, L2=12.0, h1=7.5, h2=7.5, footing_w=5.75, footing_t=1.5, hcw=2.5, a=2.0, b=1.0, x_bar=5, x_spa_in=12.0, y_bar=5, y_spa_in=12.0, c=2.4166666666666665, wingwall_conc_cy=6.67, wingwall_reinf_lbs=749, footing_conc_cy=11.0, footing_reinf_lbs=695, culvert_footing_cy_per_ft=0.55, culvert_footing_lbs_per_ft=29.04), HeadwallRow(H=8.5, footing_design=1, L1=14.0, L2=14.0, h1=8.5, h2=8.5, footing_w=6.25, footing_t=1.5, hcw=2.5, a=2.5833333333333335, b=1.0, x_bar=5, x_spa_in=17.5, y_bar=5, y_spa_in=8.75, c=3.5, wingwall_conc_cy=8.82, wingwall_reinf_lbs=1012, footing_conc_cy=13.62, footing_reinf_lbs=823, culvert_footing_cy_per_ft=0.59, culvert_footing_lbs_per_ft=30.15), HeadwallRow(H=9.5, footing_design=1, L1=16.0, L2=16.0, h1=9.5, h2=9.5, footing_w=7.0, footing_t=1.5, hcw=2.5, a=2.9166666666666665, b=1.0, x_bar=5, x_spa_in=17.5, y_bar=5, y_spa_in=8.75, c=3.6666666666666665, wingwall_conc_cy=11.26, wingwall_reinf_lbs=1261, footing_conc_cy=16.89, footing_reinf_lbs=1044, culvert_footing_cy_per_ft=0.64, culvert_footing_lbs_per_ft=33.53), HeadwallRow(H=10.5, footing_design=1, L1=18.0, L2=18.0, h1=10.5, h2=10.5, footing_w=8.0, footing_t=2.0, hcw=2.0, a=3.25, b=1.25, x_bar=5, x_spa_in=18.0, y_bar=5, y_spa_in=9.0, c=3.9166666666666665, wingwall_conc_cy=17.5, wingwall_reinf_lbs=1485, footing_conc_cy=25.34, footing_reinf_lbs=1278, culvert_footing_cy_per_ft=0.85, culvert_footing_lbs_per_ft=38.01), HeadwallRow(H=11.5, footing_design=1, L1=20.0, L2=20.0, h1=11.5, h2=11.5, footing_w=9.0, footing_t=2.0, hcw=2.0, a=3.8333333333333335, b=1.25, x_bar=6, x_spa_in=18.0, y_bar=6, y_spa_in=9.0, c=4.5, wingwall_conc_cy=21.3, wingwall_reinf_lbs=2201, footing_conc_cy=31.12, footing_reinf_lbs=1478, culvert_footing_cy_per_ft=0.92, culvert_footing_lbs_per_ft=39.56), HeadwallRow(H=12.5, footing_design=4, L1=22.0, L2=22.0, h1=12.5, h2=12.5, footing_w=9.75, footing_t=2.0, hcw=2.0, a=4.25, b=1.25, x_bar=6, x_spa_in=16.0, y_bar=6, y_spa_in=8.0, c=5.166666666666667, wingwall_conc_cy=25.47, wingwall_reinf_lbs=2775, footing_conc_cy=36.67, footing_reinf_lbs=2028, culvert_footing_cy_per_ft=1.0, culvert_footing_lbs_per_ft=49.17), HeadwallRow(H=13.5, footing_design=5, L1=24.0, L2=24.0, h1=13.5, h2=13.5, footing_w=10.5, footing_t=2.0, hcw=2.0, a=4.666666666666667, b=1.25, x_bar=6, x_spa_in=13.0, y_bar=6, y_spa_in=6.5, c=5.333333333333333, wingwall_conc_cy=30.0, wingwall_reinf_lbs=3454, footing_conc_cy=42.67, footing_reinf_lbs=2635, culvert_footing_cy_per_ft=1.06, culvert_footing_lbs_per_ft=58.62))
both wingwalls parallel to the roadway (straight extensions of the headwall line); level wall tops (note 9, designed with a 2 ft live-load surcharge).
- Type:
Type C headwall (sheet 5/6)
- civilpy.structural.odot.box_culvert_headwall.WINGWALL_BACKSLOPE = 2.0
1 backslope on Type A and Type B wingwall tops (sheet 6/6 note 8); Type C wingwall tops are level (note 9).
- Type:
2
- class civilpy.structural.odot.box_culvert_headwall.WingwallInput(length_ft: float, skew_deg: float, wall_height_ft: float, foreslope_height_ft: float, cutoff_wall_height_ft: float, footing_width_ft: float, box_wall_thickness_in: float, embankment_slope: float = 2.0)[source]
Bases:
objectProject-supplied dimensions for one wingwall + foreslope wall (sheet 2/8 “WINGWALL ELEVATION” + “SECTION A-A”). All in feet unless named
_in. Nothing here is cataloged – see the module docstring.
- class civilpy.structural.odot.box_culvert_headwall.WingwallLayout(inputs: ~civilpy.structural.odot.box_culvert_headwall.WingwallInput, wingwall_outline: tuple[tuple[float, float, float], tuple[float, float, float], tuple[float, float, float], tuple[float, float, float]], foreslope_section: tuple[tuple[float, float, float], ...], footing_outline: tuple[tuple[float, float, float], tuple[float, float, float], tuple[float, float, float], tuple[float, float, float]], notes: tuple[str, ...] = <factory>)[source]
Bases:
objectThe generated wingwall + foreslope wall.
wingwall_outlineis the wingwall’s flared elevation (top of footing at z = 0, box-face height H tapering to hf at y = L);foreslope_sectionis the Section A-A profile (cutoff wall, footing top, foreslope-wall stem with itst boxthickness, 2:1 embankment line off the back face) in the Y-Z plane;footing_outlineis the footing plan rectangle drawn at the bottom-of-cutoff elevation-hcw.- footing_outline: tuple[tuple[float, float, float], tuple[float, float, float], tuple[float, float, float], tuple[float, float, float]]
- inputs: WingwallInput
- civilpy.structural.odot.box_culvert_headwall.bend_shape(type_: str, **legs: float) tuple[tuple[float, float], ...][source]
The bend polyline for one of the BCHW legend shapes.
type_is"TYPE-1".."TYPE-8";legssupplies the leg lengths the sheet leaves blank (A,B,C,Das applicable,theta_degfor TYPE-2,skew_degfor TYPE-8). RaisesValueErrornaming the valid types and required legs.
- civilpy.structural.odot.box_culvert_headwall.box_wall_thickness_in(span_ft: float) float[source]
Precast box wall thickness
t box, wall(sheet 6/6 note 11): 8 in for 8 ft spans, 10 in for 10 ft spans, 12 in for spans of 12 ft and over.
- civilpy.structural.odot.box_culvert_headwall.design_headwall(inp: HeadwallInput) HeadwallDesign[source]
Resolve a
HeadwallInputagainst the Design Data tables: compute H = box rise + 2 (box slab thickness) + foreslope wall height (sheet 1/6), round up to the next tabulated design height, and return the row with its footing reinforcing and foreslope quantities.
- civilpy.structural.odot.box_culvert_headwall.layout_wingwall(inp: WingwallInput) WingwallLayout[source]
Generate one wingwall + foreslope wall from fully project-supplied dimensions (no catalog lookup – see the module docstring).
Raises
ValueErrorfor a non-positive length/height/width.
civilpy.structural.odot.bridge_railing module
Ohio DOT standard bridge railings and barriers.
Geometry, reinforcement, and design data transcribed from the Ohio DOT
Standard Bridge Drawings (Office of Structural Engineering). Each entry
records the crash test level stated on the drawing’s design-criteria note;
that key indexes the Table A13.2-1 design forces carried in
civilpy.structural.aashto.lrfd.railing, so a cataloged railing can be
fed straight into the yield-line and deck-overhang checks there.
Lengths are in inches and areas in square inches unless a field name says
otherwise. Concrete strength f_c and reinforcing/structural-steel
yields are in ksi. Values are spot-checked against the cited drawings in
the test suite; the drawings remain the controlling document for detailing.
- Sources (SCD number — drawing date / latest cited revision):
BR-1-13 New Jersey shape concrete bridge railing (rev. 2014-01-17) BR-2-15 Bridge sidewalk railing with concrete barrier (rev. 2024-07-19) SBR-1-20 Single slope concrete bridge railing, 42 in (rev. 2024-07-19) SBR-2-20 Single slope concrete median railing, 57 in (rev. 2024-07-19) SBR-3-20 Single slope concrete bridge railing, 36 in (rev. 2024-07-19) TST-1-99 Twin steel tube bridge railing (rev. 2021-01-15) TST-2-21 Three steel tube bridge railing (rev. 2025-01-17) DBR-2-73 Deep beam bridge guardrail (rev. 2002-07-19) DBR-3-11 Deep beam bridge retrofit railing (2011-07-15) TBR-1-11 Thrie beam retrofit railing (rev. 2013-01-18) PCB-91 Portable concrete barrier (rev. 2020-07-17)
- civilpy.structural.odot.bridge_railing.BRIDGE_RAILINGS: dict[str, BridgeRailing] = {'BR-1 (36 in)': BridgeRailing(scd='BR-1-13', scd_date='2014-01-17', designation='BR-1 (36 in)', name='New Jersey shape concrete bridge railing, 36 in', shape='New Jersey', material='reinforced concrete', test_level='TL-4', height=36.0, base_width=18.0, top_width=8.0, section_area=423.25, f_c=4.5, f_y=60.0, vertical_bar_spacing=12.0, bar_sizes=(5, 6), transition_length_ft=14.0, transition_volume_cy=1.63, post_shape='', post_spacing=None, rail_element='', f_y_steel=None, weight_per_ft=None, segment_length_ft=(), rail_height_above_in=None, notes='GFRP deflection-joint stiffening at sawcut joints <= 15 ft o.c.'), 'BR-1 (42 in)': BridgeRailing(scd='BR-1-13', scd_date='2014-01-17', designation='BR-1 (42 in)', name='New Jersey shape concrete bridge railing, 42 in', shape='New Jersey', material='reinforced concrete', test_level='TL-5', height=42.0, base_width=18.0, top_width=8.0, section_area=474.5, f_c=4.5, f_y=60.0, vertical_bar_spacing=12.0, bar_sizes=(5, 6), transition_length_ft=14.0, transition_volume_cy=1.71, post_shape='', post_spacing=None, rail_element='', f_y_steel=None, weight_per_ft=None, segment_length_ft=(), rail_height_above_in=None, notes='Taller TL-5 variant of the 36 in BR-1; transition vertical bars at 9 in o.c.'), 'BR-2 (sidewalk barrier + twin tube)': BridgeRailing(scd='BR-2-15', scd_date='2024-07-19', designation='BR-2 (sidewalk barrier + twin tube)', name='Bridge sidewalk railing with concrete barrier (twin steel tube)', shape='combination (barrier + steel tube)', material='reinforced concrete + steel', test_level='TL-4', height=42.0, base_width=12.0, top_width=12.0, section_area=None, f_c=4.5, f_y=60.0, vertical_bar_spacing=12.0, bar_sizes=(5,), transition_length_ft=None, transition_volume_cy=None, post_shape='HSS 4x4x3/16', post_spacing=78.0, rail_element='2 - HSS 4x3x1/4', f_y_steel=46.0, weight_per_ft=None, segment_length_ft=(), rail_height_above_in=24.0, notes='The 42 in rectangular concrete barrier is the TL-4 crashworthy element; a twin steel tube pedestrian rail mounts on top, extending 2\'-0" above the barrier (combined height 5\'-6"). Optional vandal protection fence (VPF-1-24).'), 'DBR-2 (deep beam)': BridgeRailing(scd='DBR-2-73', scd_date='1973-04-10', designation='DBR-2 (deep beam)', name='Deep beam bridge guardrail', shape='post-and-beam (deep beam)', material='steel', test_level='', height=None, base_width=None, top_width=None, section_area=None, f_c=None, f_y=None, vertical_bar_spacing=None, bar_sizes=(), transition_length_ft=None, transition_volume_cy=None, post_shape='W6x25', post_spacing=75.0, rail_element='deep beam rail + TS 8x4x0.1875', f_y_steel=36.0, weight_per_ft=None, segment_length_ft=(), rail_height_above_in=None, notes='Legacy 1973 guardrail; drawing states no numeric crash test level. See DBR-3-11 for the NCHRP 350 TL-3 retrofit upgrade.'), 'DBR-3 (deep beam retrofit)': BridgeRailing(scd='DBR-3-11', scd_date='2011-07-15', designation='DBR-3 (deep beam retrofit)', name='Deep beam bridge retrofit railing', shape='post-and-beam (deep beam retrofit)', material='steel', test_level='TL-3', height=29.0, base_width=None, top_width=None, section_area=None, f_c=None, f_y=None, vertical_bar_spacing=None, bar_sizes=(), transition_length_ft=None, transition_volume_cy=None, post_shape='W6x25', post_spacing=75.0, rail_element='W-beam rail + HSS 8x4x3/16', f_y_steel=36.0, weight_per_ft=None, segment_length_ft=(), rail_height_above_in=None, notes='NCHRP 350 TL-3 retrofit of DBR-2-73 (FHWA HSSD/B-207). HSS rubrail continuous over >= 3 posts.'), 'PCB (portable, anchored)': BridgeRailing(scd='PCB-91', scd_date='1992-04-24', designation='PCB (portable, anchored)', name='Portable concrete barrier, fully anchored (traffic side)', shape='New Jersey', material='precast concrete', test_level='TL-4', height=32.0, base_width=24.0, top_width=None, section_area=None, f_c=4.0, f_y=None, vertical_bar_spacing=None, bar_sizes=(5,), transition_length_ft=None, transition_volume_cy=None, post_shape='', post_spacing=None, rail_element='', f_y_steel=None, weight_per_ft=None, segment_length_ft=(10.0, 12.0), rail_height_above_in=None, notes='Same barrier as the unanchored PCB; fully anchored on the traffic side it satisfies NCHRP 350 TL-4.'), 'PCB (portable, unanchored)': BridgeRailing(scd='PCB-91', scd_date='1992-04-24', designation='PCB (portable, unanchored)', name='Portable concrete barrier, unanchored', shape='New Jersey', material='precast concrete', test_level='TL-3', height=32.0, base_width=24.0, top_width=None, section_area=None, f_c=4.0, f_y=None, vertical_bar_spacing=None, bar_sizes=(5,), transition_length_ft=None, transition_volume_cy=None, post_shape='', post_spacing=None, rail_element='', f_y_steel=None, weight_per_ft=None, segment_length_ft=(10.0, 12.0), rail_height_above_in=None, notes='Pin-and-loop hinge connection; #8/#5 reinforcement per 509.02. Anchor fully on the traffic side for TL-4 (see PCB anchored entry).'), 'SBR-1 (42 in)': BridgeRailing(scd='SBR-1-20', scd_date='2020-01-17', designation='SBR-1 (42 in)', name='Single slope concrete bridge railing, 42 in', shape='single slope', material='reinforced concrete', test_level='TL-5', height=42.0, base_width=18.0, top_width=None, section_area=588.0, f_c=4.5, f_y=60.0, vertical_bar_spacing=12.0, bar_sizes=(4, 5, 6), transition_length_ft=14.0, transition_volume_cy=1.82, post_shape='', post_spacing=None, rail_element='', f_y_steel=None, weight_per_ft=None, segment_length_ft=(), rail_height_above_in=None, notes='GFRP horizontal (X4) and stiffening (Y401/Y402) bars; steel vertical bars.'), 'SBR-2 (57 in median)': BridgeRailing(scd='SBR-2-20', scd_date='2020-07-17', designation='SBR-2 (57 in median)', name='Single slope concrete median bridge railing, 57 in, Type B1', shape='single slope median', material='reinforced concrete', test_level='TL-3', height=57.0, base_width=33.75, top_width=12.0, section_area=1303.2, f_c=4.5, f_y=60.0, vertical_bar_spacing=24.0, bar_sizes=(4, 5, 8), transition_length_ft=None, transition_volume_cy=None, post_shape='', post_spacing=None, rail_element='', f_y_steel=None, weight_per_ft=None, segment_length_ft=(), rail_height_above_in=None, notes='Single (Type B1) median barrier; #8 dowels in the unreinforced median run. Vertical bars at 24 in o.c. for Type B1.'), 'SBR-2 (57 in median, back-to-back)': BridgeRailing(scd='SBR-2-20', scd_date='2020-07-17', designation='SBR-2 (57 in median, back-to-back)', name='Single slope back-to-back concrete median bridge railing, 57 in', shape='single slope median', material='reinforced concrete', test_level='TL-5', height=57.0, base_width=33.75, top_width=12.0, section_area=1303.2, f_c=4.5, f_y=60.0, vertical_bar_spacing=7.0, bar_sizes=(4, 5, 6), transition_length_ft=None, transition_volume_cy=None, post_shape='', post_spacing=None, rail_element='', f_y_steel=None, weight_per_ft=None, segment_length_ft=(), rail_height_above_in=None, notes='Two SBR-2 barriers back-to-back with 6 in max gap; vertical bars at 7 in o.c.'), 'SBR-3 (36 in)': BridgeRailing(scd='SBR-3-20', scd_date='2020-01-17', designation='SBR-3 (36 in)', name='Single slope concrete bridge railing, 36 in', shape='single slope', material='reinforced concrete', test_level='TL-4', height=36.0, base_width=18.0, top_width=None, section_area=524.0, f_c=4.5, f_y=60.0, vertical_bar_spacing=12.0, bar_sizes=(4, 5, 6), transition_length_ft=14.0, transition_volume_cy=1.74, post_shape='', post_spacing=None, rail_element='', f_y_steel=None, weight_per_ft=None, segment_length_ft=(), rail_height_above_in=None, notes='GFRP horizontal (X4) and stiffening (Y401/Y402) bars; steel vertical bars.'), 'TBR-1 (thrie beam retrofit)': BridgeRailing(scd='TBR-1-11', scd_date='2011-10-21', designation='TBR-1 (thrie beam retrofit)', name='Thrie beam retrofit railing', shape='post-and-beam (thrie beam)', material='steel on concrete curb', test_level='', height=25.5, base_width=None, top_width=None, section_area=None, f_c=4.0, f_y=None, vertical_bar_spacing=None, bar_sizes=(), transition_length_ft=None, transition_volume_cy=None, post_shape='W6x25', post_spacing=75.0, rail_element='thrie beam (M180 Type II Class B)', f_y_steel=None, weight_per_ft=None, segment_length_ft=(), rail_height_above_in=None, notes='Retrofit for AR-1-57 / BR-1-65 railings with 1 ft or 2 ft safety curbs. NHS-acceptable; no numeric crash test level stated.'), 'TST-1 (twin steel tube)': BridgeRailing(scd='TST-1-99', scd_date='1999-07-06', designation='TST-1 (twin steel tube)', name='Twin steel tube bridge railing', shape='post-and-beam (twin tube)', material='steel', test_level='TL-4', height=None, base_width=None, top_width=None, section_area=None, f_c=None, f_y=60.0, vertical_bar_spacing=None, bar_sizes=(), transition_length_ft=None, transition_volume_cy=None, post_shape='W6x25', post_spacing=75.0, rail_element='2 - TS 8x4x5/16', f_y_steel=46.0, weight_per_ft=None, segment_length_ft=(), rail_height_above_in=None, notes='NCHRP 350 TL-4. Measurement = flush-post length + 4 ft-11 in. Not for box-beam bridges with overhang > 2 in or top flange < 5 in.'), 'TST-2 (three steel tube)': BridgeRailing(scd='TST-2-21', scd_date='2021-07-16', designation='TST-2 (three steel tube)', name='Three steel tube bridge railing', shape='post-and-beam (three tube)', material='steel', test_level='TL-4', height=None, base_width=None, top_width=None, section_area=None, f_c=4.5, f_y=60.0, vertical_bar_spacing=None, bar_sizes=(), transition_length_ft=None, transition_volume_cy=None, post_shape='', post_spacing=96.0, rail_element='3 - HSS tube', f_y_steel=50.0, weight_per_ft=80.0, segment_length_ft=(), rail_height_above_in=None, notes='MASH TL-4 (transition to MGS guardrail is MASH TL-3). Post length 4 ft-6 in; min box-beam depth 17 in; max future wearing surface 3 in.')}
Catalog keyed by
designation.
- class civilpy.structural.odot.bridge_railing.BridgeRailing(scd: str, scd_date: str, designation: str, name: str, shape: str, material: str, test_level: str, height: float | None = None, base_width: float | None = None, top_width: float | None = None, section_area: float | None = None, f_c: float | None = None, f_y: float | None = None, vertical_bar_spacing: float | None = None, bar_sizes: tuple[int, ...] = (), transition_length_ft: float | None = None, transition_volume_cy: float | None = None, post_shape: str = '', post_spacing: float | None = None, rail_element: str = '', f_y_steel: float | None = None, weight_per_ft: float | None = None, segment_length_ft: tuple[float, ...] = (), rail_height_above_in: float | None = None, notes: str = '')[source]
Bases:
objectOne Ohio DOT standard bridge railing / barrier configuration.
test_levelis the NCHRP 350 / MASH level stated on the drawing ("TL-2".."TL-6"); it keysTEST_LEVEL_LOADS. An empty string means the drawing states no numeric crash test level. Fields left asNone/""are not called out (or not applicable) on the drawing.Concrete-parapet entries populate
section_area(gross area of the standard, non-transition section),f_c/f_y, and the vertical-bar fields. Post-and-beam steel railings populatepost_shape,post_spacing,rail_element, andf_y_steelinstead.- bar_sizes: tuple[int, ...] = ()
Standard-bar designation numbers present in the section (#5, #6, …).
- design_force_check(m_c: float, m_w: float, m_b: float = 0.0, end_region: bool = False)[source]
Run the AASHTO A13.3.1 yield-line check for this railing against its own test-level design forces.
Only meaningful for concrete-parapet entries.
m_c(kip-ft/ft),m_wandm_b(kip-ft) are the wall’s flexural resistances; the railing’s catalogheight(in) is converted to feet. Returns aCheckResultwhosedemandis the Table A13.2-1 transverse forceFt.
- meets_minimum_height() bool | None[source]
Whether the railing’s height satisfies the minimum rail height
Hfor its test level (Table A13.2-1,h_min).Nonewhen the height or test level is not recorded.For combination and post-and-beam railings
heightmay be the crashworthy element height only; treat the result accordingly.
- rail_height_above_in: float | None = None
For a “combination” railing (full-height concrete barrier + steel tube pedestrian rail on top, e.g. BR-2-15): how far the steel tube assembly extends above the concrete barrier’s own
height, inches.
- test_level_load() TestLevelLoad | None[source]
The Table A13.2-1 design forces for this railing’s test level, or
Noneif the drawing states no numeric crash test level.
- transition_length_ft: float | None = None
Length of the standard approach transition section, feet.
- civilpy.structural.odot.bridge_railing.railing(designation: str) BridgeRailing[source]
Look up a railing by its
designation(e.g."BR-1 (36 in)").
- civilpy.structural.odot.bridge_railing.railings_for_test_level(test_level: str) list[BridgeRailing][source]
All cataloged railings rated for
test_level(e.g."TL-4").
civilpy.structural.odot.capped_pile_abutment module
Ohio DOT capped pile abutment for slab bridges (CPA-1-08).
Transcribed from Ohio DOT Standard Bridge Drawing CPA-1-08, “Capped Pile Abutment for Slab Bridges” (rev. 01-19-2024, 6 sheets: three railing-variant pairs – SBR-1 deflector parapet, three steel tube, twin steel tube – of part-plan/elevation views, all referencing one shared cap cross-section (Section C-C/D-D, sheet 2) and one reinforcing steel table (sheet 4)). SB-1-24’s companion, referenced from its slab elevation as “ABUT. DIAPHRAGM SEE STANDARD DRAWING CPA-1-08”.
Like BCHW (civilpy.structural.odot.box_culvert_headwall), this
sheet mixes a handful of fixed dimensions (cap width 3’-0”, the
1’-6”/1’-6” pile-zone split, max bar spacings) with project-variable
ones the reinforcing steel table itself marks with an asterisk (“DIMENSION
MAY VARY WITH EACH INDIVIDUAL STRUCTURE”) – wingwall length, pile count
and spacing, footing depth, and every skew-dependent bar length (the
S501/S502/S503 bars carry a literal sec(theta) term in their tabulated
length, 1'-5"/COS(theta) etc.). layout_capped_pile_abutment takes
those as required inputs; there is no discrete catalog to look them up
from.
The D801 bar (sheet 4’s bending diagram legend, “TYPE 6 – SEE STANDARD
BRIDGE DRAWING AS-1-15”) is the same bar as
civilpy.structural.odot.approach_slab’s D801/D802 anchor bar –
this sheet does not redefine it, so this module doesn’t either; see
d801_length_ft().
Conventions match the rest of this package: X along stations, Y transverse, Z up; feet in plan, inches for section dimensions. The origin sits on the abutment centerline at the bridge-seat elevation (z = 0), y = 0 at the cap centerline.
- class civilpy.structural.odot.capped_pile_abutment.AbutmentInput(wingwall_length_ft: float, skew_deg: float, n_piles: int, pile_spacing_ft: float, footing_depth_ft: float, cap_width_ft: float = 3.0)[source]
Bases:
objectProject-supplied dimensions for one capped pile abutment.
wingwall_length_ftis the “W” dimension (Section B-B/F-F);n_piles/pile_spacing_ftlay out the cap’s pile line;footing_depth_ftis the cap/footing depth below the bridge seat. Nothing here is cataloged – see the module docstring.
- class civilpy.structural.odot.capped_pile_abutment.AbutmentLayout(inputs: ~civilpy.structural.odot.capped_pile_abutment.AbutmentInput, cap_outline: tuple[tuple[float, float, float], tuple[float, float, float], tuple[float, float, float], tuple[float, float, float]], pile_points: tuple[tuple[float, float, float], ...], wingwall_outline: tuple[tuple[float, float, float], tuple[float, float, float], tuple[float, float, float], tuple[float, float, float]], notes: tuple[str, ...] = <factory>)[source]
Bases:
objectThe generated abutment.
cap_outlineis the cap’s plan footprint (top of cap, z = 0, the bridge seat) extending downfooting_depth_ft;pile_pointsare the pile centerlines along the cap;wingwall_outlineis one flared wingwall plane (mirrorslayout_full_height_headwall()’s convention).- cap_outline: tuple[tuple[float, float, float], tuple[float, float, float], tuple[float, float, float], tuple[float, float, float]]
- inputs: AbutmentInput
- structural_model(reaction: float = 0.0) StructuralModel[source]
Returns a MIDAS-ready StructuralModel of the abutment cap as a beam.
- class civilpy.structural.odot.capped_pile_abutment.RebarMark(mark: 'str', length_ft: 'float | None', bend_type: 'int', a_ft: 'float | None' = None, b_ft: 'float | None' = None, c_ft: 'float | None' = None, note: 'str' = '')[source]
Bases:
object
- civilpy.structural.odot.capped_pile_abutment.bend_shape(bend_type: int, **legs: float) tuple[tuple[float, float], ...][source]
The bend polyline for one of CPA-1-08’s own legend shapes (1-5).
legssupplies whatever the sheet leaves blank (A,B,Cas applicable). RaisesValueErrornaming the valid types (1-5; call intoapproach_slabfor Type 6/D801) and required legs.
- civilpy.structural.odot.capped_pile_abutment.layout_capped_pile_abutment(inp: AbutmentInput) AbutmentLayout[source]
Generate one capped pile abutment from fully project-supplied dimensions (no catalog lookup – see the module docstring).
Raises
ValueErrorfor a non-positive length/spacing/depth or fewer than 2 piles.
civilpy.structural.odot.capped_pile_pier module
Ohio DOT capped pile pier for continuous slab bridges (CPP-1-08).
Transcribed from Ohio DOT Standard Bridge Drawing CPP-1-08, “Capped
Pile Pier for Continuous Slab Bridges” (rev. 07-21-2017, 1 sheet). The
drawing remains the controlling document. CS-1-24’s companion pier
(feasibility rated in ODOT_SCD_Feasibility.md).
Unlike BCHW/CPA-1-08, this sheet is genuinely “clean and parametric”: the pier cap length is a literal formula in terms of the bridge slab width and skew, and the cap cross-section (width, end radius) is fixed regardless of span – there is no “insert design here” blank. Pile count/spacing and the reinforcing bar list quantities remain project-supplied (spacing has a stated max, not a table), same as every capped-pile-cap sheet in this package.
Design basis (General Notes / Design Instructions): AASHTO LRFD + 2008 interim revisions + 2007 ODOT BDM; HL-93; FWS 0.06 ksf; concrete f’c = 4.5 ksi; reinforcing/spiral steel min. yield 60 ksi; HP12X53 steel pile min. yield 50 ksi. Limits of design (exceeding any of these means this standard drawing does not apply): skew <= 30 deg, unsupported pile length <= 20 ft, supports a standard continuous slab with individual span <= 57.50 ft (CS-1-24), sloped embankment/debris/ice-flow lateral force on the pile bent, or piles not driven >= 10 ft into rock/firm material.
Conventions match the rest of this package: X along stations, Y transverse, Z up; feet in plan, inches for section dimensions. The origin sits on the pier centerline (X = 0) at the top-of-cap elevation (Z = 0), Y = 0 on the roadway centerline.
- class civilpy.structural.odot.capped_pile_pier.PierBarMark(mark: 'str', width_ft: 'float | None', height_is_q: 'bool', inside_radius_ft: 'float | None' = None, note: 'str' = '')[source]
Bases:
object
- class civilpy.structural.odot.capped_pile_pier.PierInput(slab_width_ft: float, skew_deg: float, n_piles: int, pile_spacing_ft: float, cap_depth_ft: float = 2.0)[source]
Bases:
objectInputs for a capped pile pier.
slab_width_ftis the bridge slab width (drivespier_length_ft());n_piles/pile_spacing_ftlay out the pile line (spacing must not exceedMAX_PILE_SPACING_FT);cap_depth_ftdefaults to the sheet’s fixedCAP_DEPTH_FT.
- class civilpy.structural.odot.capped_pile_pier.PierLayout(inputs: ~civilpy.structural.odot.capped_pile_pier.PierInput, cap_outline: tuple[tuple[float, float, float], ...], pile_points: tuple[tuple[float, float, float], ...], length_ft: float, notes: tuple[str, ...] = <factory>)[source]
Bases:
objectThe generated pier.
cap_outlineis the rounded-end cap plan footprint (top of cap, z = 0) extending downcap_depth_ft;pile_pointsare the pile centerlines (top of pile, at the cap underside).
- civilpy.structural.odot.capped_pile_pier.layout_capped_pile_pier(inp: PierInput, *, n_arc_segments: int = 8) PierLayout[source]
Generate a capped pile pier: the rounded-end cap solid outline and the pile line, from the sheet’s own pier-length formula.
Raises
ValueErrorfor a non-positive slab width/pile spacing, fewer than 2 piles, a pile spacing beyondMAX_PILE_SPACING_FT, or a skew beyondMAX_SKEW_DEG.
- civilpy.structural.odot.capped_pile_pier.pier_bar(mark: str) PierBarMark[source]
Look up a CPP-1-08 bar mark (P501-P504).
Raises
ValueErrornaming the valid marks otherwise.
civilpy.structural.odot.concrete_curb module
ODOT BP-5.1 Standard Concrete Curbs and Combined Curb & Gutter.
Transcribed from Ohio DOT Standard Roadway Construction Drawing
BP-5.1 (rev. 01-16-2026, 2 sheets), which catalogs 13 named curb/
combined-curb-and-gutter face profiles (Types 1 through 11, several
with lettered substrate variants). Each is a small, fixed cross
section – no span table or design formula – so, consistent with how
civilpy.structural.odot.bridge_railing catalogs a parapet’s
height/top_width/base_width without modeling its exact toe
kick, each entry here is a schematic (height, top_width, base_width)
trapezoid of the curb’s OWN concrete (not the paved gutter pad it may
tie into, and not the exact fillet/rolled-curb arc – those are
approximated as straight chamfers/ramps). The drawing remains the
controlling document for the true face geometry.
Several sheet labels differ only by the pavement/base course the same
curb face sits on (Types 2/2-A/2-B, 3/3-A/3-B, 4/4-A/4-B all share one
profile); those are consolidated into one catalog entry whose
sheet_labels records every name the profile answers to.
height is None for the three types (9, 10, 11) whose height is
the project-specified gutter-plate thickness T (general note:
“Thickness of gutter plate T shall be 9 in unless otherwise shown on
the plans”) – DEFAULT_GUTTER_PLATE_T_IN gives that 9 in default.
Lengths are in inches.
Source: BP-5.1 (rev. 01-16-2026).
- civilpy.structural.odot.concrete_curb.CURB_TOLERANCE_IN = (-0.09375, 0.25)
curb -3/32 to +1/4 in, gutter 0 to +1/8 in.
- Type:
Dimensional tolerances (general note)
- civilpy.structural.odot.concrete_curb.CURB_TYPES: dict[str, CurbType] = {'Type 1': CurbType(sheet_labels=('Type 1',), name='Asphalt curb (wedge)', height=6.0, top_width=4.0, base_width=9.0, toe_radius=None, notes='Sits on the asphalt concrete surface course over base; 42 deg battered face, 2 in top radius (approximated here as a straight-line wedge).'), 'Type 10': CurbType(sheet_labels=('Type 10',), name='Variable-height curb, no gutter pad', height=None, top_width=9.0, base_width=9.0, toe_radius=None, notes='Height is T (default 9 in); no integral gutter pad, back width per the Typical Sections.'), 'Type 10-A': CurbType(sheet_labels=('Type 10-A',), name='Tall curb, 45 deg chamfer', height=18.0, top_width=17.0, base_width=18.0, toe_radius=None, notes='6 in nose + 12 in pavement-contact width; 45 deg chamfer at the top corner (1 in / 2 in radii), approximated here as a 1 in top setback.'), 'Type 10-B': CurbType(sheet_labels=('Type 10-B',), name='Curb at joint (14 in)', height=14.0, top_width=6.0, base_width=6.0, toe_radius=None, notes='Preformed-joint-filler detail like Type 10-A but shorter (14 in) and without the 45 deg chamfer.'), 'Type 11': CurbType(sheet_labels=('Type 11',), name='Wide curb, compound curve face', height=None, top_width=6.0, base_width=24.0, toe_radius=None, notes='Height is T (default the 9 in gutter-plate thickness, per Typical Sections). Face is a compound curve (18 in toe radius, X=4-3/4 in / Y=4-5/8 in offsets) approximated here as a 9+9+6 in straight-segment trapezoid.'), 'Type 2': CurbType(sheet_labels=('Type 2', 'Type 2-A', 'Type 2-B'), name='Vertical curb, integral gutter pad', height=6.0, top_width=5.0, base_width=6.0, toe_radius=3.0, notes='Monolithic with new concrete pavement (Type 2), an asphalt wearing course over concrete base (Type 2-A), or a concrete base course under a wearing course (Type 2-B) -- same curb face on all three. Integral gutter pad extends 2\'-6" (30 in) beyond the toe unless the plans show otherwise, sloped 12:1 down to the pavement.'), 'Type 2-A': CurbType(sheet_labels=('Type 2', 'Type 2-A', 'Type 2-B'), name='Vertical curb, integral gutter pad', height=6.0, top_width=5.0, base_width=6.0, toe_radius=3.0, notes='Monolithic with new concrete pavement (Type 2), an asphalt wearing course over concrete base (Type 2-A), or a concrete base course under a wearing course (Type 2-B) -- same curb face on all three. Integral gutter pad extends 2\'-6" (30 in) beyond the toe unless the plans show otherwise, sloped 12:1 down to the pavement.'), 'Type 2-B': CurbType(sheet_labels=('Type 2', 'Type 2-A', 'Type 2-B'), name='Vertical curb, integral gutter pad', height=6.0, top_width=5.0, base_width=6.0, toe_radius=3.0, notes='Monolithic with new concrete pavement (Type 2), an asphalt wearing course over concrete base (Type 2-A), or a concrete base course under a wearing course (Type 2-B) -- same curb face on all three. Integral gutter pad extends 2\'-6" (30 in) beyond the toe unless the plans show otherwise, sloped 12:1 down to the pavement.'), 'Type 3': CurbType(sheet_labels=('Type 3', 'Type 3-A', 'Type 3-B'), name='Mountable (rolled) curb', height=4.0, top_width=0.0, base_width=10.0, toe_radius=None, notes='Rounds flush with the pavement over a 10 in radius arc (Type 3 on concrete pavement, 3-A on asphalt, 3-B on a wearing course over concrete base) -- approximated here as a straight ramp from pavement to the 4 in curb top, not the true arc.'), 'Type 3-A': CurbType(sheet_labels=('Type 3', 'Type 3-A', 'Type 3-B'), name='Mountable (rolled) curb', height=4.0, top_width=0.0, base_width=10.0, toe_radius=None, notes='Rounds flush with the pavement over a 10 in radius arc (Type 3 on concrete pavement, 3-A on asphalt, 3-B on a wearing course over concrete base) -- approximated here as a straight ramp from pavement to the 4 in curb top, not the true arc.'), 'Type 3-B': CurbType(sheet_labels=('Type 3', 'Type 3-A', 'Type 3-B'), name='Mountable (rolled) curb', height=4.0, top_width=0.0, base_width=10.0, toe_radius=None, notes='Rounds flush with the pavement over a 10 in radius arc (Type 3 on concrete pavement, 3-A on asphalt, 3-B on a wearing course over concrete base) -- approximated here as a straight ramp from pavement to the 4 in curb top, not the true arc.'), 'Type 4': CurbType(sheet_labels=('Type 4', 'Type 4-A', 'Type 4-B'), name='Vertical curb, no integral gutter', height=6.0, top_width=5.0, base_width=6.0, toe_radius=3.0, notes="Same face as Type 2 (concrete pavement / wearing course over concrete base / wearing course over base course respectively) but without an integral gutter pad; back width is project-specified ('as shown on Typical Sections in Plans')."), 'Type 4-A': CurbType(sheet_labels=('Type 4', 'Type 4-A', 'Type 4-B'), name='Vertical curb, no integral gutter', height=6.0, top_width=5.0, base_width=6.0, toe_radius=3.0, notes="Same face as Type 2 (concrete pavement / wearing course over concrete base / wearing course over base course respectively) but without an integral gutter pad; back width is project-specified ('as shown on Typical Sections in Plans')."), 'Type 4-B': CurbType(sheet_labels=('Type 4', 'Type 4-A', 'Type 4-B'), name='Vertical curb, no integral gutter', height=6.0, top_width=5.0, base_width=6.0, toe_radius=3.0, notes="Same face as Type 2 (concrete pavement / wearing course over concrete base / wearing course over base course respectively) but without an integral gutter pad; back width is project-specified ('as shown on Typical Sections in Plans')."), 'Type 4-C': CurbType(sheet_labels=('Type 4-C',), name='Tall curb at approach slab joint', height=16.0, top_width=5.0, base_width=6.0, toe_radius=None, notes='Used where the curb meets a pavement/approach-slab expansion joint; 1 in preformed joint filler (Item 705.03) + joint sealer (Item 705.04), full curb height per the general JOINTS note.'), 'Type 6': CurbType(sheet_labels=('Type 6',), name='Tall curb at joint (18 in)', height=18.0, top_width=6.0, base_width=8.0, toe_radius=None, notes='Taller sibling of Type 4-C (18 in vs 16 in); same preformed-joint-filler / sealer detail at pavement joints.'), 'Type 7': CurbType(sheet_labels=('Type 7',), name='Median curb against earth', height=10.0, top_width=6.5, base_width=8.0, toe_radius=None, notes='Backed by earth (not pavement/base); 1 in preformed joint filler at the pavement side.'), 'Type 8': CurbType(sheet_labels=('Type 8',), name='Median curb, shoulder/pavement joint', height=9.0, top_width=9.0, base_width=12.0, toe_radius=None, notes='Asphalt pavement or shoulder on one face, pavement on the other, with a joint-sealed interface between them.'), 'Type 9': CurbType(sheet_labels=('Type 9',), name='Variable-height curb, gutter pad', height=None, top_width=9.0, base_width=21.0, toe_radius=None, notes='Height is the project gutter-plate thickness T (default 9 in). Top cross slope matches the roadway cross slope; 9 in nose + 12 in gutter pad.')}
Catalog keyed by every sheet label it answers to (so
"Type 2-A"and"Type 2-B"both resolve to the Type 2 entry).
- class civilpy.structural.odot.concrete_curb.CurbType(sheet_labels: tuple[str, ...], name: str, height: float | None, top_width: float, base_width: float, toe_radius: float | None = None, notes: str = '')[source]
Bases:
objectOne BP-5.1 curb / combined curb-and-gutter cross section.
heightis the curb’s own face height (in),Nonewhen it is the project-variable gutter-plate thicknessT.top_width/base_widthdescribe a schematic trapezoid of the curb’s concrete only (see module docstring for what is and isn’t modeled).
- civilpy.structural.odot.concrete_curb.DEFAULT_GUTTER_PLATE_T_IN = 9.0
gutter plate thickness T defaults to 9 in unless the plans show otherwise (governs Types 9, 10, 11’s variable height).
- Type:
General note
- civilpy.structural.odot.concrete_curb.EXPANSION_JOINT_WIDTH_IN = 1.0
1 in transverse expansion joints, Item 705.03 filler / 705.04 sealer, at curb-and-gutter expansion joints and approach slabs.
- Type:
General note
- civilpy.structural.odot.concrete_curb.curb_height_in(label: str, *, gutter_plate_t_in: float | None = None) float[source]
Resolved curb height (in): the catalog
heightif fixed, else the projectgutter_plate_t_in(defaulting toDEFAULT_GUTTER_PLATE_T_IN) for the variable-height types.
- civilpy.structural.odot.concrete_curb.curb_profile_in(label: str, *, gutter_plate_t_in: float | None = None) tuple[tuple[float, float], ...][source]
Schematic closed trapezoid profile (in) for
label,(offset, z)counterclockwise from the back-bottom corner,offsetmeasured from the curb’s back face andzup from the pavement surface.
civilpy.structural.odot.continuous_slab_bridge module
Ohio DOT three-span continuous slab bridges (CS-1-24).
Transcribed from Ohio DOT Standard Bridge Drawing CS-1-24, “Continuous
Slab Bridge” (rev. 01-16-2026, 4 sheets). The drawing remains the
controlling document. SB-1-24’s continuous-span sibling; CPP-1-08 is its
pier (civilpy.structural.odot.capped_pile_pier).
Sheet 2’s SLAB DATA table gives, for 33 tabulated end spans (14 to
46 ft), the slab thickness and the full longitudinal (A/B bottom, C/D top,
E top-at-pier) and transverse (N bottom, M top, U lap) reinforcing
schedule – 779 numeric entries, the largest table in the SCD program.
The interior span is always 1.25x the end span (a fixed ratio baked
into the “SPANS (FEET)” column, e.g. “14 - 17.50 - 14”), not a separately
tabulated value – see interior_span_ft(). Sheet 1 also gives the Y
offset formula for the first M-bar (m_bar_offset_in()).
Design basis (sheet 2 notes): same as SB-1-24 – AASHTO LRFD 9th Ed. + ODOT BDM (July 2023); HL-93; FWS 60 lb/ft^2; 1 in monolithic wearing surface; concrete f’c = 4500 psi; reinforcing steel min. yield 60,000 psi, epoxy coated. Applicable for roadway widths >= 24 ft and skew <= 25 deg (identical applicability notes to SB-1-24). Additional interior spans (same length as the middle span) may be added without changing slab thickness or area of reinforcing steel (sheet 2 General note).
Conventions match civilpy.structural.odot.slab_bridge: X along
stations, Y transverse, Z up; feet in plan, inches for section
dimensions. The layout origin sits at the first (upstream) abutment
bearing line, y = 0 at one slab edge, z = 0 at the top of slab.
- class civilpy.structural.odot.continuous_slab_bridge.ABarSpec(spacing_in: 'float', size: 'int', a_ft: 'float', length_ft: 'float')[source]
Bases:
BarSpec
- class civilpy.structural.odot.continuous_slab_bridge.BarRun(mark: 'str', size: 'int', points: 'tuple[Point, ...]')[source]
Bases:
object
- class civilpy.structural.odot.continuous_slab_bridge.BarSpec(spacing_in: 'float', size: 'int')[source]
Bases:
object
- class civilpy.structural.odot.continuous_slab_bridge.CSSlabDesign(end_span_ft: int, thickness_in: float, a_bar: ABarSpec, b_bar: LenBarSpec, c_bar: LenBarSpec, d_bar: LenBarSpec, e_bar: LenBarSpec | None, n_bar: CountBarSpec, m_bar: CountBarSpec, u_bar_count: int)[source]
Bases:
objectOne
SLAB DATAtable row (sheet 2), keyed by end span (ft).- b_bar: LenBarSpec
- c_bar: LenBarSpec
- d_bar: LenBarSpec
- e_bar: LenBarSpec | None
- m_bar: CountBarSpec
- n_bar: CountBarSpec
- civilpy.structural.odot.continuous_slab_bridge.CS_SLAB_DESIGNS: dict[int, CSSlabDesign] = {14: CSSlabDesign(end_span_ft=14, thickness_in=11, a_bar=ABarSpec(spacing_in=7, size=8, a_ft='16\'-7"', length_ft=17.5), b_bar=LenBarSpec(spacing_in=7, size=8, length_ft=21.5), c_bar=LenBarSpec(spacing_in=7, size=5, length_ft=7.5), d_bar=LenBarSpec(spacing_in=7, size=8, length_ft=21.166667), e_bar=None, n_bar=CountBarSpec(spacing_in=15.0, size=6, count=47), m_bar=CountBarSpec(spacing_in=12.0, size=4, count=47), u_bar_count=78), 15: CSSlabDesign(end_span_ft=15, thickness_in=11.5, a_bar=ABarSpec(spacing_in=7, size=8, a_ft='17\'-7"', length_ft=18.5), b_bar=LenBarSpec(spacing_in=7, size=8, length_ft=22.75), c_bar=LenBarSpec(spacing_in=7, size=5, length_ft=7.833333), d_bar=LenBarSpec(spacing_in=7, size=8, length_ft=22.5), e_bar=None, n_bar=CountBarSpec(spacing_in=15.0, size=6, count=49), m_bar=CountBarSpec(spacing_in=12.0, size=4, count=50), u_bar_count=82), 16: CSSlabDesign(end_span_ft=16, thickness_in=12, a_bar=ABarSpec(spacing_in=7, size=8, a_ft='18\'-7"', length_ft=19.5), b_bar=LenBarSpec(spacing_in=7, size=8, length_ft=24.0), c_bar=LenBarSpec(spacing_in=7, size=5, length_ft=8.25), d_bar=LenBarSpec(spacing_in=7, size=8, length_ft=23.666667), e_bar=None, n_bar=CountBarSpec(spacing_in=15.0, size=6, count=52), m_bar=CountBarSpec(spacing_in=12.0, size=4, count=53), u_bar_count=88), 17: CSSlabDesign(end_span_ft=17, thickness_in=12.5, a_bar=ABarSpec(spacing_in=7, size=8, a_ft='19\'-7"', length_ft=20.5), b_bar=LenBarSpec(spacing_in=7, size=8, length_ft=25.25), c_bar=LenBarSpec(spacing_in=7, size=5, length_ft=8.583333), d_bar=LenBarSpec(spacing_in=7, size=8, length_ft=25.0), e_bar=None, n_bar=CountBarSpec(spacing_in=15.0, size=6, count=54), m_bar=CountBarSpec(spacing_in=12.0, size=4, count=56), u_bar_count=92), 18: CSSlabDesign(end_span_ft=18, thickness_in=13, a_bar=ABarSpec(spacing_in=7, size=8, a_ft='20\'-7"', length_ft=21.5), b_bar=LenBarSpec(spacing_in=7, size=8, length_ft=26.5), c_bar=LenBarSpec(spacing_in=7, size=5, length_ft=9.0), d_bar=LenBarSpec(spacing_in=7, size=8, length_ft=26.166667), e_bar=None, n_bar=CountBarSpec(spacing_in=15.0, size=6, count=57), m_bar=CountBarSpec(spacing_in=12.0, size=4, count=60), u_bar_count=98), 19: CSSlabDesign(end_span_ft=19, thickness_in=13.5, a_bar=ABarSpec(spacing_in=7, size=8, a_ft='21\'-7"', length_ft=22.5), b_bar=LenBarSpec(spacing_in=7, size=8, length_ft=27.75), c_bar=LenBarSpec(spacing_in=7, size=5, length_ft=9.333333), d_bar=LenBarSpec(spacing_in=7, size=8, length_ft=27.5), e_bar=None, n_bar=CountBarSpec(spacing_in=15.0, size=6, count=60), m_bar=CountBarSpec(spacing_in=12.0, size=4, count=63), u_bar_count=104), 20: CSSlabDesign(end_span_ft=20, thickness_in=14, a_bar=ABarSpec(spacing_in=7, size=8, a_ft='22\'-7"', length_ft=23.5), b_bar=LenBarSpec(spacing_in=7, size=8, length_ft=29.0), c_bar=LenBarSpec(spacing_in=7, size=5, length_ft=9.75), d_bar=LenBarSpec(spacing_in=7, size=8, length_ft=28.666667), e_bar=None, n_bar=CountBarSpec(spacing_in=15.0, size=6, count=62), m_bar=CountBarSpec(spacing_in=12.0, size=4, count=66), u_bar_count=108), 21: CSSlabDesign(end_span_ft=21, thickness_in=14.5, a_bar=ABarSpec(spacing_in=7, size=8, a_ft='23\'-7"', length_ft=24.5), b_bar=LenBarSpec(spacing_in=7, size=8, length_ft=30.25), c_bar=LenBarSpec(spacing_in=7, size=5, length_ft=10.083333), d_bar=LenBarSpec(spacing_in=7, size=8, length_ft=30.0), e_bar=None, n_bar=CountBarSpec(spacing_in=15.0, size=6, count=65), m_bar=CountBarSpec(spacing_in=12.0, size=4, count=69), u_bar_count=114), 22: CSSlabDesign(end_span_ft=22, thickness_in=15, a_bar=ABarSpec(spacing_in=7, size=8, a_ft='24\'-7"', length_ft=25.5), b_bar=LenBarSpec(spacing_in=7, size=8, length_ft=31.5), c_bar=LenBarSpec(spacing_in=7, size=5, length_ft=13.666667), d_bar=LenBarSpec(spacing_in=7, size=8, length_ft=24.833333), e_bar=LenBarSpec(spacing_in=7, size=5, length_ft=9.916667), n_bar=CountBarSpec(spacing_in=15.0, size=6, count=67), m_bar=CountBarSpec(spacing_in=12.0, size=4, count=73), u_bar_count=118), 23: CSSlabDesign(end_span_ft=23, thickness_in=15.5, a_bar=ABarSpec(spacing_in=7, size=8, a_ft='25\'-7"', length_ft=26.5), b_bar=LenBarSpec(spacing_in=7, size=8, length_ft=32.75), c_bar=LenBarSpec(spacing_in=7, size=5, length_ft=14.25), d_bar=LenBarSpec(spacing_in=7, size=8, length_ft=25.666667), e_bar=LenBarSpec(spacing_in=7, size=5, length_ft=10.333333), n_bar=CountBarSpec(spacing_in=15.0, size=6, count=70), m_bar=CountBarSpec(spacing_in=12.0, size=4, count=76), u_bar_count=124), 24: CSSlabDesign(end_span_ft=24, thickness_in=16, a_bar=ABarSpec(spacing_in=7, size=8, a_ft='26\'-7"', length_ft=27.5), b_bar=LenBarSpec(spacing_in=7, size=8, length_ft=34.0), c_bar=LenBarSpec(spacing_in=6, size=5, length_ft=14.833333), d_bar=LenBarSpec(spacing_in=6, size=8, length_ft=26.583333), e_bar=LenBarSpec(spacing_in=6, size=5, length_ft=10.833333), n_bar=CountBarSpec(spacing_in=15.0, size=6, count=73), m_bar=CountBarSpec(spacing_in=12.0, size=4, count=79), u_bar_count=130), 25: CSSlabDesign(end_span_ft=25, thickness_in=16.5, a_bar=ABarSpec(spacing_in=7, size=8, a_ft='27\'-7"', length_ft=28.5), b_bar=LenBarSpec(spacing_in=7, size=8, length_ft=35.25), c_bar=LenBarSpec(spacing_in=6, size=5, length_ft=15.416667), d_bar=LenBarSpec(spacing_in=6, size=8, length_ft=27.333333), e_bar=LenBarSpec(spacing_in=6, size=5, length_ft=11.25), n_bar=CountBarSpec(spacing_in=15.0, size=6, count=75), m_bar=CountBarSpec(spacing_in=12.0, size=4, count=82), u_bar_count=134), 26: CSSlabDesign(end_span_ft=26, thickness_in=17, a_bar=ABarSpec(spacing_in=7, size=8, a_ft='28\'-7"', length_ft=29.5), b_bar=LenBarSpec(spacing_in=7, size=8, length_ft=36.5), c_bar=LenBarSpec(spacing_in=6, size=5, length_ft=16.083333), d_bar=LenBarSpec(spacing_in=6, size=8, length_ft=28.083333), e_bar=LenBarSpec(spacing_in=6, size=5, length_ft=11.666667), n_bar=CountBarSpec(spacing_in=15.0, size=6, count=78), m_bar=CountBarSpec(spacing_in=12.0, size=4, count=86), u_bar_count=140), 27: CSSlabDesign(end_span_ft=27, thickness_in=17.5, a_bar=ABarSpec(spacing_in=7, size=8, a_ft='29\'-7"', length_ft=30.5), b_bar=LenBarSpec(spacing_in=7, size=8, length_ft=37.75), c_bar=LenBarSpec(spacing_in=6, size=5, length_ft=16.666667), d_bar=LenBarSpec(spacing_in=6, size=8, length_ft=28.833333), e_bar=LenBarSpec(spacing_in=6, size=5, length_ft=12.166667), n_bar=CountBarSpec(spacing_in=15.0, size=6, count=80), m_bar=CountBarSpec(spacing_in=12.0, size=4, count=89), u_bar_count=144), 28: CSSlabDesign(end_span_ft=28, thickness_in=18, a_bar=ABarSpec(spacing_in=6, size=8, a_ft='30\'-7"', length_ft=31.5), b_bar=LenBarSpec(spacing_in=6, size=8, length_ft=39.0), c_bar=LenBarSpec(spacing_in=6, size=5, length_ft=17.25), d_bar=LenBarSpec(spacing_in=6, size=8, length_ft=29.666667), e_bar=LenBarSpec(spacing_in=6, size=5, length_ft=12.583333), n_bar=CountBarSpec(spacing_in=15.0, size=6, count=83), m_bar=CountBarSpec(spacing_in=12.0, size=4, count=92), u_bar_count=150), 29: CSSlabDesign(end_span_ft=29, thickness_in=18.5, a_bar=ABarSpec(spacing_in=6, size=8, a_ft='31\'-7"', length_ft=32.5), b_bar=LenBarSpec(spacing_in=6, size=8, length_ft=40.25), c_bar=LenBarSpec(spacing_in=6, size=5, length_ft=17.833333), d_bar=LenBarSpec(spacing_in=6, size=8, length_ft=30.583333), e_bar=LenBarSpec(spacing_in=6, size=5, length_ft=13.0), n_bar=CountBarSpec(spacing_in=15.0, size=6, count=86), m_bar=CountBarSpec(spacing_in=12.0, size=4, count=95), u_bar_count=156), 30: CSSlabDesign(end_span_ft=30, thickness_in=19, a_bar=ABarSpec(spacing_in=6, size=8, a_ft='32\'-7"', length_ft=33.5), b_bar=LenBarSpec(spacing_in=6, size=8, length_ft=41.5), c_bar=LenBarSpec(spacing_in=7, size=5, length_ft=18.416667), d_bar=LenBarSpec(spacing_in=7, size=9, length_ft=33.0), e_bar=LenBarSpec(spacing_in=7, size=5, length_ft=13.5), n_bar=CountBarSpec(spacing_in=15.0, size=6, count=88), m_bar=CountBarSpec(spacing_in=12.0, size=4, count=99), u_bar_count=160), 31: CSSlabDesign(end_span_ft=31, thickness_in=19.5, a_bar=ABarSpec(spacing_in=6, size=8, a_ft='33\'-7"', length_ft=34.5), b_bar=LenBarSpec(spacing_in=6, size=8, length_ft=42.75), c_bar=LenBarSpec(spacing_in=7, size=5, length_ft=19.0), d_bar=LenBarSpec(spacing_in=7, size=9, length_ft=33.833333), e_bar=LenBarSpec(spacing_in=7, size=5, length_ft=13.916667), n_bar=CountBarSpec(spacing_in=15.0, size=6, count=91), m_bar=CountBarSpec(spacing_in=12.0, size=4, count=102), u_bar_count=166), 32: CSSlabDesign(end_span_ft=32, thickness_in=20, a_bar=ABarSpec(spacing_in=6, size=8, a_ft='34\'-7"', length_ft=35.5), b_bar=LenBarSpec(spacing_in=6, size=8, length_ft=44.0), c_bar=LenBarSpec(spacing_in=7, size=5, length_ft=19.666667), d_bar=LenBarSpec(spacing_in=7, size=9, length_ft=34.5), e_bar=LenBarSpec(spacing_in=7, size=5, length_ft=14.333333), n_bar=CountBarSpec(spacing_in=15.0, size=6, count=93), m_bar=CountBarSpec(spacing_in=12.0, size=5, count=105), u_bar_count=170), 33: CSSlabDesign(end_span_ft=33, thickness_in=20.5, a_bar=ABarSpec(spacing_in=6, size=8, a_ft='35\'-7"', length_ft=36.5), b_bar=LenBarSpec(spacing_in=6, size=8, length_ft=45.25), c_bar=LenBarSpec(spacing_in=6, size=5, length_ft=20.25), d_bar=LenBarSpec(spacing_in=6, size=9, length_ft=35.333333), e_bar=LenBarSpec(spacing_in=6, size=5, length_ft=14.75), n_bar=CountBarSpec(spacing_in=15.0, size=6, count=96), m_bar=CountBarSpec(spacing_in=12.0, size=5, count=108), u_bar_count=176), 34: CSSlabDesign(end_span_ft=34, thickness_in=21, a_bar=ABarSpec(spacing_in=6, size=8, a_ft='36\'-7"', length_ft=37.5), b_bar=LenBarSpec(spacing_in=6, size=8, length_ft=46.5), c_bar=LenBarSpec(spacing_in=6, size=5, length_ft=20.833333), d_bar=LenBarSpec(spacing_in=6, size=9, length_ft=36.25), e_bar=LenBarSpec(spacing_in=6, size=5, length_ft=15.166667), n_bar=CountBarSpec(spacing_in=15.0, size=6, count=99), m_bar=CountBarSpec(spacing_in=12.0, size=5, count=112), u_bar_count=182), 35: CSSlabDesign(end_span_ft=35, thickness_in=21.5, a_bar=ABarSpec(spacing_in=7, size=9, a_ft='37\'-10"', length_ft=39.083333), b_bar=LenBarSpec(spacing_in=7, size=9, length_ft=48.25), c_bar=LenBarSpec(spacing_in=6, size=5, length_ft=21.416667), d_bar=LenBarSpec(spacing_in=6, size=9, length_ft=37.0), e_bar=LenBarSpec(spacing_in=6, size=5, length_ft=15.666667), n_bar=CountBarSpec(spacing_in=15.0, size=6, count=101), m_bar=CountBarSpec(spacing_in=12.0, size=5, count=115), u_bar_count=186), 36: CSSlabDesign(end_span_ft=36, thickness_in=22, a_bar=ABarSpec(spacing_in=7, size=9, a_ft='38\'-10"', length_ft=40.083333), b_bar=LenBarSpec(spacing_in=7, size=9, length_ft=49.5), c_bar=LenBarSpec(spacing_in=6, size=5, length_ft=22.0), d_bar=LenBarSpec(spacing_in=6, size=9, length_ft=37.833333), e_bar=LenBarSpec(spacing_in=6, size=5, length_ft=16.083333), n_bar=CountBarSpec(spacing_in=15.0, size=6, count=104), m_bar=CountBarSpec(spacing_in=12.0, size=5, count=118), u_bar_count=192), 37: CSSlabDesign(end_span_ft=37, thickness_in=22.5, a_bar=ABarSpec(spacing_in=7, size=9, a_ft='39\'-10"', length_ft=41.083333), b_bar=LenBarSpec(spacing_in=7, size=9, length_ft=50.75), c_bar=LenBarSpec(spacing_in=6, size=5, length_ft=22.583333), d_bar=LenBarSpec(spacing_in=6, size=9, length_ft=38.75), e_bar=LenBarSpec(spacing_in=6, size=5, length_ft=16.583333), n_bar=CountBarSpec(spacing_in=15.0, size=6, count=106), m_bar=CountBarSpec(spacing_in=12.0, size=5, count=121), u_bar_count=196), 38: CSSlabDesign(end_span_ft=38, thickness_in=23, a_bar=ABarSpec(spacing_in=7, size=9, a_ft='40\'-10"', length_ft=42.083333), b_bar=LenBarSpec(spacing_in=7, size=9, length_ft=52.0), c_bar=LenBarSpec(spacing_in=7, size=5, length_ft=23.25), d_bar=LenBarSpec(spacing_in=7, size=10, length_ft=41.333333), e_bar=LenBarSpec(spacing_in=7, size=5, length_ft=17.0), n_bar=CountBarSpec(spacing_in=15.0, size=6, count=109), m_bar=CountBarSpec(spacing_in=12.0, size=5, count=125), u_bar_count=202), 39: CSSlabDesign(end_span_ft=39, thickness_in=23.5, a_bar=ABarSpec(spacing_in=7, size=9, a_ft='41\'-10"', length_ft=43.083333), b_bar=LenBarSpec(spacing_in=7, size=9, length_ft=53.25), c_bar=LenBarSpec(spacing_in=7, size=5, length_ft=23.833333), d_bar=LenBarSpec(spacing_in=7, size=10, length_ft=42.25), e_bar=LenBarSpec(spacing_in=7, size=5, length_ft=17.5), n_bar=CountBarSpec(spacing_in=15.0, size=6, count=112), m_bar=CountBarSpec(spacing_in=12.0, size=5, count=128), u_bar_count=208), 40: CSSlabDesign(end_span_ft=40, thickness_in=24, a_bar=ABarSpec(spacing_in=7, size=9, a_ft='42\'-10"', length_ft=44.083333), b_bar=LenBarSpec(spacing_in=7, size=9, length_ft=54.5), c_bar=LenBarSpec(spacing_in=7, size=5, length_ft=24.416667), d_bar=LenBarSpec(spacing_in=7, size=10, length_ft=43.0), e_bar=LenBarSpec(spacing_in=7, size=5, length_ft=17.916667), n_bar=CountBarSpec(spacing_in=15.0, size=6, count=114), m_bar=CountBarSpec(spacing_in=12.0, size=5, count=131), u_bar_count=212), 41: CSSlabDesign(end_span_ft=41, thickness_in=24.5, a_bar=ABarSpec(spacing_in=6, size=9, a_ft='43\'-10"', length_ft=45.083333), b_bar=LenBarSpec(spacing_in=6, size=9, length_ft=55.75), c_bar=LenBarSpec(spacing_in=6, size=5, length_ft=25.0), d_bar=LenBarSpec(spacing_in=6, size=10, length_ft=43.833333), e_bar=LenBarSpec(spacing_in=6, size=5, length_ft=18.416667), n_bar=CountBarSpec(spacing_in=15.0, size=6, count=117), m_bar=CountBarSpec(spacing_in=12.0, size=5, count=134), u_bar_count=218), 42: CSSlabDesign(end_span_ft=42, thickness_in=25, a_bar=ABarSpec(spacing_in=6, size=9, a_ft='44\'-10"', length_ft=46.083333), b_bar=LenBarSpec(spacing_in=6, size=9, length_ft=57.0), c_bar=LenBarSpec(spacing_in=6, size=5, length_ft=25.666667), d_bar=LenBarSpec(spacing_in=6, size=10, length_ft=44.5), e_bar=LenBarSpec(spacing_in=6, size=5, length_ft=18.833333), n_bar=CountBarSpec(spacing_in=15.0, size=6, count=119), m_bar=CountBarSpec(spacing_in=12.0, size=5, count=138), u_bar_count=222), 43: CSSlabDesign(end_span_ft=43, thickness_in=25.5, a_bar=ABarSpec(spacing_in=6, size=9, a_ft='45\'-10"', length_ft=47.083333), b_bar=LenBarSpec(spacing_in=6, size=9, length_ft=58.25), c_bar=LenBarSpec(spacing_in=6, size=5, length_ft=26.25), d_bar=LenBarSpec(spacing_in=6, size=10, length_ft=45.333333), e_bar=LenBarSpec(spacing_in=6, size=5, length_ft=19.25), n_bar=CountBarSpec(spacing_in=15.0, size=6, count=122), m_bar=CountBarSpec(spacing_in=12.0, size=5, count=141), u_bar_count=228), 44: CSSlabDesign(end_span_ft=44, thickness_in=26, a_bar=ABarSpec(spacing_in=6, size=9, a_ft='46\'-10"', length_ft=48.083333), b_bar=LenBarSpec(spacing_in=6, size=9, length_ft=59.5), c_bar=LenBarSpec(spacing_in=6, size=5, length_ft=26.833333), d_bar=LenBarSpec(spacing_in=6, size=10, length_ft=46.25), e_bar=LenBarSpec(spacing_in=6, size=5, length_ft=19.666667), n_bar=CountBarSpec(spacing_in=15.0, size=6, count=125), m_bar=CountBarSpec(spacing_in=12.0, size=5, count=144), u_bar_count=234), 45: CSSlabDesign(end_span_ft=45, thickness_in=26.5, a_bar=ABarSpec(spacing_in=7, size=10, a_ft='48\'-1"', length_ft=49.5), b_bar=LenBarSpec(spacing_in=7, size=10, length_ft=61.25), c_bar=LenBarSpec(spacing_in=6, size=5, length_ft=27.416667), d_bar=LenBarSpec(spacing_in=6, size=10, length_ft=47.0), e_bar=LenBarSpec(spacing_in=6, size=5, length_ft=20.166667), n_bar=CountBarSpec(spacing_in=15.0, size=6, count=127), m_bar=CountBarSpec(spacing_in=12.0, size=5, count=147), u_bar_count=238), 46: CSSlabDesign(end_span_ft=46, thickness_in=27, a_bar=ABarSpec(spacing_in=7, size=10, a_ft='49\'-1"', length_ft=50.5), b_bar=LenBarSpec(spacing_in=7, size=10, length_ft=62.5), c_bar=LenBarSpec(spacing_in=6, size=5, length_ft=28.083333), d_bar=LenBarSpec(spacing_in=6, size=10, length_ft=47.75), e_bar=LenBarSpec(spacing_in=6, size=5, length_ft=20.666667), n_bar=CountBarSpec(spacing_in=15.0, size=6, count=130), m_bar=CountBarSpec(spacing_in=12.0, size=5, count=151), u_bar_count=244)}
CS-1-24
SLAB DATA, keyed by end span (ft). D-bar SIZE is transcribed explicitly per row (it steps 8->9 at span 30 and 9->10 at span 38, which does not line up with the A/B/M-bar thickness thresholds below – do not infer it fromt). A/B-bar size steps 8->9 at span 35 (T=21.5) and 9->10 at span 45 (T=26.5); M-bar size steps 4->5 at span 32 (T=20).
- class civilpy.structural.odot.continuous_slab_bridge.ContinuousSlabComponent(inp: ContinuousSlabInput)[source]
Bases:
objectAnalytical component for a 3-span continuous slab (CS-1-24).
- structural_model(level: str = 'L1') StructuralModel[source]
Returns a MIDAS-ready StructuralModel (L1 strip or L2 grillage).
- class civilpy.structural.odot.continuous_slab_bridge.ContinuousSlabInput(end_span_ft: int, width_ft: float, skew_deg: float = 0.0)[source]
Bases:
objectProject dimensions for a 3-span continuous slab bridge (CS-1-24).
- class civilpy.structural.odot.continuous_slab_bridge.ContinuousSlabLayout(inputs: ~civilpy.structural.odot.continuous_slab_bridge.ContinuousSlabInput, outline: tuple[tuple[float, float, float], tuple[float, float, float], tuple[float, float, float], tuple[float, float, float]], thickness_in: float, total_length_ft: float, pier_stations: tuple[float, float], bars: tuple[~civilpy.structural.odot.continuous_slab_bridge.BarRun, ...], notes: tuple[str, ...] = <factory>)[source]
Bases:
objectThe generated three-span continuous slab bridge.
outlineis the skewed plan parallelogram at z = 0 (top of slab, uniform thickness – haunches over the piers are not modeled);pier_stationsare the two pier centerline X coordinates.- inputs: ContinuousSlabInput
- class civilpy.structural.odot.continuous_slab_bridge.CountBarSpec(spacing_in: 'float', size: 'int', count: 'int')[source]
Bases:
BarSpec
- civilpy.structural.odot.continuous_slab_bridge.INTERIOR_SPAN_RATIO = 1.25
Interior span = end span * this ratio (fixed on every tabulated row).
- civilpy.structural.odot.continuous_slab_bridge.LAP_SPLICE_FT = {4: {'single': 3.0}, 5: {'single': 3.8333333333333335}, 6: {'single': 4.333333333333333}, 8: {'bot': 7.25, 'top': 6.583333333333333}, 9: {'bot': 8.916666666666666, 'top': 7.333333333333333}, 10: {'bot': 10.916666666666666, 'top': 8.75}}
Lap splice lengths by bar size, feet (“TOP”/”BOT” where the sheet gives both; #4/#5/#6 give a single length).
- class civilpy.structural.odot.continuous_slab_bridge.LenBarSpec(spacing_in: 'float', size: 'int', length_ft: 'float')[source]
Bases:
BarSpec
- civilpy.structural.odot.continuous_slab_bridge.cs_slab_design(end_span_ft: int) CSSlabDesign[source]
Look up the CS-1-24 slab design for an end span (feet, 14-46 tabulated; interior span is always 1.25x, see
interior_span_ft()).Raises
ValueErrornaming the valid spans otherwise.
- civilpy.structural.odot.continuous_slab_bridge.interior_span_ft(end_span_ft: float) float[source]
Interior span = end span * 1.25 (fixed ratio, sheet 2’s SLAB DATA “SPANS” column, e.g. 14 ft end -> 17.50 ft interior).
- civilpy.structural.odot.continuous_slab_bridge.layout_continuous_slab(inp: ContinuousSlabInput) ContinuousSlabLayout[source]
Generate a three-span continuous slab bridge: plan outline, thickness, pier stations, and the A/B/C/D/E longitudinal bar mats (transverse N/M bars are cataloged by count, not separately drawn).
Raises
ValueErrorfor an untabulated end span or a skew beyond the sheet’s 25 deg limit.
civilpy.structural.odot.deck_design module
Ohio DOT standard reinforced concrete deck designs (BDM 309.3).
Design policy, the minimum-thickness formula, and the standard deck design table transcribed from the Ohio DOT Bridge Design Manual, 2020 Edition, January 2026 revision, Section 309.3 “Reinforced Concrete Deck on Longitudinal Members” (pp. 3-187 ff.) and Figure 309-3 (p. 3-188). The manual remains the controlling document.
Three things are carried here:
minimum_deck_thickness(BDM 309.3.1)Tmin (in) = (S + 17)(12) / 36 >= 8.5, S = effective span length in feet per LRFD 9.7.2.3, rounded up to the nearest 1/4 in. The 1 in monolithic wearing surface is included in this thickness but excluded from structural design (BDM 309.1.A).POLICY(BDM 309.3.2 / 309.2)The non-negotiable design requirements: approximate elastic (strip) method of LRFD 9.7.3 only — the empirical method (LRFD 9.7.2) and refined methods are prohibited — HL-93 live load, 0.06 ksf future wearing surface, covers, exposure factor, and the standard materials (class QC2 concrete at f’c = 4.5 ksi, Grade 60 epoxy-coated bars).
STANDARD_DECK_DESIGNS(BDM Figure 309-3)The pre-engineered deck designs for effective spans of 7.0 ft to 14.0 ft in 0.5 ft steps: thicknesses, transverse and longitudinal mats, and the additional overhang bars.
standard_deck_designlooks a design up by effective span (rounded up to the next 0.5 ft per the figure’s note 2.k) and enforces the figure’s assumption limits.
Railing designations cross-reference the SCDs cataloged in
civilpy.structural.odot.bridge_railing. Bar sizes are standard
US designators resolved through civilpy.structural.steel.Rebar.
Lengths in inches unless a name says otherwise; spans in feet.
- class civilpy.structural.odot.deck_design.BarMat(size: int, spacing: float)[source]
Bases:
objectOne reinforcing mat: bar size at a uniform spacing (in).
- civilpy.structural.odot.deck_design.DESIGN_METHOD = 'LRFD 9.7.3 approximate elastic (equivalent strip)'
Analysis method mandated by BDM 309.3.2.
- class civilpy.structural.odot.deck_design.DeckDesignPolicy(method: str = 'LRFD 9.7.3 approximate elastic (equivalent strip)', live_load: str = 'HL-93', future_wearing_surface_ksf: float = 0.06, monolithic_wearing_surface: float = 1.0, top_cover: float = 2.5, bottom_cover: float = 1.5, exposure_factor: float = 0.75, f_c: float = 4.5, f_y: float = 60.0, concrete_class: str = 'QC2', epoxy_coated: bool = True)[source]
Bases:
objectODOT concrete deck design requirements (BDM 309.3.2, 309.2, and the Figure 309-3 design assumptions). Thicknesses/covers in inches, pressures in ksf, strengths in ksi.
- class civilpy.structural.odot.deck_design.Haunch(depth: float, flange_width: float)[source]
Bases:
objectA concrete haunch per BDM 309.3.5: sides vertical and aligned with the edges of the top flange, so the haunch cross-section is simply
flange_width x depth. Depths/widths in inches.
- civilpy.structural.odot.deck_design.MIN_BEAM_LINES = 4
Figure 309-3 note 2 assumption limits.
- civilpy.structural.odot.deck_design.MIN_DESIGN_HAUNCH = 2.0
Minimum design haunch (in) between top of beam/girder flange and bottom of deck (BDM 309.3.5). Haunches absorb unforeseen camber variation so the slab never thins below design.
- civilpy.structural.odot.deck_design.MIN_OVERHANG_THICKNESS: dict[str, float] = {'TST-1-99': 18.0, 'TST-2-21': 20.0}
Note 2.k minimum overhang deck thickness overrides for the steel-tube railings (in); these govern over the tabulated overhang thickness.
- civilpy.structural.odot.deck_design.POLICY = DeckDesignPolicy(method='LRFD 9.7.3 approximate elastic (equivalent strip)', live_load='HL-93', future_wearing_surface_ksf=0.06, monolithic_wearing_surface=1.0, top_cover=2.5, bottom_cover=1.5, exposure_factor=0.75, f_c=4.5, f_y=60.0, concrete_class='QC2', epoxy_coated=True)
The BDM deck design policy; treat as read-only.
- civilpy.structural.odot.deck_design.PROHIBITED_METHODS = ('LRFD 9.7.2 empirical design', 'refined methods of analysis')
Methods BDM 309.3.2 explicitly prohibits for ODOT deck design.
- civilpy.structural.odot.deck_design.STANDARD_DECK_DESIGNS: tuple[StandardDeckDesign, ...] = (StandardDeckDesign(effective_span_ft=7.0, deck_thickness=8.5, overhang_thickness=10.5, transverse_top=BarMat(size=5, spacing=6.0), transverse_bottom=BarMat(size=5, spacing=6.0), longitudinal_top=BarMat(size=4, spacing=12.5), longitudinal_bottom=BarMat(size=5, spacing=10.75), overhang_bar_size=5, overhang_cutoff=54.0), StandardDeckDesign(effective_span_ft=7.5, deck_thickness=8.5, overhang_thickness=10.5, transverse_top=BarMat(size=5, spacing=6.0), transverse_bottom=BarMat(size=5, spacing=6.0), longitudinal_top=BarMat(size=4, spacing=12.0), longitudinal_bottom=BarMat(size=5, spacing=10.25), overhang_bar_size=5, overhang_cutoff=54.0), StandardDeckDesign(effective_span_ft=8.0, deck_thickness=8.5, overhang_thickness=10.5, transverse_top=BarMat(size=5, spacing=6.0), transverse_bottom=BarMat(size=5, spacing=6.0), longitudinal_top=BarMat(size=4, spacing=11.5), longitudinal_bottom=BarMat(size=5, spacing=9.75), overhang_bar_size=5, overhang_cutoff=54.0), StandardDeckDesign(effective_span_ft=8.5, deck_thickness=8.5, overhang_thickness=10.5, transverse_top=BarMat(size=5, spacing=5.75), transverse_bottom=BarMat(size=5, spacing=5.75), longitudinal_top=BarMat(size=4, spacing=11.0), longitudinal_bottom=BarMat(size=5, spacing=9.25), overhang_bar_size=4, overhang_cutoff=54.0), StandardDeckDesign(effective_span_ft=9.0, deck_thickness=8.75, overhang_thickness=10.75, transverse_top=BarMat(size=5, spacing=5.75), transverse_bottom=BarMat(size=5, spacing=5.75), longitudinal_top=BarMat(size=4, spacing=11.0), longitudinal_bottom=BarMat(size=5, spacing=9.25), overhang_bar_size=4, overhang_cutoff=54.0), StandardDeckDesign(effective_span_ft=9.5, deck_thickness=9.0, overhang_thickness=11.0, transverse_top=BarMat(size=5, spacing=5.75), transverse_bottom=BarMat(size=5, spacing=5.75), longitudinal_top=BarMat(size=4, spacing=11.0), longitudinal_bottom=BarMat(size=5, spacing=9.25), overhang_bar_size=4, overhang_cutoff=54.0), StandardDeckDesign(effective_span_ft=10.0, deck_thickness=9.0, overhang_thickness=11.0, transverse_top=BarMat(size=5, spacing=5.25), transverse_bottom=BarMat(size=5, spacing=5.25), longitudinal_top=BarMat(size=4, spacing=10.0), longitudinal_bottom=BarMat(size=5, spacing=8.75), overhang_bar_size=4, overhang_cutoff=48.0), StandardDeckDesign(effective_span_ft=10.5, deck_thickness=9.25, overhang_thickness=11.25, transverse_top=BarMat(size=5, spacing=5.25), transverse_bottom=BarMat(size=5, spacing=5.25), longitudinal_top=BarMat(size=4, spacing=10.0), longitudinal_bottom=BarMat(size=5, spacing=8.75), overhang_bar_size=4, overhang_cutoff=48.0), StandardDeckDesign(effective_span_ft=11.0, deck_thickness=9.5, overhang_thickness=11.5, transverse_top=BarMat(size=5, spacing=5.0), transverse_bottom=BarMat(size=5, spacing=5.0), longitudinal_top=BarMat(size=4, spacing=9.5), longitudinal_bottom=BarMat(size=5, spacing=8.75), overhang_bar_size=4, overhang_cutoff=48.0), StandardDeckDesign(effective_span_ft=11.5, deck_thickness=9.5, overhang_thickness=11.5, transverse_top=BarMat(size=6, spacing=5.75), transverse_bottom=BarMat(size=5, spacing=5.75), longitudinal_top=BarMat(size=4, spacing=7.75), longitudinal_bottom=BarMat(size=5, spacing=8.75), overhang_bar_size=4, overhang_cutoff=28.0), StandardDeckDesign(effective_span_ft=12.0, deck_thickness=9.75, overhang_thickness=11.75, transverse_top=BarMat(size=6, spacing=5.75), transverse_bottom=BarMat(size=5, spacing=5.75), longitudinal_top=BarMat(size=4, spacing=7.75), longitudinal_bottom=BarMat(size=5, spacing=8.75), overhang_bar_size=4, overhang_cutoff=28.0), StandardDeckDesign(effective_span_ft=12.5, deck_thickness=10.0, overhang_thickness=12.0, transverse_top=BarMat(size=6, spacing=5.75), transverse_bottom=BarMat(size=5, spacing=5.75), longitudinal_top=BarMat(size=4, spacing=7.75), longitudinal_bottom=BarMat(size=5, spacing=8.75), overhang_bar_size=None, overhang_cutoff=None), StandardDeckDesign(effective_span_ft=13.0, deck_thickness=10.0, overhang_thickness=12.0, transverse_top=BarMat(size=6, spacing=5.75), transverse_bottom=BarMat(size=5, spacing=5.75), longitudinal_top=BarMat(size=4, spacing=7.75), longitudinal_bottom=BarMat(size=5, spacing=8.75), overhang_bar_size=None, overhang_cutoff=None), StandardDeckDesign(effective_span_ft=13.5, deck_thickness=10.25, overhang_thickness=12.25, transverse_top=BarMat(size=6, spacing=5.75), transverse_bottom=BarMat(size=5, spacing=5.75), longitudinal_top=BarMat(size=4, spacing=7.75), longitudinal_bottom=BarMat(size=5, spacing=8.75), overhang_bar_size=None, overhang_cutoff=None), StandardDeckDesign(effective_span_ft=14.0, deck_thickness=10.5, overhang_thickness=12.5, transverse_top=BarMat(size=6, spacing=5.75), transverse_bottom=BarMat(size=5, spacing=5.75), longitudinal_top=BarMat(size=4, spacing=7.75), longitudinal_bottom=BarMat(size=5, spacing=8.75), overhang_bar_size=None, overhang_cutoff=None))
BDM Figure 309-3, one entry per tabulated effective span.
- class civilpy.structural.odot.deck_design.StandardDeckDesign(effective_span_ft: float, deck_thickness: float, overhang_thickness: float, transverse_top: BarMat, transverse_bottom: BarMat, longitudinal_top: BarMat, longitudinal_bottom: BarMat, overhang_bar_size: int | None, overhang_cutoff: float | None)[source]
Bases:
objectOne row of BDM Figure 309-3.
deck_thicknessandoverhang_thicknessare totals including the 1 in monolithic wearing surface.overhang_bar_size/overhang_cutoffare the additional overhang bar and the length (in) beyond the fascia beam/girder centerline where it is no longer required (note 5); both areNonewhere the figure tabulates none. Longitudinal spacings exclude the additional negative-moment reinforcement required over piers (note 6; LRFD 6.10.1.7 / 5.6.3.2).
- civilpy.structural.odot.deck_design.VALID_RAILINGS: tuple[str, ...] = ('BR-1-13', 'SBR-1-20', 'SBR-2-20', 'SBR-3-20', 'BR-2-15', 'TST-1-99', 'TST-2-21')
Railing SCDs the overhang design is valid for (note 2.k); designations resolve through
civilpy.structural.odot.bridge_railing.railing().
- civilpy.structural.odot.deck_design.haunch_depth_at(design_haunch: float, camber_residual: float) float[source]
Theoretical haunch depth (in) at a station where the girder sits
camber_residualinches BELOW its theoretical profile (positive = girder low -> deeper haunch; negative = girder high -> shallower). The result may fall belowMIN_DESIGN_HAUNCH— that is the signal the design haunch must be increased, not clamped away.
- civilpy.structural.odot.deck_design.minimum_deck_thickness(effective_span_ft: float) float[source]
Minimum total deck thickness (in) per BDM 309.3.1.
Tmin = (S + 17)(12)/36 >= 8.5 inrounded up to the nearest 1/4 in, whereeffective_span_ftis the effective span length per LRFD 9.7.2.3. Includes the 1 in monolithic wearing surface; subtractDeckDesignPolicy.monolithic_wearing_surfacefor the structural design thickness.
- civilpy.structural.odot.deck_design.overhang_thickness(design: StandardDeckDesign, railing: str | None = None) float[source]
Overhang deck thickness (in) for a standard design, applying the note 2.k minimums for the TST steel-tube railings when they govern.
- civilpy.structural.odot.deck_design.secondary_longitudinal_reinforcement(main: BarMat) BarMat[source]
Minimum longitudinal top-mat (secondary) reinforcement per BDM 309.3.4.1: at least 1/3 of the main (transverse) reinforcement, spaced uniformly, detailed as #4 bars — unless that would put the #4s closer than 3 in, in which case a larger bar at >= 3 in spacing is returned.
Applies the 1/3 rule to the provided main steel, which is slightly conservative against BDM Figure 309-3 (whose longitudinal mats derive from the required steel); for spans the figure tabulates, use the figure’s mats — this helper is for custom designs outside it.
- civilpy.structural.odot.deck_design.standard_deck_design(effective_span_ft: float, *, railing: str | None = None, beam_lines: int | None = None, beam_spacing_ft: float | None = None, overhang_ft: float | None = None) StandardDeckDesign[source]
Look up the BDM Figure 309-3 standard design for an effective span.
effective_span_ftis the effective span length per LRFD 9.7.3.2; it is rounded up to the next tabulated 0.5 ft increment (note 2.k). The optional keywords assert the figure’s design assumptions —railing(SCD designation, note 2.k),beam_lines(>= 4, note 2.a),beam_spacing_ft(<= 15 ft, note 2.b) andoverhang_ft(<= 4 ft, note 2.j) — and raiseValueErrorwhen the standard designs do not apply, in which case the deck must be designed per BDM 309.3.2 instead.
civilpy.structural.odot.drip_strip module
ODOT DS-1-92 Drip Strip for Structures with Over the Side Drainage.
Transcribed from Ohio DOT Standard Construction Drawing DS-1-92 (revised 07-15-22, 2 sheets). The drawing remains the controlling document.
The drip strip is a bent stainless steel sheet cast into (or fastened to) the fascia edge of the deck: a 4-1/2 in perforated plate is embedded horizontally with a 3 in leg bent up 90 degrees against the formwork; after form removal the leg is bent out to its final 45 degree position. The lower strip runs continuously along the full length of each side of the bridge (pieces tightly butted, never lapped); a short upper strip (1’-6” for DBR-2-73 and TST-1-99 railings, 2’-0” for TST-2-21) is added at each railing post, its leg turned up while the lower strip’s leg turns down. On prestressed box beams without a cast deck the bent strips are instead fastened to the beam edge with 1-1/4 in x 3/32 in button head spikes with deformed shanks or expansion anchors at 1’-6” c/c max, all devices galvanized or stainless.
Material: stainless steel, minimum 22 gage, ASTM A167 Type 304, mill finish. Measurement: by the foot, totaling upper and lower strips (pay item “Special, Steel Drip Strip”).
Conventions match the other SCD modules: plan lengths in feet, section dimensions in inches.
- class civilpy.structural.odot.drip_strip.DripStripPlacement(railing: str, upper_strip_length_in: float, root_depth_in: float)[source]
Bases:
objectUpper-strip length and the strip root depth below the deck (or wearing) surface for one railing type.
- civilpy.structural.odot.drip_strip.STRUCTURE_TYPES = ('concrete slab', 'noncomposite box beam', 'composite box beam')
Deck/structure families the sheet details (each shown with all three railings; “deck on concrete or steel beam similar”).
- class civilpy.structural.odot.drip_strip.StripRun(kind: str, start_ft: float, end_ft: float)[source]
Bases:
objectOne strip piece along the fascia: stations in feet from the start of the run, plus which profile it carries.
- civilpy.structural.odot.drip_strip.drip_strip_runs(length_ft: float, post_stations_ft: tuple[float, ...], railing: str) tuple[StripRun, ...][source]
The strip pieces along ONE fascia edge: the continuous lower strip over the full length plus an upper strip centered at each railing post (clipped to the fascia). Raises
ValueErrorfor an unknown railing or non-positive length.
- civilpy.structural.odot.drip_strip.hole_centers_in(strip_length_in: float) list[tuple[float, float]][source]
Perforation centers over a strip of the given length, in the embedded-plate plane: (s, w) with s along the strip from its start and w measured from the bend line into the deck (0 to EMBED_WIDTH_IN).
Two staggered rows 1-1/2 in from each plate edge, 4 in c/c along each row, second row offset 2 in (view G-G).
- civilpy.structural.odot.drip_strip.pay_length_ft(runs: tuple[StripRun, ...], sides: int = 1) float[source]
Measured length (ft): the total of upper and lower strips.
sides=2doubles a single-fascia takeoff for both edges.
- civilpy.structural.odot.drip_strip.placement(railing: str) DripStripPlacement[source]
Placement data for a railing type; raises
ValueErrorlisting the railings DS-1-92 details.
- civilpy.structural.odot.drip_strip.strip_profile_in(kind: str, *, bent: bool = True, include_embedded: bool = True) tuple[tuple[float, float], ...][source]
Cross-section polyline of one strip, inches, in the (h, v) plane: h positive outward from the fascia face (h = 0 at the bend line), v positive up.
kindis"upper"(leg turned up 45 degrees) or"lower"(leg turned down).bent=Falsegives the pre-placement shape (leg vertical against the form).include_embedded=Falsereturns only the exposed leg.
civilpy.structural.odot.fixed_bearing module
Ohio DOT fixed bearings for steel beam and girder bridges (FB-1-82).
Dimension and capacity table transcribed from Ohio DOT Standard Bridge Drawing FB-1-82 (Office of Structural Engineering, rev. 05-10-1982, rev. 07-19-2024). The drawing remains the controlling document.
Each row is a pin-bearing assembly: a masonry (base) plate F x G, a
cylindrical bearing pin of diameter DIA, and a top plate A x B under
the girder, overall height H. F-50/F-100 use only 2 anchor rods
(diagonally opposite corners, note 1); F-350/F-400 require bearing
stiffeners both sides of the girder web (note 2).
Design basis (General Notes): AASHTO Standard Specifications (1977 + 1978-
1981 interims) + Ohio supplement, masonry plates designed for 30,000 psi
allowable bending, uniform bearing distribution assumed. Anchor rods are
1-1/4 in dia x 1’-7 in long in 1-5/8 in dia holes. Lateral expansion
clearance is 1/8 in per end for superstructure widths up to 120 ft (1/4 in
for widths over 60 ft, per the note’s own overlapping ranges – see
LATERAL_CLEARANCE_IN/LATERAL_CLEARANCE_WIDE_IN).
Dimensions in inches, weight in pounds, load in pounds. Spot-checked against the drawing in the test suite.
- civilpy.structural.odot.fixed_bearing.DIM_LETTERS: tuple[str, ...] = ('A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'K', 'DIA')
Dimension letters in FB-1-82 table column order.
- civilpy.structural.odot.fixed_bearing.FIXED_BEARINGS: dict[str, FixedBearing] = {'F-100': FixedBearing(designation='F-100', max_load_lb=100000, dims={'A': 7, 'B': 9, 'C': 1.75, 'D': 4, 'E': 1.5, 'F': 9, 'G': 18, 'H': 1.5, 'K': 5.625, 'DIA': 2}, weight_lb=143, two_anchor_rods=True, stiffeners_required=False), 'F-150': FixedBearing(designation='F-150', max_load_lb=150000, dims={'A': 9, 'B': 9, 'C': 2.5, 'D': 5, 'E': 1.5, 'F': 11, 'G': 20, 'H': 2, 'K': 6.875, 'DIA': 2.5}, weight_lb=244, two_anchor_rods=False, stiffeners_required=False), 'F-200': FixedBearing(designation='F-200', max_load_lb=200000, dims={'A': 10, 'B': 10, 'C': 3, 'D': 6, 'E': 2, 'F': 11, 'G': 22, 'H': 2, 'K': 7.875, 'DIA': 2.5}, weight_lb=300, two_anchor_rods=False, stiffeners_required=False), 'F-250': FixedBearing(designation='F-250', max_load_lb=250000, dims={'A': 11, 'B': 10, 'C': 3.5, 'D': 7, 'E': 2, 'F': 12, 'G': 24, 'H': 2.5, 'K': 8.875, 'DIA': 3}, weight_lb=400, two_anchor_rods=False, stiffeners_required=False), 'F-300': FixedBearing(designation='F-300', max_load_lb=300000, dims={'A': 12, 'B': 11, 'C': 3.75, 'D': 8, 'E': 2.5, 'F': 14, 'G': 25, 'H': 2.5, 'K': 9.625, 'DIA': 3}, weight_lb=502, two_anchor_rods=False, stiffeners_required=False), 'F-350': FixedBearing(designation='F-350', max_load_lb=350000, dims={'A': 12, 'B': 11, 'C': 3.75, 'D': 8, 'E': 2.5, 'F': 16, 'G': 25, 'H': 2.5, 'K': 9.625, 'DIA': 3}, weight_lb=540, two_anchor_rods=False, stiffeners_required=True), 'F-400': FixedBearing(designation='F-400', max_load_lb=400000, dims={'A': 12, 'B': 12, 'C': 3.75, 'D': 8, 'E': 2.5, 'F': 18, 'G': 26, 'H': 2.5, 'K': 9.625, 'DIA': 3}, weight_lb=610, two_anchor_rods=False, stiffeners_required=True), 'F-50': FixedBearing(designation='F-50', max_load_lb=50000, dims={'A': 6, 'B': 6, 'C': 1.5, 'D': 3, 'E': 1.25, 'F': 8, 'G': 16, 'H': 1.5, 'K': 5.625, 'DIA': 2}, weight_lb=100, two_anchor_rods=True, stiffeners_required=False)}
Fixed-bearing lines keyed by designation (“F-50” .. “F-400”).
- class civilpy.structural.odot.fixed_bearing.FixedBearing(designation: str, max_load_lb: float, dims: dict[str, float], weight_lb: float, two_anchor_rods: bool = False, stiffeners_required: bool = False)[source]
Bases:
objectOne FB-1-82 fixed-bearing capacity line.
two_anchor_rods(note 1) is true only for F-50/F-100; otherwise 4 anchor rods are used (one per masonry-plate corner).stiffeners_required(note 2) is true only for F-350/F-400.
- class civilpy.structural.odot.fixed_bearing.FixedBearingLayout(fb: civilpy.structural.odot.fixed_bearing.FixedBearing, base_outline: tuple[tuple[float, float, float], tuple[float, float, float], tuple[float, float, float], tuple[float, float, float]], base_thickness_in: float, top_outline: tuple[tuple[float, float, float], tuple[float, float, float], tuple[float, float, float], tuple[float, float, float]], top_z_in: float, pin_diameter_in: float, pin_center: tuple[float, float, float], notes: tuple[str, ...] = <factory>)[source]
Bases:
object- base_outline: tuple[tuple[float, float, float], tuple[float, float, float], tuple[float, float, float], tuple[float, float, float]]
- fb: FixedBearing
- civilpy.structural.odot.fixed_bearing.LATERAL_CLEARANCE_IN = 0.125
Lateral expansion clearance per end of the bearing pin, inches.
- civilpy.structural.odot.fixed_bearing.fixed_bearing(designation: str) FixedBearing[source]
Look up a FB-1-82 fixed-bearing line by designation (“F-50”, …, “F-400”). Raises
ValueErrornaming the valid designations otherwise.
- civilpy.structural.odot.fixed_bearing.lateral_clearance_in(superstructure_width_ft: float) float[source]
Lateral expansion clearance per end of the bearing pin (General Notes): 1/8 in normally, 1/4 in for a superstructure over 60 ft wide (up to the 120 ft this note addresses).
- civilpy.structural.odot.fixed_bearing.layout_fixed_bearing(fb: FixedBearing) FixedBearingLayout[source]
Generate the drawable subset of one FB-1-82 line: the masonry plate, the top plate, and the bearing pin centerline.
Eis used as the masonry plate thickness (it is the smallest tabulated dimension, consistent with a base-plate thickness) andHas the clearance from the top of that plate to the pin center, so the stack (plate + pin + top plate) is self-consistent even though the sheet does not label a dimension “base plate thickness” outright – see SCD_BUILD_QUESTIONS.md.
- civilpy.structural.odot.fixed_bearing.smallest_for_load(load_lb: float) FixedBearing[source]
The lightest standard fixed bearing whose maximum load covers
load_lb; raisesValueErrorif the load exceeds the F-400 line.
civilpy.structural.odot.full_height_headwall module
Ohio DOT full-height headwalls (HW-1.1).
Transcribed from Ohio DOT Standard Bridge Drawing HW-1.1, “Full-Height Headwalls” (rev. 07-18-2025, 2 sheets). The drawing remains the controlling document.
HW-1.1 covers full-height headwalls with wingwalls for circular pipe or
pipe-arch culverts, 42 to 84 in inclusive, skewed or non-skewed. Type A
(skew_deg <= 10) uses a wingwall symmetrical about the culvert
centerline, flared 45 deg each side; Type B (skew_deg > 10) uses an
asymmetric pair of wingwalls flared 45 - skew/2 and 45 + skew/2 deg
off the culvert centerline (sheet 1 plan views). The dimension table
(sheet 2) tabulates quantities at four discrete skew angles (0, 15, 30,
45 deg); intermediate skews use the nearest tabulated bucket, which is
standard ODOT practice for this drawing (its own title reads “theta ~=”).
Design basis (sheet 1 notes): internal friction angle of backfill soil phi_bf = 30 deg, backfill unit weight = 120 pcf, foundation soil drained friction angle phi_f = 28 deg, foundation undrained shear strength = 1500 psf, concrete unit weight = 150 pcf, backfill slope = 2:1. Concrete Class QC1 (f’c = 4000 psi). Reinforcing steel ASTM A615/A616/A617 Grade 60, epoxy coated.
Conventions match civilpy.structural.odot.headwall: X along the
culvert/wall centerline is not used here – instead Y is along the
headwall face (wingwall spread direction), X is out from the culvert
centerline (positive downstream), Z is up with z = 0 at the flow line /
wall base. Feet in plan, inches only where the sheet itself uses them
(pipe diameter, chamfer, weepholes).
- civilpy.structural.odot.full_height_headwall.FULL_HEIGHT_HEADWALLS: dict[float, FullHeightHeadwallDesign] = {42.0: FullHeightHeadwallDesign(diameter_in=42.0, height_ft=5.333333333333333, a_ft=3.25, b_ft=1.5, c_ft=2.5, ts_ft=1.5, bar_size=5, skews=(SkewGroup(skew_deg=0.0, L1=None, L2=3.5833333333333335, h1=None, h2=3.5, concrete_cmp_cy=7.2, concrete_rcp_cy=7.1, steel_lb=695), SkewGroup(skew_deg=15.0, L1=8.75, L2=4.5, h1=4.083333333333333, h2=3.5833333333333335, concrete_cmp_cy=7.6, concrete_rcp_cy=7.5, steel_lb=656), SkewGroup(skew_deg=30.0, L1=7.833333333333333, L2=5.75, h1=3.5833333333333335, h2=3.6666666666666665, concrete_cmp_cy=7.8, concrete_rcp_cy=7.7, steel_lb=688), SkewGroup(skew_deg=45.0, L1=7.833333333333333, L2=7.75, h1=3.5833333333333335, h2=3.6666666666666665, concrete_cmp_cy=9.0, concrete_rcp_cy=8.9, steel_lb=794))), 48.0: FullHeightHeadwallDesign(diameter_in=48.0, height_ft=5.833333333333333, a_ft=3.5, b_ft=1.5, c_ft=2.75, ts_ft=1.5, bar_size=5, skews=(SkewGroup(skew_deg=0.0, L1=None, L2=4.333333333333333, h1=None, h2=3.75, concrete_cmp_cy=8.8, concrete_rcp_cy=8.6, steel_lb=861), SkewGroup(skew_deg=15.0, L1=10.0, L2=5.333333333333333, h1=4.5, h2=3.8333333333333335, concrete_cmp_cy=9.3, concrete_rcp_cy=9.1, steel_lb=806), SkewGroup(skew_deg=30.0, L1=8.75, L2=6.833333333333333, h1=3.8333333333333335, h2=3.9166666666666665, concrete_cmp_cy=9.4, concrete_rcp_cy=9.2, steel_lb=833), SkewGroup(skew_deg=45.0, L1=8.75, L2=9.166666666666666, h1=3.8333333333333335, h2=4.0, concrete_cmp_cy=10.9, concrete_rcp_cy=10.8, steel_lb=970))), 54.0: FullHeightHeadwallDesign(diameter_in=54.0, height_ft=6.416666666666667, a_ft=3.75, b_ft=1.5, c_ft=3.0, ts_ft=1.5, bar_size=5, skews=(SkewGroup(skew_deg=0.0, L1=None, L2=5.166666666666667, h1=None, h2=4.166666666666667, concrete_cmp_cy=10.8, concrete_rcp_cy=10.5, steel_lb=1001), SkewGroup(skew_deg=15.0, L1=11.333333333333334, L2=6.25, h1=5.0, h2=4.166666666666667, concrete_cmp_cy=11.3, concrete_rcp_cy=11.0, steel_lb=977), SkewGroup(skew_deg=30.0, L1=9.666666666666666, L2=7.916666666666667, h1=4.166666666666667, h2=4.25, concrete_cmp_cy=11.2, concrete_rcp_cy=11.0, steel_lb=1002), SkewGroup(skew_deg=45.0, L1=9.666666666666666, L2=10.583333333333334, h1=4.166666666666667, h2=4.333333333333333, concrete_cmp_cy=13.1, concrete_rcp_cy=12.9, steel_lb=1149))), 60.0: FullHeightHeadwallDesign(diameter_in=60.0, height_ft=7.0, a_ft=4.0, b_ft=1.5, c_ft=3.25, ts_ft=1.5, bar_size=5, skews=(SkewGroup(skew_deg=0.0, L1=None, L2=5.916666666666667, h1=None, h2=4.416666666666667, concrete_cmp_cy=12.7, concrete_rcp_cy=12.4, steel_lb=1151), SkewGroup(skew_deg=15.0, L1=12.583333333333334, L2=7.166666666666667, h1=5.333333333333333, h2=4.5, concrete_cmp_cy=13.4, concrete_rcp_cy=13.1, steel_lb=1127), SkewGroup(skew_deg=30.0, L1=10.583333333333334, L2=9.0, h1=4.333333333333333, h2=4.583333333333333, concrete_cmp_cy=13.2, concrete_rcp_cy=12.9, steel_lb=1124), SkewGroup(skew_deg=45.0, L1=10.583333333333334, L2=12.0, h1=4.333333333333333, h2=4.583333333333333, concrete_cmp_cy=15.4, concrete_rcp_cy=15.1, steel_lb=1306))), 72.0: FullHeightHeadwallDesign(diameter_in=72.0, height_ft=8.166666666666666, a_ft=4.5, b_ft=1.5833333333333335, c_ft=3.75, ts_ft=1.5, bar_size=7, skews=(SkewGroup(skew_deg=0.0, L1=None, L2=7.416666666666667, h1=None, h2=5.0, concrete_cmp_cy=17.5, concrete_rcp_cy=17.1, steel_lb=1808), SkewGroup(skew_deg=15.0, L1=15.083333333333334, L2=8.916666666666666, h1=6.166666666666667, h2=5.083333333333333, concrete_cmp_cy=18.5, concrete_rcp_cy=18.0, steel_lb=1803), SkewGroup(skew_deg=30.0, L1=12.416666666666666, L2=11.166666666666666, h1=4.833333333333333, h2=5.166666666666667, concrete_cmp_cy=18.0, concrete_rcp_cy=17.5, steel_lb=1770), SkewGroup(skew_deg=45.0, L1=12.416666666666666, L2=14.833333333333334, h1=4.833333333333333, h2=5.25, concrete_cmp_cy=21.0, concrete_rcp_cy=20.6, steel_lb=2080))), 84.0: FullHeightHeadwallDesign(diameter_in=84.0, height_ft=9.333333333333334, a_ft=5.0, b_ft=1.8333333333333335, c_ft=4.25, ts_ft=1.5, bar_size=8, skews=(SkewGroup(skew_deg=0.0, L1=None, L2=9.0, h1=None, h2=5.666666666666667, concrete_cmp_cy=24.6, concrete_rcp_cy=24.0, steel_lb=2608), SkewGroup(skew_deg=15.0, L1=17.583333333333332, L2=10.75, h1=7.0, h2=5.75, concrete_cmp_cy=25.7, concrete_rcp_cy=25.1, steel_lb=2563), SkewGroup(skew_deg=30.0, L1=14.583333333333334, L2=13.333333333333334, h1=5.5, h2=5.833333333333333, concrete_cmp_cy=25.1, concrete_rcp_cy=24.5, steel_lb=2559), SkewGroup(skew_deg=45.0, L1=14.25, L2=17.666666666666668, h1=5.333333333333333, h2=5.833333333333333, concrete_cmp_cy=28.9, concrete_rcp_cy=28.3, steel_lb=2943)))}
HW-1.1 “FULL-HEIGHT HEADWALLS (ENGLISH)” table, sheet 2, keyed by pipe diameter (inches). L/H columns in feet-inches on the sheet, converted with
_fi(); concrete in CY, steel in lbs.
- class civilpy.structural.odot.full_height_headwall.FullHeightHeadwallDesign(diameter_in: float, height_ft: float, a_ft: float, b_ft: float, c_ft: float, ts_ft: float, bar_size: int, skews: tuple[SkewGroup, ...])[source]
Bases:
objectOne HW-1.1 table row (a pipe diameter), with all four skew columns.
- class civilpy.structural.odot.full_height_headwall.FullHeightHeadwallLayout(inputs: ~civilpy.structural.odot.full_height_headwall.HeadwallInput, table: ~civilpy.structural.odot.full_height_headwall.FullHeightHeadwallDesign, skew: ~civilpy.structural.odot.full_height_headwall.SkewGroup, skew_bucket_deg: float, type_: str, center_face: tuple[tuple[float, float, float], tuple[float, float, float], tuple[float, float, float], tuple[float, float, float]], wing1: tuple[tuple[float, float, float], tuple[float, float, float], tuple[float, float, float], tuple[float, float, float]], wing2: tuple[tuple[float, float, float], tuple[float, float, float], tuple[float, float, float], tuple[float, float, float]], concrete_cy: float, steel_lb: float, notes: tuple[str, ...] = <factory>)[source]
Bases:
objectThe generated headwall+wingwall unit.
center_faceis the vertical rectangular panel at the culvert centerline (X-Z plane at y = 0, width D centered on x = 0, height H);wing1/wing2are the two wingwall planes as(near_top, near_base, far_base, far_top)quads swept from the center face’s top corners out to each wingwall’s far end.wing1is the acute-side (L1/h1) wingwall,wing2the obtuse-side (L2/h2) wingwall; for Type A (skew snapped to 0) both use the L2/h2 data and are mirror images. Origin: x = 0 on the culvert centerline, y = 0 at the headwall front face (wall behind, +y downstream), z = 0 at the flow line / wall base.- center_face: tuple[tuple[float, float, float], tuple[float, float, float], tuple[float, float, float], tuple[float, float, float]]
- inputs: HeadwallInput
- table: FullHeightHeadwallDesign
- class civilpy.structural.odot.full_height_headwall.HeadwallInput(diameter_in: float, skew_deg: float = 0.0)[source]
Bases:
objectInputs for a full-height headwall + wingwall solid.
diameter_inmust be a tabulated pipe diameter;skew_degis snapped to the nearest tabulated bucket (0/15/30/45 deg – seenearest_skew_bucket()).
- civilpy.structural.odot.full_height_headwall.MIN_DIAMETER_IN = 42.0
Applicable pipe diameter/rise range (sheet 1 “APPLICATION” note).
- civilpy.structural.odot.full_height_headwall.SKEW_BUCKETS: tuple[float, ...] = (0.0, 15.0, 30.0, 45.0)
The dimension table only tabulates quantities at these nominal skew angles;
nearest_skew_bucketsnaps any input to the closest one.
- class civilpy.structural.odot.full_height_headwall.SkewGroup(skew_deg: float, L1: float | None, L2: float, h1: float | None, h2: float, concrete_cmp_cy: float, concrete_rcp_cy: float, steel_lb: float)[source]
Bases:
objectOne skew-angle column of the HW-1.1 table for a given pipe diameter.
L1/h1areNoneatskew_deg == 0(Type A: only one wingwall shape, tabulated asL2/h2, symmetric about the centerline).
- civilpy.structural.odot.full_height_headwall.full_height_headwall_design(diameter_in: float) FullHeightHeadwallDesign[source]
Look up the HW-1.1 table row for a pipe diameter (inches).
Raises
ValueErrornaming the tabulated sizes ifdiameter_inis not one of them.
- civilpy.structural.odot.full_height_headwall.layout_full_height_headwall(inp: HeadwallInput) FullHeightHeadwallLayout[source]
Generate the full-height headwall + wingwall solid.
Raises
ValueError(viafull_height_headwall_design()) for an untabulated pipe diameter, and (vianearest_skew_bucket()) for a skew beyond the table’s 45 deg range.
- civilpy.structural.odot.full_height_headwall.nearest_skew_bucket(skew_deg: float) float[source]
Snap a skew angle to the nearest tabulated bucket (0/15/30/45 deg).
The 0 deg cutoff is pinned to
SKEW_TYPE_A_MAX_DEG(10 deg) – sheet 1’s own Type A/B boundary – rather than the halfway point (7.5 deg) so a skew that the sheet calls Type A never gets Type B’s asymmetric wingwall data; 15/30/45 split at their halfway points (22.5, 37.5) as plain nearest-neighbor. RaisesValueErrorfor a skew outside the table’s range (sheet 1 tabulates through 45 deg only; beyond that the standard drawing does not apply).
civilpy.structural.odot.guardrail module
Ohio DOT Midwest Guardrail System (MGS) roadway drawings.
Geometry and layout transcribed from the Ohio DOT Standard Roadway
Construction Drawings, MGS series (Office of Roadway Engineering). The
standard system parameters (rail height, post spacing, blockouts, post
sections) come from MGS-2.1; the series registry maps every MGS drawing and
flags the bridge terminal assemblies that connect a guardrail run to the
bridge railings cataloged in civilpy.structural.odot.bridge_railing.
Lengths are in inches unless a field name says otherwise. Values are spot-checked against the cited drawings in the test suite; the drawings remain the controlling document for detailing.
Beyond the MGS-2.1 system parameters this module carries the three
bridge terminal assemblies as typed post-by-post layouts
(BRIDGE_TERMINALS / layout_bridge_terminal()) — the
guardrail-to-bridge-railing hardware — and a standard-
run post/panel layout (layout_mgs_run()).
- Sources (SCD number — latest cited revision):
MGS-2.1 Midwest Guardrail System, Standard Type MGS (rev. 2026-01-16) MGS-3.1 MGS Bridge Terminal Assembly, Type 1 (rev. 2026-01-16) MGS-3.2 MGS Bridge Terminal Assembly, Type 2 (rev. 2025-07-18) MGS-3.3 MGS Bridge Terminal Assembly, Type TST-2 (rev. 2026-01-16) MGS-4.3 Guardrail Transitions (rev. 2025-07-18) (plus the full MGS series registry, MGS_DRAWINGS)
- class civilpy.structural.odot.guardrail.BridgeTerminalAssembly(scd: str, scd_date: str, designation: str, origin: str, start_offset_in: float, post_spacings_in: tuple[float, ...], post_groups: tuple[TerminalPostGroup, ...] = (), rail_elements: tuple[str, ...] = (), connection: str = '', curb_note: str = '', connects_to: tuple[str, ...] = (), pay_item: str = '', notes: str = '')[source]
Bases:
objectOne MGS bridge terminal assembly (SCD MGS-3.1 / 3.2 / 3.3).
post_spacings_inare the successive c/c spacings starting fromorigin(each sheet’s own stationing direction);start_offset_inis the distance from the origin to post 1.rail_elementslist the transition rail pieces in the same order. Payment is Item 606, Each.- post_groups: tuple[TerminalPostGroup, ...] = ()
- class civilpy.structural.odot.guardrail.BridgeTerminalLayout(terminal: BridgeTerminalAssembly, post_stations_in: tuple[float, ...], posts: tuple[tuple[int, str, float, str], ...], length_in: float, notes: tuple[str, ...] = ())[source]
Bases:
objectPost stations and members of one MGS bridge terminal assembly.
- terminal: BridgeTerminalAssembly
- civilpy.structural.odot.guardrail.MGS = MGSStandard(scd='MGS-2.1', scd_date='2026-01-16', rail_height=31.0, rail_height_tolerance_new=1.0, rail_height_tolerance_existing=3.0, rail='12 gauge W-beam (CMS 606.02)', rail_panel_lengths=(12.5, 25.0), standard_post_length=72.0, round_wood_post_length=68.0, long_post_length=97.0, embedment=40.0, round_wood_embedment=36.0, post_bolt_diameter=0.625, blockout_section='6 x 12', transition_rate_in_per_ft=0.08)
The standard Type MGS guardrail (MGS-2.1).
- class civilpy.structural.odot.guardrail.MGSDrawing(scd: str, title: str, sheets: int, scd_date: str, category: str, connects_to: tuple[str, ...] = (), notes: str = '')[source]
Bases:
objectOne drawing in the Ohio DOT MGS roadway series.
categoryis one ofstandard,special,bridge_terminal,transition,anchor,terminal,layout,bridge.connects_tolists bridge-railing SCD numbers a terminal assembly ties into, where stated on the drawing.
- class civilpy.structural.odot.guardrail.MGSRunLayout(length_ft: float, spacing: PostSpacing, post_stations_ft: tuple[float, ...], n_panels: int, panel_length_ft: float, rail_height_in: float = 31.0, notes: tuple[str, ...] = ())[source]
Bases:
objectPosts and W-beam panels of one straight standard-MGS run.
- spacing: PostSpacing
- class civilpy.structural.odot.guardrail.MGSStandard(scd: str = 'MGS-2.1', scd_date: str = '2026-01-16', rail_height: float = 31.0, rail_height_tolerance_new: float = 1.0, rail_height_tolerance_existing: float = 3.0, rail: str = '12 gauge W-beam (CMS 606.02)', rail_panel_lengths: tuple[float, ...] = (12.5, 25.0), standard_post_length: float = 72.0, round_wood_post_length: float = 68.0, long_post_length: float = 97.0, embedment: float = 40.0, round_wood_embedment: float = 36.0, post_bolt_diameter: float = 0.625, blockout_section: str = '6 x 12', transition_rate_in_per_ft: float = 0.08)[source]
Bases:
objectStandard Type MGS guardrail parameters (MGS-2.1).
Heights/lengths in inches;
rail_panel_lengths(between splices) and transition rate are in feet.- long_post_length: float = 97.0
Long post length (steel / rectangular wood near slope break), inches.
- post_spacing(name: str = 'standard') float[source]
On-center post spacing (inches) for
"standard","half", or"quarter"spacing.
- civilpy.structural.odot.guardrail.MGS_DRAWINGS: dict[str, MGSDrawing] = {'MGS-2.1': MGSDrawing(scd='MGS-2.1', title='Midwest Guardrail System, Standard Type MGS', sheets=7, scd_date='2026-01-16', category='standard', connects_to=(), notes='31 in rail height; W-beam on W6x8.5/W6x9 steel, 6x8 rectangular wood, or 7.25 in round wood posts.'), 'MGS-2.2': MGSDrawing(scd='MGS-2.2', title='Barrier Design with Rub Rail', sheets=2, scd_date='2026-01-16', category='special', connects_to=(), notes='Standard MGS with a rub rail below the W-beam for curbed/vulnerable-user locations.'), 'MGS-2.3': MGSDrawing(scd='MGS-2.3', title='Long-Span Guardrail', sheets=1, scd_date='2025-07-18', category='special', connects_to=(), notes='Unposted MGS span over low-fill culverts (posts omitted across the structure); 31 in rail height kept. Paid per foot as Item 606 - Guardrail, Type MGS, Long-Span.'), 'MGS-2.4': MGSDrawing(scd='MGS-2.4', title='Socketed Weak Post Attached to Headwall', sheets=2, scd_date='2026-01-16', category='special', connects_to=(), notes='Weak posts grouted into sockets cast in an HW-series headwall where embedment is impossible. Paid per foot as Item 606 - Guardrail, Type MGS With Socketed Posts.'), 'MGS-3.1': MGSDrawing(scd='MGS-3.1', title='MGS Bridge Terminal Assembly, Type 1', sheets=2, scd_date='2026-01-16', category='bridge_terminal', connects_to=('BR-1-13', 'TST-1-99', 'RM-4.6'), notes='Connects guardrail to deflector-parapet bridge railings (BR-1-13, single-slope SBR), twin steel tube (TST-1-99), and concrete barrier end sections (RM-4.6). 12 ft-6 in nested thrie beam + 6 ft-3 in thrie + 6 ft-3 in asymmetrical transition; posts 1-6 at quarter spacing.'), 'MGS-3.2': MGSDrawing(scd='MGS-3.2', title='MGS Bridge Terminal Assembly, Type 2', sheets=1, scd_date='2025-07-18', category='bridge_terminal', connects_to=('RM-4.5', 'RM-4.6'), notes='Trailing-end connection (one-directional roadways only): W-beam terminal connector through-bolted to an 11x10x5/8 in bearing plate on the wall end.'), 'MGS-3.3': MGSDrawing(scd='MGS-3.3', title='MGS Bridge Terminal Assembly, Type TST-2', sheets=2, scd_date='2026-01-16', category='bridge_terminal', connects_to=('TST-2-21',), notes='Terminal assembly connecting MGS to the three steel tube bridge railing (TST-2-21).'), 'MGS-4.1': MGSDrawing(scd='MGS-4.1', title='MGS Type A Anchor Assembly', sheets=1, scd_date='2025-07-18', category='anchor', connects_to=(), notes='Buried anchor block terminating a run away from traffic: 18\'-9" rail into a reinforced concrete anchor. Paid Each as Item 606 - Anchor Assembly, Type A (or Barrier Design, Type A).'), 'MGS-4.2': MGSDrawing(scd='MGS-4.2', title='MGS Type T Anchor Assembly', sheets=7, scd_date='2025-07-18', category='anchor', connects_to=(), notes='Crashworthy tangent end terminal: 12\'-6" rounded-end 12-gauge W-beam on breakaway posts with a Type 2 BCT anchor cable and bearing plate. Paid Each as Item 606 - Anchor Assembly, MGS Type T.'), 'MGS-4.3': MGSDrawing(scd='MGS-4.3', title='Guardrail Transitions', sheets=1, scd_date='2025-07-18', category='transition', connects_to=(), notes='Type 5-to-MGS transition: ramp rail height 27 in to 31 in at max 2 in per 25 ft; half-spacing post between.'), 'MGS-4.5': MGSDrawing(scd='MGS-4.5', title='MGS Buried in Backslope End Terminal', sheets=2, scd_date='2025-07-18', category='terminal', connects_to=(), notes=''), 'MGS-5.2': MGSDrawing(scd='MGS-5.2', title='Introduction of Guardrail Runs (Foreslopes 6:1 or Flatter)', sheets=1, scd_date='2016-07-15', category='layout', connects_to=(), notes=''), 'MGS-5.3': MGSDrawing(scd='MGS-5.3', title='Introduction of Guardrail Runs (Foreslopes 6:1 or Steeper)', sheets=1, scd_date='2016-07-15', category='layout', connects_to=(), notes=''), 'MGS-6.1': MGSDrawing(scd='MGS-6.1', title='Guardrail at Bridges', sheets=2, scd_date='2018-01-19', category='bridge', connects_to=(), notes='Arrangement of runs at structures: 25 ft bridge terminal + 12\'-6" min MGS, 7:1 max taper / flare arcs, driveway and side-road opening treatments; anchor assemblies per L&D Vol. 1 603-3.'), 'MGS-6.2': MGSDrawing(scd='MGS-6.2', title='MGS Guardrail at Piers', sheets=1, scd_date='2025-07-18', category='bridge', connects_to=(), notes=''), 'MGS-6.3': MGSDrawing(scd='MGS-6.3', title='Thrie Beam Bullnose with Steel Breakaway Posts', sheets=8, scd_date='2025-07-18', category='terminal', connects_to=(), notes='')}
MGS drawing series keyed by SCD number.
- civilpy.structural.odot.guardrail.MGS_POST_SPACINGS: dict[str, PostSpacing] = {'half': PostSpacing(name='half', spacing=37.5, blockout_height=10.0), 'quarter': PostSpacing(name='quarter', spacing=18.75, blockout_height=14.0), 'standard': PostSpacing(name='standard', spacing=75.0, blockout_height=12.0)}
MGS post-spacing options (on-center spacing and required blockout height).
- civilpy.structural.odot.guardrail.MGS_STEEL_POSTS: dict[str, SteelPost] = {'6x8.5 welded': SteelPost(designation='6x8.5', fabrication='welded', depth=6.0, flange_width=3.94, flange_thickness=0.193, web_thickness=0.17), '6x9 welded': SteelPost(designation='6x9', fabrication='welded', depth=6.0, flange_width=3.94, flange_thickness=0.215, web_thickness=0.17), 'W6x8.5 rolled': SteelPost(designation='W6x8.5', fabrication='rolled', depth=5.8, flange_width=3.94, flange_thickness=0.193, web_thickness=0.17), 'W6x9 rolled': SteelPost(designation='W6x9', fabrication='rolled', depth=5.9, flange_width=3.94, flange_thickness=0.215, web_thickness=0.17)}
MGS steel beam post sections (MGS-2.1 sheet P.2).
- class civilpy.structural.odot.guardrail.PostSpacing(name: str, spacing: float, blockout_height: float)[source]
Bases:
objectOne MGS post-spacing option and the blockout height it requires (MGS-2.1 sheets P.1-P.2).
spacingandblockout_heightin inches.
- class civilpy.structural.odot.guardrail.SteelPost(designation: str, fabrication: str, depth: float, flange_width: float, flange_thickness: float, web_thickness: float)[source]
Bases:
objectAn MGS steel beam post section (MGS-2.1 sheet P.2 table). All dimensions in inches.
- class civilpy.structural.odot.guardrail.TerminalPostGroup(first: int, last: int, post: str, length_in: float, blockout: str)[source]
Bases:
objectA run of identical posts within a bridge terminal assembly.
first/lastare 1-based post numbers; lengths in inches.
- civilpy.structural.odot.guardrail.bridge_terminal(designation: Literal['Type 1', 'Type 2', 'Type TST-2']) BridgeTerminalAssembly[source]
Look up a bridge terminal assembly (
"Type 1","Type 2","Type TST-2").
- civilpy.structural.odot.guardrail.bridge_terminal_assemblies() list[MGSDrawing][source]
The MGS bridge terminal assemblies (transitions to bridge railings).
- civilpy.structural.odot.guardrail.layout_bridge_terminal(designation: Literal['Type 1', 'Type 2', 'Type TST-2']) BridgeTerminalLayout[source]
Expand a
BRIDGE_TERMINALSentry into per-post members.
- civilpy.structural.odot.guardrail.layout_mgs_run(length_ft: float, *, spacing: Literal['standard', 'half', 'quarter'] = 'standard', panel_length_ft: float = 25.0) MGSRunLayout[source]
Lay out a straight MGS-2.1 guardrail run: posts at the chosen spacing (
"standard"/"half"/"quarter") and W-beam panels ofpanel_length_ft(12.5 or 25 ft between splices). RaisesValueErrorfor a non-positive length, an unknown spacing, or a non-standard panel length.
- civilpy.structural.odot.guardrail.mgs_drawing(scd: str) MGSDrawing[source]
Look up an MGS drawing by SCD number (e.g.
"MGS-3.1").
- civilpy.structural.odot.guardrail.terminals_for_railing(scd: str) list[MGSDrawing][source]
MGS terminal assemblies that connect to bridge railing
scd(e.g."TST-2-21").
civilpy.structural.odot.headwall module
Ohio DOT cast-in-place half-height headwalls (HW-2.1, HW-2.2).
Cast-in-place headwall dimension tables transcribed from two Ohio DOT Standard Bridge Drawings (Office of Structural Engineering):
HW-2.1 Half-Height Headwalls for Corrugated Metal Pipe and Plastic
Pipe (2018-07-20, rev. 2022-07-15)
HW-2.2 Half-Height Headwalls for Concrete Pipe (rev. 2018-07-20)
For each pipe size the table gives headwall width W, height H,
thickness T, and the cast-in-place concrete quantity. HW-2.1 is keyed
by circular-pipe diameter D (the corrugated-metal/plastic primary
table; its pipe-arch tables are not transcribed here). HW-2.2 carries both
a circular table (by diameter) and an elliptical table (by rise and span).
The data lives in the res/hw_2_*.csv files and is loaded once at import.
All dimensions are inches; concrete quantity is cubic yards. Spot-checked
against the drawings in the test suite.
- class civilpy.structural.odot.headwall.EllipticalHeadwall(rise: float, span: float, width: float, height: float, thickness: float, concrete_cy: float)[source]
Bases:
objectOne HW-2.2 elliptical-pipe headwall line.
riseandspanare the pipe rise R and span;width(W),height(H) andthickness(T) are the headwall dimensions;concrete_cyis the cast-in-place concrete quantity. All inches.
- civilpy.structural.odot.headwall.HEADWALLS_BY_DIAMETER: dict[float, Headwall] = {12.0: Headwall(diameter=12.0, width=24.0, height=36.0, thickness=12.0, concrete_cy=0.21, note=''), 15.0: Headwall(diameter=15.0, width=30.0, height=38.0, thickness=12.0, concrete_cy=0.27, note=''), 18.0: Headwall(diameter=18.0, width=36.0, height=39.0, thickness=12.0, concrete_cy=0.33, note=''), 21.0: Headwall(diameter=21.0, width=42.0, height=40.0, thickness=12.0, concrete_cy=0.39, note=''), 24.0: Headwall(diameter=24.0, width=48.0, height=42.0, thickness=12.0, concrete_cy=0.46, note=''), 27.0: Headwall(diameter=27.0, width=54.0, height=44.0, thickness=12.0, concrete_cy=0.53, note=''), 30.0: Headwall(diameter=30.0, width=60.0, height=45.0, thickness=12.0, concrete_cy=0.6, note=''), 33.0: Headwall(diameter=33.0, width=66.0, height=46.0, thickness=12.0, concrete_cy=0.68, note=''), 36.0: Headwall(diameter=36.0, width=72.0, height=48.0, thickness=12.0, concrete_cy=0.76, note=''), 39.0: Headwall(diameter=39.0, width=78.0, height=50.0, thickness=12.0, concrete_cy=0.84, note=''), 42.0: Headwall(diameter=42.0, width=84.0, height=51.0, thickness=12.0, concrete_cy=0.92, note=''), 48.0: Headwall(diameter=48.0, width=96.0, height=54.0, thickness=12.0, concrete_cy=1.1, note=''), 54.0: Headwall(diameter=54.0, width=111.0, height=57.0, thickness=12.0, concrete_cy=1.33, note=''), 60.0: Headwall(diameter=60.0, width=126.0, height=60.0, thickness=12.0, concrete_cy=1.78, note=''), 66.0: Headwall(diameter=66.0, width=141.0, height=63.0, thickness=12.0, concrete_cy=2.06, note=''), 72.0: Headwall(diameter=72.0, width=156.0, height=72.0, thickness=12.0, concrete_cy=2.37, note=''), 78.0: Headwall(diameter=78.0, width=171.0, height=75.0, thickness=14.0, concrete_cy=2.94, note=''), 84.0: Headwall(diameter=84.0, width=186.0, height=78.0, thickness=14.0, concrete_cy=3.3, note=''), 90.0: Headwall(diameter=90.0, width=201.0, height=81.0, thickness=16.0, concrete_cy=4.0, note=''), 96.0: Headwall(diameter=96.0, width=216.0, height=84.0, thickness=16.0, concrete_cy=4.4, note=''), 102.0: Headwall(diameter=102.0, width=231.0, height=87.0, thickness=18.0, concrete_cy=5.28, note=''), 108.0: Headwall(diameter=108.0, width=246.0, height=90.0, thickness=20.0, concrete_cy=6.21, note=''), 114.0: Headwall(diameter=114.0, width=261.0, height=93.0, thickness=22.0, concrete_cy=7.25, note=''), 120.0: Headwall(diameter=120.0, width=276.0, height=96.0, thickness=24.0, concrete_cy=8.38, note=''), 126.0: Headwall(diameter=126.0, width=276.0, height=99.0, thickness=26.0, concrete_cy=8.64, note='between end treatment A and B'), 132.0: Headwall(diameter=132.0, width=276.0, height=102.0, thickness=28.0, concrete_cy=9.23, note=''), 138.0: Headwall(diameter=138.0, width=289.0, height=105.0, thickness=30.0, concrete_cy=10.5, note=''), 144.0: Headwall(diameter=144.0, width=302.0, height=108.0, thickness=32.0, concrete_cy=11.89, note=''), 150.0: Headwall(diameter=150.0, width=316.0, height=111.0, thickness=34.0, concrete_cy=13.38, note=''), 156.0: Headwall(diameter=156.0, width=329.0, height=114.0, thickness=36.0, concrete_cy=15.01, note=''), 162.0: Headwall(diameter=162.0, width=343.0, height=117.0, thickness=38.0, concrete_cy=16.75, note=''), 168.0: Headwall(diameter=168.0, width=356.0, height=120.0, thickness=40.0, concrete_cy=18.61, note=''), 174.0: Headwall(diameter=174.0, width=369.0, height=123.0, thickness=42.0, concrete_cy=20.28, note=''), 180.0: Headwall(diameter=180.0, width=383.0, height=126.0, thickness=43.0, concrete_cy=21.87, note=''), 186.0: Headwall(diameter=186.0, width=396.0, height=129.0, thickness=44.0, concrete_cy=23.54, note=''), 192.0: Headwall(diameter=192.0, width=410.0, height=132.0, thickness=45.0, concrete_cy=25.3, note=''), 198.0: Headwall(diameter=198.0, width=423.0, height=135.0, thickness=46.0, concrete_cy=27.12, note=''), 204.0: Headwall(diameter=204.0, width=436.0, height=138.0, thickness=47.0, concrete_cy=29.15, note=''), 210.0: Headwall(diameter=210.0, width=450.0, height=141.0, thickness=48.0, concrete_cy=31.03, note=''), 216.0: Headwall(diameter=216.0, width=463.0, height=144.0, thickness=49.0, concrete_cy=33.43, note=''), 222.0: Headwall(diameter=222.0, width=477.0, height=147.0, thickness=50.0, concrete_cy=36.26, note=''), 228.0: Headwall(diameter=228.0, width=490.0, height=150.0, thickness=51.0, concrete_cy=37.52, note=''), 234.0: Headwall(diameter=234.0, width=504.0, height=153.0, thickness=52.0, concrete_cy=39.86, note=''), 240.0: Headwall(diameter=240.0, width=517.0, height=156.0, thickness=53.0, concrete_cy=42.28, note=''), 246.0: Headwall(diameter=246.0, width=530.0, height=159.0, thickness=54.0, concrete_cy=44.83, note=''), 252.0: Headwall(diameter=252.0, width=544.0, height=162.0, thickness=54.0, concrete_cy=47.44, note='')}
Circular headwalls keyed by pipe diameter (inches).
- civilpy.structural.odot.headwall.HEADWALLS_CIRCULAR: list[Headwall] = [Headwall(diameter=12.0, width=24.0, height=36.0, thickness=12.0, concrete_cy=0.21, note=''), Headwall(diameter=15.0, width=30.0, height=38.0, thickness=12.0, concrete_cy=0.27, note=''), Headwall(diameter=18.0, width=36.0, height=39.0, thickness=12.0, concrete_cy=0.33, note=''), Headwall(diameter=21.0, width=42.0, height=40.0, thickness=12.0, concrete_cy=0.39, note=''), Headwall(diameter=24.0, width=48.0, height=42.0, thickness=12.0, concrete_cy=0.46, note=''), Headwall(diameter=27.0, width=54.0, height=44.0, thickness=12.0, concrete_cy=0.53, note=''), Headwall(diameter=30.0, width=60.0, height=45.0, thickness=12.0, concrete_cy=0.6, note=''), Headwall(diameter=33.0, width=66.0, height=46.0, thickness=12.0, concrete_cy=0.68, note=''), Headwall(diameter=36.0, width=72.0, height=48.0, thickness=12.0, concrete_cy=0.76, note=''), Headwall(diameter=39.0, width=78.0, height=50.0, thickness=12.0, concrete_cy=0.84, note=''), Headwall(diameter=42.0, width=84.0, height=51.0, thickness=12.0, concrete_cy=0.92, note=''), Headwall(diameter=48.0, width=96.0, height=54.0, thickness=12.0, concrete_cy=1.1, note=''), Headwall(diameter=54.0, width=111.0, height=57.0, thickness=12.0, concrete_cy=1.33, note=''), Headwall(diameter=60.0, width=126.0, height=60.0, thickness=12.0, concrete_cy=1.78, note=''), Headwall(diameter=66.0, width=141.0, height=63.0, thickness=12.0, concrete_cy=2.06, note=''), Headwall(diameter=72.0, width=156.0, height=72.0, thickness=12.0, concrete_cy=2.37, note=''), Headwall(diameter=78.0, width=171.0, height=75.0, thickness=14.0, concrete_cy=2.94, note=''), Headwall(diameter=84.0, width=186.0, height=78.0, thickness=14.0, concrete_cy=3.3, note=''), Headwall(diameter=90.0, width=201.0, height=81.0, thickness=16.0, concrete_cy=4.0, note=''), Headwall(diameter=96.0, width=216.0, height=84.0, thickness=16.0, concrete_cy=4.4, note=''), Headwall(diameter=102.0, width=231.0, height=87.0, thickness=18.0, concrete_cy=5.28, note=''), Headwall(diameter=108.0, width=246.0, height=90.0, thickness=20.0, concrete_cy=6.21, note=''), Headwall(diameter=114.0, width=261.0, height=93.0, thickness=22.0, concrete_cy=7.25, note=''), Headwall(diameter=120.0, width=276.0, height=96.0, thickness=24.0, concrete_cy=8.38, note=''), Headwall(diameter=126.0, width=276.0, height=99.0, thickness=26.0, concrete_cy=8.64, note='between end treatment A and B'), Headwall(diameter=132.0, width=276.0, height=102.0, thickness=28.0, concrete_cy=9.23, note=''), Headwall(diameter=138.0, width=289.0, height=105.0, thickness=30.0, concrete_cy=10.5, note=''), Headwall(diameter=144.0, width=302.0, height=108.0, thickness=32.0, concrete_cy=11.89, note=''), Headwall(diameter=150.0, width=316.0, height=111.0, thickness=34.0, concrete_cy=13.38, note=''), Headwall(diameter=156.0, width=329.0, height=114.0, thickness=36.0, concrete_cy=15.01, note=''), Headwall(diameter=162.0, width=343.0, height=117.0, thickness=38.0, concrete_cy=16.75, note=''), Headwall(diameter=168.0, width=356.0, height=120.0, thickness=40.0, concrete_cy=18.61, note=''), Headwall(diameter=174.0, width=369.0, height=123.0, thickness=42.0, concrete_cy=20.28, note=''), Headwall(diameter=180.0, width=383.0, height=126.0, thickness=43.0, concrete_cy=21.87, note=''), Headwall(diameter=186.0, width=396.0, height=129.0, thickness=44.0, concrete_cy=23.54, note=''), Headwall(diameter=192.0, width=410.0, height=132.0, thickness=45.0, concrete_cy=25.3, note=''), Headwall(diameter=198.0, width=423.0, height=135.0, thickness=46.0, concrete_cy=27.12, note=''), Headwall(diameter=204.0, width=436.0, height=138.0, thickness=47.0, concrete_cy=29.15, note=''), Headwall(diameter=210.0, width=450.0, height=141.0, thickness=48.0, concrete_cy=31.03, note=''), Headwall(diameter=216.0, width=463.0, height=144.0, thickness=49.0, concrete_cy=33.43, note=''), Headwall(diameter=222.0, width=477.0, height=147.0, thickness=50.0, concrete_cy=36.26, note=''), Headwall(diameter=228.0, width=490.0, height=150.0, thickness=51.0, concrete_cy=37.52, note=''), Headwall(diameter=234.0, width=504.0, height=153.0, thickness=52.0, concrete_cy=39.86, note=''), Headwall(diameter=240.0, width=517.0, height=156.0, thickness=53.0, concrete_cy=42.28, note=''), Headwall(diameter=246.0, width=530.0, height=159.0, thickness=54.0, concrete_cy=44.83, note=''), Headwall(diameter=252.0, width=544.0, height=162.0, thickness=54.0, concrete_cy=47.44, note='')]
HW-2.1 circular-pipe headwalls, ordered by pipe diameter.
- civilpy.structural.odot.headwall.HEADWALLS_CONCRETE_BY_DIAMETER: dict[float, Headwall] = {12.0: Headwall(diameter=12.0, width=24.0, height=36.0, thickness=12.0, concrete_cy=0.2, note=''), 15.0: Headwall(diameter=15.0, width=30.0, height=38.0, thickness=12.0, concrete_cy=0.25, note=''), 18.0: Headwall(diameter=18.0, width=36.0, height=39.0, thickness=12.0, concrete_cy=0.31, note=''), 21.0: Headwall(diameter=21.0, width=42.0, height=40.0, thickness=12.0, concrete_cy=0.37, note=''), 24.0: Headwall(diameter=24.0, width=48.0, height=42.0, thickness=12.0, concrete_cy=0.43, note=''), 27.0: Headwall(diameter=27.0, width=54.0, height=44.0, thickness=12.0, concrete_cy=0.49, note=''), 30.0: Headwall(diameter=30.0, width=60.0, height=45.0, thickness=12.0, concrete_cy=0.56, note=''), 33.0: Headwall(diameter=33.0, width=66.0, height=46.0, thickness=12.0, concrete_cy=0.62, note=''), 36.0: Headwall(diameter=36.0, width=72.0, height=48.0, thickness=12.0, concrete_cy=0.69, note=''), 39.0: Headwall(diameter=39.0, width=78.0, height=50.0, thickness=12.0, concrete_cy=0.77, note=''), 42.0: Headwall(diameter=42.0, width=84.0, height=51.0, thickness=12.0, concrete_cy=0.84, note=''), 48.0: Headwall(diameter=48.0, width=96.0, height=54.0, thickness=14.0, concrete_cy=1.09, note=''), 54.0: Headwall(diameter=54.0, width=111.0, height=57.0, thickness=14.0, concrete_cy=1.32, note=''), 60.0: Headwall(diameter=60.0, width=126.0, height=66.0, thickness=16.0, concrete_cy=1.93, note=''), 66.0: Headwall(diameter=66.0, width=141.0, height=69.0, thickness=18.0, concrete_cy=2.42, note=''), 72.0: Headwall(diameter=72.0, width=156.0, height=72.0, thickness=18.0, concrete_cy=2.77, note=''), 78.0: Headwall(diameter=78.0, width=171.0, height=75.0, thickness=20.0, concrete_cy=3.37, note=''), 84.0: Headwall(diameter=84.0, width=186.0, height=78.0, thickness=22.0, concrete_cy=4.05, note=''), 90.0: Headwall(diameter=90.0, width=201.0, height=81.0, thickness=22.0, concrete_cy=4.51, note=''), 96.0: Headwall(diameter=96.0, width=216.0, height=84.0, thickness=24.0, concrete_cy=5.31, note=''), 102.0: Headwall(diameter=102.0, width=231.0, height=87.0, thickness=26.0, concrete_cy=6.2, note=''), 108.0: Headwall(diameter=108.0, width=246.0, height=90.0, thickness=26.0, concrete_cy=6.78, note=''), 114.0: Headwall(diameter=114.0, width=261.0, height=93.0, thickness=28.0, concrete_cy=7.81, note=''), 120.0: Headwall(diameter=120.0, width=276.0, height=96.0, thickness=30.0, concrete_cy=8.93, note=''), 126.0: Headwall(diameter=126.0, width=291.0, height=99.0, thickness=30.0, concrete_cy=9.57, note=''), 132.0: Headwall(diameter=132.0, width=306.0, height=102.0, thickness=32.0, concrete_cy=10.84, note=''), 144.0: Headwall(diameter=144.0, width=344.0, height=108.0, thickness=34.0, concrete_cy=13.0, note='')}
HW-2.2 concrete circular headwalls keyed by pipe diameter (inches).
- civilpy.structural.odot.headwall.HEADWALLS_CONCRETE_CIRCULAR: list[Headwall] = [Headwall(diameter=12.0, width=24.0, height=36.0, thickness=12.0, concrete_cy=0.2, note=''), Headwall(diameter=15.0, width=30.0, height=38.0, thickness=12.0, concrete_cy=0.25, note=''), Headwall(diameter=18.0, width=36.0, height=39.0, thickness=12.0, concrete_cy=0.31, note=''), Headwall(diameter=21.0, width=42.0, height=40.0, thickness=12.0, concrete_cy=0.37, note=''), Headwall(diameter=24.0, width=48.0, height=42.0, thickness=12.0, concrete_cy=0.43, note=''), Headwall(diameter=27.0, width=54.0, height=44.0, thickness=12.0, concrete_cy=0.49, note=''), Headwall(diameter=30.0, width=60.0, height=45.0, thickness=12.0, concrete_cy=0.56, note=''), Headwall(diameter=33.0, width=66.0, height=46.0, thickness=12.0, concrete_cy=0.62, note=''), Headwall(diameter=36.0, width=72.0, height=48.0, thickness=12.0, concrete_cy=0.69, note=''), Headwall(diameter=39.0, width=78.0, height=50.0, thickness=12.0, concrete_cy=0.77, note=''), Headwall(diameter=42.0, width=84.0, height=51.0, thickness=12.0, concrete_cy=0.84, note=''), Headwall(diameter=48.0, width=96.0, height=54.0, thickness=14.0, concrete_cy=1.09, note=''), Headwall(diameter=54.0, width=111.0, height=57.0, thickness=14.0, concrete_cy=1.32, note=''), Headwall(diameter=60.0, width=126.0, height=66.0, thickness=16.0, concrete_cy=1.93, note=''), Headwall(diameter=66.0, width=141.0, height=69.0, thickness=18.0, concrete_cy=2.42, note=''), Headwall(diameter=72.0, width=156.0, height=72.0, thickness=18.0, concrete_cy=2.77, note=''), Headwall(diameter=78.0, width=171.0, height=75.0, thickness=20.0, concrete_cy=3.37, note=''), Headwall(diameter=84.0, width=186.0, height=78.0, thickness=22.0, concrete_cy=4.05, note=''), Headwall(diameter=90.0, width=201.0, height=81.0, thickness=22.0, concrete_cy=4.51, note=''), Headwall(diameter=96.0, width=216.0, height=84.0, thickness=24.0, concrete_cy=5.31, note=''), Headwall(diameter=102.0, width=231.0, height=87.0, thickness=26.0, concrete_cy=6.2, note=''), Headwall(diameter=108.0, width=246.0, height=90.0, thickness=26.0, concrete_cy=6.78, note=''), Headwall(diameter=114.0, width=261.0, height=93.0, thickness=28.0, concrete_cy=7.81, note=''), Headwall(diameter=120.0, width=276.0, height=96.0, thickness=30.0, concrete_cy=8.93, note=''), Headwall(diameter=126.0, width=291.0, height=99.0, thickness=30.0, concrete_cy=9.57, note=''), Headwall(diameter=132.0, width=306.0, height=102.0, thickness=32.0, concrete_cy=10.84, note=''), Headwall(diameter=144.0, width=344.0, height=108.0, thickness=34.0, concrete_cy=13.0, note='')]
HW-2.2 concrete-pipe circular headwalls, ordered by diameter.
- civilpy.structural.odot.headwall.HEADWALLS_CONCRETE_ELLIPTICAL: list[EllipticalHeadwall] = [EllipticalHeadwall(rise=14.0, span=23.0, width=36.0, height=38.0, thickness=12.0, concrete_cy=0.29), EllipticalHeadwall(rise=19.0, span=30.0, width=43.0, height=40.0, thickness=12.0, concrete_cy=0.35), EllipticalHeadwall(rise=22.0, span=34.0, width=47.0, height=41.0, thickness=12.0, concrete_cy=0.38), EllipticalHeadwall(rise=24.0, span=38.0, width=54.0, height=42.0, thickness=12.0, concrete_cy=0.44), EllipticalHeadwall(rise=29.0, span=45.0, width=62.0, height=44.0, thickness=12.0, concrete_cy=0.49), EllipticalHeadwall(rise=34.0, span=53.0, width=71.0, height=48.0, thickness=14.0, concrete_cy=0.66), EllipticalHeadwall(rise=38.0, span=60.0, width=82.0, height=50.0, thickness=14.0, concrete_cy=0.82), EllipticalHeadwall(rise=43.0, span=68.0, width=96.0, height=52.0, thickness=16.0, concrete_cy=1.01), EllipticalHeadwall(rise=48.0, span=76.0, width=110.0, height=60.0, thickness=16.0, concrete_cy=1.34), EllipticalHeadwall(rise=53.0, span=83.0, width=124.0, height=62.0, thickness=18.0, concrete_cy=1.65), EllipticalHeadwall(rise=58.0, span=91.0, width=138.0, height=65.0, thickness=18.0, concrete_cy=1.97), EllipticalHeadwall(rise=63.0, span=98.0, width=151.0, height=67.0, thickness=20.0, concrete_cy=2.38), EllipticalHeadwall(rise=68.0, span=106.0, width=165.0, height=70.0, thickness=20.0, concrete_cy=2.69), EllipticalHeadwall(rise=72.0, span=113.0, width=177.0, height=72.0, thickness=22.0, concrete_cy=3.14), EllipticalHeadwall(rise=77.0, span=121.0, width=191.0, height=75.0, thickness=22.0, concrete_cy=3.49), EllipticalHeadwall(rise=82.0, span=128.0, width=204.0, height=77.0, thickness=24.0, concrete_cy=4.04), EllipticalHeadwall(rise=87.0, span=136.0, width=218.0, height=80.0, thickness=24.0, concrete_cy=4.84), EllipticalHeadwall(rise=92.0, span=143.0, width=232.0, height=82.0, thickness=26.0, concrete_cy=5.12), EllipticalHeadwall(rise=97.0, span=151.0, width=246.0, height=85.0, thickness=26.0, concrete_cy=5.42), EllipticalHeadwall(rise=106.0, span=166.0, width=271.0, height=89.0, thickness=28.0, concrete_cy=6.6), EllipticalHeadwall(rise=116.0, span=180.0, width=298.0, height=94.0, thickness=30.0, concrete_cy=7.99)]
HW-2.2 concrete-pipe elliptical headwalls, ordered by rise.
- class civilpy.structural.odot.headwall.Headwall(diameter: float, width: float, height: float, thickness: float, concrete_cy: float, note: str = '')[source]
Bases:
objectOne HW-2.1 circular-pipe headwall line.
diameteris the pipe inside diameter D;width(W),height(H) andthickness(T) are the headwall dimensions;concrete_cyis the cast-in-place concrete quantity.noteflags special rows (e.g. pipe sizes between end treatments A and B).
- class civilpy.structural.odot.headwall.HeadwallInput(diameter_in: float, concrete: bool = False)[source]
Bases:
objectInputs for a circular-pipe headwall solid.
diameter_inis a tabulated pipe inside diameter D;concreteselects the HW-2.2 concrete-pipe table instead of the HW-2.1 corrugated-metal/plastic table.
- class civilpy.structural.odot.headwall.HeadwallLayout(inputs: ~civilpy.structural.odot.headwall.HeadwallInput, table: ~civilpy.structural.odot.headwall.Headwall, front_outline: tuple[tuple[float, float, float], tuple[float, float, float], tuple[float, float, float], tuple[float, float, float]], side_profile: tuple[tuple[float, float, float], tuple[float, float, float], tuple[float, float, float], tuple[float, float, float]], pipe_center: tuple[float, float, float], pipe_diameter_ft: float, width_ft: float, height_ft: float, base_thickness_ft: float, top_thickness_ft: float, cover_in: float, concrete_cy: float, notes: tuple[str, ...] = <factory>)[source]
Bases:
objectThe generated headwall.
front_outlineis the vertical front face (counterclockwise in the X-Z plane at y = 0);side_profileis the battered wall cross-section in the Y-Z plane at x = -W/2 (front vertical, back battered 12 in -> T); the solid isside_profileswept the full width W in +X with the circularpipeopening (centrepipe_center, diameterpipe_diameter_ft) cut through it along Y. Origin: x = 0 on the wall centreline, y = 0 at the front face (wall behind, -y), z = 0 at the flow line / wall base.- front_outline: tuple[tuple[float, float, float], tuple[float, float, float], tuple[float, float, float], tuple[float, float, float]]
- inputs: HeadwallInput
- civilpy.structural.odot.headwall.elliptical_headwall_for_rise(rise: float) EllipticalHeadwall[source]
Look up the HW-2.2 concrete elliptical headwall by pipe rise (inches).
- civilpy.structural.odot.headwall.headwall_for_diameter(diameter: float, concrete: bool = False) Headwall[source]
Look up the circular headwall for a pipe diameter (inches).
concrete=Falseuses the HW-2.1 corrugated-metal/plastic table;concrete=Trueuses the HW-2.2 concrete-pipe table. RaisesKeyErrorif the diameter is not a tabulated size.
- civilpy.structural.odot.headwall.layout_headwall(inp: HeadwallInput) HeadwallLayout[source]
Generate the rectangular circular-pipe headwall solid (end treatment “A”).
Raises
KeyErrorfor a pipe diameter that is not a tabulated size andValueErrorfor a size whose cover over the pipe crown drops below the 6 in minimum (end treatment “B”, not modeled here).
civilpy.structural.odot.portable_barrier module
ODOT PCB-91 Standard Portable Concrete Barrier Details.
Transcribed from Ohio DOT Standard Construction Drawing PCB-91
(revised 07-17-2020, 1 sheet). The drawing remains the controlling
document. Crash-test levels, materials, and the catalog listing live in
civilpy.structural.odot.bridge_railing (designations
"PCB (portable, unanchored)" — NCHRP 350 TL-3 — and
"PCB (portable, anchored)" — TL-4 fully anchored on the traffic
side); this module adds the drawable geometry: the New Jersey shape
section, segment/joint layout, anchor-hole stations, and the
drainage/lifting slot.
Segments are 10’-0” or 12’-0” long, connected by 3/4 in dia. galvanized
hinge-bar loops pinned with a vertical 1-1/4 in dia. H.S. bolt (plate
washers + hex nut): barriers are set closer together so the bolt drops
through the loops, and joints must be fully open (1-3/4 in max gap)
before the nut is tightened. Anchors are 1 in dia. H.S. bolts through
1-1/4 in dia. holes — thru bolts or partial-depth bolts embedded a
minimum of 6-1/2 in and grouted (705.20). Concrete f’c >= 4,000 psi;
all hardware per 711.09 (ASTM A325), galvanized per 711.02; reinforcing
(including hinge bars) per 509.02. Segments are marked PCB-BXX-350
(XX = year cast) in 2 in impressed lettering.
Units: section dimensions in inches, run stations in feet.
- class civilpy.structural.odot.portable_barrier.BarrierSegment(index: int, start_ft: float, end_ft: float)[source]
Bases:
objectOne placed segment: stations (ft) along the run.
- civilpy.structural.odot.portable_barrier.anchor_hole_stations_ft(segment_length_ft: float) tuple[float, ...][source]
Anchor-hole stations along one segment (ft from its start): 1’-0” from each end, equally spaced at 2’-0” c/c (5 holes per row on a 10 ft segment, 6 on a 12 ft).
- civilpy.structural.odot.portable_barrier.barrier_run(n_segments: int, segment_length_ft: float = 10.0, joint_gap_in: float = 0.25) tuple[BarrierSegment, ...][source]
Lay out
n_segmentsalong a straight run with the given joint gap (closed 1/4 in up to the fully-open 1-3/4 in max).
- civilpy.structural.odot.portable_barrier.profile_points_in(chamfered: bool = True) tuple[tuple[float, float], ...][source]
The closed New Jersey shape section, counterclockwise from the bottom-left corner, as (x, y) inches with x transverse from the barrier centerline and y up from the deck surface.
chamferedincludes the 3/4 in top chamfers (the sheet allows a 1 in radius instead).
- civilpy.structural.odot.portable_barrier.run_length_ft(segments: tuple[BarrierSegment, ...]) float[source]
Overall length of a laid-out run (ft), including joint gaps.
civilpy.structural.odot.ps_i_beam module
Ohio DOT prestressed concrete I-beam bridge details (PSID-1-13).
Transcribed from Ohio DOT Standard Bridge Drawing PSID-1-13, “Prestressed Concrete I-Beam Bridge Details” (rev. 07-18-2025, 10 sheets). The drawing remains the controlling document.
Thirteen standard sections:
AASHTO Type 2/3/4 and three deepened “Modified AASHTO Type 4” webs (60/66/72 in overall depth) – sheet 1’s
SECTION PROPERTIEStable. The Modified Type 4s keep Type 4’s 26 in bottom flange but carry a wide, thin top flange (36 in for the 60/66, 48 in for the 72 – verified against sheet 1’s own dimension strings and the shipping-strand offsets), not Type 4’s 20 in flange.WF36-49 .. WF72-49 wide-flange sections (sheets 2-3, sheet 3’s
SECTION PROPERTIEStable): 49 in top flange, 40 in bottom flange, 8 in web, 62 permissible bottom-flange strand locations each.
Beyond the section tables this module also catalogs, per section, the
sheet’s permissible strand grid (the + marks: 2 in lattice both
ways, exact per-row offsets extracted from the drawing’s vector marks –
row totals reconcile with the sheet’s stated 26/40/52/62 permissible
location counts), the WF web locations that must be draped if
utilized (sheet 2 note), the Modified-AASHTO/WF shipping strand
locations, and the sheet 10 design constants (0.6 in Grade 270
low-relaxation strand at 0.217 in^2, designer-selected f'c /
f'ci ranges, HL-93 + 60 psf FWS, spacing < 14 ft, skew < 45 deg).
No PSIDD companion design-data sheet exists (unlike PSBD/PSBDD for
box beams), so there are no tabulated standard strand patterns;
civilpy.structural.ps_i_beam_pipeline designs a pattern on this
grid instead.
Lengths in inches, area in in^2, weight in lb/ft, moment of inertia in in^4, section moduli in in^3, unless noted. Spot-checked against the drawing in the test suite.
- civilpy.structural.odot.ps_i_beam.DIAPHRAGM_FC_KSI = 4.5
Diaphragm concrete (Item 511), ksi.
- civilpy.structural.odot.ps_i_beam.FCI_RANGE_KSI = (4.0, 5.0)
Designer-selected release strength range, ksi (sheet 10).
- civilpy.structural.odot.ps_i_beam.FC_RANGE_KSI = (5.5, 7.0)
Designer-selected 28-day strength range, ksi (sheet 10).
- civilpy.structural.odot.ps_i_beam.FWS_PSF = 60.0
Future wearing surface dead load, lb/ft^2 (sheet 10 design loading).
- civilpy.structural.odot.ps_i_beam.MAX_BEAM_SPACING_FT = 14.0
The standard applies to beam spacings under 14 ft and skews under 45 degrees (sheet 10 general notes).
- class civilpy.structural.odot.ps_i_beam.PSIBeamLayout(section: ~civilpy.structural.odot.ps_i_beam.PSIBeamSection, profile: tuple[tuple[float, float], ...], length_ft: float, notes: tuple[str, ...] = <factory>)[source]
Bases:
objectA simplified I-shaped cross-section profile (top flange, web, bottom flange) – straight-line approximation, no fillet/bulb radii – extruded
length_ft. Profile points (y, z) inches, y transverse, z up from the bottom; the beam centerline is y = 0.- section: PSIBeamSection
- class civilpy.structural.odot.ps_i_beam.PSIBeamSection(name: str, depth_in: float, area_in2: float, weight_plf: float, yb_in: float, yt_in: float, i_in4: float, sb_in3: float, st_in3: float, vol_surf_ratio: float, top_flange_width_in: float, bottom_flange_width_in: float, max_bottom_flange_strands: int, web_in: float = 8.0, strand_rows: tuple = (), draped_required: tuple = (), shipping_strand_locations: tuple = ())[source]
Bases:
objectOne PSID-1-13 standard section (sheet 1 / sheet 3 SECTION PROPERTIES tables).
strand_rowsis the sheet’s permissible strand grid: a tuple of(z, (y, ...))rows –zinches above the beam bottom,ytransverse offsets from the beam centerline (2 in lattice). The row totals equalmax_bottom_flange_strands.draped_requiredlists the grid locations the sheet marks “if utilized, these strand locations must be draped” (WF sections’ upper web column).shipping_strand_locationsare the optional debonded shipping strands the fabricator may add in the top flange (Modified AASHTO / WF sheets; the sheet ties them to general-note bonding rules – seeSHIPPING_STRAND_BOND_FT).
- civilpy.structural.odot.ps_i_beam.PS_I_BEAM_SECTIONS: dict[str, PSIBeamSection] = {'AASHTO Type 2': PSIBeamSection(name='AASHTO Type 2', depth_in=36.0, area_in2=369.0, weight_plf=384.0, yb_in=15.83, yt_in=20.17, i_in4=50979, sb_in3=3221, st_in3=2527, vol_surf_ratio=3.371, top_flange_width_in=12.0, bottom_flange_width_in=18.0, max_bottom_flange_strands=26, web_in=6.0, strand_rows=((2.0, (-6.0, -4.0, 0.0, 4.0, 6.0)), (4.0, (-6.0, -4.0, -2.0, 0.0, 2.0, 4.0, 6.0)), (6.0, (-6.0, -4.0, 0.0, 4.0, 6.0)), (8.0, (-4.0, -2.0, 0.0, 2.0, 4.0)), (10.0, (-2.0, 0.0, 2.0)), (12.0, (0.0,))), draped_required=(), shipping_strand_locations=()), 'AASHTO Type 3': PSIBeamSection(name='AASHTO Type 3', depth_in=45.0, area_in2=560.0, weight_plf=583.0, yb_in=20.27, yt_in=24.73, i_in4=125390, sb_in3=6185, st_in3=5071, vol_surf_ratio=4.056, top_flange_width_in=16.0, bottom_flange_width_in=22.0, max_bottom_flange_strands=40, web_in=7.0, strand_rows=((2.0, (-7.0, -5.0, 5.0, 7.0)), (4.0, (-9.0, -7.0, -5.0, -3.0, -1.0, 1.0, 3.0, 5.0, 7.0, 9.0)), (6.0, (-9.0, -7.0, -5.0, 5.0, 7.0, 9.0)), (8.0, (-7.0, -5.0, -3.0, -1.0, 1.0, 3.0, 5.0, 7.0)), (10.0, (-5.0, -3.0, -1.0, 1.0, 3.0, 5.0)), (12.0, (-3.0, -1.0, 1.0, 3.0)), (14.0, (-1.0, 1.0))), draped_required=(), shipping_strand_locations=()), 'AASHTO Type 4': PSIBeamSection(name='AASHTO Type 4', depth_in=54.0, area_in2=789.0, weight_plf=822.0, yb_in=24.73, yt_in=29.27, i_in4=260741, sb_in3=10542, st_in3=8909, vol_surf_ratio=4.741, top_flange_width_in=20.0, bottom_flange_width_in=26.0, max_bottom_flange_strands=52, web_in=8.0, strand_rows=((2.0, (-10.0, -8.0, -6.0, -4.0, 0.0, 4.0, 6.0, 8.0, 10.0)), (4.0, (-10.0, -8.0, -6.0, -4.0, 0.0, 4.0, 6.0, 8.0, 10.0)), (6.0, (-10.0, -8.0, -6.0, -4.0, 0.0, 4.0, 6.0, 8.0, 10.0)), (8.0, (-10.0, -8.0, -6.0, -4.0, 0.0, 4.0, 6.0, 8.0, 10.0)), (10.0, (-8.0, -6.0, -4.0, 0.0, 4.0, 6.0, 8.0)), (12.0, (-6.0, -4.0, 0.0, 4.0, 6.0)), (14.0, (-4.0, 0.0, 4.0)), (16.0, (0.0,))), draped_required=(), shipping_strand_locations=()), 'Modified AASHTO Type 4 (60in)': PSIBeamSection(name='Modified AASHTO Type 4 (60in)', depth_in=60.0, area_in2=860.0, weight_plf=896.0, yb_in=28.74, yt_in=31.26, i_in4=384705, sb_in3=13385, st_in3=12307, vol_surf_ratio=4.089, top_flange_width_in=36.0, bottom_flange_width_in=26.0, max_bottom_flange_strands=52, web_in=8.0, strand_rows=((2.0, (-10.0, -8.0, -6.0, -4.0, 0.0, 4.0, 6.0, 8.0, 10.0)), (4.0, (-10.0, -8.0, -6.0, -4.0, 0.0, 4.0, 6.0, 8.0, 10.0)), (6.0, (-10.0, -8.0, -6.0, -4.0, 0.0, 4.0, 6.0, 8.0, 10.0)), (8.0, (-10.0, -8.0, -6.0, -4.0, 0.0, 4.0, 6.0, 8.0, 10.0)), (10.0, (-8.0, -6.0, -4.0, 0.0, 4.0, 6.0, 8.0)), (12.0, (-6.0, -4.0, 0.0, 4.0, 6.0)), (14.0, (-4.0, 0.0, 4.0)), (16.0, (0.0,))), draped_required=(), shipping_strand_locations=((-10.0, 57.25), (-8.0, 57.25), (-6.0, 57.25), (6.0, 57.25), (8.0, 57.25), (10.0, 57.25))), 'Modified AASHTO Type 4 (66in)': PSIBeamSection(name='Modified AASHTO Type 4 (66in)', depth_in=66.0, area_in2=908.0, weight_plf=946.0, yb_in=31.58, yt_in=34.42, i_in4=492212, sb_in3=15588, st_in3=14299, vol_surf_ratio=4.085, top_flange_width_in=36.0, bottom_flange_width_in=26.0, max_bottom_flange_strands=52, web_in=8.0, strand_rows=((2.0, (-10.0, -8.0, -6.0, -4.0, 0.0, 4.0, 6.0, 8.0, 10.0)), (4.0, (-10.0, -8.0, -6.0, -4.0, 0.0, 4.0, 6.0, 8.0, 10.0)), (6.0, (-10.0, -8.0, -6.0, -4.0, 0.0, 4.0, 6.0, 8.0, 10.0)), (8.0, (-10.0, -8.0, -6.0, -4.0, 0.0, 4.0, 6.0, 8.0, 10.0)), (10.0, (-8.0, -6.0, -4.0, 0.0, 4.0, 6.0, 8.0)), (12.0, (-6.0, -4.0, 0.0, 4.0, 6.0)), (14.0, (-4.0, 0.0, 4.0)), (16.0, (0.0,))), draped_required=(), shipping_strand_locations=((-10.0, 63.25), (-8.0, 63.25), (-6.0, 63.25), (6.0, 63.25), (8.0, 63.25), (10.0, 63.25))), 'Modified AASHTO Type 4 (72in)': PSIBeamSection(name='Modified AASHTO Type 4 (72in)', depth_in=72.0, area_in2=1015.0, weight_plf=1058.0, yb_in=36.52, yt_in=35.48, i_in4=684726, sb_in3=18749, st_in3=19299, vol_surf_ratio=3.947, top_flange_width_in=48.0, bottom_flange_width_in=26.0, max_bottom_flange_strands=52, web_in=8.0, strand_rows=((2.0, (-10.0, -8.0, -6.0, -4.0, 0.0, 4.0, 6.0, 8.0, 10.0)), (4.0, (-10.0, -8.0, -6.0, -4.0, 0.0, 4.0, 6.0, 8.0, 10.0)), (6.0, (-10.0, -8.0, -6.0, -4.0, 0.0, 4.0, 6.0, 8.0, 10.0)), (8.0, (-10.0, -8.0, -6.0, -4.0, 0.0, 4.0, 6.0, 8.0, 10.0)), (10.0, (-8.0, -6.0, -4.0, 0.0, 4.0, 6.0, 8.0)), (12.0, (-6.0, -4.0, 0.0, 4.0, 6.0)), (14.0, (-4.0, 0.0, 4.0)), (16.0, (0.0,))), draped_required=(), shipping_strand_locations=((-10.0, 69.25), (-8.0, 69.25), (-6.0, 69.25), (6.0, 69.25), (8.0, 69.25), (10.0, 69.25))), 'WF36-49': PSIBeamSection(name='WF36-49', depth_in=36.0, area_in2=878.3, weight_plf=915.0, yb_in=18.2, yt_in=17.8, i_in4=145592, sb_in3=8000, st_in3=8179, vol_surf_ratio=4.16, top_flange_width_in=49.0, bottom_flange_width_in=40.0, max_bottom_flange_strands=62, web_in=8.0, strand_rows=((2.0, (-16.0, -14.0, -12.0, -10.0, -8.0, -6.0, -4.0, 0.0, 4.0, 6.0, 8.0, 10.0, 12.0, 14.0, 16.0)), (4.0, (-18.0, -16.0, -14.0, -12.0, -10.0, -8.0, -6.0, -4.0, 0.0, 4.0, 6.0, 8.0, 10.0, 12.0, 14.0, 16.0, 18.0)), (6.0, (-14.0, -12.0, -10.0, -8.0, -6.0, -4.0, 0.0, 4.0, 6.0, 8.0, 10.0, 12.0, 14.0)), (8.0, (-10.0, -8.0, -6.0, -4.0, 0.0, 4.0, 6.0, 8.0, 10.0)), (10.0, (-6.0, -4.0, 0.0, 4.0, 6.0)), (12.0, (0.0,)), (14.0, (0.0,)), (16.0, (0.0,))), draped_required=((0.0, 14.0), (0.0, 16.0)), shipping_strand_locations=((-10.0, 33.25), (-8.0, 33.25), (-6.0, 33.25), (6.0, 33.25), (8.0, 33.25), (10.0, 33.25))), 'WF42-49': PSIBeamSection(name='WF42-49', depth_in=42.0, area_in2=926.3, weight_plf=965.0, yb_in=21.1, yt_in=20.9, i_in4=217461, sb_in3=10306, st_in3=10405, vol_surf_ratio=4.152, top_flange_width_in=49.0, bottom_flange_width_in=40.0, max_bottom_flange_strands=62, web_in=8.0, strand_rows=((2.0, (-16.0, -14.0, -12.0, -10.0, -8.0, -6.0, -4.0, 0.0, 4.0, 6.0, 8.0, 10.0, 12.0, 14.0, 16.0)), (4.0, (-18.0, -16.0, -14.0, -12.0, -10.0, -8.0, -6.0, -4.0, 0.0, 4.0, 6.0, 8.0, 10.0, 12.0, 14.0, 16.0, 18.0)), (6.0, (-14.0, -12.0, -10.0, -8.0, -6.0, -4.0, 0.0, 4.0, 6.0, 8.0, 10.0, 12.0, 14.0)), (8.0, (-10.0, -8.0, -6.0, -4.0, 0.0, 4.0, 6.0, 8.0, 10.0)), (10.0, (-6.0, -4.0, 0.0, 4.0, 6.0)), (12.0, (0.0,)), (14.0, (0.0,)), (16.0, (0.0,))), draped_required=((0.0, 14.0), (0.0, 16.0)), shipping_strand_locations=((-10.0, 39.25), (-8.0, 39.25), (-6.0, 39.25), (6.0, 39.25), (8.0, 39.25), (10.0, 39.25))), 'WF48-49': PSIBeamSection(name='WF48-49', depth_in=48.0, area_in2=974.3, weight_plf=1015.0, yb_in=24.0, yt_in=24.0, i_in4=305994, sb_in3=12750, st_in3=12750, vol_surf_ratio=4.144, top_flange_width_in=49.0, bottom_flange_width_in=40.0, max_bottom_flange_strands=62, web_in=8.0, strand_rows=((2.0, (-16.0, -14.0, -12.0, -10.0, -8.0, -6.0, -4.0, 0.0, 4.0, 6.0, 8.0, 10.0, 12.0, 14.0, 16.0)), (4.0, (-18.0, -16.0, -14.0, -12.0, -10.0, -8.0, -6.0, -4.0, 0.0, 4.0, 6.0, 8.0, 10.0, 12.0, 14.0, 16.0, 18.0)), (6.0, (-14.0, -12.0, -10.0, -8.0, -6.0, -4.0, 0.0, 4.0, 6.0, 8.0, 10.0, 12.0, 14.0)), (8.0, (-10.0, -8.0, -6.0, -4.0, 0.0, 4.0, 6.0, 8.0, 10.0)), (10.0, (-6.0, -4.0, 0.0, 4.0, 6.0)), (12.0, (0.0,)), (14.0, (0.0,)), (16.0, (0.0,))), draped_required=((0.0, 14.0), (0.0, 16.0)), shipping_strand_locations=((-10.0, 45.25), (-8.0, 45.25), (-6.0, 45.25), (6.0, 45.25), (8.0, 45.25), (10.0, 45.25))), 'WF54-49': PSIBeamSection(name='WF54-49', depth_in=54.0, area_in2=1022.3, weight_plf=1065.0, yb_in=27.0, yt_in=27.0, i_in4=412056, sb_in3=15261, st_in3=15261, vol_surf_ratio=4.137, top_flange_width_in=49.0, bottom_flange_width_in=40.0, max_bottom_flange_strands=62, web_in=8.0, strand_rows=((2.0, (-16.0, -14.0, -12.0, -10.0, -8.0, -6.0, -4.0, 0.0, 4.0, 6.0, 8.0, 10.0, 12.0, 14.0, 16.0)), (4.0, (-18.0, -16.0, -14.0, -12.0, -10.0, -8.0, -6.0, -4.0, 0.0, 4.0, 6.0, 8.0, 10.0, 12.0, 14.0, 16.0, 18.0)), (6.0, (-14.0, -12.0, -10.0, -8.0, -6.0, -4.0, 0.0, 4.0, 6.0, 8.0, 10.0, 12.0, 14.0)), (8.0, (-10.0, -8.0, -6.0, -4.0, 0.0, 4.0, 6.0, 8.0, 10.0)), (10.0, (-6.0, -4.0, 0.0, 4.0, 6.0)), (12.0, (0.0,)), (14.0, (0.0,)), (16.0, (0.0,))), draped_required=((0.0, 14.0), (0.0, 16.0)), shipping_strand_locations=((-10.0, 51.25), (-8.0, 51.25), (-6.0, 51.25), (6.0, 51.25), (8.0, 51.25), (10.0, 51.25))), 'WF60-49': PSIBeamSection(name='WF60-49', depth_in=60.0, area_in2=1070.3, weight_plf=1115.0, yb_in=29.9, yt_in=30.1, i_in4=536513, sb_in3=17944, st_in3=17824, vol_surf_ratio=4.131, top_flange_width_in=49.0, bottom_flange_width_in=40.0, max_bottom_flange_strands=62, web_in=8.0, strand_rows=((2.0, (-16.0, -14.0, -12.0, -10.0, -8.0, -6.0, -4.0, 0.0, 4.0, 6.0, 8.0, 10.0, 12.0, 14.0, 16.0)), (4.0, (-18.0, -16.0, -14.0, -12.0, -10.0, -8.0, -6.0, -4.0, 0.0, 4.0, 6.0, 8.0, 10.0, 12.0, 14.0, 16.0, 18.0)), (6.0, (-14.0, -12.0, -10.0, -8.0, -6.0, -4.0, 0.0, 4.0, 6.0, 8.0, 10.0, 12.0, 14.0)), (8.0, (-10.0, -8.0, -6.0, -4.0, 0.0, 4.0, 6.0, 8.0, 10.0)), (10.0, (-6.0, -4.0, 0.0, 4.0, 6.0)), (12.0, (0.0,)), (14.0, (0.0,)), (16.0, (0.0,))), draped_required=((0.0, 14.0), (0.0, 16.0)), shipping_strand_locations=((-10.0, 57.25), (-8.0, 57.25), (-6.0, 57.25), (6.0, 57.25), (8.0, 57.25), (10.0, 57.25))), 'WF66-49': PSIBeamSection(name='WF66-49', depth_in=66.0, area_in2=1118.3, weight_plf=1165.0, yb_in=32.9, yt_in=33.1, i_in4=680229, sb_in3=20676, st_in3=20551, vol_surf_ratio=4.125, top_flange_width_in=49.0, bottom_flange_width_in=40.0, max_bottom_flange_strands=62, web_in=8.0, strand_rows=((2.0, (-16.0, -14.0, -12.0, -10.0, -8.0, -6.0, -4.0, 0.0, 4.0, 6.0, 8.0, 10.0, 12.0, 14.0, 16.0)), (4.0, (-18.0, -16.0, -14.0, -12.0, -10.0, -8.0, -6.0, -4.0, 0.0, 4.0, 6.0, 8.0, 10.0, 12.0, 14.0, 16.0, 18.0)), (6.0, (-14.0, -12.0, -10.0, -8.0, -6.0, -4.0, 0.0, 4.0, 6.0, 8.0, 10.0, 12.0, 14.0)), (8.0, (-10.0, -8.0, -6.0, -4.0, 0.0, 4.0, 6.0, 8.0, 10.0)), (10.0, (-6.0, -4.0, 0.0, 4.0, 6.0)), (12.0, (0.0,)), (14.0, (0.0,)), (16.0, (0.0,))), draped_required=((0.0, 14.0), (0.0, 16.0)), shipping_strand_locations=((-10.0, 63.25), (-8.0, 63.25), (-6.0, 63.25), (6.0, 63.25), (8.0, 63.25), (10.0, 63.25))), 'WF72-49': PSIBeamSection(name='WF72-49', depth_in=72.0, area_in2=1166.3, weight_plf=1215.0, yb_in=35.8, yt_in=36.2, i_in4=844069, sb_in3=23577, st_in3=23317, vol_surf_ratio=4.12, top_flange_width_in=49.0, bottom_flange_width_in=40.0, max_bottom_flange_strands=62, web_in=8.0, strand_rows=((2.0, (-16.0, -14.0, -12.0, -10.0, -8.0, -6.0, -4.0, 0.0, 4.0, 6.0, 8.0, 10.0, 12.0, 14.0, 16.0)), (4.0, (-18.0, -16.0, -14.0, -12.0, -10.0, -8.0, -6.0, -4.0, 0.0, 4.0, 6.0, 8.0, 10.0, 12.0, 14.0, 16.0, 18.0)), (6.0, (-14.0, -12.0, -10.0, -8.0, -6.0, -4.0, 0.0, 4.0, 6.0, 8.0, 10.0, 12.0, 14.0)), (8.0, (-10.0, -8.0, -6.0, -4.0, 0.0, 4.0, 6.0, 8.0, 10.0)), (10.0, (-6.0, -4.0, 0.0, 4.0, 6.0)), (12.0, (0.0,)), (14.0, (0.0,)), (16.0, (0.0,))), draped_required=((0.0, 14.0), (0.0, 16.0)), shipping_strand_locations=((-10.0, 69.25), (-8.0, 69.25), (-6.0, 69.25), (6.0, 69.25), (8.0, 69.25), (10.0, 69.25)))}
PSID-1-13 standard I-beam sections, keyed by name.
- civilpy.structural.odot.ps_i_beam.SHIPPING_STRAND_BOND_FT = 10.0
Shipping strands are debonded except the last 10 ft each end (sheet 10).
- civilpy.structural.odot.ps_i_beam.STRAND_AREA_IN2 = 0.217
Nominal strand area (in^2) – 0.6 in seven-wire strand (sheet 10).
- civilpy.structural.odot.ps_i_beam.STRAND_DIAMETER_IN = 0.6
Strand diameter, inches.
- civilpy.structural.odot.ps_i_beam.STRAND_FPU_KSI = 270.0
Strand ultimate strength, ksi (711.27 / ASTM A416 Grade 270, low-lax).
- civilpy.structural.odot.ps_i_beam.i_beam_diaphragm_stations_ft(span_ft: float) list[float][source]
Intermediate-diaphragm centerline stations (ft from the span start) per sheet 5: one at midspan for spans up to 80 ft, at the quarter points beyond that. (Cast-in-place required under 60 in deep beams; 60/66/72 in beams may use the sheet 9 galvanized-steel diaphragms instead – sheet 10 general notes.)
- civilpy.structural.odot.ps_i_beam.layout_ps_i_beam(name: str, length_ft: float, web_thickness_in: float = 8.0, flange_thickness_in: float = 8.0) PSIBeamLayout[source]
Generate a simplified I-beam cross-section profile for
name(ps_i_beam_section()), extrudedlength_ft.Raises
ValueErrorfor a non-positive length or an unknown section name.
- civilpy.structural.odot.ps_i_beam.ps_i_beam_profile(name: str) tuple[tuple[float, float], ...][source]
The true tapered cross-section outline of a PSID-1-13 section as closed-polygon vertices
(y, z)in inches,ytransverse from the beam centerline,zup from the bottom – counter-clockwise, starting at the bottom-left corner. Straight-line approximation: fillet and 3/4 in chamfer radii are not modeled (unlikelayout_ps_i_beam(), the flange tapers are).
- civilpy.structural.odot.ps_i_beam.ps_i_beam_section(name: str) PSIBeamSection[source]
Look up a PSID-1-13 standard section by name.
Raises
ValueErrornaming the valid sections otherwise.
- civilpy.structural.odot.ps_i_beam.strand_centroid_in(pattern: list[tuple[float, float]]) float[source]
Height of a strand pattern’s centroid above the beam bottom (in).
- civilpy.structural.odot.ps_i_beam.strand_grid(name: str) list[tuple[float, float]][source]
Every permissible bottom-flange/web strand location of a section as
(y, z)inches, in the standard fill order: row by row from the bottom up, outermost locations first within a row (the fill order keeps each partial pattern symmetric and its centroid low).Locations in
PSIBeamSection.draped_requiredcome last so a straight-strand design never occupies them by accident.
civilpy.structural.odot.roadway_barrier module
Ohio DOT standard roadway (at-grade) single-slope concrete barriers.
Office of Roadway Engineering counterparts of the Office of Structural
Engineering’s bridge parapets in civilpy.structural.odot.bridge_railing
– same 5.25:1 single-slope face, but freestanding at grade (median or
shoulder) rather than backed against a deck edge. shape carries
"single slope" so civilpy.structural.rhino_barrier.shape_family()
routes these through the same profile-sweep engine; unlike a deck-edge
parapet a roadway barrier is placed with side=0 (freestanding, symmetric
about its centerline).
Types B/B1/D/N are fully dimensioned on their drawings (fixed height, top,
and base width). Types C/C1 are variable-height siblings of B/B1 – the
drawings show a project-defined upper extension (“Varies … See Plans for
dimensions”) added above the fixed B/B1 body, so no formula is transcribed
for the extension; height/base_width here are the B/B1 base-body
values and notes records the variable range. Type E (RM-4.9) differs
structurally – a shorter 36 in barrier on a cast-in-place moment slab
foundation with a curved/vertical face – and its concrete envelope is not
dimensioned on the drawing (only the rebar cage is); its catalog entry
therefore omits top_width/base_width rather than inventing them, and
layout_roadway_barrier() raises if asked to build its profile.
Two companion drawings extend the same profile engine along the run:
RM-4.6 end sections (
layout_barrier_end_section()): the cast-in-place taper that steps a Type B / B1 / D barrier down to a 32 in vertical-faced end for a Bridge Terminal Assembly or impact attenuator connection — profiles at the drawing’s stations, ready to loft.RM-4.4 transitions (
layout_barrier_transition()): the plan-view widening that wraps a Type B/B1/C/C1 barrier around a sign support / light tower foundation or a bridge pier — half-width per station over the 40 ft tapers.
Lengths are in inches unless noted. Concrete strength f_c in ksi.
- Sources (SCD number — drawing date / latest cited revision):
RM-4.3 Single slope barrier, Types B, B1, C, C1 (rev. 2025-07-18) RM-4.4 Single slope barrier transitions (rev. 2025-01-17) RM-4.5 Single slope barrier, Type D (rev. 2026-01-16) RM-4.6 Concrete barrier end sections, Types B, B1, D (rev. 2025-07-18) RM-4.8 Single slope barrier, Type N (general design) (rev. 2026-01-16) RM-4.9 Single slope barrier, Type E, moment slab foundation (rev. 2025-07-18)
- civilpy.structural.odot.roadway_barrier.BARRIER_END_SECTIONS: dict[str, BarrierEndSection] = {'Type B': BarrierEndSection(scd='RM-4.6', scd_date='2025-07-18', designation='Type B', parent='Type B', total_length_ft=30.0, body_length_ft=16.0, face_transition_ft=10.0, vertical_run_in=32.0, end_taper_in=16.0, end_height_in=32.0, end_width_in=32.0, end_core_width_in=24.0, median=True, notes='Median end section for the 42 in Type B; X501-X505 #5 / Y601-Y603 #6 cage per the sheet 1 steel list.'), 'Type B1': BarrierEndSection(scd='RM-4.6', scd_date='2025-07-18', designation='Type B1', parent='Type B1', total_length_ft=30.0, body_length_ft=16.0, face_transition_ft=10.0, vertical_run_in=32.0, end_taper_in=16.0, end_height_in=32.0, end_width_in=32.0, end_core_width_in=24.0, median=True, notes='Median end section for the 57 in Type B1; the top tapers 57 -> 42 in over the 16 ft body, then follows the Type B transition. X511-X515 / Y611-Y613 cage per the sheet 2 list.'), 'Type D': BarrierEndSection(scd='RM-4.6', scd_date='2025-07-18', designation='Type D', parent='Type D', total_length_ft=14.0, body_length_ft=0.0, face_transition_ft=10.0, vertical_run_in=32.0, end_taper_in=16.0, end_height_in=32.0, end_width_in=20.0, end_core_width_in=16.0, median=False, notes='Roadside end section for the 42 in Type D (traffic on one side); single-slope traffic face only. X521-X524 / Y621-Y623 cage per the sheet 3 list.')}
RM-4.6 end sections keyed by designation.
- class civilpy.structural.odot.roadway_barrier.BarrierEndSection(scd: str, scd_date: str, designation: str, parent: str, total_length_ft: float, body_length_ft: float, face_transition_ft: float, vertical_run_in: float, end_taper_in: float, end_height_in: float, end_width_in: float, end_core_width_in: float, median: bool = True, notes: str = '')[source]
Bases:
objectOne RM-4.6 cast-in-place concrete barrier end section.
Steps the parent single-slope barrier down to a 32 in tall, vertical-faced end that a Bridge Terminal Assembly (SCD MGS-3.1/3.2/ 3.3, Item 606) or impact attenuator attaches to; the single-slope faces transition to vertical over 10 ft to prevent snagging, and the concrete end carries a 4:1 plan flare over the last 16 in. Paid as Item 622 “Concrete Barrier End Section, Type _”, Each.
- class civilpy.structural.odot.roadway_barrier.BarrierEndSectionLayout(end_section: BarrierEndSection, stations: tuple[tuple[float, tuple[tuple[float, float], ...]], ...], notes: tuple[str, ...] = ())[source]
Bases:
objectStationed cross-sections of an RM-4.6 end section, ready to loft.
stationsis a tuple of(station_ft, profile)pairs from the parent-barrier joint (station 0) to the end; each profile is a closed(offset_in, z_in)loop in the roadway-barrier convention. The 4:1 plan end flare inside the last 16 in is described innotesrather than drawn (it rounds the very end plan corners).- end_section: BarrierEndSection
- class civilpy.structural.odot.roadway_barrier.BarrierTransitionLayout(barrier: RoadwayBarrier, kind: str, obstruction_width_in: float, stations: tuple[tuple[float, float], ...], total_length_ft: float, notes: tuple[str, ...] = ())[source]
Bases:
objectPlan-view widening of an RM-4.4 single-slope barrier transition.
stationsis a tuple of(station_ft, width_in)pairs of the barrier’s overall plan width from the start of the first taper; the cross-section at any station keeps the parent barrier’s height and 5.25:1 faces with the extra width filled solid between them.- barrier: RoadwayBarrier
- civilpy.structural.odot.roadway_barrier.PIER_PROTECTION_WIDTH_IN = 48.0
Barrier width at a protected pier column, inches.
- civilpy.structural.odot.roadway_barrier.PIER_RUN_EACH_SIDE_FT = 5.0
Flat run beyond each pier column face, ft.
- civilpy.structural.odot.roadway_barrier.ROADWAY_BARRIERS: dict[str, RoadwayBarrier] = {'Type B': RoadwayBarrier(scd='RM-4.3', scd_date='2025-07-18', designation='Type B', name='Single slope barrier, Type B (concrete pavement)', shape='single slope', material='reinforced concrete', height=42.0, top_width=12.0, base_width=28.0, slope_h_to_v=5.25, f_c=4.0, foundation='pavement', joint_spacing_ft=20.0, notes='Cast on new concrete pavement (8+12+8 in base split); asphalt-pavement variant uses the same body with an alternate 59 in extended toe (not modeled).'), 'Type B1': RoadwayBarrier(scd='RM-4.3', scd_date='2025-07-18', designation='Type B1', name='Single slope barrier, Type B1 (asphalt pavement)', shape='single slope', material='reinforced concrete', height=57.0, top_width=12.0, base_width=33.75, slope_h_to_v=5.25, f_c=4.0, foundation='pavement', joint_spacing_ft=20.0, notes='Taller (57 in) variant of Type B for asphalt pavement (10.875+12+10.875 in base split).'), 'Type C': RoadwayBarrier(scd='RM-4.3', scd_date='2025-07-18', designation='Type C', name='Single slope barrier, Type C (variable height, asphalt)', shape='single slope', material='reinforced concrete', height=42.0, top_width=12.0, base_width=28.0, slope_h_to_v=5.25, f_c=4.0, foundation='pavement', joint_spacing_ft=20.0, notes='Variable-height sibling of Type B: an additional 0-24 in extension is added above this 42 in body per project plans (sheet gives no formula for the extension geometry); overall height ranges 42-66 in. Height/base values here are the fixed Type B base body only.'), 'Type C1': RoadwayBarrier(scd='RM-4.3', scd_date='2025-07-18', designation='Type C1', name='Single slope barrier, Type C1 (variable height, concrete)', shape='single slope', material='reinforced concrete', height=57.0, top_width=12.0, base_width=33.75, slope_h_to_v=5.25, f_c=4.0, foundation='pavement', joint_spacing_ft=20.0, notes='Variable-height sibling of Type B1: an additional 0-24 in extension above this 57 in body per project plans; overall height ranges 57-81 in. Height/base values here are the fixed Type B1 base body only.'), 'Type D': RoadwayBarrier(scd='RM-4.5', scd_date='2026-01-16', designation='Type D', name='Single slope barrier, Type D (obstructions, compacted soil)', shape='single slope', material='reinforced concrete', height=42.0, top_width=12.0, base_width=28.0, slope_h_to_v=5.25, f_c=4.0, foundation='compacted soil', joint_spacing_ft=20.0, notes='Used at obstructions (light poles, piers, etc.) in the median/shoulder; founded on compacted soil (20 in min shoulder, 20:1 permissible batter, 2:1 max embankment beyond) rather than doweled to pavement. Longitudinal steel not required when top width >= 12 in. Transitions to MGS Bridge Terminal Assembly, Type 1/2 (SCD MGS-3.1) at each end; End Sections per RM-4.6.'), 'Type E': RoadwayBarrier(scd='RM-4.9', scd_date='2025-07-18', designation='Type E', name='Single slope barrier, Type E (moment slab foundation)', shape='single slope (moment slab)', material='reinforced concrete', height=36.0, top_width=None, base_width=None, slope_h_to_v=None, f_c=None, foundation='moment slab', joint_spacing_ft=100.0, notes="MASH TL-4. Mounted on a cast-in-place moment slab (5 ft min width, 1 ft min thickness, 6 - #5 bars @ 5 equal spaces plus Bar U #4 stirrups at 6 in) rather than doweled to pavement/leveling pad. Bar S (#4) vertical face bars at 6 in o.c.; 3/4 in PEJF at 20 ft min / 100 ft max barrier-segment joints and at the moment slab / adjacent pavement interface. Concrete face envelope (top/base width) is not dimensioned on this sheet -- only the rebar cage is -- so it is not transcribed; coordinate with plans or treat RM-4.3 Type B's 42 in profile as a rough visual stand-in. Transitions from RM-4.5's 42 in Type D barrier (see sheet 3)."), 'Type N': RoadwayBarrier(scd='RM-4.8', scd_date='2026-01-16', designation='Type N', name='Single slope barrier, Type N (general design)', shape='single slope', material='reinforced concrete', height=81.0, top_width=12.0, base_width=42.875, slope_h_to_v=5.25, f_c=4.0, foundation='leveling pad', joint_spacing_ft=10.0, notes='Tallest of the family (81 in); cast on a 9 in concrete leveling pad (Item 451, Class QC 1P) over Item 304 aggregate base for new pavement, or doweled to a sawcut existing pavement edge. 1 in PEJF (CMS 705.03) at the leveling pad / pavement interface, sealed with CMS 705.04. #8 x 12 in epoxy dowels; 4 in min raceway clearance to conduits (2 in ITS / 4 in lighting).')}
Catalog keyed by
designation(e.g."Type B","Type N").
- class civilpy.structural.odot.roadway_barrier.RoadwayBarrier(scd: str, scd_date: str, designation: str, name: str, shape: str, material: str = 'reinforced concrete', height: float | None = None, top_width: float | None = None, base_width: float | None = None, slope_h_to_v: float | None = None, f_c: float | None = None, foundation: str = 'pavement', joint_spacing_ft: float | None = None, notes: str = '')[source]
Bases:
objectOne Ohio DOT standard roadway single-slope barrier type.
Mirrors the field names
civilpy.structural.rhino_barrier .barrier_profile()reads (shape,height,base_width,top_width) so the same profile-sweep engine renders these as it does the structural bridge parapets.
- class civilpy.structural.odot.roadway_barrier.RoadwayBarrierInput(designation: str, length_ft: float)[source]
Bases:
objectInputs for one straight run of a roadway single-slope barrier.
- class civilpy.structural.odot.roadway_barrier.RoadwayBarrierLayout(barrier: RoadwayBarrier, length_ft: float, profile: tuple[tuple[float, float], ...], notes: tuple[str, ...] = ())[source]
Bases:
objectSymmetric cross-section plus run length for a roadway barrier.
profileis a closed list of(offset_in, z_in)vertices,offsetmeasured from the barrier centerline andzfrom its base – the same conventioncivilpy.structural.rhino_barrier.barrier_profile()uses for a freestanding (side=0) section.- barrier: RoadwayBarrier
- civilpy.structural.odot.roadway_barrier.SIGN_SUPPORT_RUN_FT = 10.0
Flat run at a sign support / light tower foundation, ft.
- civilpy.structural.odot.roadway_barrier.SIGN_SUPPORT_WIDTH_RANGE_IN = (36.0, 48.0)
Foundation-width band the sheet allows at a sign support, inches.
- civilpy.structural.odot.roadway_barrier.TRANSITION_RACEWAYS = ('2 in ITS raceway (HDPE per SS809)', '4 in lighting raceway (CMS 625.12)')
Raceways cast into the widened barrier (RACEWAY PLACEMENT detail).
- civilpy.structural.odot.roadway_barrier.TRANSITION_TAPER_FT = 40.0
RM-4.4 plan-taper length each side of the obstruction, ft.
- civilpy.structural.odot.roadway_barrier.barrier_end_section(designation: str) BarrierEndSection[source]
Look up an RM-4.6 end section by designation (
"Type B","Type B1","Type D").
- civilpy.structural.odot.roadway_barrier.layout_barrier_end_section(designation: str) BarrierEndSectionLayout[source]
Build the lofting stations for an RM-4.6 end section.
- civilpy.structural.odot.roadway_barrier.layout_barrier_transition(designation: str, kind: str, *, obstruction_width_in: float | None = None, obstruction_length_ft: float = 0.0) BarrierTransitionLayout[source]
Build the RM-4.4 plan-width stations for a barrier transition.
designationis an RM-4.3 type (B/B1/C/C1);kindis"sign support"(light tower / sign foundation, 36-48 in wide, 10 ft run) or"pier"(48 in wide pier column protection;obstruction_length_ftis the variable column run between the two 5 ft shoulders). RaisesValueErrorfor other barrier types or a sign-support width outside the sheet’s 36-48 in band.
- civilpy.structural.odot.roadway_barrier.layout_roadway_barrier(inp: RoadwayBarrierInput) RoadwayBarrierLayout[source]
Build the symmetric single-slope cross-section for
inp.
- civilpy.structural.odot.roadway_barrier.roadway_barrier(designation: str) RoadwayBarrier[source]
Look up a roadway barrier type by its
designation(e.g."Type B","Type N").
civilpy.structural.odot.roadway_portable_barrier module
Ohio DOT standard roadway (at-grade) portable concrete barriers.
Office of Roadway Engineering successors to Structural Engineering’s
PCB-91 (civilpy.structural.odot.portable_barrier): the same New
Jersey shape family, reused here via BridgeRailing so name containing "portable"
routes through civilpy.structural.rhino_barrier.shape_family()’s
freestanding symmetric F-shape profile exactly as PCB-91 does.
Both are pin-and-loop / hinge-bar connected precast segments, NOT suitable at bridge deck edges or similar dropoffs (a fixed anchored barrier or bridge-mounted PCB is required there instead).
- Sources (SCD number — drawing date / latest cited revision):
- RM-4.2 32 in Portable Concrete Barrier, New Jersey shape, pin & loop
connection (rev. 2026-01-16)
- RM-4.1 50 in Portable Concrete Barrier + 50->32 in transition section
(hinge bar connection) (rev. 2020-01-17)
- civilpy.structural.odot.roadway_portable_barrier.CONNECTOR_BOLT_SPEC = '7/8" dia through bolts, ASTM A325 or A449'
7/8 in dia ASTM A325 or A449; at least 5 installed, 3 in the outer vertical row, >= 6 in from the segment end and >= 3 in from lifting holes/voids.
- Type:
Terminal-connector through bolts
- civilpy.structural.odot.roadway_portable_barrier.CONNECTOR_END_DISTANCE_MIN_IN = 6.0
Minimum distance from the PCB end to the terminal connector.
- civilpy.structural.odot.roadway_portable_barrier.PCB_GAP_MAX_IN = 12.0
Maximum plan gap between the two PCB ends.
- civilpy.structural.odot.roadway_portable_barrier.ROADWAY_PORTABLE_BARRIERS: dict[str, BridgeRailing] = {'RM Portable (32 in, pin & loop)': BridgeRailing(scd='RM-4.2', scd_date='2026-01-16', designation='RM Portable (32 in, pin & loop)', name='Portable concrete barrier, 32 in, New Jersey shape, pin & loop', shape='New Jersey', material='precast concrete', test_level='', height=32.0, base_width=24.0, top_width=6.0, section_area=None, f_c=4.0, f_y=None, vertical_bar_spacing=None, bar_sizes=(), transition_length_ft=None, transition_volume_cy=None, post_shape='', post_spacing=None, rail_element='', f_y_steel=None, weight_per_ft=None, segment_length_ft=(10.0, 12.0, 20.0), rail_height_above_in=None, notes="Office of Roadway Engineering successor to PCB-91: pin & loop connection (vs. PCB-91's hinge bar + through-bolt), segments 10-20 ft (vs. PCB-91's fixed 10/12 ft). Not for bridge deck edges or similar dropoffs. Drawing states no numeric NCHRP/MASH test level."), 'RM Portable (50 in, hinge bar)': BridgeRailing(scd='RM-4.1', scd_date='2020-01-17', designation='RM Portable (50 in, hinge bar)', name='Portable concrete barrier, 50 in, New Jersey shape, hinge bar', shape='New Jersey', material='precast concrete', test_level='TL-3', height=50.0, base_width=24.0, top_width=12.0, section_area=None, f_c=4.0, f_y=None, vertical_bar_spacing=None, bar_sizes=(), transition_length_ft=None, transition_volume_cy=None, post_shape='', post_spacing=None, rail_element='', f_y_steel=None, weight_per_ft=None, segment_length_ft=(12.0, 14.0), rail_height_above_in=None, notes="Marked PCB-RXX-350-TL3. Not to be used on bridge deck edges or similar dropoffs -- the only suitable barrier there is the 32 in PCB per Structural Engineering's PCB-91 (or an approved alternative). Mates to a 32 in barrier (RM-4.2 or PCB-91) only through the 50 in Transition Section; Impact Attenuators may only attach to that transition's 32 in end.")}
Catalog keyed by
designation.
- civilpy.structural.odot.roadway_portable_barrier.SPACER_PLATE_IN = (6.0, 10.0, 0.25)
Terminal-connector steel spacer (CMS 711.01, galvanized 711.02): 6 x 10 x 1/4 in plate with 1 in dia holes; add spacers to fit field conditions.
- civilpy.structural.odot.roadway_portable_barrier.THRIE_BEAM_ELEMENT = '6 ft-3 in nested 12-gauge thrie-beam'
Nested thrie-beam element bridging the joint.
- civilpy.structural.odot.roadway_portable_barrier.THRIE_BEAM_PCB_TRANSITIONS: dict[tuple[str, str], ThrieBeamPCBTransition] = {('Generic 32" F-shape PCB', 'J-J Hook 32" F-shape PCB'): ThrieBeamPCBTransition(sheet=3, barrier_a='Generic 32" F-shape PCB', barrier_b='J-J Hook 32" F-shape PCB', notes=''), ('Generic 32" New Jersey shape PCB', 'Generic 32" F-shape PCB'): ThrieBeamPCBTransition(sheet=1, barrier_a='Generic 32" New Jersey shape PCB', barrier_b='Generic 32" F-shape PCB', notes='May also connect barriers of the same shape. Not approved for the J-J Hook 32 in New Jersey shape PCB.'), ('Generic 32" New Jersey shape PCB', 'J-J Hook 32" F-shape PCB'): ThrieBeamPCBTransition(sheet=2, barrier_a='Generic 32" New Jersey shape PCB', barrier_b='J-J Hook 32" F-shape PCB', notes='')}
RM-4.7 connection pairs keyed by
(a, b)shape names.
- civilpy.structural.odot.roadway_portable_barrier.TOE_PLATE_IN = (108.0, 5.5, 0.625)
9 ft-0 in x 5-1/2 in x 5/8 in with 24 holes (1 in dia) at 4-3/4 in; anchors 7/8 x 6 in (CMS 712.01 or FF-S325 Grp VIII Type 1), >= 4 per end.
- Type:
Toe plate along the base (CMS 711.01, galvanized 711.02)
- civilpy.structural.odot.roadway_portable_barrier.TRANSITION_50_TO_32 = TransitionSection(scd='RM-4.1', name='50 in to 32 in portable barrier transition section', height_from_in=50.0, height_to_in=32.0, length_ft=6.0, notes="Tapers RM-4.1's 50 in barrier down to a 32 in end compatible with RM-4.2 or PCB-91; only this 32 in end may attach to an Impact Attenuator or to Guardrail per RM-4.2 notes/MT-101.80.")
The RM-4.1 50 in -> 32 in taper joining the two roadway PCB families.
- class civilpy.structural.odot.roadway_portable_barrier.ThrieBeamPCBTransition(sheet: int, barrier_a: str, barrier_b: str, notes: str = '')[source]
Bases:
objectOne RM-4.7 connection pair (one sheet each).
barrier_a/barrier_bname the generic/proprietary 32 in PCB shapes joined; the hardware set is common to all three pairs.
- class civilpy.structural.odot.roadway_portable_barrier.TransitionSection(scd: str, name: str, height_from_in: float, height_to_in: float, length_ft: float, notes: str = '')[source]
Bases:
objectA tapered end section joining two different barrier heights.
- civilpy.structural.odot.roadway_portable_barrier.USE_LIMIT = 'once per mile with project engineer approval'
Deployment limits (general notes, all sheets).
- civilpy.structural.odot.roadway_portable_barrier.roadway_portable_barrier(designation: str) BridgeRailing[source]
Look up a roadway portable barrier by its
designation(e.g."RM Portable (32 in, pin & loop)").
- civilpy.structural.odot.roadway_portable_barrier.thrie_beam_pcb_transition(barrier_a: str, barrier_b: str) ThrieBeamPCBTransition[source]
Look up the RM-4.7 pair joining two PCB shapes (order-free). Raises
ValueErrornaming the cataloged pairs otherwise — in particular there is no approved pair involving the J-J Hook 32 in New Jersey shape PCB.
civilpy.structural.odot.rocker_bolster module
Ohio DOT structural steel rockers and bolsters (RB-1-55).
Dimension and capacity table transcribed from the Ohio DOT Standard Bridge Drawing RB-1-55, “Rockers and Bolsters for Steel and Girder Bridges” (Office of Structural Engineering, 1955-03-01, rev. 2024-07-19).
Each row pairs a bolster (fixed bearing) with a rocker (expansion bearing)
of the same rated capacity; the number in the B-xxx / R-xxx
designation is the maximum load in kips. The dimension letters key the
figure on RB-1-55 and are stored in dims (all inches). Per the
drawing, this design is limited to anticipated movement of 2 in or less.
Dimensions in inches, weights in pounds, load in pounds. Spot-checked against the drawing in the test suite.
- civilpy.structural.odot.rocker_bolster.DIM_LETTERS: tuple[str, ...] = ('A', 'B', 'C', 'D', 'F', 'G', 'H', 'K', 'L', 'M', 'R', 'T', 'Y')
Dimension letters in RB-1-55 table column order.
- civilpy.structural.odot.rocker_bolster.MAX_MOVEMENT = 2.0
Maximum anticipated movement this bearing design allows, inches.
- civilpy.structural.odot.rocker_bolster.ROCKER_BOLSTERS: dict[int, RockerBolster] = {75: RockerBolster(capacity_kips=75, bolster_no='', rocker_no='R-75', dims={'A': 2.5, 'B': 8, 'C': 2.5, 'D': 1.75, 'F': 0.5, 'G': 7, 'H': 9.625, 'K': 9, 'L': 18, 'M': 16, 'R': 5.5, 'T': 1.5, 'Y': 1.1875}, weight_bolster_lb=None, weight_rocker_lb=205, max_load_lb=75000.0), 100: RockerBolster(capacity_kips=100, bolster_no='B-100', rocker_no='R-100', dims={'A': 2.5, 'B': 10, 'C': 2.5, 'D': 2, 'F': 0.5, 'G': 7.5, 'H': 10.625, 'K': 9, 'L': 19, 'M': 17, 'R': 6.5, 'T': 1.5, 'Y': 1.1875}, weight_bolster_lb=225, weight_rocker_lb=250, max_load_lb=100000.0), 125: RockerBolster(capacity_kips=125, bolster_no='B-125', rocker_no='R-125', dims={'A': 3, 'B': 11, 'C': 3, 'D': 2, 'F': 0.5, 'G': 8, 'H': 12.125, 'K': 10.5, 'L': 20, 'M': 18, 'R': 7.5, 'T': 1.5, 'Y': 1.4375}, weight_bolster_lb=295, weight_rocker_lb=315, max_load_lb=125000.0), 150: RockerBolster(capacity_kips=150, bolster_no='B-150', rocker_no='R-150', dims={'A': 3, 'B': 12, 'C': 3, 'D': 2.25, 'F': 0.5, 'G': 8.5, 'H': 13.375, 'K': 11.5, 'L': 22, 'M': 19, 'R': 8.5, 'T': 1.75, 'Y': 1.4375}, weight_bolster_lb=360, weight_rocker_lb=400, max_load_lb=150000.0), 175: RockerBolster(capacity_kips=175, bolster_no='B-175', rocker_no='R-175', dims={'A': 3, 'B': 14, 'C': 3.5, 'D': 2.5, 'F': 0.5, 'G': 9, 'H': 15.125, 'K': 12, 'L': 23, 'M': 20, 'R': 9.5, 'T': 2, 'Y': 1.4375}, weight_bolster_lb=455, weight_rocker_lb=505, max_load_lb=175000.0), 200: RockerBolster(capacity_kips=200, bolster_no='B-200', rocker_no='R-200', dims={'A': 3, 'B': 16, 'C': 3.5, 'D': 2.75, 'F': 0.625, 'G': 9, 'H': 16.375, 'K': 12, 'L': 24, 'M': 21, 'R': 10.5, 'T': 2.25, 'Y': 1.4375}, weight_bolster_lb=540, weight_rocker_lb=605, max_load_lb=200000.0), 225: RockerBolster(capacity_kips=225, bolster_no='B-225', rocker_no='R-225', dims={'A': 3, 'B': 17, 'C': 3.5, 'D': 2.75, 'F': 0.625, 'G': 9, 'H': 16.875, 'K': 13, 'L': 25, 'M': 22, 'R': 11, 'T': 2.25, 'Y': 1.4375}, weight_bolster_lb=590, weight_rocker_lb=665, max_load_lb=225000.0), 250: RockerBolster(capacity_kips=250, bolster_no='B-250', rocker_no='R-250', dims={'A': 3.5, 'B': 18, 'C': 3.5, 'D': 2.75, 'F': 0.75, 'G': 10, 'H': 17.625, 'K': 13, 'L': 26, 'M': 23, 'R': 11.5, 'T': 2.5, 'Y': 1.6875}, weight_bolster_lb=695, weight_rocker_lb=775, max_load_lb=250000.0), 275: RockerBolster(capacity_kips=275, bolster_no='B-275', rocker_no='R-275', dims={'A': 3.5, 'B': 19, 'C': 3.5, 'D': 3.25, 'F': 0.75, 'G': 12, 'H': 18.375, 'K': 14, 'L': 27, 'M': 24, 'R': 12, 'T': 2.75, 'Y': 1.6875}, weight_bolster_lb=800, weight_rocker_lb=945, max_load_lb=275000.0), 300: RockerBolster(capacity_kips=300, bolster_no='B-300', rocker_no='R-300', dims={'A': 3.5, 'B': 20, 'C': 3.5, 'D': 3.25, 'F': 0.75, 'G': 12, 'H': 19.125, 'K': 14, 'L': 28, 'M': 25, 'R': 12.5, 'T': 3, 'Y': 1.6875}, weight_bolster_lb=895, weight_rocker_lb=1050, max_load_lb=300000.0)}
Rocker/bolster lines keyed by capacity in kips.
- class civilpy.structural.odot.rocker_bolster.RockerBolster(capacity_kips: int, bolster_no: str, rocker_no: str, dims: dict[str, float], weight_bolster_lb: float | None, weight_rocker_lb: float, max_load_lb: float)[source]
Bases:
objectOne RB-1-55 rocker/bolster capacity line.
bolster_nois empty for the smallest line (R-75 has no matching bolster).dimsis keyed by the letters inDIM_LETTERS.
- class civilpy.structural.odot.rocker_bolster.RockerBolsterLayout(rb: ~civilpy.structural.odot.rocker_bolster.RockerBolster, base_outline: tuple[tuple[float, float, float], tuple[float, float, float], tuple[float, float, float], tuple[float, float, float]], base_thickness_in: float, bolster_top: tuple[tuple[float, float, float], tuple[float, float, float], tuple[float, float, float], tuple[float, float, float]], bolster_height_in: float, rocker_top_radius_in: float, rocker_height_in: float, notes: tuple[str, ...] = <factory>)[source]
Bases:
objectThe generated bolster + rocker pair for one capacity line, sharing the base-plate footprint origin at plan center, z = 0 at the bottom of the base plate.
- base_outline: tuple[tuple[float, float, float], tuple[float, float, float], tuple[float, float, float], tuple[float, float, float]]
- bolster_top: tuple[tuple[float, float, float], tuple[float, float, float], tuple[float, float, float], tuple[float, float, float]]
- rb: RockerBolster
- civilpy.structural.odot.rocker_bolster.layout_rocker_bolster(rb: RockerBolster) RockerBolsterLayout[source]
Generate the drawable subset of one RB-1-55 capacity line: the shared base-plate footprint, the bolster’s tapered+flat-top body, and the rocker’s tapered+curved-top body.
- civilpy.structural.odot.rocker_bolster.rocker_bolster(capacity_kips: int) RockerBolster[source]
Look up a rocker/bolster line by rated capacity in kips (75..300).
- civilpy.structural.odot.rocker_bolster.smallest_for_load(load_lb: float) RockerBolster[source]
The lightest standard rocker/bolster whose maximum load covers
load_lb; raisesValueErrorif the load exceeds the 300-kip line.
civilpy.structural.odot.slab_bridge module
Ohio DOT single span slab bridges (SB-1-24).
Transcribed from Ohio DOT Standard Bridge Drawing SB-1-24, “Single Span Slab Bridges” (rev. 01-16-2026, 2 sheets). The drawing remains the controlling document.
Sheet 1’s SLAB DATA table gives the slab thickness and the A/B/M/N
longitudinal reinforcing bar spacing/size for spans 11-38 ft; sheet 2’s
EDGE BEAM SLAB DATA table gives the edge-beam depth D, taper
X, and D/E-bar spacing/size for the two edge conditions (over-the-side
drainage vs. a concrete parapet, which allows a shallower edge beam).
Design basis (sheet 2 notes): AASHTO LRFD 9th Ed. + ODOT BDM (July 2023); HL-93; FWS 60 lb/ft^2; 1 in monolithic wearing surface; concrete f’c = 4500 psi; reinforcing steel min. yield 60,000 psi, epoxy coated. Applicable for roadway widths >= 24 ft and skew <= 25 deg. For skew 0 < theta <= 25 deg, longitudinal bars stay parallel to the roadway centerline and transverse bars parallel to the pier/abutment skew line (the slab plan is a skewed parallelogram, same shear convention as every other flared/skewed layout in this package).
Conventions: X along stations, Y transverse, Z up; feet in plan, inches for section dimensions. The layout origin sits at the upstream bearing line, y = 0 at one slab edge, z = 0 at the top of slab.
- civilpy.structural.odot.slab_bridge.BEARING_SEAT_IN = 9.0
Bearing-seat width at each abutment, inches (elevation view “9”/COS(theta)”).
- class civilpy.structural.odot.slab_bridge.BarRun(mark: 'str', size: 'int', points: 'tuple[Point, ...]')[source]
Bases:
object
- class civilpy.structural.odot.slab_bridge.BarSpec(spacing_in: 'float', size: 'int')[source]
Bases:
object
- civilpy.structural.odot.slab_bridge.EDGE_BEAM_DESIGNS: dict[int, EdgeBeamDesign] = {11: EdgeBeamDesign(span_ft=11, over_the_side=EdgeBarSpec(depth_in=20, taper_in=45, bar_size=7, bar_count=8), parapet=EdgeBarSpec(depth_in=18, taper_in=57, bar_size=7, bar_count=8)), 12: EdgeBeamDesign(span_ft=12, over_the_side=EdgeBarSpec(depth_in=20, taper_in=45, bar_size=7, bar_count=8), parapet=EdgeBarSpec(depth_in=18, taper_in=57, bar_size=7, bar_count=8)), 13: EdgeBeamDesign(span_ft=13, over_the_side=EdgeBarSpec(depth_in=20, taper_in=45, bar_size=7, bar_count=8), parapet=EdgeBarSpec(depth_in=18, taper_in=57, bar_size=7, bar_count=8)), 14: EdgeBeamDesign(span_ft=14, over_the_side=EdgeBarSpec(depth_in=20, taper_in=45, bar_size=7, bar_count=8), parapet=EdgeBarSpec(depth_in=18, taper_in=57, bar_size=7, bar_count=8)), 15: EdgeBeamDesign(span_ft=15, over_the_side=EdgeBarSpec(depth_in=20, taper_in=45, bar_size=7, bar_count=8), parapet=EdgeBarSpec(depth_in=18, taper_in=57, bar_size=7, bar_count=8)), 16: EdgeBeamDesign(span_ft=16, over_the_side=EdgeBarSpec(depth_in=20, taper_in=45, bar_size=7, bar_count=8), parapet=EdgeBarSpec(depth_in=18, taper_in=57, bar_size=8, bar_count=7)), 17: EdgeBeamDesign(span_ft=17, over_the_side=EdgeBarSpec(depth_in=20, taper_in=45, bar_size=8, bar_count=7), parapet=EdgeBarSpec(depth_in=18, taper_in=57, bar_size=8, bar_count=8)), 18: EdgeBeamDesign(span_ft=18, over_the_side=EdgeBarSpec(depth_in=20, taper_in=45, bar_size=8, bar_count=7), parapet=EdgeBarSpec(depth_in=18, taper_in=57, bar_size=8, bar_count=8)), 19: EdgeBeamDesign(span_ft=19, over_the_side=EdgeBarSpec(depth_in=20, taper_in=48, bar_size=8, bar_count=8), parapet=EdgeBarSpec(depth_in=18, taper_in=60, bar_size=8, bar_count=9)), 20: EdgeBeamDesign(span_ft=20, over_the_side=EdgeBarSpec(depth_in=20, taper_in=48, bar_size=8, bar_count=8), parapet=EdgeBarSpec(depth_in=18, taper_in=60, bar_size=8, bar_count=10)), 21: EdgeBeamDesign(span_ft=21, over_the_side=EdgeBarSpec(depth_in=20, taper_in=48, bar_size=9, bar_count=8), parapet=EdgeBarSpec(depth_in=18, taper_in=60, bar_size=8, bar_count=10)), 22: EdgeBeamDesign(span_ft=22, over_the_side=EdgeBarSpec(depth_in=20, taper_in=48, bar_size=9, bar_count=8), parapet=EdgeBarSpec(depth_in=18, taper_in=60, bar_size=9, bar_count=9)), 23: EdgeBeamDesign(span_ft=23, over_the_side=EdgeBarSpec(depth_in=20, taper_in=48, bar_size=9, bar_count=8), parapet=EdgeBarSpec(depth_in=18, taper_in=60, bar_size=9, bar_count=10)), 24: EdgeBeamDesign(span_ft=24, over_the_side=EdgeBarSpec(depth_in=20, taper_in=48, bar_size=9, bar_count=9), parapet=EdgeBarSpec(depth_in=18.25, taper_in=60, bar_size=9, bar_count=10)), 25: EdgeBeamDesign(span_ft=25, over_the_side=EdgeBarSpec(depth_in=20, taper_in=48, bar_size=9, bar_count=9), parapet=EdgeBarSpec(depth_in=18.75, taper_in=60, bar_size=9, bar_count=10)), 26: EdgeBeamDesign(span_ft=26, over_the_side=EdgeBarSpec(depth_in=20, taper_in=48, bar_size=10, bar_count=8), parapet=EdgeBarSpec(depth_in=19.25, taper_in=60, bar_size=9, bar_count=11)), 27: EdgeBeamDesign(span_ft=27, over_the_side=EdgeBarSpec(depth_in=20, taper_in=48, bar_size=10, bar_count=8), parapet=EdgeBarSpec(depth_in=19.75, taper_in=63, bar_size=10, bar_count=9)), 28: EdgeBeamDesign(span_ft=28, over_the_side=EdgeBarSpec(depth_in=20.5, taper_in=48, bar_size=10, bar_count=9), parapet=EdgeBarSpec(depth_in=20.5, taper_in=63, bar_size=10, bar_count=10)), 29: EdgeBeamDesign(span_ft=29, over_the_side=EdgeBarSpec(depth_in=21.0, taper_in=48, bar_size=10, bar_count=9), parapet=EdgeBarSpec(depth_in=21.0, taper_in=63, bar_size=10, bar_count=10)), 30: EdgeBeamDesign(span_ft=30, over_the_side=EdgeBarSpec(depth_in=21.5, taper_in=48, bar_size=10, bar_count=9), parapet=EdgeBarSpec(depth_in=21.5, taper_in=63, bar_size=10, bar_count=10)), 31: EdgeBeamDesign(span_ft=31, over_the_side=EdgeBarSpec(depth_in=22.25, taper_in=48, bar_size=10, bar_count=9), parapet=EdgeBarSpec(depth_in=22.0, taper_in=63, bar_size=10, bar_count=10)), 32: EdgeBeamDesign(span_ft=32, over_the_side=EdgeBarSpec(depth_in=22.75, taper_in=48, bar_size=10, bar_count=9), parapet=EdgeBarSpec(depth_in=22.75, taper_in=63, bar_size=10, bar_count=10)), 33: EdgeBeamDesign(span_ft=33, over_the_side=EdgeBarSpec(depth_in=23.25, taper_in=48, bar_size=10, bar_count=9), parapet=EdgeBarSpec(depth_in=23.25, taper_in=63, bar_size=10, bar_count=11)), 34: EdgeBeamDesign(span_ft=34, over_the_side=EdgeBarSpec(depth_in=23.75, taper_in=48, bar_size=10, bar_count=10), parapet=EdgeBarSpec(depth_in=23.75, taper_in=63, bar_size=10, bar_count=11)), 35: EdgeBeamDesign(span_ft=35, over_the_side=EdgeBarSpec(depth_in=24.25, taper_in=48, bar_size=10, bar_count=10), parapet=EdgeBarSpec(depth_in=24.25, taper_in=63, bar_size=10, bar_count=11)), 36: EdgeBeamDesign(span_ft=36, over_the_side=EdgeBarSpec(depth_in=25.0, taper_in=48, bar_size=10, bar_count=10), parapet=EdgeBarSpec(depth_in=25.0, taper_in=63, bar_size=10, bar_count=11)), 37: EdgeBeamDesign(span_ft=37, over_the_side=EdgeBarSpec(depth_in=25.5, taper_in=48, bar_size=10, bar_count=10), parapet=EdgeBarSpec(depth_in=25.5, taper_in=63, bar_size=10, bar_count=12)), 38: EdgeBeamDesign(span_ft=38, over_the_side=EdgeBarSpec(depth_in=26.0, taper_in=48, bar_size=10, bar_count=10), parapet=EdgeBarSpec(depth_in=26.0, taper_in=63, bar_size=10, bar_count=12))}
SB-1-24
EDGE BEAM SLAB DATA, keyed by span (ft).
- class civilpy.structural.odot.slab_bridge.EdgeBarSpec(depth_in: 'float', taper_in: 'float', bar_size: 'int', bar_count: 'int')[source]
Bases:
object
- class civilpy.structural.odot.slab_bridge.EdgeBeamDesign(span_ft: int, over_the_side: EdgeBarSpec, parapet: EdgeBarSpec)[source]
Bases:
objectOne
EDGE BEAM SLAB DATAtable row (sheet 2): the edge-beam depth and D/E-bar schedule for both edge conditions.- over_the_side: EdgeBarSpec
- parapet: EdgeBarSpec
- civilpy.structural.odot.slab_bridge.LAP_SPLICE_FT = {5: {'bot': 3.6666666666666665, 'top': 3.8333333333333335}, 7: {'bot': 4.416666666666667}, 8: {'bot': 7.25}, 9: {'bot': 8.916666666666666}, 10: {'bot': 10.916666666666666}}
{“top”/”bot”: length_ft}}. No.5 gives both faces; larger sizes are bottom-face laps only (sheet 2).
- Type:
Lap splice lengths by bar size, feet
- Type:
{size
- civilpy.structural.odot.slab_bridge.SLAB_DESIGNS: dict[int, SlabDesign] = {11: SlabDesign(span_ft=11, thickness_in=11.25, a_bar=BarSpec(spacing_in=6, size=7), b_bar=BarSpec(spacing_in=12.0, size=5), m_bar=BarSpec(spacing_in=10.0, size=5), n_bar=BarSpec(spacing_in=12.0, size=5)), 12: SlabDesign(span_ft=12, thickness_in=11.75, a_bar=BarSpec(spacing_in=6, size=7), b_bar=BarSpec(spacing_in=12.0, size=5), m_bar=BarSpec(spacing_in=10.0, size=5), n_bar=BarSpec(spacing_in=12.0, size=5)), 13: SlabDesign(span_ft=13, thickness_in=12.5, a_bar=BarSpec(spacing_in=6, size=7), b_bar=BarSpec(spacing_in=12.0, size=5), m_bar=BarSpec(spacing_in=10.0, size=5), n_bar=BarSpec(spacing_in=12.0, size=5)), 14: SlabDesign(span_ft=14, thickness_in=13.0, a_bar=BarSpec(spacing_in=6, size=7), b_bar=BarSpec(spacing_in=12.0, size=5), m_bar=BarSpec(spacing_in=10.0, size=5), n_bar=BarSpec(spacing_in=12.0, size=5)), 15: SlabDesign(span_ft=15, thickness_in=13.5, a_bar=BarSpec(spacing_in=6, size=7), b_bar=BarSpec(spacing_in=12.0, size=5), m_bar=BarSpec(spacing_in=10.0, size=5), n_bar=BarSpec(spacing_in=12.0, size=5)), 16: SlabDesign(span_ft=16, thickness_in=14.0, a_bar=BarSpec(spacing_in=6, size=7), b_bar=BarSpec(spacing_in=12.0, size=5), m_bar=BarSpec(spacing_in=10.0, size=5), n_bar=BarSpec(spacing_in=12.0, size=5)), 17: SlabDesign(span_ft=17, thickness_in=14.75, a_bar=BarSpec(spacing_in=7, size=8), b_bar=BarSpec(spacing_in=12.0, size=5), m_bar=BarSpec(spacing_in=10.0, size=5), n_bar=BarSpec(spacing_in=12.0, size=5)), 18: SlabDesign(span_ft=18, thickness_in=15.25, a_bar=BarSpec(spacing_in=7, size=8), b_bar=BarSpec(spacing_in=12.0, size=5), m_bar=BarSpec(spacing_in=10.0, size=5), n_bar=BarSpec(spacing_in=12.0, size=5)), 19: SlabDesign(span_ft=19, thickness_in=15.75, a_bar=BarSpec(spacing_in=7, size=8), b_bar=BarSpec(spacing_in=12.0, size=5), m_bar=BarSpec(spacing_in=10.0, size=5), n_bar=BarSpec(spacing_in=12.0, size=5)), 20: SlabDesign(span_ft=20, thickness_in=16.25, a_bar=BarSpec(spacing_in=7, size=8), b_bar=BarSpec(spacing_in=12.0, size=5), m_bar=BarSpec(spacing_in=10.0, size=5), n_bar=BarSpec(spacing_in=12.0, size=5)), 21: SlabDesign(span_ft=21, thickness_in=16.75, a_bar=BarSpec(spacing_in=6, size=8), b_bar=BarSpec(spacing_in=12.0, size=5), m_bar=BarSpec(spacing_in=10.0, size=5), n_bar=BarSpec(spacing_in=12.0, size=5)), 22: SlabDesign(span_ft=22, thickness_in=17.25, a_bar=BarSpec(spacing_in=6, size=8), b_bar=BarSpec(spacing_in=12.0, size=5), m_bar=BarSpec(spacing_in=10.0, size=5), n_bar=BarSpec(spacing_in=12.0, size=5)), 23: SlabDesign(span_ft=23, thickness_in=17.75, a_bar=BarSpec(spacing_in=6, size=8), b_bar=BarSpec(spacing_in=12.0, size=5), m_bar=BarSpec(spacing_in=10.0, size=5), n_bar=BarSpec(spacing_in=12.0, size=5)), 24: SlabDesign(span_ft=24, thickness_in=18.25, a_bar=BarSpec(spacing_in=6, size=8), b_bar=BarSpec(spacing_in=12.0, size=5), m_bar=BarSpec(spacing_in=10.0, size=5), n_bar=BarSpec(spacing_in=12.0, size=5)), 25: SlabDesign(span_ft=25, thickness_in=18.75, a_bar=BarSpec(spacing_in=6, size=8), b_bar=BarSpec(spacing_in=12.0, size=5), m_bar=BarSpec(spacing_in=10.0, size=5), n_bar=BarSpec(spacing_in=12.0, size=5)), 26: SlabDesign(span_ft=26, thickness_in=19.25, a_bar=BarSpec(spacing_in=7, size=9), b_bar=BarSpec(spacing_in=12.0, size=5), m_bar=BarSpec(spacing_in=10.0, size=5), n_bar=BarSpec(spacing_in=12.0, size=5)), 27: SlabDesign(span_ft=27, thickness_in=19.75, a_bar=BarSpec(spacing_in=7, size=9), b_bar=BarSpec(spacing_in=12.0, size=5), m_bar=BarSpec(spacing_in=10.0, size=5), n_bar=BarSpec(spacing_in=12.0, size=5)), 28: SlabDesign(span_ft=28, thickness_in=20.5, a_bar=BarSpec(spacing_in=7, size=9), b_bar=BarSpec(spacing_in=12.0, size=5), m_bar=BarSpec(spacing_in=10.0, size=5), n_bar=BarSpec(spacing_in=12.0, size=5)), 29: SlabDesign(span_ft=29, thickness_in=21.0, a_bar=BarSpec(spacing_in=7, size=9), b_bar=BarSpec(spacing_in=12.0, size=5), m_bar=BarSpec(spacing_in=10.0, size=5), n_bar=BarSpec(spacing_in=12.0, size=5)), 30: SlabDesign(span_ft=30, thickness_in=21.5, a_bar=BarSpec(spacing_in=6, size=9), b_bar=BarSpec(spacing_in=12.0, size=5), m_bar=BarSpec(spacing_in=10.0, size=5), n_bar=BarSpec(spacing_in=12.0, size=5)), 31: SlabDesign(span_ft=31, thickness_in=22.25, a_bar=BarSpec(spacing_in=6, size=9), b_bar=BarSpec(spacing_in=12.0, size=5), m_bar=BarSpec(spacing_in=10.0, size=5), n_bar=BarSpec(spacing_in=12.0, size=5)), 32: SlabDesign(span_ft=32, thickness_in=22.75, a_bar=BarSpec(spacing_in=6, size=9), b_bar=BarSpec(spacing_in=12.0, size=5), m_bar=BarSpec(spacing_in=10.0, size=5), n_bar=BarSpec(spacing_in=12.0, size=5)), 33: SlabDesign(span_ft=33, thickness_in=23.25, a_bar=BarSpec(spacing_in=6, size=9), b_bar=BarSpec(spacing_in=12.0, size=5), m_bar=BarSpec(spacing_in=10.0, size=5), n_bar=BarSpec(spacing_in=12.0, size=5)), 34: SlabDesign(span_ft=34, thickness_in=23.75, a_bar=BarSpec(spacing_in=6, size=9), b_bar=BarSpec(spacing_in=12.0, size=5), m_bar=BarSpec(spacing_in=10.0, size=5), n_bar=BarSpec(spacing_in=12.0, size=5)), 35: SlabDesign(span_ft=35, thickness_in=24.25, a_bar=BarSpec(spacing_in=6, size=9), b_bar=BarSpec(spacing_in=12.0, size=5), m_bar=BarSpec(spacing_in=10.0, size=5), n_bar=BarSpec(spacing_in=12.0, size=5)), 36: SlabDesign(span_ft=36, thickness_in=25.0, a_bar=BarSpec(spacing_in=7, size=10), b_bar=BarSpec(spacing_in=12.0, size=5), m_bar=BarSpec(spacing_in=10.0, size=5), n_bar=BarSpec(spacing_in=12.0, size=5)), 37: SlabDesign(span_ft=37, thickness_in=25.5, a_bar=BarSpec(spacing_in=7, size=10), b_bar=BarSpec(spacing_in=12.0, size=5), m_bar=BarSpec(spacing_in=10.0, size=5), n_bar=BarSpec(spacing_in=12.0, size=5)), 38: SlabDesign(span_ft=38, thickness_in=26.0, a_bar=BarSpec(spacing_in=7, size=10), b_bar=BarSpec(spacing_in=12.0, size=5), m_bar=BarSpec(spacing_in=10.0, size=5), n_bar=BarSpec(spacing_in=12.0, size=5))}
SB-1-24
SLAB DATA, keyed by span (ft). B/M/N bars never vary across spans on this sheet (12 in #5 / 10 in #5 / 12 in #5) – transcribed in full per row anyway, since a future revision could change that.
- class civilpy.structural.odot.slab_bridge.SlabBridgeComponent(inp: SlabBridgeInput)[source]
Bases:
objectBridgeComponent implementation for a single-span slab bridge (SB-1-24).
- calculate_l1_envelope(*, samples: int = 41)[source]
Calculates the L1 equivalent-strip moment envelope for the slab.
This uses the pure-Python girder_line_envelope which applies HL-93 live loads via influence lines and uniform dead loads, scaled by the AASHTO equivalent strip width.
- extract_bearing_reactions(model: StructuralModel) dict[source]
Extracts vertical reactions at supports from the StructuralModel results.
- reconcile_analysis(midas_results: dict | None = None) dict[source]
Compares pure-Python L1 results with MIDAS results.
If midas_results is provided (e.g. from MidasCivil.beam_forces), it calculates the error/reconciliation between the two models.
- structural_model(level: str = 'L1') StructuralModel[source]
Returns a MIDAS-ready StructuralModel (L1 strip or L2 grillage).
- class civilpy.structural.odot.slab_bridge.SlabBridgeInput(span_ft: int, width_ft: float, skew_deg: float = 0.0, edge_condition: Literal['over_the_side', 'parapet'] = 'over_the_side')[source]
Bases:
objectInputs for a single-span slab bridge.
edge_conditionselects the edge-beam schedule:"over_the_side"(drainage over the fascia) or"parapet"(shallower edge beam under a concrete parapet, per the sheet’s edge-beam option).
- class civilpy.structural.odot.slab_bridge.SlabBridgeLayout(inputs: ~civilpy.structural.odot.slab_bridge.SlabBridgeInput, outline: tuple[tuple[float, float, float], tuple[float, float, float], tuple[float, float, float], tuple[float, float, float]], thickness_in: float, bridge_length_ft: float, bars: tuple[~civilpy.structural.odot.slab_bridge.BarRun, ...], edge_beam: ~civilpy.structural.odot.slab_bridge.EdgeBarSpec, notes: tuple[str, ...] = <factory>)[source]
Bases:
objectThe generated slab bridge.
outlineis the skewed plan parallelogram at z = 0 (top of slab); the slab extends downthickness_in.barsare the A/B/M/N longitudinal runs.- edge_beam: EdgeBarSpec
- inputs: SlabBridgeInput
- class civilpy.structural.odot.slab_bridge.SlabDesign(span_ft: int, thickness_in: float, a_bar: BarSpec, b_bar: BarSpec, m_bar: BarSpec, n_bar: BarSpec)[source]
Bases:
objectOne
SLAB DATAtable row (sheet 1).
- civilpy.structural.odot.slab_bridge.bridge_length_ft(span_ft: float, skew_deg: float = 0.0) float[source]
BRIDGE LENGTH = SPAN + (1.5' / COS(theta))(sheet 1).
- civilpy.structural.odot.slab_bridge.edge_beam_design(span_ft: int) EdgeBeamDesign[source]
Look up the SB-1-24 edge-beam design for a span (feet, 11-38).
Raises
ValueErrornaming the valid spans otherwise.
- civilpy.structural.odot.slab_bridge.layout_slab_bridge(inp: SlabBridgeInput) SlabBridgeLayout[source]
Generate a single-span slab bridge: plan outline, thickness, and the A/B/M/N longitudinal bar mats.
Raises
ValueErrorfor an untabulated span, an unknownedge_condition, or a skew beyond the sheet’s 25 deg limit.
- civilpy.structural.odot.slab_bridge.slab_design(span_ft: int) SlabDesign[source]
Look up the SB-1-24 slab design for a span (feet, 11-38 tabulated).
Raises
ValueErrornaming the valid spans otherwise.
civilpy.structural.odot.sleeper_slab module
ODOT AS-2-15 Approach Slab Installation — the drawable subset.
Transcribed from Ohio DOT Standard Construction Drawing AS-2-15 (revised 01-20-2023, 14 sheets). The drawing remains the controlling document.
AS-2-15 covers how the AS-1-15 approach slab meets the roadway: the
reinforced concrete sleeper slab under the approach-slab/pavement
joint (Type A and Type C installations), the 25-foot flexible pavement
transition, underdrains, and the joint systems. The sleeper slab is the
parametric geometry this module generates; the fourteen installation
configurations are cataloged as data (INSTALLATION_INDEX). Type B
has no sleeper slab — it uses a reinforced joint mesh measured by the
square yard.
Design basis (sheet 14): AASHTO LRFD (2014) + ODOT BDM (2007); HL-93; FWS 0.060 ksf; concrete f’c = 4.5 ksi; fy = 60 ksi. The sleeper slab is measured by the linear foot along the skew at the end of the approach slab and placed parallel to that skew.
Conventions match civilpy.structural.odot.approach_slab: X along
stations (increasing away from the bridge), Y transverse, Z up; feet in
plan, inches for section dimensions. The layout origin sits on the
sleeper slab centerline (directly under the approach-slab/pavement
joint) at the y = 0 edge, with z = 0 at the TOP of the sleeper slab.
- class civilpy.structural.odot.sleeper_slab.BarRun(mark: str, size: int, points: tuple[tuple[float, float, float], ...])[source]
Bases:
object
- class civilpy.structural.odot.sleeper_slab.Installation(type: str, sheets: tuple[int, ...], wall: str, pavement: str, has_sleeper_slab: bool, joint: str)[source]
Bases:
objectOne AS-2-15 installation configuration.
- class civilpy.structural.odot.sleeper_slab.SleeperSlabInput(width_ft: float, skew_deg: float = 0.0, installation: str = 'A')[source]
Bases:
objectInputs for a Type A / Type C sleeper slab: the approach slab width it supports and the skew it parallels.
- class civilpy.structural.odot.sleeper_slab.SleeperSlabLayout(inputs: ~civilpy.structural.odot.sleeper_slab.SleeperSlabInput, outline: tuple[tuple[float, float, float], tuple[float, float, float], tuple[float, float, float], tuple[float, float, float]], thickness_in: float, bars: tuple[~civilpy.structural.odot.sleeper_slab.BarRun, ...], underdrain: tuple[tuple[float, float, float], tuple[float, float, float]], pma_joint: tuple[tuple[float, float, float], tuple[float, float, float], tuple[float, float, float], tuple[float, float, float]], aggregate_drain: tuple[tuple[float, float, float], tuple[float, float, float], tuple[float, float, float], tuple[float, float, float]], measured_length_ft: float, notes: tuple[str, ...] = <factory>)[source]
Bases:
objectThe generated sleeper slab.
outlineis the counterclockwise plan parallelogram at z = 0 (top of sleeper); the solid extends downSLEEPER_THICKNESS_IN.underdrainis the pipe centerline;pma_jointis the joint-system outline sitting on the sleeper top over the centerline, andaggregate_drainthe trench outline below the slab.- aggregate_drain: tuple[tuple[float, float, float], tuple[float, float, float], tuple[float, float, float], tuple[float, float, float]]
- inputs: SleeperSlabInput
- outline: tuple[tuple[float, float, float], tuple[float, float, float], tuple[float, float, float], tuple[float, float, float]]
- civilpy.structural.odot.sleeper_slab.installations(type_: str) tuple[Installation, ...][source]
All cataloged configurations of the given installation type.
- civilpy.structural.odot.sleeper_slab.layout_sleeper_slab(inp: SleeperSlabInput) SleeperSlabLayout[source]
Generate the sleeper slab under the approach-slab/pavement joint.
Raises
ValueErrorfor a Type B installation (no sleeper slab), an unknown type, or out-of-range width/skew.
- civilpy.structural.odot.sleeper_slab.ss501_length_ft(width_ft: float, skew_deg: float = 0.0) float[source]
SS501 length A = (W - 0.5’)/cos(theta) (sheet 1 bending table).
civilpy.structural.odot.strip_seal_joint module
Ohio DOT strip seal expansion joints for steel stringer structures (EXJ-4-87).
Transcribed from Ohio DOT Standard Bridge Drawing EXJ-4-87, “Strip Seal Expansion Joints, Steel Stringer Structures” (rev. 01-19-2024, 4 sheets). The drawing remains the controlling document.
Like BCHW/CPA-1-08, most of this sheet is a detailing template: the strip-seal gland itself is a manufacturer-generic elastomeric extrusion (not tabulated here), and the joint runs the full skewed width of the structure with project-specific stringer spacing. What is a genuine parametric formula (sheet 1, SECTION C-C) is the support-angle segment length at each stringer, which depends on the stringer top flange width and the skew angle:
a1 = top_flange_width / cos(theta) - 2 * (1” / cos(theta)) - 4” * tan(theta) a2 = 1” + 0.5 * top_flange_width / cos(theta) a3 = 1” + top_flange_width / cos(theta) + 4” * tan(theta) + 1” a4 = a3 - a2
(a1 is the clear gap the support angle must span between plate “A” retainers; a2/a3 lay out the angle relative to the stringer centerline; a4 = a3 - a2 is used directly in Sections B-B/C-C.) These mirror image for a left-forward skew (sheet’s own note).
Conventions match the rest of this package: X along stations, Y transverse, Z up; feet in plan, inches for section dimensions. The origin sits on the joint centerline (X = 0) at the top of deck (Z = 0), Y = 0 at one deck edge.
- class civilpy.structural.odot.strip_seal_joint.StripSealJointInput(width_ft: float, skew_deg: float, stringer_stations_ft: tuple[float, ...], top_flange_width_in: float = 12.0)[source]
Bases:
objectInputs for one strip seal joint run.
stringer_stations_ftare the transverse stringer positions (Y, ft) across the deck width;top_flange_width_inis the (uniform, assumed) stringer top flange width used in the support-angle formulas.
- class civilpy.structural.odot.strip_seal_joint.StripSealJointLayout(inputs: ~civilpy.structural.odot.strip_seal_joint.StripSealJointInput, joint_line: tuple[tuple[float, float, float], tuple[float, float, float]], support_angles: tuple[~civilpy.structural.odot.strip_seal_joint.SupportAngleRun, ...], notes: tuple[str, ...] = <factory>)[source]
Bases:
objectThe generated joint:
joint_lineis the skewed gland centerline across the full deck width (z = 0, top of deck);support_anglesis one short transverse segment per stringer station, sized bysupport_angle_lengths_in().- inputs: StripSealJointInput
- support_angles: tuple[SupportAngleRun, ...]
- class civilpy.structural.odot.strip_seal_joint.SupportAngleRun(station_ft: float, points: tuple[tuple[float, float, float], tuple[float, float, float]], a1_in: float, a2_in: float, a3_in: float, a4_in: float)[source]
Bases:
object
- civilpy.structural.odot.strip_seal_joint.layout_strip_seal_joint(inp: StripSealJointInput) StripSealJointLayout[source]
Generate a strip seal joint: the skewed joint line and one support-angle run per stringer station.
Raises
ValueErrorfor a non-positive width or an emptystringer_stations_ft.
- civilpy.structural.odot.strip_seal_joint.support_angle_lengths_in(top_flange_width_in: float, skew_deg: float) tuple[float, float, float, float][source]
The a1/a2/a3/a4 support-angle formulas (sheet 1, SECTION C-C).
Returns
(a1, a2, a3, a4)in inches; mirror the sign convention for a left-forward skew per the sheet’s own note (use the same magnitude, mirrored in plan by the caller).
civilpy.structural.odot.strip_seal_joint_box_beam module
Ohio DOT strip seal expansion joints for concrete box beam structures (EXJ-5-93).
Transcribed from Ohio DOT Standard Bridge Drawing EXJ-5-93, “Strip Seal
Expansion Joints, Concrete Box Beam Structures” (rev. 01-19-2024,
4 sheets). The drawing remains the controlling document. Same pattern
as EXJ-4-87 (civilpy.structural.odot.strip_seal_joint) but for box
beams instead of steel stringers: the strip-seal gland is again
manufacturer-generic, and the joint runs the skewed width of the
structure. What’s cataloged here is the plate “A”/”B”/”C” spacing table
(keyed by beam width, END OF SUPERSTRUCTURE detail) and the joint-length
formula (sheet 1’s own “LEGEND”):
L = [(N - 1) * (1/2) + N * W] / (12 * cos(theta))
L is the joint length edge-to-edge of deck (ft), N the number of
beams, W the nominal beam width (inches, 36 or 48), theta the
joint skew angle. The plates repeat A-B-B-C-B-B-C-… across the joint
width, one A/B/C group per beam-to-beam gap (see the sheet’s “PLATE ‘A’
SPACING” callout row).
Conventions match the rest of this package: X along stations, Y transverse, Z up; feet in plan, inches for section dimensions. The origin sits on the joint centerline (X = 0) at the top of deck (Z = 0), Y = 0 at one deck edge.
- class civilpy.structural.odot.strip_seal_joint_box_beam.BoxBeamJointInput(n_beams: int, beam_width_in: float, skew_deg: float = 0.0)[source]
Bases:
object
- class civilpy.structural.odot.strip_seal_joint_box_beam.BoxBeamJointLayout(inputs: ~civilpy.structural.odot.strip_seal_joint_box_beam.BoxBeamJointInput, joint_line: tuple[tuple[float, float, float], tuple[float, float, float]], length_ft: float, beam_gap_stations_ft: tuple[float, ...], spacing: ~civilpy.structural.odot.strip_seal_joint_box_beam.PlateSpacing, notes: tuple[str, ...] = <factory>)[source]
Bases:
objectThe generated joint:
joint_lineis the skewed gland centerline across the full deck width (z = 0, top of deck);beam_gap_stationsare the transverse (Y) positions of each beam-to-beam gap, where a plate “A”/”B”/”C” group sits.- inputs: BoxBeamJointInput
- spacing: PlateSpacing
- civilpy.structural.odot.strip_seal_joint_box_beam.PLATE_SPACING: dict[float, PlateSpacing] = {36.0: PlateSpacing(beam_width_in=36.0, dim_a_in=6.0, dim_b_in=12.25, dim_c_in=12.0), 48.0: PlateSpacing(beam_width_in=48.0, dim_a_in=8.0, dim_b_in=16.25, dim_c_in=16.0)}
EXJ-5-93 plate “A”/”B”/”C” spacing table, keyed by beam width (inches).
- class civilpy.structural.odot.strip_seal_joint_box_beam.PlateSpacing(beam_width_in: float, dim_a_in: float, dim_b_in: float, dim_c_in: float)[source]
Bases:
object
- civilpy.structural.odot.strip_seal_joint_box_beam.joint_length_ft(n_beams: int, beam_width_in: float, skew_deg: float = 0.0) float[source]
L = [(N-1)*(1/2) + N*W] / (12*cos(theta))(sheet 1’s LEGEND): joint length edge-to-edge of deck, feet.
- civilpy.structural.odot.strip_seal_joint_box_beam.layout_box_beam_joint(inp: BoxBeamJointInput) BoxBeamJointLayout[source]
Generate a box-beam strip seal joint: the skewed joint line and the beam-to-beam gap stations where plate “A”/”B”/”C” groups sit.
Raises
ValueErrorfor fewer than 2 beams or an untabulated beam width (plate_spacing()).
- civilpy.structural.odot.strip_seal_joint_box_beam.plate_spacing(beam_width_in: float) PlateSpacing[source]
Look up the EXJ-5-93 plate spacing for a beam width (36 or 48 in).
Raises
ValueErrornaming the valid widths otherwise.
civilpy.structural.odot.typical_abutment module
Ohio DOT typical abutment detail for bridges with expansion joints (A-1-20).
Transcribed from Ohio DOT Standard Bridge Drawing A-1-20, “Typical Abutment Detail for Bridges with Expansion Joints” (rev. 01-19-2024, 5 sheets). The drawing remains the controlling document. Steel girders are shown; PSID-1-13 covers the modifications for prestressed concrete I-beams.
This sheet is explicitly guidance, not a standalone standard (General
note, sheet 1, verbatim): “Treat the abutment dimensions, construction
joints and reinforcing shown in this drawing as MINIMUM VALUES and
perform a complete design for the abutment. Do not reference these
drawings in the contract plans and do not use as standalone construction
drawings.” That is a stronger disclaimer than BCHW/CPA-1-08’s “insert
design here” blanks – every dimension here is a floor, not a value to
build to, and this module’s layout_typical_abutment should be read
the same way: a reasonable visual check, never a substitute for the
abutment design.
What’s fixed: two literal formulas (the bearing-seat dimension and the wingwall unsupported-length limit) plus a handful of section minimums (cover, bar spacing, backwall/footing minimum widths). Concrete f’c = 4.0 ksi, reinforcing steel min. yield 60 ksi; bars are #5 unless noted.
Conventions match the rest of this package: X along stations, Y transverse, Z up; feet in plan, inches for section dimensions. The origin sits on the abutment centerline at the low beam seat elevation (Z = 0), Y = 0 at the backwall centerline.
- class civilpy.structural.odot.typical_abutment.AbutmentInput(width_ft: float, skew_deg: float, wingwall_length_ft: float, footing_depth_ft: float, backwall_height_ft: float)[source]
Bases:
objectProject-supplied dimensions for a typical (girder-bridge) abutment.
wingwall_length_ftshould not exceedWINGWALL_UNSUPPORTED_MAX_FTwithout an extended footing (the sheet’s own limit, not enforced here since “extend the footing” is itself a valid design response, not a hard cap on the wingwall).
- class civilpy.structural.odot.typical_abutment.AbutmentLayout(inputs: ~civilpy.structural.odot.typical_abutment.AbutmentInput, backwall_outline: tuple[tuple[float, float, float], tuple[float, float, float], tuple[float, float, float], tuple[float, float, float]], footing_outline: tuple[tuple[float, float, float], tuple[float, float, float], tuple[float, float, float], tuple[float, float, float]], wingwall_outline: tuple[tuple[float, float, float], tuple[float, float, float], tuple[float, float, float], tuple[float, float, float]], dim_a_ft: float, notes: tuple[str, ...] = <factory>)[source]
Bases:
objectThe generated abutment.
backwall_outlineis the backwall’s plan footprint (top of footing, z = 0) extending upbackwall_height_ft;footing_outlineis the footing plan rectangle (extending downfooting_depth_ft);wingwall_outlineis one flared wingwall plane, perWINGWALL_MIN_HEIGHT_FT.- backwall_outline: tuple[tuple[float, float, float], tuple[float, float, float], tuple[float, float, float], tuple[float, float, float]]
- footing_outline: tuple[tuple[float, float, float], tuple[float, float, float], tuple[float, float, float], tuple[float, float, float]]
- inputs: AbutmentInput
- civilpy.structural.odot.typical_abutment.bearing_seat_dim_a_ft(skew_deg: float = 0.0) float[source]
DIM. A = 2'-0" / COS(skew)(sheet 2’s skewed part-plan).
- civilpy.structural.odot.typical_abutment.layout_typical_abutment(inp: AbutmentInput) AbutmentLayout[source]
Generate a typical abutment backwall + footing + one flared wingwall from fully project-supplied dimensions.
Raises
ValueErrorfor a non-positive width/wingwall length/footing depth/backwall height.
civilpy.structural.odot.vandal_fence module
Ohio DOT vandal protection fence (VPF-1-24).
Transcribed from Ohio DOT Standard Bridge Drawing VPF-1-24, “Vandal Protection Fence” (rev. 01-17-2025, 6 sheets). The drawing remains the controlling document.
Mostly a materials/hardware specification (posts, rails, fabric, tension wire, fittings, base plates, anchors – General Notes 1-25) rather than a dimensioned standard; the one genuine geometric table is the three post sections (sheet 2), each pairing a post type with its base plate and maximum spacing. The designer specifies which post type/base plate to use and the actual post spacing on a project’s own schematic deck plan (sheet 1, note 25).
Conventions match the rest of this package: X along the fence run, Y transverse (fixed at the railing face), Z up; feet in plan. The origin sits at the first post, z = 0 at the base plate.
- class civilpy.structural.odot.vandal_fence.FenceRunInput(length_ft: 'float', post_name: 'str' = 'PS-2/BP-1', spacing_ft: 'float | None' = None)[source]
Bases:
object
- class civilpy.structural.odot.vandal_fence.FenceRunLayout(inputs: ~civilpy.structural.odot.vandal_fence.FenceRunInput, section: ~civilpy.structural.odot.vandal_fence.PostSection, post_stations_ft: tuple[float, ...], top_rail: tuple[tuple[float, float, float], tuple[float, float, float]], bottom_rail: tuple[tuple[float, float, float], tuple[float, float, float]], notes: tuple[str, ...] = <factory>)[source]
Bases:
objectThe generated fence run:
post_stations_ftare evenly-spaced post positions along the run (never exceeding the section’s max spacing);top_rail/bottom_railare the rail lines at post height / base.- inputs: FenceRunInput
- section: PostSection
- civilpy.structural.odot.vandal_fence.POST_SECTIONS: dict[str, PostSection] = {'PS-1': PostSection(name='PS-1', base_plate='BP-3', height_ft=9.989583333333334, max_spacing_ft=7.0, curved=True, curve_radius_ft=2.6666666666666665, note='12 ft curved fence; extends over a steel railing on a concrete barrier'), 'PS-2/BP-1': PostSection(name='PS-2', base_plate='BP-1', height_ft=6.0, max_spacing_ft=10.0, curved=False, curve_radius_ft=None, note='6 ft straight fence on single slope railing'), 'PS-2/BP-2': PostSection(name='PS-2', base_plate='BP-2', height_ft=6.0, max_spacing_ft=5.0, curved=False, curve_radius_ft=None, note='6 ft straight fence on deflector railing (closer spacing)')}
VPF-1-24 post sections, keyed by name.
- class civilpy.structural.odot.vandal_fence.PostSection(name: str, base_plate: str, height_ft: float, max_spacing_ft: float, curved: bool = False, curve_radius_ft: float | None = None, note: str = '')[source]
Bases:
objectOne VPF-1-24 post section (sheet 2).
- civilpy.structural.odot.vandal_fence.layout_fence_run(inp: FenceRunInput) FenceRunLayout[source]
Generate a fence run: evenly-spaced posts (spacing never exceeding the section’s tabulated maximum) plus top/bottom rail lines.
Raises
ValueErrorfor a non-positive length or an unknown post section name.
- civilpy.structural.odot.vandal_fence.post_section(name: str) PostSection[source]
Look up a VPF-1-24 post section (“PS-1”, “PS-2/BP-1”, “PS-2/BP-2”).
Raises
ValueErrornaming the valid names otherwise.
Module contents
Catalog of Ohio DOT Standard Construction Drawings (SCDs).
This package transcribes the geometry, reinforcement, and design data published on Ohio Department of Transportation standard bridge and roadway drawings into structured, queryable Python objects. Each catalog entry cites its SCD number and revision date; the underlying drawings are public-domain Ohio DOT documents.
Sub-modules:
bridge_railingBridge railings and barriers (BR, SBR, TST, DBR, TBR, PCB series), each carrying its NCHRP 350 / MASH crash test level so it links to the Table A13.2-1 design forces in
civilpy.structural.aashto.lrfd.guardrailMidwest Guardrail System (MGS) roadway drawings: the standard system parameters (height, post spacing, blockouts, post sections) plus the series registry and the bridge terminal assemblies that tie a guardrail run into the cataloged bridge railings.
box_beamPrestressed concrete box beam construction details (PSBD-1-25): tie rods, anchor dowels, shear keys, diaphragm placement rules, and the standard elastomeric bearing pads.
box_beam_designPrestressed box beam standard designs and LRFR load ratings (PSBDD-1-25): strand patterns, eccentricities, camber, and rating factors for the composite (CB) and non-composite (B) families at five depths.
deck_designODOT BDM 309.3 reinforced concrete deck design: the minimum-thickness formula, the mandatory design policy (LRFD 9.7.3 strip method, HL-93), and the BDM Figure 309-3 standard deck designs by effective span.
rocker_bolsterStructural steel rocker and bolster bearing dimensions and capacities (RB-1-55), plus
layout_rocker_bolster: the shared base plate, the bolster’s flat-top tapered body, and the rocker’s curved-top body (TOP BEARING DETAIL radius formula) behind the RB-1-55 component.headwallCast-in-place half-height headwall dimension tables (HW-2.1 corrugated- metal/plastic, HW-2.2 concrete) plus the
layout_headwallgenerator behind the HW-2.1 Grasshopper component: the rectangular circular-pipe headwall solid (end treatment “A”), battered back face, pipe opening.approach_slabReinforced concrete approach slab (AS-1-15): the reinforcing steel table, bar count/length formulas, seat and joint details, and the pure-Python layout generator behind the AS-1-15 Grasshopper component.
drip_stripStainless steel drip strips for over-the-side drainage (DS-1-92): section profile, perforation pattern, railing-dependent placement, and the fascia run generator behind the DS-1-92 component.
portable_barrierPortable concrete barrier geometry (PCB-91): the New Jersey shape section, segment/joint/anchor layout behind the PCB-91 component (crash test levels stay in
bridge_railing).sleeper_slabApproach slab installation / sleeper slab (AS-2-15): the Type A/C reinforced concrete sleeper slab under the approach-slab/pavement joint, its SS501/SS502 reinforcement, underdrain and joint layout, and the installation-type catalog (Type B has no sleeper slab).
full_height_headwallFull-height headwalls with wingwalls (HW-1.1): the pipe-diameter x skew-angle dimension/quantity table (0-84 in, skew 0-45 deg) and the
layout_full_height_headwallgenerator behind the HW-1.1 component – Type A symmetric and Type B asymmetric (skewed) wingwalls.box_culvert_headwallPrecast box culvert headwall/wingwall plan insert (BCHW): a detailing template rather than a dimensioned standard, so
layout_wingwalltakes every dimension as a project-supplied input; also catalogs the general notes (payment items, waterproofing, weepholes, PEJF, lap splices) and the eight standard rebar bend shapes (bend_shape,TYPE-1..``TYPE-8``) the bar list references.slab_bridgeSingle span slab bridges (SB-1-24): the span-keyed
SLAB DATAtable (thickness + A/B/M/N bar schedule, 11-38 ft) andEDGE BEAM SLAB DATAtable (over-the-side-drainage vs. parapet edge conditions), and thelayout_slab_bridgegenerator behind the SB-1-24 component.capped_pile_abutmentCapped pile abutment for slab bridges (CPA-1-08), SB-1-24’s companion: fixed section constants, the reinforcing bend legend (
bend_shape, Types 1-5; Type 6/D801 isapproach_slab’s bar), andlayout_capped_pile_abutment– another detailing-template sheet (like BCHW) whose overall dimensions are project-supplied.capped_pile_pierCapped pile pier for continuous slab bridges (CPP-1-08), CS-1-24’s companion: the sheet’s own pier-length formula (
pier_length_ft), fixed cap width/end-radius, the P501-P504 bar bend data, andlayout_capped_pile_pier– unlike the other capped-pile-cap sheets, this one is genuinely parametric (no blank “insert design here”), only pile count/spacing stay project-supplied.continuous_slab_bridgeThree-span continuous slab bridges (CS-1-24), SB-1-24’s continuous sibling: the end-span-keyed
SLAB DATAtable (thickness + A/B bottom, C/D top, E top-at-pier bar schedule, 14-46 ft – the largest table in the SCD program, 779 numeric entries), the fixed 1.25x interior-span ratio, andlayout_continuous_slab.typical_abutmentTypical abutment detail for girder bridges with expansion joints (A-1-20): explicitly guidance/minimum-values, not a standalone standard (see the module docstring). The bearing-seat and wingwall-limit formulas, section minimums, and
layout_typical_abutmentfor a visual check only.fixed_bearingFixed (pin) bearings for steel beam and girder bridges (FB-1-82): the F-50..F-400 dimension/capacity table and
layout_fixed_bearing(masonry plate + bearing pin + top plate) behind the FB-1-82 component.strip_seal_jointStrip seal expansion joints, steel stringer structures (EXJ-4-87): the support-angle length formulas (a1-a4, skew-dependent) and
layout_strip_seal_joint– the gland itself is manufacturer- generic and not modeled.strip_seal_joint_box_beamStrip seal expansion joints, concrete box beam structures (EXJ-5-93): the plate “A”/”B”/”C” spacing table (36/48 in beams), the joint- length formula, and
layout_box_beam_joint.
- class civilpy.structural.odot.AbutmentInput(wingwall_length_ft: float, skew_deg: float, n_piles: int, pile_spacing_ft: float, footing_depth_ft: float, cap_width_ft: float = 3.0)[source]
Bases:
objectProject-supplied dimensions for one capped pile abutment.
wingwall_length_ftis the “W” dimension (Section B-B/F-F);n_piles/pile_spacing_ftlay out the cap’s pile line;footing_depth_ftis the cap/footing depth below the bridge seat. Nothing here is cataloged – see the module docstring.
- class civilpy.structural.odot.AbutmentLayout(inputs: ~civilpy.structural.odot.capped_pile_abutment.AbutmentInput, cap_outline: tuple[tuple[float, float, float], tuple[float, float, float], tuple[float, float, float], tuple[float, float, float]], pile_points: tuple[tuple[float, float, float], ...], wingwall_outline: tuple[tuple[float, float, float], tuple[float, float, float], tuple[float, float, float], tuple[float, float, float]], notes: tuple[str, ...] = <factory>)[source]
Bases:
objectThe generated abutment.
cap_outlineis the cap’s plan footprint (top of cap, z = 0, the bridge seat) extending downfooting_depth_ft;pile_pointsare the pile centerlines along the cap;wingwall_outlineis one flared wingwall plane (mirrorslayout_full_height_headwall()’s convention).- cap_outline: tuple[tuple[float, float, float], tuple[float, float, float], tuple[float, float, float], tuple[float, float, float]]
- inputs: AbutmentInput
- structural_model(reaction: float = 0.0) StructuralModel[source]
Returns a MIDAS-ready StructuralModel of the abutment cap as a beam.
- class civilpy.structural.odot.AnchorDowelDetail(diameter: float = 1.0, beam_hole_diameter: float = 2.0, beam_hole_diameter_compression_seal: float = 2.5, fixed_substructure_hole_min: float = 1.0625, expansion_substructure_hole_min: float = 1.25)[source]
Bases:
objectAnchor dowel details (PSBD-1-25 sheets 1 & 5).
- class civilpy.structural.odot.ApproachSlabDesign(length_ft: float, thickness_in: float, a_bar_spacing_in: float, a_bar_mark: str, a_bar_length_ft: float, a_bar_dimension_ft: float, b501_bottom_spacing_in: float, b501_bottom_count: int, b501_top_count: int, c_bar_mark: str, c_bar_length_ft: float)[source]
Bases:
objectOne row of the AS-1-15 reinforcing steel table.
Lengths in feet, spacings/thicknesses in inches. Bar counts that depend on the slab width W are computed by the module-level functions, matching the tabulated formulas (e.g.
12(W-0.5)/K + 1).
- class civilpy.structural.odot.ApproachSlabInput(length_ft: float, width_ft: float, skew_deg: float = 0.0, end_thickness_in: float | None = None, seat_length_in: float = 9.0, backwall_thickness_in: float = 14.0)[source]
Bases:
objectThe design choices an engineer makes on the project plans.
length_ftmust be one of the tabulated L values.width_ftis the approach slab width W per the sheet’s width-dimension figure (out-to-out without curbs, toe-to-toe of curbs, or toe-to-toe of barrier).end_thickness_inis X (thickness at the abutment end); the sheet requires X >= T and expresses X in feet in its formulas.seat_length_inis the bearing length on the seat/backwall (6 in to 1’-0” per section B-B).backwall_thickness_inselects the anchor bar (D801 needs >= 14 in; D802 covers the 11 in PS box beam case).
- class civilpy.structural.odot.ApproachSlabLayout(inputs: ~civilpy.structural.odot.approach_slab.ApproachSlabInput, design: ~civilpy.structural.odot.approach_slab.ApproachSlabDesign, outline: tuple[tuple[float, float, float], tuple[float, float, float], tuple[float, float, float], tuple[float, float, float]], profile: tuple[tuple[float, float], ...], bars: tuple[~civilpy.structural.odot.approach_slab.BarRun, ...], anchor_mark: str, anchor_length_ft: float, pay_area_sy: float, notes: tuple[str, ...] = <factory>)[source]
Bases:
objectEverything the Grasshopper component draws.
outlineis the counterclockwise plan parallelogram at z = 0 (top of slab), starting at the bridge-limit / y = 0 corner.profileis the longitudinal section polyline in (u, z) feet, u measured from the bridge limit along the roadway; it is swept transversely (with the skew shear) to form the solid.- design: ApproachSlabDesign
- inputs: ApproachSlabInput
- class civilpy.structural.odot.BarMat(size: int, spacing: float)[source]
Bases:
objectOne reinforcing mat: bar size at a uniform spacing (in).
- class civilpy.structural.odot.BarrierEndSection(scd: str, scd_date: str, designation: str, parent: str, total_length_ft: float, body_length_ft: float, face_transition_ft: float, vertical_run_in: float, end_taper_in: float, end_height_in: float, end_width_in: float, end_core_width_in: float, median: bool = True, notes: str = '')[source]
Bases:
objectOne RM-4.6 cast-in-place concrete barrier end section.
Steps the parent single-slope barrier down to a 32 in tall, vertical-faced end that a Bridge Terminal Assembly (SCD MGS-3.1/3.2/ 3.3, Item 606) or impact attenuator attaches to; the single-slope faces transition to vertical over 10 ft to prevent snagging, and the concrete end carries a 4:1 plan flare over the last 16 in. Paid as Item 622 “Concrete Barrier End Section, Type _”, Each.
- class civilpy.structural.odot.BarrierEndSectionLayout(end_section: BarrierEndSection, stations: tuple[tuple[float, tuple[tuple[float, float], ...]], ...], notes: tuple[str, ...] = ())[source]
Bases:
objectStationed cross-sections of an RM-4.6 end section, ready to loft.
stationsis a tuple of(station_ft, profile)pairs from the parent-barrier joint (station 0) to the end; each profile is a closed(offset_in, z_in)loop in the roadway-barrier convention. The 4:1 plan end flare inside the last 16 in is described innotesrather than drawn (it rounds the very end plan corners).- end_section: BarrierEndSection
- class civilpy.structural.odot.BarrierSegment(index: int, start_ft: float, end_ft: float)[source]
Bases:
objectOne placed segment: stations (ft) along the run.
- class civilpy.structural.odot.BarrierTransitionLayout(barrier: RoadwayBarrier, kind: str, obstruction_width_in: float, stations: tuple[tuple[float, float], ...], total_length_ft: float, notes: tuple[str, ...] = ())[source]
Bases:
objectPlan-view widening of an RM-4.4 single-slope barrier transition.
stationsis a tuple of(station_ft, width_in)pairs of the barrier’s overall plan width from the start of the first taper; the cross-section at any station keeps the parent barrier’s height and 5.25:1 faces with the extra width filled solid between them.- barrier: RoadwayBarrier
- class civilpy.structural.odot.BearingDesignData(durometer: int = 50, allowable_compressive_stress: float = 1.25, shear_modulus_compressive: float = 0.095, shear_modulus_horizontal: float = 0.13, creep_deflection_percent: float = 25.0, bearings_per_beam: int = 4, spec_edition: str = 'AASHTO LRFD BDS 10th Edition (2024)')[source]
Bases:
objectElastomeric bearing design data (PSBD-1-25 sheet 6/6).
- creep_deflection_percent: float = 25.0
25-year creep deflection / instantaneous deflection, percent.
- class civilpy.structural.odot.BearingPad(name: str, length: float, width: float, total_thickness: float, t_external: float, t_internal: float, t_steel: float, n_laminates: int, max_total_load: float, max_expansion_length: float, max_movement: float, rotation_capacity: float = 0.024)[source]
Bases:
objectA standard steel-reinforced elastomeric bearing pad (PSBD-1-25 sheet 6/6 table). Lengths in inches, load in kips, expansion length in feet.
- class civilpy.structural.odot.BeveledLoadPlate(min_thickness: float = 1.5, plate_grade: str = 'ASTM A709 Gr 50', anchor_rod_diameter: float = 0.75, plate_washer: str = '3 x 3 x 1/2', expansion_anchor_hole: float = 1.25, stud_yield: float = 50.0)[source]
Bases:
objectBeveled steel load plate detail (BD-1-11).
- class civilpy.structural.odot.BikewayRailingInput(length_ft: float, flared_ends: bool = True, low_shoulder: bool = False)[source]
Bases:
objectOne straight bikeway railing run.
length_ftis the fence length between flares (as shown on plans); flared ends addFLARED_END_LENGTH_FTeach whenflared_ends.
- class civilpy.structural.odot.BikewayRailingLayout(inputs: BikewayRailingInput, post_stations_ft: tuple[float, ...], midspan_stations_ft: tuple[float, ...], post_length_in: float, embedment_in: float, n_rail_pieces: int, total_length_ft: float, notes: tuple[str, ...] = ())[source]
Bases:
objectMembers of one bikeway railing run.
post_stations_ftare full-post centers from the run start;midspan_stations_ftthe 18 in rail-stiffener posts centered in each bay. Rails run the full length in <= 20 ft pieces butt- jointed on posts (top rail and lower face rail staggered to alternate posts, note 6).- inputs: BikewayRailingInput
- class civilpy.structural.odot.BoxBeamDesign(beam_type: str, box: str, depth: int, width: int, span: int, e_beam: float, e_composite: float | None, n_strands: int, strands_2in: int, strands_4in: int, strands_6in: int, stirrup_w_pairs: int, stirrup_zone_x: float, stirrup_y: float, stirrup_z: float, camber_d0: float, camber_d30: float, deflection: float, bearing_type: str)[source]
Bases:
objectOne standard box-beam design line (PSBDD-1-25 sheets 1 & 3).
e_compositeisNonefor non-composite beams.strands_2in/strands_4in/strands_6inare the strand counts in the rows 2, 4, and 6 in above the soffit (their sum isn_strands). Camber values are at release (camber_d0) and erection (camber_d30);deflectionis the residual midspan deflection under remaining dead load. All lengths in inches.
- class civilpy.structural.odot.BoxBeamDesignSpec(fc_28day_range: tuple[float, float] = (5.5, 7.0), fci_release_range: tuple[float, float] = (4.0, 5.0), fc_cast_in_place: float = 4.5, fy_reinforcing: float = 60.0, strand_grade: int = 270, strand_diameter: float = 0.5, strand_area_options: tuple[float, ...] = (0.153, 0.167))[source]
Bases:
objectDesign-stress and material specifications (PSBD-1-25 sheet 1/6).
Concrete strengths are designer-selected ranges; the strand and reinforcing values are fixed by the standard. Stresses in ksi.
- fc_28day_range: tuple[float, float] = (5.5, 7.0)
Designer-selected 28-day concrete strength range, ksi.
- class civilpy.structural.odot.BoxBeamJointInput(n_beams: int, beam_width_in: float, skew_deg: float = 0.0)[source]
Bases:
object
- class civilpy.structural.odot.BoxBeamJointLayout(inputs: ~civilpy.structural.odot.strip_seal_joint_box_beam.BoxBeamJointInput, joint_line: tuple[tuple[float, float, float], tuple[float, float, float]], length_ft: float, beam_gap_stations_ft: tuple[float, ...], spacing: ~civilpy.structural.odot.strip_seal_joint_box_beam.PlateSpacing, notes: tuple[str, ...] = <factory>)[source]
Bases:
objectThe generated joint:
joint_lineis the skewed gland centerline across the full deck width (z = 0, top of deck);beam_gap_stationsare the transverse (Y) positions of each beam-to-beam gap, where a plate “A”/”B”/”C” group sits.- inputs: BoxBeamJointInput
- spacing: PlateSpacing
- class civilpy.structural.odot.BoxBeamRating(beam_type: str, box: str, width_ft: int, n_beams: int, span: int, rating_factors: dict[str, float]=<factory>)[source]
Bases:
objectLRFR rating factors for one box / span / bridge width (PSBDD-1-25 sheets 2 & 4).
rating_factorsis keyed byRATING_VEHICLES.
- class civilpy.structural.odot.BoxSectionProperties(depth: int, width: float = 48.0, area: float = 0.0, i: float = 0.0, yb: float = 0.0, zt: float = 0.0, zb: float = 0.0, ic: float = 0.0, ybc: float = 0.0, ztc: float = 0.0, zbc: float = 0.0)[source]
Bases:
objectNon-composite (“beam only”) and composite section properties for one standard box-beam depth (PSBD-1-25 sheet 4/6 tables). Lengths in inches;
areain in^2,i/icin in^4,zt/zb/ztc/zbcin in^3. The composite values assume the standardCOMPOSITE_SLAB_STRUCTURAL_THICKNESS_INtopping atCOMPOSITE_MODULAR_RATIO; they apply to any beam of this depth when a CIP composite slab is cast, independent of which design table (composite vs. non-composite strand pattern) governs the beam itself.
- class civilpy.structural.odot.BridgeRailing(scd: str, scd_date: str, designation: str, name: str, shape: str, material: str, test_level: str, height: float | None = None, base_width: float | None = None, top_width: float | None = None, section_area: float | None = None, f_c: float | None = None, f_y: float | None = None, vertical_bar_spacing: float | None = None, bar_sizes: tuple[int, ...] = (), transition_length_ft: float | None = None, transition_volume_cy: float | None = None, post_shape: str = '', post_spacing: float | None = None, rail_element: str = '', f_y_steel: float | None = None, weight_per_ft: float | None = None, segment_length_ft: tuple[float, ...] = (), rail_height_above_in: float | None = None, notes: str = '')[source]
Bases:
objectOne Ohio DOT standard bridge railing / barrier configuration.
test_levelis the NCHRP 350 / MASH level stated on the drawing ("TL-2".."TL-6"); it keysTEST_LEVEL_LOADS. An empty string means the drawing states no numeric crash test level. Fields left asNone/""are not called out (or not applicable) on the drawing.Concrete-parapet entries populate
section_area(gross area of the standard, non-transition section),f_c/f_y, and the vertical-bar fields. Post-and-beam steel railings populatepost_shape,post_spacing,rail_element, andf_y_steelinstead.- bar_sizes: tuple[int, ...] = ()
Standard-bar designation numbers present in the section (#5, #6, …).
- design_force_check(m_c: float, m_w: float, m_b: float = 0.0, end_region: bool = False)[source]
Run the AASHTO A13.3.1 yield-line check for this railing against its own test-level design forces.
Only meaningful for concrete-parapet entries.
m_c(kip-ft/ft),m_wandm_b(kip-ft) are the wall’s flexural resistances; the railing’s catalogheight(in) is converted to feet. Returns aCheckResultwhosedemandis the Table A13.2-1 transverse forceFt.
- meets_minimum_height() bool | None[source]
Whether the railing’s height satisfies the minimum rail height
Hfor its test level (Table A13.2-1,h_min).Nonewhen the height or test level is not recorded.For combination and post-and-beam railings
heightmay be the crashworthy element height only; treat the result accordingly.
- rail_height_above_in: float | None = None
For a “combination” railing (full-height concrete barrier + steel tube pedestrian rail on top, e.g. BR-2-15): how far the steel tube assembly extends above the concrete barrier’s own
height, inches.
- test_level_load() TestLevelLoad | None[source]
The Table A13.2-1 design forces for this railing’s test level, or
Noneif the drawing states no numeric crash test level.
- transition_length_ft: float | None = None
Length of the standard approach transition section, feet.
- class civilpy.structural.odot.BridgeTerminalAssembly(scd: str, scd_date: str, designation: str, origin: str, start_offset_in: float, post_spacings_in: tuple[float, ...], post_groups: tuple[TerminalPostGroup, ...] = (), rail_elements: tuple[str, ...] = (), connection: str = '', curb_note: str = '', connects_to: tuple[str, ...] = (), pay_item: str = '', notes: str = '')[source]
Bases:
objectOne MGS bridge terminal assembly (SCD MGS-3.1 / 3.2 / 3.3).
post_spacings_inare the successive c/c spacings starting fromorigin(each sheet’s own stationing direction);start_offset_inis the distance from the origin to post 1.rail_elementslist the transition rail pieces in the same order. Payment is Item 606, Each.- post_groups: tuple[TerminalPostGroup, ...] = ()
- class civilpy.structural.odot.BridgeTerminalLayout(terminal: BridgeTerminalAssembly, post_stations_in: tuple[float, ...], posts: tuple[tuple[int, str, float, str], ...], length_in: float, notes: tuple[str, ...] = ())[source]
Bases:
objectPost stations and members of one MGS bridge terminal assembly.
- terminal: BridgeTerminalAssembly
- class civilpy.structural.odot.CSSlabDesign(end_span_ft: int, thickness_in: float, a_bar: ABarSpec, b_bar: LenBarSpec, c_bar: LenBarSpec, d_bar: LenBarSpec, e_bar: LenBarSpec | None, n_bar: CountBarSpec, m_bar: CountBarSpec, u_bar_count: int)[source]
Bases:
objectOne
SLAB DATAtable row (sheet 2), keyed by end span (ft).- b_bar: LenBarSpec
- c_bar: LenBarSpec
- d_bar: LenBarSpec
- e_bar: LenBarSpec | None
- m_bar: CountBarSpec
- n_bar: CountBarSpec
- class civilpy.structural.odot.ContinuousSlabInput(end_span_ft: int, width_ft: float, skew_deg: float = 0.0)[source]
Bases:
objectProject dimensions for a 3-span continuous slab bridge (CS-1-24).
- class civilpy.structural.odot.ContinuousSlabLayout(inputs: ~civilpy.structural.odot.continuous_slab_bridge.ContinuousSlabInput, outline: tuple[tuple[float, float, float], tuple[float, float, float], tuple[float, float, float], tuple[float, float, float]], thickness_in: float, total_length_ft: float, pier_stations: tuple[float, float], bars: tuple[~civilpy.structural.odot.continuous_slab_bridge.BarRun, ...], notes: tuple[str, ...] = <factory>)[source]
Bases:
objectThe generated three-span continuous slab bridge.
outlineis the skewed plan parallelogram at z = 0 (top of slab, uniform thickness – haunches over the piers are not modeled);pier_stationsare the two pier centerline X coordinates.- inputs: ContinuousSlabInput
- class civilpy.structural.odot.CurbType(sheet_labels: tuple[str, ...], name: str, height: float | None, top_width: float, base_width: float, toe_radius: float | None = None, notes: str = '')[source]
Bases:
objectOne BP-5.1 curb / combined curb-and-gutter cross section.
heightis the curb’s own face height (in),Nonewhen it is the project-variable gutter-plate thicknessT.top_width/base_widthdescribe a schematic trapezoid of the curb’s concrete only (see module docstring for what is and isn’t modeled).
- class civilpy.structural.odot.DeckDesignPolicy(method: str = 'LRFD 9.7.3 approximate elastic (equivalent strip)', live_load: str = 'HL-93', future_wearing_surface_ksf: float = 0.06, monolithic_wearing_surface: float = 1.0, top_cover: float = 2.5, bottom_cover: float = 1.5, exposure_factor: float = 0.75, f_c: float = 4.5, f_y: float = 60.0, concrete_class: str = 'QC2', epoxy_coated: bool = True)[source]
Bases:
objectODOT concrete deck design requirements (BDM 309.3.2, 309.2, and the Figure 309-3 design assumptions). Thicknesses/covers in inches, pressures in ksf, strengths in ksi.
- class civilpy.structural.odot.DripStripPlacement(railing: str, upper_strip_length_in: float, root_depth_in: float)[source]
Bases:
objectUpper-strip length and the strip root depth below the deck (or wearing) surface for one railing type.
- class civilpy.structural.odot.EdgeBarSpec(depth_in: 'float', taper_in: 'float', bar_size: 'int', bar_count: 'int')[source]
Bases:
object
- class civilpy.structural.odot.EdgeBeamDesign(span_ft: int, over_the_side: EdgeBarSpec, parapet: EdgeBarSpec)[source]
Bases:
objectOne
EDGE BEAM SLAB DATAtable row (sheet 2): the edge-beam depth and D/E-bar schedule for both edge conditions.- over_the_side: EdgeBarSpec
- parapet: EdgeBarSpec
- class civilpy.structural.odot.EllipticalHeadwall(rise: float, span: float, width: float, height: float, thickness: float, concrete_cy: float)[source]
Bases:
objectOne HW-2.2 elliptical-pipe headwall line.
riseandspanare the pipe rise R and span;width(W),height(H) andthickness(T) are the headwall dimensions;concrete_cyis the cast-in-place concrete quantity. All inches.
- class civilpy.structural.odot.FenceRunInput(length_ft: 'float', post_name: 'str' = 'PS-2/BP-1', spacing_ft: 'float | None' = None)[source]
Bases:
object
- class civilpy.structural.odot.FenceRunLayout(inputs: ~civilpy.structural.odot.vandal_fence.FenceRunInput, section: ~civilpy.structural.odot.vandal_fence.PostSection, post_stations_ft: tuple[float, ...], top_rail: tuple[tuple[float, float, float], tuple[float, float, float]], bottom_rail: tuple[tuple[float, float, float], tuple[float, float, float]], notes: tuple[str, ...] = <factory>)[source]
Bases:
objectThe generated fence run:
post_stations_ftare evenly-spaced post positions along the run (never exceeding the section’s max spacing);top_rail/bottom_railare the rail lines at post height / base.- inputs: FenceRunInput
- section: PostSection
- class civilpy.structural.odot.FixedBearing(designation: str, max_load_lb: float, dims: dict[str, float], weight_lb: float, two_anchor_rods: bool = False, stiffeners_required: bool = False)[source]
Bases:
objectOne FB-1-82 fixed-bearing capacity line.
two_anchor_rods(note 1) is true only for F-50/F-100; otherwise 4 anchor rods are used (one per masonry-plate corner).stiffeners_required(note 2) is true only for F-350/F-400.
- class civilpy.structural.odot.FixedBearingLayout(fb: civilpy.structural.odot.fixed_bearing.FixedBearing, base_outline: tuple[tuple[float, float, float], tuple[float, float, float], tuple[float, float, float], tuple[float, float, float]], base_thickness_in: float, top_outline: tuple[tuple[float, float, float], tuple[float, float, float], tuple[float, float, float], tuple[float, float, float]], top_z_in: float, pin_diameter_in: float, pin_center: tuple[float, float, float], notes: tuple[str, ...] = <factory>)[source]
Bases:
object- base_outline: tuple[tuple[float, float, float], tuple[float, float, float], tuple[float, float, float], tuple[float, float, float]]
- fb: FixedBearing
- class civilpy.structural.odot.FullHeightHeadwallDesign(diameter_in: float, height_ft: float, a_ft: float, b_ft: float, c_ft: float, ts_ft: float, bar_size: int, skews: tuple[SkewGroup, ...])[source]
Bases:
objectOne HW-1.1 table row (a pipe diameter), with all four skew columns.
- civilpy.structural.odot.FullHeightHeadwallInput
alias of
HeadwallInput
- class civilpy.structural.odot.FullHeightHeadwallLayout(inputs: ~civilpy.structural.odot.full_height_headwall.HeadwallInput, table: ~civilpy.structural.odot.full_height_headwall.FullHeightHeadwallDesign, skew: ~civilpy.structural.odot.full_height_headwall.SkewGroup, skew_bucket_deg: float, type_: str, center_face: tuple[tuple[float, float, float], tuple[float, float, float], tuple[float, float, float], tuple[float, float, float]], wing1: tuple[tuple[float, float, float], tuple[float, float, float], tuple[float, float, float], tuple[float, float, float]], wing2: tuple[tuple[float, float, float], tuple[float, float, float], tuple[float, float, float], tuple[float, float, float]], concrete_cy: float, steel_lb: float, notes: tuple[str, ...] = <factory>)[source]
Bases:
objectThe generated headwall+wingwall unit.
center_faceis the vertical rectangular panel at the culvert centerline (X-Z plane at y = 0, width D centered on x = 0, height H);wing1/wing2are the two wingwall planes as(near_top, near_base, far_base, far_top)quads swept from the center face’s top corners out to each wingwall’s far end.wing1is the acute-side (L1/h1) wingwall,wing2the obtuse-side (L2/h2) wingwall; for Type A (skew snapped to 0) both use the L2/h2 data and are mirror images. Origin: x = 0 on the culvert centerline, y = 0 at the headwall front face (wall behind, +y downstream), z = 0 at the flow line / wall base.- center_face: tuple[tuple[float, float, float], tuple[float, float, float], tuple[float, float, float], tuple[float, float, float]]
- inputs: HeadwallInput
- table: FullHeightHeadwallDesign
- class civilpy.structural.odot.Haunch(depth: float, flange_width: float)[source]
Bases:
objectA concrete haunch per BDM 309.3.5: sides vertical and aligned with the edges of the top flange, so the haunch cross-section is simply
flange_width x depth. Depths/widths in inches.
- class civilpy.structural.odot.Headwall(diameter: float, width: float, height: float, thickness: float, concrete_cy: float, note: str = '')[source]
Bases:
objectOne HW-2.1 circular-pipe headwall line.
diameteris the pipe inside diameter D;width(W),height(H) andthickness(T) are the headwall dimensions;concrete_cyis the cast-in-place concrete quantity.noteflags special rows (e.g. pipe sizes between end treatments A and B).
- class civilpy.structural.odot.LoadPlateLayout(bevel_plate: BeveledLoadPlate, bottom_face: tuple[tuple[float, float, float], tuple[float, float, float], tuple[float, float, float], tuple[float, float, float]], top_face: tuple[tuple[float, float, float], tuple[float, float, float], tuple[float, float, float], tuple[float, float, float]], notes: tuple[str, ...] = ())[source]
Bases:
objectThe generated BD-1-11 beveled load plate, sized to a bearing pad’s plan footprint (
bearing_pad(name).lengthx.width).top_facecarries the bevel: each corner’s Z is offset by its (x, y) distance from plate center times the transverse/longitudinal bevel slope, so the plate top is a single tilted plane (not warped).- bevel_plate: BeveledLoadPlate
- class civilpy.structural.odot.MGSDrawing(scd: str, title: str, sheets: int, scd_date: str, category: str, connects_to: tuple[str, ...] = (), notes: str = '')[source]
Bases:
objectOne drawing in the Ohio DOT MGS roadway series.
categoryis one ofstandard,special,bridge_terminal,transition,anchor,terminal,layout,bridge.connects_tolists bridge-railing SCD numbers a terminal assembly ties into, where stated on the drawing.
- class civilpy.structural.odot.MGSRunLayout(length_ft: float, spacing: PostSpacing, post_stations_ft: tuple[float, ...], n_panels: int, panel_length_ft: float, rail_height_in: float = 31.0, notes: tuple[str, ...] = ())[source]
Bases:
objectPosts and W-beam panels of one straight standard-MGS run.
- spacing: PostSpacing
- class civilpy.structural.odot.MGSStandard(scd: str = 'MGS-2.1', scd_date: str = '2026-01-16', rail_height: float = 31.0, rail_height_tolerance_new: float = 1.0, rail_height_tolerance_existing: float = 3.0, rail: str = '12 gauge W-beam (CMS 606.02)', rail_panel_lengths: tuple[float, ...] = (12.5, 25.0), standard_post_length: float = 72.0, round_wood_post_length: float = 68.0, long_post_length: float = 97.0, embedment: float = 40.0, round_wood_embedment: float = 36.0, post_bolt_diameter: float = 0.625, blockout_section: str = '6 x 12', transition_rate_in_per_ft: float = 0.08)[source]
Bases:
objectStandard Type MGS guardrail parameters (MGS-2.1).
Heights/lengths in inches;
rail_panel_lengths(between splices) and transition rate are in feet.- long_post_length: float = 97.0
Long post length (steel / rectangular wood near slope break), inches.
- post_spacing(name: str = 'standard') float[source]
On-center post spacing (inches) for
"standard","half", or"quarter"spacing.
- class civilpy.structural.odot.PSIBeamLayout(section: ~civilpy.structural.odot.ps_i_beam.PSIBeamSection, profile: tuple[tuple[float, float], ...], length_ft: float, notes: tuple[str, ...] = <factory>)[source]
Bases:
objectA simplified I-shaped cross-section profile (top flange, web, bottom flange) – straight-line approximation, no fillet/bulb radii – extruded
length_ft. Profile points (y, z) inches, y transverse, z up from the bottom; the beam centerline is y = 0.- section: PSIBeamSection
- class civilpy.structural.odot.PSIBeamSection(name: str, depth_in: float, area_in2: float, weight_plf: float, yb_in: float, yt_in: float, i_in4: float, sb_in3: float, st_in3: float, vol_surf_ratio: float, top_flange_width_in: float, bottom_flange_width_in: float, max_bottom_flange_strands: int, web_in: float = 8.0, strand_rows: tuple = (), draped_required: tuple = (), shipping_strand_locations: tuple = ())[source]
Bases:
objectOne PSID-1-13 standard section (sheet 1 / sheet 3 SECTION PROPERTIES tables).
strand_rowsis the sheet’s permissible strand grid: a tuple of(z, (y, ...))rows –zinches above the beam bottom,ytransverse offsets from the beam centerline (2 in lattice). The row totals equalmax_bottom_flange_strands.draped_requiredlists the grid locations the sheet marks “if utilized, these strand locations must be draped” (WF sections’ upper web column).shipping_strand_locationsare the optional debonded shipping strands the fabricator may add in the top flange (Modified AASHTO / WF sheets; the sheet ties them to general-note bonding rules – seeSHIPPING_STRAND_BOND_FT).
- class civilpy.structural.odot.PierBarMark(mark: 'str', width_ft: 'float | None', height_is_q: 'bool', inside_radius_ft: 'float | None' = None, note: 'str' = '')[source]
Bases:
object
- class civilpy.structural.odot.PierInput(slab_width_ft: float, skew_deg: float, n_piles: int, pile_spacing_ft: float, cap_depth_ft: float = 2.0)[source]
Bases:
objectInputs for a capped pile pier.
slab_width_ftis the bridge slab width (drivespier_length_ft());n_piles/pile_spacing_ftlay out the pile line (spacing must not exceedMAX_PILE_SPACING_FT);cap_depth_ftdefaults to the sheet’s fixedCAP_DEPTH_FT.
- class civilpy.structural.odot.PierLayout(inputs: ~civilpy.structural.odot.capped_pile_pier.PierInput, cap_outline: tuple[tuple[float, float, float], ...], pile_points: tuple[tuple[float, float, float], ...], length_ft: float, notes: tuple[str, ...] = <factory>)[source]
Bases:
objectThe generated pier.
cap_outlineis the rounded-end cap plan footprint (top of cap, z = 0) extending downcap_depth_ft;pile_pointsare the pile centerlines (top of pile, at the cap underside).
- class civilpy.structural.odot.PlateSpacing(beam_width_in: float, dim_a_in: float, dim_b_in: float, dim_c_in: float)[source]
Bases:
object
- class civilpy.structural.odot.PostSection(name: str, base_plate: str, height_ft: float, max_spacing_ft: float, curved: bool = False, curve_radius_ft: float | None = None, note: str = '')[source]
Bases:
objectOne VPF-1-24 post section (sheet 2).
- class civilpy.structural.odot.PostSpacing(name: str, spacing: float, blockout_height: float)[source]
Bases:
objectOne MGS post-spacing option and the blockout height it requires (MGS-2.1 sheets P.1-P.2).
spacingandblockout_heightin inches.
- class civilpy.structural.odot.RoadwayBarrier(scd: str, scd_date: str, designation: str, name: str, shape: str, material: str = 'reinforced concrete', height: float | None = None, top_width: float | None = None, base_width: float | None = None, slope_h_to_v: float | None = None, f_c: float | None = None, foundation: str = 'pavement', joint_spacing_ft: float | None = None, notes: str = '')[source]
Bases:
objectOne Ohio DOT standard roadway single-slope barrier type.
Mirrors the field names
civilpy.structural.rhino_barrier .barrier_profile()reads (shape,height,base_width,top_width) so the same profile-sweep engine renders these as it does the structural bridge parapets.
- class civilpy.structural.odot.RoadwayBarrierInput(designation: str, length_ft: float)[source]
Bases:
objectInputs for one straight run of a roadway single-slope barrier.
- class civilpy.structural.odot.RoadwayBarrierLayout(barrier: RoadwayBarrier, length_ft: float, profile: tuple[tuple[float, float], ...], notes: tuple[str, ...] = ())[source]
Bases:
objectSymmetric cross-section plus run length for a roadway barrier.
profileis a closed list of(offset_in, z_in)vertices,offsetmeasured from the barrier centerline andzfrom its base – the same conventioncivilpy.structural.rhino_barrier.barrier_profile()uses for a freestanding (side=0) section.- barrier: RoadwayBarrier
- class civilpy.structural.odot.RockerBolster(capacity_kips: int, bolster_no: str, rocker_no: str, dims: dict[str, float], weight_bolster_lb: float | None, weight_rocker_lb: float, max_load_lb: float)[source]
Bases:
objectOne RB-1-55 rocker/bolster capacity line.
bolster_nois empty for the smallest line (R-75 has no matching bolster).dimsis keyed by the letters inDIM_LETTERS.
- class civilpy.structural.odot.RockerBolsterLayout(rb: ~civilpy.structural.odot.rocker_bolster.RockerBolster, base_outline: tuple[tuple[float, float, float], tuple[float, float, float], tuple[float, float, float], tuple[float, float, float]], base_thickness_in: float, bolster_top: tuple[tuple[float, float, float], tuple[float, float, float], tuple[float, float, float], tuple[float, float, float]], bolster_height_in: float, rocker_top_radius_in: float, rocker_height_in: float, notes: tuple[str, ...] = <factory>)[source]
Bases:
objectThe generated bolster + rocker pair for one capacity line, sharing the base-plate footprint origin at plan center, z = 0 at the bottom of the base plate.
- base_outline: tuple[tuple[float, float, float], tuple[float, float, float], tuple[float, float, float], tuple[float, float, float]]
- bolster_top: tuple[tuple[float, float, float], tuple[float, float, float], tuple[float, float, float], tuple[float, float, float]]
- rb: RockerBolster
- class civilpy.structural.odot.ShearKeyDetail(grout_depth_from_top: float = 5.0, composite_backer_rod_min: float = 2.0, end_shear_key_depth: float = 1.0, end_shear_key_width: float = 38.0)[source]
Bases:
objectShear-key details between adjacent box beams (PSBD-1-25 sheets 1 & 5).
- class civilpy.structural.odot.SlabBridgeInput(span_ft: int, width_ft: float, skew_deg: float = 0.0, edge_condition: Literal['over_the_side', 'parapet'] = 'over_the_side')[source]
Bases:
objectInputs for a single-span slab bridge.
edge_conditionselects the edge-beam schedule:"over_the_side"(drainage over the fascia) or"parapet"(shallower edge beam under a concrete parapet, per the sheet’s edge-beam option).
- class civilpy.structural.odot.SlabBridgeLayout(inputs: ~civilpy.structural.odot.slab_bridge.SlabBridgeInput, outline: tuple[tuple[float, float, float], tuple[float, float, float], tuple[float, float, float], tuple[float, float, float]], thickness_in: float, bridge_length_ft: float, bars: tuple[~civilpy.structural.odot.slab_bridge.BarRun, ...], edge_beam: ~civilpy.structural.odot.slab_bridge.EdgeBarSpec, notes: tuple[str, ...] = <factory>)[source]
Bases:
objectThe generated slab bridge.
outlineis the skewed plan parallelogram at z = 0 (top of slab); the slab extends downthickness_in.barsare the A/B/M/N longitudinal runs.- edge_beam: EdgeBarSpec
- inputs: SlabBridgeInput
- class civilpy.structural.odot.SlabDesign(span_ft: int, thickness_in: float, a_bar: BarSpec, b_bar: BarSpec, m_bar: BarSpec, n_bar: BarSpec)[source]
Bases:
objectOne
SLAB DATAtable row (sheet 1).
- civilpy.structural.odot.SleeperInstallation
alias of
Installation
- class civilpy.structural.odot.SleeperSlabInput(width_ft: float, skew_deg: float = 0.0, installation: str = 'A')[source]
Bases:
objectInputs for a Type A / Type C sleeper slab: the approach slab width it supports and the skew it parallels.
- class civilpy.structural.odot.SleeperSlabLayout(inputs: ~civilpy.structural.odot.sleeper_slab.SleeperSlabInput, outline: tuple[tuple[float, float, float], tuple[float, float, float], tuple[float, float, float], tuple[float, float, float]], thickness_in: float, bars: tuple[~civilpy.structural.odot.sleeper_slab.BarRun, ...], underdrain: tuple[tuple[float, float, float], tuple[float, float, float]], pma_joint: tuple[tuple[float, float, float], tuple[float, float, float], tuple[float, float, float], tuple[float, float, float]], aggregate_drain: tuple[tuple[float, float, float], tuple[float, float, float], tuple[float, float, float], tuple[float, float, float]], measured_length_ft: float, notes: tuple[str, ...] = <factory>)[source]
Bases:
objectThe generated sleeper slab.
outlineis the counterclockwise plan parallelogram at z = 0 (top of sleeper); the solid extends downSLEEPER_THICKNESS_IN.underdrainis the pipe centerline;pma_jointis the joint-system outline sitting on the sleeper top over the centerline, andaggregate_drainthe trench outline below the slab.- aggregate_drain: tuple[tuple[float, float, float], tuple[float, float, float], tuple[float, float, float], tuple[float, float, float]]
- inputs: SleeperSlabInput
- outline: tuple[tuple[float, float, float], tuple[float, float, float], tuple[float, float, float], tuple[float, float, float]]
- class civilpy.structural.odot.StandardDeckDesign(effective_span_ft: float, deck_thickness: float, overhang_thickness: float, transverse_top: BarMat, transverse_bottom: BarMat, longitudinal_top: BarMat, longitudinal_bottom: BarMat, overhang_bar_size: int | None, overhang_cutoff: float | None)[source]
Bases:
objectOne row of BDM Figure 309-3.
deck_thicknessandoverhang_thicknessare totals including the 1 in monolithic wearing surface.overhang_bar_size/overhang_cutoffare the additional overhang bar and the length (in) beyond the fascia beam/girder centerline where it is no longer required (note 5); both areNonewhere the figure tabulates none. Longitudinal spacings exclude the additional negative-moment reinforcement required over piers (note 6; LRFD 6.10.1.7 / 5.6.3.2).
- class civilpy.structural.odot.SteelPost(designation: str, fabrication: str, depth: float, flange_width: float, flange_thickness: float, web_thickness: float)[source]
Bases:
objectAn MGS steel beam post section (MGS-2.1 sheet P.2 table). All dimensions in inches.
- class civilpy.structural.odot.StripRun(kind: str, start_ft: float, end_ft: float)[source]
Bases:
objectOne strip piece along the fascia: stations in feet from the start of the run, plus which profile it carries.
- class civilpy.structural.odot.StripSealJointInput(width_ft: float, skew_deg: float, stringer_stations_ft: tuple[float, ...], top_flange_width_in: float = 12.0)[source]
Bases:
objectInputs for one strip seal joint run.
stringer_stations_ftare the transverse stringer positions (Y, ft) across the deck width;top_flange_width_inis the (uniform, assumed) stringer top flange width used in the support-angle formulas.
- class civilpy.structural.odot.StripSealJointLayout(inputs: ~civilpy.structural.odot.strip_seal_joint.StripSealJointInput, joint_line: tuple[tuple[float, float, float], tuple[float, float, float]], support_angles: tuple[~civilpy.structural.odot.strip_seal_joint.SupportAngleRun, ...], notes: tuple[str, ...] = <factory>)[source]
Bases:
objectThe generated joint:
joint_lineis the skewed gland centerline across the full deck width (z = 0, top of deck);support_anglesis one short transverse segment per stringer station, sized bysupport_angle_lengths_in().- inputs: StripSealJointInput
- support_angles: tuple[SupportAngleRun, ...]
- class civilpy.structural.odot.SupportAngleRun(station_ft: float, points: tuple[tuple[float, float, float], tuple[float, float, float]], a1_in: float, a2_in: float, a3_in: float, a4_in: float)[source]
Bases:
object
- class civilpy.structural.odot.TerminalPostGroup(first: int, last: int, post: str, length_in: float, blockout: str)[source]
Bases:
objectA run of identical posts within a bridge terminal assembly.
first/lastare 1-based post numbers; lengths in inches.
- class civilpy.structural.odot.ThrieBeamPCBTransition(sheet: int, barrier_a: str, barrier_b: str, notes: str = '')[source]
Bases:
objectOne RM-4.7 connection pair (one sheet each).
barrier_a/barrier_bname the generic/proprietary 32 in PCB shapes joined; the hardware set is common to all three pairs.
- class civilpy.structural.odot.TieRodDetail(diameter: float = 1.0, thread_root_min_diameter: float = 0.838, torque_ft_lb: float = 250.0, plate_washer: str = '4 x 4 x 1/2', hole_min_diameter: float = 2.0, hole_max_diameter: float = 3.0, max_beams_per_rod: int = 3)[source]
Bases:
objectTransverse tie rod details (PSBD-1-25 sheets 1 & 4).
- class civilpy.structural.odot.TransitionSection(scd: str, name: str, height_from_in: float, height_to_in: float, length_ft: float, notes: str = '')[source]
Bases:
objectA tapered end section joining two different barrier heights.
- civilpy.structural.odot.TypicalAbutmentInput
alias of
AbutmentInput
- civilpy.structural.odot.TypicalAbutmentLayout
alias of
AbutmentLayout
- class civilpy.structural.odot.WingwallInput(length_ft: float, skew_deg: float, wall_height_ft: float, foreslope_height_ft: float, cutoff_wall_height_ft: float, footing_width_ft: float, box_wall_thickness_in: float, embankment_slope: float = 2.0)[source]
Bases:
objectProject-supplied dimensions for one wingwall + foreslope wall (sheet 2/8 “WINGWALL ELEVATION” + “SECTION A-A”). All in feet unless named
_in. Nothing here is cataloged – see the module docstring.
- class civilpy.structural.odot.WingwallLayout(inputs: ~civilpy.structural.odot.box_culvert_headwall.WingwallInput, wingwall_outline: tuple[tuple[float, float, float], tuple[float, float, float], tuple[float, float, float], tuple[float, float, float]], foreslope_section: tuple[tuple[float, float, float], ...], footing_outline: tuple[tuple[float, float, float], tuple[float, float, float], tuple[float, float, float], tuple[float, float, float]], notes: tuple[str, ...] = <factory>)[source]
Bases:
objectThe generated wingwall + foreslope wall.
wingwall_outlineis the wingwall’s flared elevation (top of footing at z = 0, box-face height H tapering to hf at y = L);foreslope_sectionis the Section A-A profile (cutoff wall, footing top, foreslope-wall stem with itst boxthickness, 2:1 embankment line off the back face) in the Y-Z plane;footing_outlineis the footing plan rectangle drawn at the bottom-of-cutoff elevation-hcw.- footing_outline: tuple[tuple[float, float, float], tuple[float, float, float], tuple[float, float, float], tuple[float, float, float]]
- inputs: WingwallInput
- civilpy.structural.odot.anchor_bar_mark(backwall_thickness_in: float) str[source]
Which anchor bar the sheet permits for a given backwall thickness.
D801 cannot be used on backwalls less than 14 in thick; D802 is for prestressed box beam bridges with 11 in backwalls.
- civilpy.structural.odot.anchor_hole_stations_ft(segment_length_ft: float) tuple[float, ...][source]
Anchor-hole stations along one segment (ft from its start): 1’-0” from each end, equally spaced at 2’-0” c/c (5 holes per row on a 10 ft segment, 6 on a 12 ft).
- civilpy.structural.odot.approach_slab_design(length_ft: float) ApproachSlabDesign[source]
The standard design for an approach slab length L (ft).
- civilpy.structural.odot.barrier_end_section(designation: str) BarrierEndSection[source]
Look up an RM-4.6 end section by designation (
"Type B","Type B1","Type D").
- civilpy.structural.odot.barrier_run(n_segments: int, segment_length_ft: float = 10.0, joint_gap_in: float = 0.25) tuple[BarrierSegment, ...][source]
Lay out
n_segmentsalong a straight run with the given joint gap (closed 1/4 in up to the fully-open 1-3/4 in max).
- civilpy.structural.odot.bearing_pad(name: str) BearingPad[source]
Look up a standard bearing pad by name (
"B1"or"B2").
- civilpy.structural.odot.bearing_seat_dim_a_ft(skew_deg: float = 0.0) float[source]
DIM. A = 2'-0" / COS(skew)(sheet 2’s skewed part-plan).
- civilpy.structural.odot.bend_shape(type_: str, **legs: float) tuple[tuple[float, float], ...][source]
The bend polyline for one of the BCHW legend shapes.
type_is"TYPE-1".."TYPE-8";legssupplies the leg lengths the sheet leaves blank (A,B,C,Das applicable,theta_degfor TYPE-2,skew_degfor TYPE-8). RaisesValueErrornaming the valid types and required legs.
- civilpy.structural.odot.box_beam_design(box: str, span: int) BoxBeamDesign[source]
The design line for a box designation and span in feet.
- civilpy.structural.odot.box_beam_rating(box: str, span: int, width_ft: int) BoxBeamRating[source]
The load rating for a box, span (ft), and bridge width (24/28/32 ft).
- civilpy.structural.odot.box_section_properties(depth_in: int) BoxSectionProperties[source]
Look up the 48 in wide box-beam section properties for a standard depth (17/21/27/33/42 in).
- civilpy.structural.odot.box_void_dimensions(depth_in: float, width_in: float = 48.0) tuple[float, float][source]
Void
(width, height)in inches for a box beam ofdepth_in/width_in:BOX_WEB_THICKNESS_INwebs each side,BOX_FLANGE_THICKNESS_INflanges top and bottom (PSBD-1-25 sheet 2/6 dimension chains).
- civilpy.structural.odot.bridge_length_ft(span_ft: float, skew_deg: float = 0.0) float[source]
BRIDGE LENGTH = SPAN + (1.5' / COS(theta))(sheet 1).
- civilpy.structural.odot.bridge_terminal(designation: Literal['Type 1', 'Type 2', 'Type TST-2']) BridgeTerminalAssembly[source]
Look up a bridge terminal assembly (
"Type 1","Type 2","Type TST-2").
- civilpy.structural.odot.bridge_terminal_assemblies() list[MGSDrawing][source]
The MGS bridge terminal assemblies (transitions to bridge railings).
- civilpy.structural.odot.cpa_bend_shape(bend_type: int, **legs: float) tuple[tuple[float, float], ...]
The bend polyline for one of CPA-1-08’s own legend shapes (1-5).
legssupplies whatever the sheet leaves blank (A,B,Cas applicable). RaisesValueErrornaming the valid types (1-5; call intoapproach_slabfor Type 6/D801) and required legs.
- civilpy.structural.odot.cpa_rebar_mark(mark: str) tuple[RebarMark, ...]
All
REBAR_TABLErows for a bar mark (usually one;A801has two – the standard anchor bar and the optional hooked-dowel alternate).Raises
ValueErrornaming the valid marks otherwise.
- civilpy.structural.odot.cs_slab_design(end_span_ft: int) CSSlabDesign[source]
Look up the CS-1-24 slab design for an end span (feet, 14-46 tabulated; interior span is always 1.25x, see
interior_span_ft()).Raises
ValueErrornaming the valid spans otherwise.
- civilpy.structural.odot.curb_height_in(label: str, *, gutter_plate_t_in: float | None = None) float[source]
Resolved curb height (in): the catalog
heightif fixed, else the projectgutter_plate_t_in(defaulting toDEFAULT_GUTTER_PLATE_T_IN) for the variable-height types.
- civilpy.structural.odot.curb_profile_in(label: str, *, gutter_plate_t_in: float | None = None) tuple[tuple[float, float], ...][source]
Schematic closed trapezoid profile (in) for
label,(offset, z)counterclockwise from the back-bottom corner,offsetmeasured from the curb’s back face andzup from the pavement surface.
- civilpy.structural.odot.curb_type(label: str) CurbType[source]
Look up a curb cross section by any of its sheet labels (e.g.
"Type 2","Type 2-A","Type 10-B").
- civilpy.structural.odot.designs_for_box(box: str) list[BoxBeamDesign][source]
All span designs for one box designation, shortest span first.
- civilpy.structural.odot.diaphragm_count(span_ft: float) int[source]
Number of intermediate diaphragms for a span, per PSBD-1-25 sheet 4/6: 1 for spans <= 50 ft, 2 for 50 ft < span <= 75 ft, 3 for spans > 75 ft.
- civilpy.structural.odot.diaphragm_end_offset(beam_depth: int) float[source]
Distance from beam end to the end diaphragm, inches (PSBD-1-25 sheet 4/6): 24 in for 17/21 in deep beams, 30 in for 27/33/42 in deep beams.
- civilpy.structural.odot.diaphragm_stations_ft(span_ft: float, beam_depth: int) tuple[float, ...][source]
Station (ft, from the beam start) of every diaphragm, sorted: the two end diaphragms plus
diaphragm_count()intermediate ones.A 70 ft CB27-48 therefore has four – ends at 2.5 and 67.5 ft, intermediates at 24.17 and 45.83 – which is what PSBD-1-25 sheet 4/6 details and what the beam is cast solid at.
- civilpy.structural.odot.drip_strip_runs(length_ft: float, post_stations_ft: tuple[float, ...], railing: str) tuple[StripRun, ...][source]
The strip pieces along ONE fascia edge: the continuous lower strip over the full length plus an upper strip centered at each railing post (clipped to the fascia). Raises
ValueErrorfor an unknown railing or non-positive length.
- civilpy.structural.odot.edge_beam_design(span_ft: int) EdgeBeamDesign[source]
Look up the SB-1-24 edge-beam design for a span (feet, 11-38).
Raises
ValueErrornaming the valid spans otherwise.
- civilpy.structural.odot.elliptical_headwall_for_rise(rise: float) EllipticalHeadwall[source]
Look up the HW-2.2 concrete elliptical headwall by pipe rise (inches).
- civilpy.structural.odot.end_diaphragm_stations_ft(span_ft: float, beam_depth: int) tuple[float, float][source]
Station (ft) of the two end diaphragms, one
diaphragm_end_offset()in from each beam end (PSBD-1-25 sheet 4/6). These are cast inside the solid end blocks – seesolid_end_block_in()– not in the voided length.
- civilpy.structural.odot.fixed_bearing(designation: str) FixedBearing[source]
Look up a FB-1-82 fixed-bearing line by designation (“F-50”, …, “F-400”). Raises
ValueErrornaming the valid designations otherwise.
- civilpy.structural.odot.fixed_bearing_smallest_for_load(load_lb: float) FixedBearing
The lightest standard fixed bearing whose maximum load covers
load_lb; raisesValueErrorif the load exceeds the F-400 line.
- civilpy.structural.odot.full_height_headwall_design(diameter_in: float) FullHeightHeadwallDesign[source]
Look up the HW-1.1 table row for a pipe diameter (inches).
Raises
ValueErrornaming the tabulated sizes ifdiameter_inis not one of them.
- civilpy.structural.odot.haunch_depth_at(design_haunch: float, camber_residual: float) float[source]
Theoretical haunch depth (in) at a station where the girder sits
camber_residualinches BELOW its theoretical profile (positive = girder low -> deeper haunch; negative = girder high -> shallower). The result may fall belowMIN_DESIGN_HAUNCH— that is the signal the design haunch must be increased, not clamped away.
- civilpy.structural.odot.headwall_for_diameter(diameter: float, concrete: bool = False) Headwall[source]
Look up the circular headwall for a pipe diameter (inches).
concrete=Falseuses the HW-2.1 corrugated-metal/plastic table;concrete=Trueuses the HW-2.2 concrete-pipe table. RaisesKeyErrorif the diameter is not a tabulated size.
- civilpy.structural.odot.i_beam_diaphragm_stations_ft(span_ft: float) list[float][source]
Intermediate-diaphragm centerline stations (ft from the span start) per sheet 5: one at midspan for spans up to 80 ft, at the quarter points beyond that. (Cast-in-place required under 60 in deep beams; 60/66/72 in beams may use the sheet 9 galvanized-steel diaphragms instead – sheet 10 general notes.)
- civilpy.structural.odot.interior_span_ft(end_span_ft: float) float[source]
Interior span = end span * 1.25 (fixed ratio, sheet 2’s SLAB DATA “SPANS” column, e.g. 14 ft end -> 17.50 ft interior).
- civilpy.structural.odot.intermediate_diaphragm_stations_ft(span_ft: float, beam_depth: int) tuple[float, ...][source]
Station (ft) of each intermediate diaphragm.
diaphragm_count()of them, dividing the length between the two end diaphragms into equal bays: one lands at midspan, two at the third points of that length, three at the quarter points. The drawing states the count and the end offset but not an explicit multi-diaphragm spacing rule; equal bays is the standard detailing assumption.Note
This used to be folded into
diaphragm_stations_ftwith ank / (n - 1)interpolation, which for two diaphragms returned the two end stations and so produced no intermediate diaphragms at all – a 70 ft span came back as(2.5, 67.5). A model built on that had its tie rods buried in the end blocks and no diaphragm anywhere in the span.
- civilpy.structural.odot.joint_length_ft(n_beams: int, beam_width_in: float, skew_deg: float = 0.0) float[source]
L = [(N-1)*(1/2) + N*W] / (12*cos(theta))(sheet 1’s LEGEND): joint length edge-to-edge of deck, feet.
- civilpy.structural.odot.lateral_clearance_in(superstructure_width_ft: float) float[source]
Lateral expansion clearance per end of the bearing pin (General Notes): 1/8 in normally, 1/4 in for a superstructure over 60 ft wide (up to the 120 ft this note addresses).
- civilpy.structural.odot.layout_approach_slab(inp: ApproachSlabInput) ApproachSlabLayout[source]
Generate the AS-1-15 approach slab layout.
Raises
ValueErrorwhen inputs leave the drawing’s assumptions (untabulated length, X < T, seat length outside 6-12 in, skew >= 60 degrees, or a backwall too thin for either anchor bar).
- civilpy.structural.odot.layout_barrier_end_section(designation: str) BarrierEndSectionLayout[source]
Build the lofting stations for an RM-4.6 end section.
- civilpy.structural.odot.layout_barrier_transition(designation: str, kind: str, *, obstruction_width_in: float | None = None, obstruction_length_ft: float = 0.0) BarrierTransitionLayout[source]
Build the RM-4.4 plan-width stations for a barrier transition.
designationis an RM-4.3 type (B/B1/C/C1);kindis"sign support"(light tower / sign foundation, 36-48 in wide, 10 ft run) or"pier"(48 in wide pier column protection;obstruction_length_ftis the variable column run between the two 5 ft shoulders). RaisesValueErrorfor other barrier types or a sign-support width outside the sheet’s 36-48 in band.
- civilpy.structural.odot.layout_bikeway_railing(inp: BikewayRailingInput) BikewayRailingLayout[source]
Lay out posts and rails for one RM-5.2 bikeway railing run.
Full posts at up to 10 ft centers with a mid-span stiffener post in each bay; each flared end (20 ft at 30 degrees away from the path) is treated as additional railing length with the same spacing. Raises
ValueErrorfor a non-positive length.
- civilpy.structural.odot.layout_box_beam_joint(inp: BoxBeamJointInput) BoxBeamJointLayout[source]
Generate a box-beam strip seal joint: the skewed joint line and the beam-to-beam gap stations where plate “A”/”B”/”C” groups sit.
Raises
ValueErrorfor fewer than 2 beams or an untabulated beam width (plate_spacing()).
- civilpy.structural.odot.layout_bridge_terminal(designation: Literal['Type 1', 'Type 2', 'Type TST-2']) BridgeTerminalLayout[source]
Expand a
BRIDGE_TERMINALSentry into per-post members.
- civilpy.structural.odot.layout_capped_pile_abutment(inp: AbutmentInput) AbutmentLayout[source]
Generate one capped pile abutment from fully project-supplied dimensions (no catalog lookup – see the module docstring).
Raises
ValueErrorfor a non-positive length/spacing/depth or fewer than 2 piles.
- civilpy.structural.odot.layout_capped_pile_pier(inp: PierInput, *, n_arc_segments: int = 8) PierLayout[source]
Generate a capped pile pier: the rounded-end cap solid outline and the pile line, from the sheet’s own pier-length formula.
Raises
ValueErrorfor a non-positive slab width/pile spacing, fewer than 2 piles, a pile spacing beyondMAX_PILE_SPACING_FT, or a skew beyondMAX_SKEW_DEG.
- civilpy.structural.odot.layout_continuous_slab(inp: ContinuousSlabInput) ContinuousSlabLayout[source]
Generate a three-span continuous slab bridge: plan outline, thickness, pier stations, and the A/B/C/D/E longitudinal bar mats (transverse N/M bars are cataloged by count, not separately drawn).
Raises
ValueErrorfor an untabulated end span or a skew beyond the sheet’s 25 deg limit.
- civilpy.structural.odot.layout_fence_run(inp: FenceRunInput) FenceRunLayout[source]
Generate a fence run: evenly-spaced posts (spacing never exceeding the section’s tabulated maximum) plus top/bottom rail lines.
Raises
ValueErrorfor a non-positive length or an unknown post section name.
- civilpy.structural.odot.layout_fixed_bearing(fb: FixedBearing) FixedBearingLayout[source]
Generate the drawable subset of one FB-1-82 line: the masonry plate, the top plate, and the bearing pin centerline.
Eis used as the masonry plate thickness (it is the smallest tabulated dimension, consistent with a base-plate thickness) andHas the clearance from the top of that plate to the pin center, so the stack (plate + pin + top plate) is self-consistent even though the sheet does not label a dimension “base plate thickness” outright – see SCD_BUILD_QUESTIONS.md.
- civilpy.structural.odot.layout_full_height_headwall(inp: HeadwallInput) FullHeightHeadwallLayout[source]
Generate the full-height headwall + wingwall solid.
Raises
ValueError(viafull_height_headwall_design()) for an untabulated pipe diameter, and (vianearest_skew_bucket()) for a skew beyond the table’s 45 deg range.
- civilpy.structural.odot.layout_load_plate(bearing_pad_name: str, longitudinal_grade: float = 0.0, skew_deg: float = 0.0, plate: BeveledLoadPlate = BeveledLoadPlate(min_thickness=1.5, plate_grade='ASTM A709 Gr 50', anchor_rod_diameter=0.75, plate_washer='3 x 3 x 1/2', expansion_anchor_hole=1.25, stud_yield=50.0)) LoadPlateLayout[source]
Generate the BD-1-11 beveled load plate sized to
bearing_pad_name("B1"or"B2",bearing_pad()), tilted perload_plate_bevel(). Origin at plate-bottom center, z = 0 at the bottom face; x = bearing length (beam axis), y = bearing width.
- civilpy.structural.odot.layout_mgs_run(length_ft: float, *, spacing: Literal['standard', 'half', 'quarter'] = 'standard', panel_length_ft: float = 25.0) MGSRunLayout[source]
Lay out a straight MGS-2.1 guardrail run: posts at the chosen spacing (
"standard"/"half"/"quarter") and W-beam panels ofpanel_length_ft(12.5 or 25 ft between splices). RaisesValueErrorfor a non-positive length, an unknown spacing, or a non-standard panel length.
- civilpy.structural.odot.layout_ps_i_beam(name: str, length_ft: float, web_thickness_in: float = 8.0, flange_thickness_in: float = 8.0) PSIBeamLayout[source]
Generate a simplified I-beam cross-section profile for
name(ps_i_beam_section()), extrudedlength_ft.Raises
ValueErrorfor a non-positive length or an unknown section name.
- civilpy.structural.odot.layout_roadway_barrier(inp: RoadwayBarrierInput) RoadwayBarrierLayout[source]
Build the symmetric single-slope cross-section for
inp.
- civilpy.structural.odot.layout_rocker_bolster(rb: RockerBolster) RockerBolsterLayout[source]
Generate the drawable subset of one RB-1-55 capacity line: the shared base-plate footprint, the bolster’s tapered+flat-top body, and the rocker’s tapered+curved-top body.
- civilpy.structural.odot.layout_slab_bridge(inp: SlabBridgeInput) SlabBridgeLayout[source]
Generate a single-span slab bridge: plan outline, thickness, and the A/B/M/N longitudinal bar mats.
Raises
ValueErrorfor an untabulated span, an unknownedge_condition, or a skew beyond the sheet’s 25 deg limit.
- civilpy.structural.odot.layout_sleeper_slab(inp: SleeperSlabInput) SleeperSlabLayout[source]
Generate the sleeper slab under the approach-slab/pavement joint.
Raises
ValueErrorfor a Type B installation (no sleeper slab), an unknown type, or out-of-range width/skew.
- civilpy.structural.odot.layout_strip_seal_joint(inp: StripSealJointInput) StripSealJointLayout[source]
Generate a strip seal joint: the skewed joint line and one support-angle run per stringer station.
Raises
ValueErrorfor a non-positive width or an emptystringer_stations_ft.
- civilpy.structural.odot.layout_typical_abutment(inp: AbutmentInput) AbutmentLayout[source]
Generate a typical abutment backwall + footing + one flared wingwall from fully project-supplied dimensions.
Raises
ValueErrorfor a non-positive width/wingwall length/footing depth/backwall height.
- civilpy.structural.odot.layout_wingwall(inp: WingwallInput) WingwallLayout[source]
Generate one wingwall + foreslope wall from fully project-supplied dimensions (no catalog lookup – see the module docstring).
Raises
ValueErrorfor a non-positive length/height/width.
- civilpy.structural.odot.load_plate_bevel(longitudinal_grade: float, skew_deg: float) tuple[float, float][source]
Transverse and longitudinal bevels of the BD-1-11 load plate.
The plate top is beveled to match the roadway grade resolved into the bearing’s local axes (BD-1-11 bevel notes): the component across the bearing width is
grade * sin(skew)and the component along the bearing length isgrade * cos(skew).longitudinal_gradeis the roadway grade (rise/run, e.g. 0.04 for 4%);skew_degis the structure skew angle in degrees. Returns(transverse, longitudinal)bevel slopes in the same rise/run units as the grade.
- civilpy.structural.odot.m_bar_offset_in(bridge_limits_ft: float, n_m_bars: int, m_bar_spacing_ft: float) float[source]
Sheet 1’s
Yformula: the offset from the bearing line to the first M-bar,Y = 1/2 * [bridge limits - (n_m_bars - 1) * spacing] * 12(inches).
- civilpy.structural.odot.mgs_drawing(scd: str) MGSDrawing[source]
Look up an MGS drawing by SCD number (e.g.
"MGS-3.1").
- civilpy.structural.odot.minimum_deck_thickness(effective_span_ft: float) float[source]
Minimum total deck thickness (in) per BDM 309.3.1.
Tmin = (S + 17)(12)/36 >= 8.5 inrounded up to the nearest 1/4 in, whereeffective_span_ftis the effective span length per LRFD 9.7.2.3. Includes the 1 in monolithic wearing surface; subtractDeckDesignPolicy.monolithic_wearing_surfacefor the structural design thickness.
- civilpy.structural.odot.nearest_skew_bucket(skew_deg: float) float[source]
Snap a skew angle to the nearest tabulated bucket (0/15/30/45 deg).
The 0 deg cutoff is pinned to
SKEW_TYPE_A_MAX_DEG(10 deg) – sheet 1’s own Type A/B boundary – rather than the halfway point (7.5 deg) so a skew that the sheet calls Type A never gets Type B’s asymmetric wingwall data; 15/30/45 split at their halfway points (22.5, 37.5) as plain nearest-neighbor. RaisesValueErrorfor a skew outside the table’s range (sheet 1 tabulates through 45 deg only; beyond that the standard drawing does not apply).
- civilpy.structural.odot.overhang_thickness(design: StandardDeckDesign, railing: str | None = None) float[source]
Overhang deck thickness (in) for a standard design, applying the note 2.k minimums for the TST steel-tube railings when they govern.
- civilpy.structural.odot.pcb_profile_points_in(chamfered: bool = True) tuple[tuple[float, float], ...]
The closed New Jersey shape section, counterclockwise from the bottom-left corner, as (x, y) inches with x transverse from the barrier centerline and y up from the deck surface.
chamferedincludes the 3/4 in top chamfers (the sheet allows a 1 in radius instead).
- civilpy.structural.odot.pier_bar(mark: str) PierBarMark[source]
Look up a CPP-1-08 bar mark (P501-P504).
Raises
ValueErrornaming the valid marks otherwise.
- civilpy.structural.odot.plate_spacing(beam_width_in: float) PlateSpacing[source]
Look up the EXJ-5-93 plate spacing for a beam width (36 or 48 in).
Raises
ValueErrornaming the valid widths otherwise.
- civilpy.structural.odot.post_section(name: str) PostSection[source]
Look up a VPF-1-24 post section (“PS-1”, “PS-2/BP-1”, “PS-2/BP-2”).
Raises
ValueErrornaming the valid names otherwise.
- civilpy.structural.odot.ps_i_beam_profile(name: str) tuple[tuple[float, float], ...][source]
The true tapered cross-section outline of a PSID-1-13 section as closed-polygon vertices
(y, z)in inches,ytransverse from the beam centerline,zup from the bottom – counter-clockwise, starting at the bottom-left corner. Straight-line approximation: fillet and 3/4 in chamfer radii are not modeled (unlikelayout_ps_i_beam(), the flange tapers are).
- civilpy.structural.odot.ps_i_beam_section(name: str) PSIBeamSection[source]
Look up a PSID-1-13 standard section by name.
Raises
ValueErrornaming the valid sections otherwise.
- civilpy.structural.odot.railing(designation: str) BridgeRailing[source]
Look up a railing by its
designation(e.g."BR-1 (36 in)").
- civilpy.structural.odot.railings_for_test_level(test_level: str) list[BridgeRailing][source]
All cataloged railings rated for
test_level(e.g."TL-4").
- civilpy.structural.odot.roadway_barrier(designation: str) RoadwayBarrier[source]
Look up a roadway barrier type by its
designation(e.g."Type B","Type N").
- civilpy.structural.odot.roadway_portable_barrier(designation: str) BridgeRailing[source]
Look up a roadway portable barrier by its
designation(e.g."RM Portable (32 in, pin & loop)").
- civilpy.structural.odot.rocker_bolster(capacity_kips: int) RockerBolster[source]
Look up a rocker/bolster line by rated capacity in kips (75..300).
- civilpy.structural.odot.s_bar_length_ft(base_ft: float, skew_deg: float) float[source]
S501/S502/S503’s tabulated
base/COS(theta)length formula.
- civilpy.structural.odot.secondary_longitudinal_reinforcement(main: BarMat) BarMat[source]
Minimum longitudinal top-mat (secondary) reinforcement per BDM 309.3.4.1: at least 1/3 of the main (transverse) reinforcement, spaced uniformly, detailed as #4 bars — unless that would put the #4s closer than 3 in, in which case a larger bar at >= 3 in spacing is returned.
Applies the 1/3 rule to the provided main steel, which is slightly conservative against BDM Figure 309-3 (whose longitudinal mats derive from the required steel); for spans the figure tabulates, use the figure’s mats — this helper is for custom designs outside it.
- civilpy.structural.odot.slab_design(span_ft: int) SlabDesign[source]
Look up the SB-1-24 slab design for a span (feet, 11-38 tabulated).
Raises
ValueErrornaming the valid spans otherwise.
- civilpy.structural.odot.sleeper_installations(type_: str) tuple[Installation, ...]
All cataloged configurations of the given installation type.
- civilpy.structural.odot.smallest_for_load(load_lb: float) RockerBolster[source]
The lightest standard rocker/bolster whose maximum load covers
load_lb; raisesValueErrorif the load exceeds the 300-kip line.
- civilpy.structural.odot.solid_diaphragm_block_in(skew_deg: float = 0.0, width_in: float = 48.0) float[source]
Longitudinal length of an intermediate diaphragm’s solid block.
Zero skew gives
SOLID_DIAPHRAGM_BLOCK_IN; a skewed beam needsX/2 + 6inches,X = width * tan(skew), so the block still contains the full diaphragm once it runs on the bias.
- civilpy.structural.odot.solid_end_block_in(depth_in: int) float[source]
Length of the solid end block for a beam of
depth_in.
- civilpy.structural.odot.ss501_length_ft(width_ft: float, skew_deg: float = 0.0) float[source]
SS501 length A = (W - 0.5’)/cos(theta) (sheet 1 bending table).
- civilpy.structural.odot.ss502_count(width_ft: float) int[source]
SS502 bars at 1’-0” max, measured perpendicular to CL roadway, across the (W - 0.5) bar band — spaces rounded up.
- civilpy.structural.odot.ss502_length_ft(skew_deg: float = 0.0) float[source]
SS502 length B = 7.5’/cos(theta) (sheet 1 bending table).
- civilpy.structural.odot.standard_deck_design(effective_span_ft: float, *, railing: str | None = None, beam_lines: int | None = None, beam_spacing_ft: float | None = None, overhang_ft: float | None = None) StandardDeckDesign[source]
Look up the BDM Figure 309-3 standard design for an effective span.
effective_span_ftis the effective span length per LRFD 9.7.3.2; it is rounded up to the next tabulated 0.5 ft increment (note 2.k). The optional keywords assert the figure’s design assumptions —railing(SCD designation, note 2.k),beam_lines(>= 4, note 2.a),beam_spacing_ft(<= 15 ft, note 2.b) andoverhang_ft(<= 4 ft, note 2.j) — and raiseValueErrorwhen the standard designs do not apply, in which case the deck must be designed per BDM 309.3.2 instead.
- civilpy.structural.odot.standard_hook_bar_length_ft(span_ft: float) float[source]
A/D/E-bar standard-hook length:
span + 10"(the bending-diagram formula shared by all three bar marks).
- civilpy.structural.odot.strand_centroid_in(pattern: list[tuple[float, float]]) float[source]
Height of a strand pattern’s centroid above the beam bottom (in).
- civilpy.structural.odot.strand_grid(name: str) list[tuple[float, float]][source]
Every permissible bottom-flange/web strand location of a section as
(y, z)inches, in the standard fill order: row by row from the bottom up, outermost locations first within a row (the fill order keeps each partial pattern symmetric and its centroid low).Locations in
PSIBeamSection.draped_requiredcome last so a straight-strand design never occupies them by accident.
- civilpy.structural.odot.strand_group_height_in(design: BoxBeamDesign) float[source]
Height of the strand-group centroid above the soffit (in), the strand-count-weighted average of the 2/4/6 in row heights. A schematic single-height tendon path uses this; it is consistent with (Yb of the matching
BoxSectionProperties) minusdesign.e_beamto within drawing rounding.
- civilpy.structural.odot.strand_pattern(name: str, n_strands: int) list[tuple[float, float]][source]
The first
n_strandslocations ofstrand_grid()– the pattern the pipeline’s designer uses. RaisesValueErrorwhenn_strandsexceeds the section’s permissible locations.
- civilpy.structural.odot.strip_profile_in(kind: str, *, bent: bool = True, include_embedded: bool = True) tuple[tuple[float, float], ...][source]
Cross-section polyline of one strip, inches, in the (h, v) plane: h positive outward from the fascia face (h = 0 at the bend line), v positive up.
kindis"upper"(leg turned up 45 degrees) or"lower"(leg turned down).bent=Falsegives the pre-placement shape (leg vertical against the form).include_embedded=Falsereturns only the exposed leg.
- civilpy.structural.odot.structural_design_thickness(total_thickness: float) float[source]
Deck thickness used in structural design (in): the total thickness minus the monolithic wearing surface (BDM 309.3.1 / 309.1.A).
- civilpy.structural.odot.support_angle_lengths_in(top_flange_width_in: float, skew_deg: float) tuple[float, float, float, float][source]
The a1/a2/a3/a4 support-angle formulas (sheet 1, SECTION C-C).
Returns
(a1, a2, a3, a4)in inches; mirror the sign convention for a left-forward skew per the sheet’s own note (use the same magnitude, mirrored in plan by the caller).
- civilpy.structural.odot.terminals_for_railing(scd: str) list[MGSDrawing][source]
MGS terminal assemblies that connect to bridge railing
scd(e.g."TST-2-21").
- civilpy.structural.odot.thrie_beam_pcb_transition(barrier_a: str, barrier_b: str) ThrieBeamPCBTransition[source]
Look up the RM-4.7 pair joining two PCB shapes (order-free). Raises
ValueErrornaming the cataloged pairs otherwise — in particular there is no approved pair involving the J-J Hook 32 in New Jersey shape PCB.