Structs with Unitful Types

I am creating a number of structs with unitful types. Here is a small example:

const float_ft = typeof(1.0ft) # ft, inch, and kcf previously defined constants
const float_inch = typeof(1.0inch)
const float_kcf = typeof(1.0kcf)

@with_kw struct Slab
    width::float_ft
    thickness::float_inch = 8.5inch
    fws_thickness::float_inch = 0.0inch
    fws_density::float_kcf = 0.15kcf
    cross_slope::Float64 = 0.0
end

s = Slab(40ft) #will convert to Slab(40.0ft) (rest of fields left out for clarity)

This works great when I pass in unitful types. However, I foresee pulling information from excel or maybe from a gui where I will have to convert from a number or string to a number with the proper unit. Like so:

From Excel

width = XLSX.readdata("myfile.xlsx", "mysheet!A1") * ft
thickness = XLSX.readdata("myfile.xlsx", "mysheet!A1") * inch
# ... rest of code parsing
Slab(width, thickness, fws_thickness, fws_density, cross_slope)

From GUI

width = parse(Float64, tb_width) * ft # tb_width is some textbox with string number
# ... rest of code

I would like for the constructor to convert to the proper unit no matter the number of arguments. So Slab(40.0) would correctly create the Slab(40.0ft) (rest of fields left out for clarity). I assume this would need to be an inner constructor, but not sure how I would do that in a robust way.

I have many structs and about 10 different units so far, so it seems like the amount of boiler plate code is going to get bigger and bigger as well as the potential error.

I am curious if anyone else has dealt with this and any possible solutions?

We solved that issue in Meshes.jl where all our structs now have units, but we still allow non-unitful constructors (which default to meter units). Maybe you can take a look into our source code to learn some of the tricks? @eliascarv can share more details if you have further questions.

Perhaps all you need are “geometries” in your application? Is a “slab” a piece of stone with given shape? I wonder if you could simply use Meshes.jl to represent these. You can create aliases in your application like const Slab = Hexahedron to still use “jargon” names.

1 Like

Thanks I will look into the Meshes.jl code. A slab is like a deck of a bridge. Which could easily be defined with an object that is probably present in Meshes.jl. The girders I am just drawing from a set of x and y points.
image

I will probably try to use Meshes.jl eventualy if I can ever get to it. There is a python package called sectionproperties that makes use of shapley and a mesh package to define section properties of shapes. I am curious if something similar could be made in Julia.

1 Like

Doesn’t this work?

slab(;a=da, b=db, c=dc) = Slab(uconvert(A, a), uconvert(B, b), uconvert(C, c))