# Changing component boundingbox rotation axes

**URL:** <https://forums.sketchup.com/t/changing-component-boundingbox-rotation-axes/203485>\
**Category:** Ruby API\
**Created:** [July 16, 2022, 4:46pm UTC](https://forums.sketchup.com/t/changing-component-boundingbox-rotation-axes/203485 "2022-07-16T16:46:01Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![rtches](https://sea2.discourse-cdn.com/sketchup/user_avatar/forums.sketchup.com/rtches/32/131827_2.png) [@rtches](https://forums.sketchup.com/u/rtches)\
**Post date:** [July 16, 2022, 4:46pm UTC](https://forums.sketchup.com/t/changing-component-boundingbox-rotation-axes/203485/1 "2022-07-16T16:46:01Z")

</div>

Is there a simple way to change component axis rotation in ruby? It’s very simple in sketchup but I need to do that in order to retrieve the right dimensions of the wall with ruby.  
I have read and trying a lot but nothing works  
 ![rotate component axis](https://global.discourse-cdn.com/sketchup/original/3X/0/f/0fe4da03e94f476d313b4d371afedcfbc455a382.jpeg)

---

<div class="post-metadata">

**Author:** ![dezmo](https://sea2.discourse-cdn.com/sketchup/user_avatar/forums.sketchup.com/dezmo/32/51058_2.png) [@dezmo](https://forums.sketchup.com/u/dezmo)\
**Post date:** [July 17, 2022, 7:22am UTC](https://forums.sketchup.com/t/changing-component-boundingbox-rotation-axes/203485/2 "2022-07-17T07:22:51Z")

</div>

> [@rtches](#):
>
> It’s very simple in sketchup…

One “_very simple_” method to do it involving 4 times interaction of the USER:

- Right click on a desired component to select Change Axes
- Pick point for origin of axes
- Pick direction for red axis
- Pick direction for green axis

Actually you need to write a methods to determine the object, a point and at least two axes in a question.  
Then you have to create a [transformation](https://ruby.sketchup.com/Geom/Transformation.html) and apply to the object then apply the inverse of this transformation to the object entities.

Perhaps you can start to check this:

> **[GitHub - thomthom/axes-tools: Tools for manipulating component and group axes...](https://github.com/thomthom/axes-tools)**
>
> Tools for manipulating component and group axes in SketchUp. - GitHub - thomthom/axes-tools: Tools for manipulating component and group axes in SketchUp.

.

* * *

.  
Also, you can check if this one already fulfills your needs:  
[s4u-reset-axis](https://extensions.sketchup.com/extension/76f3a41e-6883-417a-95af-1b699bc8fe05/s4u-reset-axis)  
(Be careful because the developer is lying about the price of this extension on EWH)

---

<div class="post-metadata">

**Author:** ![rtches](https://sea2.discourse-cdn.com/sketchup/user_avatar/forums.sketchup.com/rtches/32/131827_2.png) [@rtches](https://forums.sketchup.com/u/rtches)\
**Post date:** [July 17, 2022, 6:28pm UTC](https://forums.sketchup.com/t/changing-component-boundingbox-rotation-axes/203485/3 "2022-07-17T18:28:55Z")

</div>

thanks @dezmo

> [@dezmo](#):
>
> Actually you need to write a methods to determine the object, a point and at least two axes in a question.  
> Then you have to create a [transformation](https://ruby.sketchup.com/Geom/Transformation.html) and apply to the object then apply the inverse of this transformation to the object entities.

¿I did the first part but how can I aply the inverse to the object entiies?

```rb
a = Sketchup.active_model.selection[0]
targetPoint = a.bounds.center
vector = Geom::Vector3d.new(0,0,1)
degreesToRotate = 45.degrees
t=Geom::Transformation.rotation(targetPoint,vector,degreesToRotate)
a.transform!(t)

```

this doesn’t works

```rb
for ent in a.definition.entities
	a.transform!(t.inverse)
end
``
```

---

<div class="post-metadata">

**Author:** ![dezmo](https://sea2.discourse-cdn.com/sketchup/user_avatar/forums.sketchup.com/dezmo/32/51058_2.png) [@dezmo](https://forums.sketchup.com/u/dezmo)\
**Post date:** [July 17, 2022, 6:40pm UTC](https://forums.sketchup.com/t/changing-component-boundingbox-rotation-axes/203485/4 "2022-07-17T18:40:34Z")

</div>

> [@Flickering faces import IFC due to component axes](https://forums.sketchup.com/t/flickering-faces-import-ifc-due-to-component-axes/182160/20):
>
> A quick one…not really tested, but it looks like is O.K innocent No guarantee! Use your own risk! Backup, Backup… Follow the animation: Select the desired components, groups or everything (Ctrl+A) Open Ruby Console Copy-Paste the code from below into Ruby Console Hit Enter (Return) The axis origin of selected components, groups will set to its bound left front bottom corner. Including all nested… You can Undo it. [Dezmo\_reset\_axes] module Dezmo module Reset\_Axes extend self …

---

<div class="post-metadata">

**Author:** ![rtches](https://sea2.discourse-cdn.com/sketchup/user_avatar/forums.sketchup.com/rtches/32/131827_2.png) [@rtches](https://forums.sketchup.com/u/rtches)\
**Post date:** [July 17, 2022, 7:18pm UTC](https://forums.sketchup.com/t/changing-component-boundingbox-rotation-axes/203485/5 "2022-07-17T19:18:33Z")

</div>

Thanks a lot @dezmo I’m sure it will helps me.

---

<div class="post-metadata">

**Author:** ![DanRathbun](https://sea2.discourse-cdn.com/sketchup/user_avatar/forums.sketchup.com/danrathbun/32/500_2.png) [@DanRathbun](https://forums.sketchup.com/u/DanRathbun)\
**Post date:** [July 17, 2022, 11:39pm UTC](https://forums.sketchup.com/t/changing-component-boundingbox-rotation-axes/203485/6 "2022-07-17T23:39:35Z")

</div>

@rtches Here is an example modified from @thomthom’s Skippy library  
(which is used by the his Axes Tools.)

I modified it to try to determine what the new origin and 3 axis should be.  
Test fully and modify further as needed.

Here is a test model:  
[instance\_axes\_reset.skp](https://forums.sketchup.com/uploads/short-url/b3eiTS7iLuLz7LS2fZXM8SNYVkU.skp) (21.7 KB)

```ruby
module SomeAuthor::SomePlugin

  extend self

  def reset_axes(
      instance = Sketchup.active_model.selection.first
    )
    return nil unless instance && instance.respond_to?(:definition)
    model = instance.model
    definition = instance.definition
    # Get a new axes for the instance's definition:
    new_axes = get_new_axes(definition)
    # Adjust all the definition's entities to the new internal axes:
    model.start_operation("Adjust Axes", true)
    ###
      # Transform all of the definition's entities to the new axes:
      definition.entities.transform_entities(
        new_axes.inverse,
        definition.entities.to_a
      )
      # Adjust the instance transformations:
      definition.instances.each do |instance|
        instance.transformation *= new_axes
      end
      #
    ###
    model.commit_operation
    return instance
  end

  def get_new_axes(definition)
    entities = definition.entities
    edges = entities.grep(Sketchup::Edge)
    pts = edges.flat_map(&:vertices).uniq.map(&:position)
    # Determine a new origin point for the new axes:
    origin = get_new_origin(pts)
    # Determine a new axes for the entities based upon edges
    # that use the vertex at the new origin point.
    edges.keep_if do |e|
      e.vertices.any? {|v| v.position == origin }
    end
    # Map the edges to the points of their other vertex:
    pts = edges.map do |e|
      e.other_vertex(
        e.vertices.find {|v| v.position == origin }
      ).position
    end
    # Now map those pts to normalized vectors along the edges:
    vecs = pts.map {|pt| origin.vector_to(pt).normalize }
    # Get an array of offset points from the normalized vectors:
    pts = vecs.map {|vec| origin.offset(vec) }
    # Sort by the z value:
    pts.sort! {|a,b| a.z <=> b.z }
    # Keep the 2 vectors with the smallest z values:
    vecs.keep_if {|vec| pts[0..1].include?(origin.offset(vec)) }
    # Sort these 2 vectors by their angle to the X_AXIS:
    vecs.sort! {|a,b| a.angle_between(X_AXIS) <=> b.angle_between(X_AXIS) }
    # The first vector in the sorted array will use as xaxis:
    xaxis = vecs.first
    # The zaxis will be a vector perpendicular to both other vectors.
    # We use the cross product to find it:
    zaxis = xaxis.cross(vecs[1])
    # We do not know if vecs[1] is perpendicular in the XY plane to
    # the xaxis. (Ie, the edges found may not be at right angles.)
    # So we again produce another perpendicular vector by cross product:
    yaxis = zaxis.cross(xaxis)
    return Geom::Transformation::axes(origin, xaxis, yaxis, zaxis)
  end

  def get_new_origin(pts)
    # Sort by the z value:
    pts.sort! {|a,b| a.z <=> b.z }
    # Keep only those whose z value is minimal:
    z_min = pts.first.z
    pts.keep_if {|pt| pt.z == z_min }
    # Look for the point closest to X_AXIS (with smallest y value):
    # Sort by the y value:
    pts.sort! {|a,b| a.y <=> b.y }
    y_min = pts[0].y
    # Keep only points whose y is minimum:
    pts.keep_if {|pt| pt.y == y_min }
    if pts.size == 1
      # Use it:
      pts.first
    else
      # There are duplicate points equidistant from X_AXIS, so
      # use the one furthest to the "right" with highest x value:
      pts.sort! {|a,b| a.x <=> b.x }
      pts.last
    end
  end

end # extension namespace module

```

---

<div class="post-metadata">

**Author:** ![rtches](https://sea2.discourse-cdn.com/sketchup/user_avatar/forums.sketchup.com/rtches/32/131827_2.png) [@rtches](https://forums.sketchup.com/u/rtches)\
**Post date:** [July 18, 2022, 6:57am UTC](https://forums.sketchup.com/t/changing-component-boundingbox-rotation-axes/203485/7 "2022-07-18T06:57:25Z")

</div>

@DanRathbun Brilliant!

My main goal is to make an extension that attach to the IFC classification of each element a PSet containing the quantity take off information as specified by Building SMART. When I collaborate with other teams their IFCs have such a PSet because Revit or Archicad add them but mine doesn’t.

Example with IfcWall  
[https://standards.buildingsmart.org/MVD/RELEASE/IFC4/ADD2\_TC1/RV1\_2/HTML/schema/ifcsharedbldgelements/lexical/ifcwall.htm](https://standards.buildingsmart.org/MVD/RELEASE/IFC4/ADD2_TC1/RV1_2/HTML/schema/ifcsharedbldgelements/lexical/ifcwall.htm)

 ![Captura de Pantalla 2022-07-18 a las 8.34.29](https://global.discourse-cdn.com/sketchup/original/3X/b/c/bc1b45620d6098ec61c1a6b6820f337a487de5b2.jpeg)

At the moment I have achieved this:  
What IFC Manager adds to the component:

 ![Captura de Pantalla 2022-07-18 a las 8.40.16](https://global.discourse-cdn.com/sketchup/original/3X/2/8/28be4e014203825ec8b07704326fb6bd25956509.jpeg)

What my pluging is adding now hence my aim to get the correct axes.  
 ![Captura de Pantalla 2022-07-18 a las 8.43.38](https://global.discourse-cdn.com/sketchup/original/3X/f/e/fe61933ccc2b134bf68e8bdeccb765ea68993d66.jpeg)

When I export the model to IFC that information goes with the model and IFC viewers (Bim Vision, Bim Collabs Zoom, Trimble Connect, etc) show them as properties.

Thanks again @DanRathbun also @dezmo and @thomthom for your contributions.

---

<div class="post-metadata">

**Author:** ![DanRathbun](https://sea2.discourse-cdn.com/sketchup/user_avatar/forums.sketchup.com/danrathbun/32/500_2.png) [@DanRathbun](https://forums.sketchup.com/u/DanRathbun)\
**Post date:** [July 18, 2022, 3:59pm UTC](https://forums.sketchup.com/t/changing-component-boundingbox-rotation-axes/203485/8 "2022-07-18T15:59:28Z")

</div>

Uh… huh. Thanks for the context (but it is a bit more information than is really needed for this specific topic.)

So just for a bit more advice, be aware of issues with getting the volume of scaled instances.

- See [API Tracker Issue 692 : **Volume calculation**](https://github.com/SketchUp/api-issue-tracker/issues/692)

To discuss volume further, respond in topic:  
[How do you reliably get a group/component instances volume?](https://forums.sketchup.com/t/how-do-you-reliably-get-a-group-component-instances-volume/173349)

---

<div class="post-metadata">

**Author:** ![rtches](https://sea2.discourse-cdn.com/sketchup/user_avatar/forums.sketchup.com/rtches/32/131827_2.png) [@rtches](https://forums.sketchup.com/u/rtches)\
**Post date:** [July 18, 2022, 5:49pm UTC](https://forums.sketchup.com/t/changing-component-boundingbox-rotation-axes/203485/9 "2022-07-18T17:49:08Z")

</div>

Thanks @DanRathbun I suffered it but in order to export to IFC I try to simplify geometry before.
