[Code] format volume in model units

Continuing the discussion from Since SU2017 exploding a group replaces all entities:

Scenario: Given a numeric value of cubic inches, … get a formatted string of volume in model units.


(Note, Version 1, previously posted in another thread, was a “cutsie” one-liner that failed.)


VERSION 2

Barebones but might fail if the "SuppressUnitsDisplay" switch is true.
(See discussion and Version 3, below.)

(Click to show Version 2) ...
# format_volume_in_model_units( volume, spacing, precision )
#
# @param volume [Numeric] The volume in cubic inches.
# @param spacing [Integer] The spaces before unit symbol. (Default=0)
# @param precision [Integer] The numbers shown after decimal point.
#   Defaults to the current model units precision (Range 0..6). Allows higher.
# @return [String] The volume in cubic model units.
def format_volume_in_model_units(
  volume,
  spacing = 0,
  precision = Sketchup::active_model.options['UnitsOptions']['LengthPrecision']
)
  inch_side = Math::cbrt(volume)
  unit_side = Sketchup::format_length(inch_side).to_f
  unit_vol  = unit_side**3
  unit = Sketchup::format_length(1.0).split(/~?\s*\d+\.?\d*/).last
  unit = 'in' if unit == '"'       
  unit = 'ft' if unit == "'"
  "%.#{precision}f%s%s³" % [ unit_vol, ' '*spacing, unit ]
end

VERSION 3

Incorporating some modifications discussed below by Christina

(Click to show Version 3) ...
# format_volume_in_model_units( volume, spacing, precision )
#
# @param volume [Numeric] The volume in cubic inches.
# @param hideunit [Boolean] Whether to hide the unit symbols, or not.
#   Defaults to the current model units "SuppressUnitsDisplay" switch.
# @param spacing [Integer] The spaces before unit symbol. (Default=0)
# @param precision [Integer] The numbers shown after decimal point.
#   Defaults to the current model units precision (Range 0..6). Allows higher.
# @return [String] The volume in cubic model units.
def format_volume_in_model_units(
  volume,
  hideunit = Sketchup::active_model.options['UnitsOptions']['SuppressUnitsDisplay'],
  spacing  = 0,
  precision = Sketchup::active_model.options['UnitsOptions']['LengthPrecision']
)
  inch_side = Math::cbrt(volume)
  unit_side = Sketchup::format_length(inch_side).to_f
  unit_vol  = unit_side**3
  if hideunit
    "%.#{precision}f" % unit_vol
  else
    i = Sketchup::active_model.options['UnitsOptions']['LengthUnit']
    unit = ['in','ft','mm','cm','m'][i]
    "%.#{precision}f%s%s³" % [ unit_vol, ' '*spacing, unit ]
  end
end

VERSION 4

  1. Fixed the "~ " prefix bug that fools String#to_f.
    (Core Ruby method that fails silently if string does not begin with numeral characters.)

  2. Moved precision to be 2nd argument (as it’s likely to be the most used optional parameter.)

  3. Simplified spacing argument to expect Boolean. (If a number is passed 0 will be taken as false, anything else will be evaluated in the Ruby conditional way, so any other number will be true.)
    !
    There are now only no space (SketchUp’s mode) or one space choices.
    I decided simplicity is best, and that a report column output format can be done in a subsequent call.
    The output from this method (using 1 space,) can be split into an array of two strings, and this array used as the argument to String#%, ie:

# To right-justify the volume into a 12 character column,
#  followed by the unit right-justified in a 7 wide column:
str = format_volume_in_model_units( volume, 6, false, true )
"%12s%7s" % str.split

In actual use, report values would be stored in an array of arrays, etc. and output in a formatting loop.

Here is version 4 …

# format_volume_in_model_units( volume, precision, hideunit, spacing )
#
# @param volume [Numeric] The volume in cubic inches.
# @param precision [Integer] The numbers shown after decimal point.
#   Defaults to the current model units precision (Range 0..6). Allows higher.
# @param hideunit [Boolean] Whether to hide the unit symbols, or not.
#   Defaults to the current model units "SuppressUnitsDisplay" switch.
# @param spacing [Boolean] Whether a space before unit symbol (Default=false).
#
# @return [String] The volume in cubic model units.
def format_volume_in_model_units(
  volume,
  precision = Sketchup::active_model.options['UnitsOptions']['LengthPrecision'],
  hideunit = Sketchup::active_model.options['UnitsOptions']['SuppressUnitsDisplay'],
  spacing  = false
)
  inch_side = Math::cbrt(volume)
  unit_side = Sketchup::format_length(inch_side).delete('~').lstrip.to_f
  unit_vol  = unit_side**3
  if hideunit
    "%.#{precision}f" % unit_vol
  else
    spacing = false if spacing == 0
    i = Sketchup::active_model.options['UnitsOptions']['LengthUnit']
    unit = ['in','ft','mm','cm','m'][i]
    if spacing
      "%.#{precision}f %s³" % [ unit_vol, unit ]
    else
      "%.#{precision}f%s³" % [ unit_vol, unit ]
    end
  end
end
2 Likes

When the user has un-ticked Display Unit Format in Model Info > Units this code is unable access the length unit string representation. On my system it returns the decimal separator “,” instead.

One solution could be to just hard code strings for all units and rely on [“UnitsOptions”][“LengthUnit”] but that would be (somewhat) language dependent.

Another solution would be to change [“UnitsOptions”][“SuppressUnitsDisplay”] to false before getting the string and then change it back. This action does not save to the undo stack.

1 Like

I knew someone would suggest this. I was rushed because my first posting was flawed (… I tried to get “cute” and do a one-liner.) Anyhow, I did have a literal hash in their but removed it and replaced with a couple of if statements.

Hmmm,… perhaps a literal lookup hash or array makes more sense ?

Posting a 3rd version above …

Next question.

Are the order of arguments what you’d expect ?
Ie, does the order make sense ?
The goal should be to have the 2nd arg be the one most overridden and so forth …

@tt_su, So, do SketchUp non-English editions use translated unit symbols ?

@eneroth3, Do you see “tum” instead of “in” in the Swedish edition ?

Playing around with Bing Translator and Japanese I find:

'in' => 'インチ',
'ft' => 'フィート',
'mm' => 'ミリメートル',
'cm' => 'センチメートル',
'm' => 'メートル',

… however, each also shows the alternate translation is just the latin abbreviation.

To deal with unit translations, a support mixin module would most likely be a better idea.

That’s a good question: are the abbreviations for units standardized along with the units themselves? If so, there should not be a need to translate!

I thought that the SI standard at least encouraged everyone to use the latin abbreviations.

1 Like

That’s what I thought too, but I was too lazy to look it up :wink:

Well I did not either. I just “thinking out loud”.

However, it seems clear from playing with the translator(s) that the imperial units inch and feet, do vary per language.

AND, … I found another bug.

If Sketchup::format_length produces a string beginning "~ " then String#to_f fails …

us = "~ 34.56m".to_f
#=> 0.0

Ah yes! Lost some hair dealing with that one in an extension I wrote!

I don’t know how often the spaces argument would be used. If I’m not mistaking the SI standard also states there should be a single space between the number and the unit, except for degrees, minutes and seconds (angular). However SU do not do this.

1 Like

Yes, I tried to follow what SketchUp does, even if it’s wrong. (I prefer the space.)

I put spacing to follow hideunit because if hideunit is set false, spacing is moot.

I think that precision is the one most likely to be changed per preference or for special formatting output. It is sometimes a pain to have to change the model unit settings just to get the output one desires.
So, it seems to make most sense that the ordered args are: ( precision, hideunit, spacing )

Agree.

By the way, a thousand separator would make large numbers way easier to read. With mm being the modeling unit 5 m^3 would be written as 5 000 000 000 mm^3. As a user you could just ignore the last 3 digit groups.

When comma is used as decimal separator a space is used as delimiter. Historically it was a dot though (same as some countries uses for decimal separator). When dot is used as decimal separator comma seems to be heavily used as thousand separator which can cause much confusion. I.e. does 1,500 mean 1,5 or 1 500?

I didn’t know before but it seem the international standars prohibit both comma and dot as thousand separators which is good news for avoiding any confusion.

The 22nd General Conference on Weights and Measures declared in 2003 that “the symbol for the decimal marker shall be either the point on the line or the comma on the line”. It further reaffirmed that “numbers may be divided in groups of three in order to facilitate reading; neither dots nor commas are ever inserted in the spaces between groups”[14] (e.g. 1 000 000 000). This usage has therefore been recommended by technical organizations, such as the United States’ National Institute of Standards and Technology.

( source: Decimal separator - Wikipedia)

No confusion here in US, it’s one thousand five hundred.

Ruby has a way of using underscore as group separators.

Either I’ll need to follow what SketchUp does, or do it right and make all the format methods (length, area, volume, angle, … etc.)

It gets confusing as the exact same string means something completely different to other people while both “1 500,0” and “1 500.0” can be understood regardless of what format you are used to. I think some industries in USA even use comma as decimal separators but I’m not sure.

That said the ambiguity probably doesn’t become much of a problem when the number is printed locally on someone’s computer, but for e.g. web publishing it can be a real problem.

SketchUp doesn’t use any thousand delimiter but it has been requested numerous times.

1 Like

A big flaw with the Dynamic Components extension is that it relies on the unit abbreviations in Sketchup to determine its behaviour. If the user turns the units format display off in Model Info, it goes haywire and all units revert to inches. I don’t know anything about programming, but as SketchUp itself works OK with units display off, I would assume that it stores the current unit in some internal key. The same goes for the decimal separator.

1 Like

SketchUp works entirely with inches internally. The value is only converted to other units when printed to the user. For some reason DCs don’t adhere to this paradigm.

2 Likes

In the Swedish version “Tum” is used in the dropdown where units are selected but " is used when a length is printed.

2018-01-02_10h51_35

1 Like

This topic was automatically closed 91 days after the last reply. New replies are no longer allowed.