Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to implement Measured::Area and Measured::Volume? #91

Open
jocubeit opened this issue Jul 4, 2017 · 9 comments
Open

How to implement Measured::Area and Measured::Volume? #91

jocubeit opened this issue Jul 4, 2017 · 9 comments

Comments

@jocubeit
Copy link

jocubeit commented Jul 4, 2017

I added a custom implementation for Measured::Time, but having trouble working out how I might implement Area and Volume. I have a specific use-case for these for an app designed for the trades industry.

@jocubeit
Copy link
Author

jocubeit commented Jul 5, 2017

This is what I've come up with for Area so far, not sure how accurate the conversion figures are though as I used Google to convert from one unit to another:

Measured::Area = Measured.build do
  unit :mm2, value: ['0.01 cm2'], aliases: [:square_millimeter, :square_millimeters, :square_millimetre, :square_millimetres]
  unit :cm2, value: ['0.0001 m2'], aliases: [:square_centimeter, :square_centimeters, :square_centimetre, :square_centimetres]
  unit :m2,  aliases: [:square_meter, :square_meters, :square_metre, :square_metres]
  unit :km2, value: ['1000000 m2'],  aliases: [:square_kilometer, :square_kilometers, :square_kilometre, :square_kilometres]
  unit :mi2, value: ['2.58999 km2'],  aliases: [:square_mile, :square_miles]
  unit :yd2, value: ['0.836127970373 m2'],  aliases: [:square_yard, :square_yards]
  unit :ft2, value: ['0.092903 m2'],  aliases: [:square_foot, :square_feet]
  unit :in2, value: ['6.4516 cm2'], aliases: [:square_inch, :square_inches]
  unit :ha, value: ['10000 m2'], aliases: [:hectare, :hectares]
  unit :ac, value: ['4046.86 m2'], aliases: [:acre, :acres]
end

Any comments are most welcome.

@jocubeit
Copy link
Author

jocubeit commented Jul 5, 2017

And this is what I've come up with for Volume, again not sure how accurate it is:

Measured::Volume = Measured.build do
  unit :l, aliases: [:litre, :liter, :litres, :liters]
  unit :ml, value: ['0.001 l'], aliases: [:millilitre, :milliliter, :milliliter, :milliliters]
  unit :m3, value: ['1000 l'], aliases: [:cubic_meter, :cubic_meters, :cubic_metre, :cubic_metres]
  unit :ft3, value: ['0.0353147 l'], aliases: [:cubic_foot, :cubic_feet]
  unit :in3, value: ['0.0163871 l'], aliases: [:cubic_inch, :cubic_inches]
  unit :gal, value: ['4.54609 l'], aliases: [:imp_gal, :imperial_gallon, :imperial_gallons]
  unit :us_gal, value: ['3.78541 l'], aliases: [:us_gallon, :us_gallons, :us_liquid_gallon, :us_liquid_gallons]
  unit :qt, value: ['1.13652 l'], aliases: [:q, :imp_qt, :imperial_quart, :imperial_quarts]
  unit :us_qt, value: ['0.946353 l'], aliases: [:us_quart, :us_quarts, :us_fluid_quart, :us_fluid_quarts, :us_liquid_quart, :us_liquid_quarts]
  unit :pt, value: ['0.568261 l'], aliases: [:p, :imp_pt, :imperial_pint, :imperial_pints]
  unit :us_pt, value: ['0.473176 l'], aliases: [:us_pint, :us_pints, :us_liquid_pint, :us_liquid_pints]
  unit :oz, value: ['0.0284131 l'], aliases: [:fl_oz, :imp_fl_oz, :fluid_ounce, :imperial_fluid_ounce, :fluid_ounces, :imperial_fluid_ounces]
  unit :us_oz, value: ['0.0295735 l'], aliases: [:us_fl_oz, :us_fluid_ounce, :us_fluid_ounces]
end

Do you think these conversions are acceptable?

@jocubeit
Copy link
Author

@thegedge, @kmcphillips I can see you two are active on this repo, any comments?

@thegedge
Copy link
Contributor

thegedge commented Aug 15, 2017

Hey, @JurgenJocubeit, thanks for the issue and sorry I missed it (I'm watching the repo now 😸). These look good at first glance, although I haven't verified the numbers (I would do that in code review). If you'd like to push a PR (preferably one for area and one for volume), I'd be happy to review it.

My plan was to one day try to get something working for things like area and volume where you could multiply lengths together and get areas/volumes, but I haven't thought through such an implementation much (performance being the key concern). I do know that squared representations would come out like unit^2 with such a change, or maybe even squared unit,

Nevertheless, even if I could multiply 1m * 1m to get 1m^2, for example, there are area measurements that won't fit that pattern (e.g., acre, hectare), so there's a need for something like this. We can start with manually defining squared lengths, and once I get around to implementing such a change I'll figure out how to best deal with the construction of a unit system 😃

@jocubeit
Copy link
Author

jocubeit commented Aug 15, 2017

Thanks for your reply, I have forked and started two feature branches. Have the code and readme done, just need to finish the unit tests.

Although I agree that the ability to calculate area and volume from length inputs would be nice, I do feel it's a bit out of scope for the gem in it's current form. The gem tends to currently lean towards conversion. Of course, calculation would always be welcome, albeit quite a challenge! :-)

@thegedge
Copy link
Contributor

Thanks for your reply, I have forked and started two feature branches. Have the code and readme done, just need to finish the unit tests.

Great! Just add me as a reviewer when you send out the PRs.

Although I agree that the ability to calculate area and volume from length inputs would be nice, I do feel it's a bit out of scope for the gem in it's current form.

Yeah, for now I don't have the time to invest in a prototype for this. But I'd love to be able to do something like this:

> distance = Measured::Weight.new("12", "m")
> time = Measured::Time.new("6", "s")
> distance / time
#<Measured::Speed: 2 #<Measured::Unit: m/s>>

@jocubeit
Copy link
Author

Just wanted to let you know I haven't forgotten this, got waylaid on a few other things. Will come back to this tonight and finish writing those tests.

@panbanda
Copy link

Greetings! Is there a latest on this PR? I may have some time if I can get the latest.

@saraid
Copy link
Contributor

saraid commented Nov 12, 2021

Instead of coming up with new units, I'd suggest adding a new concept of "derived units". For example,

Measured::DerivedUnit.new(Measured::Unit.new(:m), :/, Measured::Unit.new(:s)) #=> #<Measured::DerivedUnit :"m/s">
Measured::DerivedUnit.new(Measured::Unit.new(:m), :*, Measured::Unit.new(:m)) #=> #<Measured::DerivedUnit :"m^2">

Velocity = Measured::DerivedUnit.new(Measured::Unit.new(:m), :/, Measured::Unit.new(:s))
Acceleration = Measured::DerivedUnit.new(Velocity, :/, Measured::Unit.new(:s))
Force = Measured::DerivedUnit.new(Measured::Unit.new(:kg), :*, Acceleration)

You may be able to go from there to defining Area as Length*Length and both Speed and Velocity as Length/Time. You might then want to go back and provide them as first-class citizens again by pre-deriving units, explicitly stating that N=kg*m/s/s somehow.

I did something similar to this strategy here: https://github.com/saraid/units/blob/main/lib/units/derived_unit.rb but I wasn't considering performance, so I'm sure it wins no awards there. (This was some fairly hacky experimentation I did; I might take some time to clean it up and make it a real gem with tests and stuff at some point.)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants