Displaying the volume of an object instantaneously during scaling

Hello,

Is there any way/extension that I can display the volume of a particular object instantaneously during resizing?

The object is solid and I can see its volume in the Entity Info panel when selecting the object after scaling (resizing) each time, but not DURING resizing. This object (let’s call A) is one of many components under object B. What I am looking for is the volume of object A when I change the size of its umbrella object (Object B).

I saw that Dimensions update instantaneously during scaling. Can the volume be displayed in the same way like that?

If the object is to be scaled uniformly about the three axis, you need first to calculate the volume scaling factor (VSF) using the actual volume (AV) and the final volume (FV) using this formula:

VSF = FV / AV

Then you can calculate the linear scale factor (LSF) by using the following formula:

LSF = Cube Root of VSF

Use the Scale Tool and scale uniformly, entering the LSF value obtained above.

For example, you have an object that is 50 cubic inches and you want to scale it to get 100 cubic inches.

The VSF is 100 / 50 = 2.

The LSF is cube root of 2 or 1.2599

Use 1.2599 with the Scale Tool.

Hello jean_lemire_1,
Thank you for the interesting information, but what I’m looking for is quite the other way around.

I would like to adjust the object’s size (maybe across 1,2, or 3 axes) by using mouse based on discussion and inputs from my team during a meeting. However, I would like the volume of the object to show in real time as I adjust the object. Is there any way to display the volume instantaneously as I drag my cursor to adjust the object?

The object A is a component. I assume that is the case.

The component A is one of many components under object B? Is object B a component or a group?

The component A is one of many components. Are all those components the same or varied?

You interchange the word object and component. Hard to understand what you are attempting.

rkleins thank you for pointing that out. I am sorry. I didn’t use the terms accurately.

The object A is a group within object B (an umbrella group).

I think the answer is No. When the object (group or component) is selected the volume is displayed. When you then select a face to Push/Pull the area of the face is displayed in Entity info. Push/Pull changes the same faces of identical named components in the same way.

If you select one of the identical components and apply “scale” only the scaled component changes.

I am not too familiar with components. I made a sample and tried various methods.

I’ll change my answer to No/ maybe.

Edit, I posted this at the same time VN2 posted his clarification.

I’m not aware of an extension that displays the volume as you scale an object, but there is Scale 2 Volume that will help you adjust the size of objects to match a particular volume. So if you and your colleagues have discussed making something a specific volume, this allows you to do that.

2 Likes

Of course, it is possible using Ruby (an extension). However, the concept snippets below is a bit kind of hacking and uncomfortable - need to be tuned more… but does the task, if I understood right… :slight_smile:
After copy-paste the code below to Ruby console You can select one single, solid object to examine its volume during scaling itself or the containing object…

If you right click on a single, solid object and no other object selected there will be a context menu: “Show Instant volume”. You can start showing its volume “instantly” at a Status Bar by clicking on this menu.
(The format of the volume displayed is depends on a setting in Window>>Model Info>>Units )

Actually, the code is refreshing the value at every 0,3 sec, but if the curent Tool also displaying something at a Status Bar, then it will blink alternately… (That is one reason I call it "uncomfortable " and concept…)

You can stop showing this volume by right click on some object and select the context menu: “Stop showing Instant volume”, or it will stop after 5 minutes itself.
Then you can select an other single, solid object to examine its volume during scaling itself or the containing object…

Click here to see the code: No warranties! Use it at your own risk!

No warranties! Use it at your own risk!

Copy-paste the code below to Ruby Console and hit Return (Enter).

module Dezmo
module InstantVolumes
  @@loaded = false unless defined?(@@loaded)
  @@runing = false unless defined?(@@runing)
  extend self
    
  def update_volume( instance_path )
    instance = instance_path.last
    @@runing = true
    @note_timer = UI.start_timer(0.3, true){
      if instance.valid? 
        vol = calculate_volume( instance_path )
        Sketchup.status_text = Sketchup.format_volume( vol )
      else
        stop()
      end
    }
  end
  
  def stop()
    UI.stop_timer(@note_timer) if @note_timer
    @@runing = false
    puts "InstantVolumes stopped"
  end
  
  def start(instance_path)
    puts "InstantVolumes started"
    update_volume( instance_path )
    # Limit to run for 5 minutes:
    UI.start_timer(300, false){
      stop()
    }
  end

  def instance?(e)
    e.is_a?(Sketchup::Group) || e.is_a?(Sketchup::ComponentInstance)
  end
  
  def valid_solid( sel = Sketchup.active_model.selection )
    return false if sel.empty?
    return false unless sel.single_object?
    return false unless instance?( sel.first )
    return false unless sel.first.manifold?
    active_path = Sketchup.active_model.active_path
    if active_path
      return active_path.to_a<<sel.first
    else
      return [sel.first]
    end
  end
  
  ## Credit to Christina Eneroth
  #https://forums.sketchup.com/t/how-do-you-reliably-get-a-group-component-instances-volume/173349/4?u
  def calculate_volume(instance_path)
    leaf_instance = instance_path.to_a.last
    parents = instance_path.to_a[0..-2]
    parent_transformation = parents.map(&:transformation).inject(IDENTITY, :*)
    leaf_instance.volume * determinant(parent_transformation)
  end

  def determinant(transformation)
    xaxis(transformation) % (yaxis(transformation) * zaxis(transformation))
  end

  def xaxis(transformation)
    v = Geom::Vector3d.new(transformation.to_a.values_at(0..2))
    v.length /= transformation.to_a[15]
    v
  end

  def yaxis(transformation)
    v = Geom::Vector3d.new(transformation.to_a.values_at(4..6))
    v.length /= transformation.to_a[15]
    v
  end

  def zaxis(transformation)
    v = Geom::Vector3d.new(transformation.to_a.values_at(8..10))
    v.length /= transformation.to_a[15]
    v
  end
  ##############################

  unless @@loaded
    cmd1 = UI::Command.new("Show Instant volume"){
      start( valid_solid() )
    }
    cmd2 = UI::Command.new("Stop showing Instant volume"){
      stop()
    }
    tip = "Display the volume of the selected solid instance during modification"
    cmd1.tooltip = tip
    cmd1.status_bar_text = tip
    UI.add_context_menu_handler{|context_menu|
      context_menu.add_item( cmd1 ) if valid_solid() && !@@runing
      context_menu.add_item( cmd2 ) if @@runing
    }
    @@loaded = true
  end
end# module Dezmo
end# module InstantVolume

Dezmo_InstantVolume

4 Likes

Thank you, @Box. That would be helpful. If we need to specify a particular volume, we will try that.

Thank you so much, @dezmo!!! This is very promising and very similar to what we are looking for. We will try that.

You are welcome!


This version might be a little more “spectacular”… and can handle more solids at once.
Now there will be a “normal” menu under Extensions to toggle on-off the instant volumes: “Show Instant volumes” (When it is on there will be a checkmark.)

You need to put text label “vol” or “Vol” at the root of the model pointing to the solid(s) in question. There will be a warning if there are no such… These labels will show the volumes dynamically when you start to Show Instant volumes and e.g. scaling.

After 5 minutes there will be a warning (only once) to not forget to switch off…(otherwise it takes up resources constantly, not much but still…)
But will not switch off itself, unless you deleted the label(s) or the solid(s) which was taken into consideration when you activated.

If you switch off, the labels will remain to show the last volumes. So if you want to activate again you need to rename these labels to “Vol” again…

Dezmo_InstantVolumeB

.
.

Click here to see the code (B): No warranties! Use it at your own risk!

No warranties! Use it at your own risk!

Copy-paste the code below to Ruby Console and hit Return (Enter).

module Dezmo
module InstantVolumesB
  @@loaded = false unless defined?(@@loaded)
  @@runing = false unless defined?(@@runing)
  extend self
    
  def update_volume( texts )
    return if @@runing
    @@runing = true
    @note_timer = UI.start_timer(0.3, true){
      count = 0
      to_delete = []
      texts.each{|text, path|
        if path.last.valid? && text.valid?
          vol = calculate_volume( path )
          text.set_text( Sketchup.format_volume( vol ) )
          count += 1
        else
          to_delete<<text
        end
      }
      Sketchup.active_model.active_view.invalidate
      to_delete.each{ |k| texts.delete(k) }
      puts "Error finding label or solid!" if count == 0
      stop() if texts.empty?
    }
  end
  
  def stop()
    UI.stop_timer(@note_timer) if @note_timer
    @@runing = false
    puts "InstantVolumes stopped"
  end
  
  def start_stop()
    return stop() if @@runing
    texts = valid_labels()
    if texts.empty?
      UI.messagebox('Please label solids with "Vol" at root of the model.', MB_OK)
    else
      puts "InstantVolumes started"
      update_volume( texts )
      # Warning if run for 5 minutes:
      UI.start_timer(300, false){
        if @@runing
          UI.messagebox(
            'Please dont forget to turn off Showing Instant volumes.', 
            MB_OK
          )
        end
      }
    end
  end

  def instance?(e)
    e.is_a?(Sketchup::Group) || e.is_a?(Sketchup::ComponentInstance)
  end
  
  def valid_labels()
    texts = {}
    Sketchup.active_model.entities.select{|ent| 
      ent.is_a?( Sketchup::Text ) &&
      (ent.text == "Vol" || ent.text == "vol") &&
      ent.attached_to &&
      (ent.attached_to[0].to_a[-2].is_a?(Sketchup::Group) ||
       ent.attached_to[0].to_a[-2].is_a?(Sketchup::ComponentInstance) ) &&
      ent.attached_to[0].to_a[-2].manifold?
    }.each{|text| 
      texts[text] = text.attached_to[0].to_a[0..-2]
    }
    texts
  end
  
  ##############################
  ## Credit to Christina Eneroth
  #https://forums.sketchup.com/t/how-do-you-reliably-get-a-group-component-instances-volume/173349/4?u
  def calculate_volume(instance_path)
    leaf_instance = instance_path.to_a.last
    parents = instance_path.to_a[0..-2]
    parent_transformation = parents.map(&:transformation).inject(IDENTITY, :*)
    leaf_instance.volume * determinant(parent_transformation)
  end

  def determinant(transformation)
    xaxis(transformation) % (yaxis(transformation) * zaxis(transformation))
  end

  def xaxis(transformation)
    v = Geom::Vector3d.new(transformation.to_a.values_at(0..2))
    v.length /= transformation.to_a[15]
    v
  end

  def yaxis(transformation)
    v = Geom::Vector3d.new(transformation.to_a.values_at(4..6))
    v.length /= transformation.to_a[15]
    v
  end

  def zaxis(transformation)
    v = Geom::Vector3d.new(transformation.to_a.values_at(8..10))
    v.length /= transformation.to_a[15]
    v
  end
  ##############################

  unless @@loaded
    cmd1 = UI::Command.new("Show Instant volumes"){
      start_stop()
    }
    tip = 'Display the volume of the "Vol" labeled solid instances during modification'
    cmd1.tooltip = tip
    cmd1.status_bar_text = tip
    cmd1.set_validation_proc{
      @@runing ? MF_CHECKED : MF_UNCHECKED
    }
    UI.menu("Plugin").add_item cmd1
    @@loaded = true
  end
end# module Dezmo
end# module InstantVolume

.
That’s it for today. :innocent:

4 Likes

@dezmo Wow, this is awesome. Thank you so much. It is greatly helpful.