Ruby dimensions

The real issue is the inability to restrict the dimension to one of the cardinal planes. For example, I want to show the distance between two points in the Z direction only, even if the points do not have the same X or Y value. This is easy in the UI - it likes to “snap” a dimension to one of the cardinal planes. But it’s not possible with the API.

Oh, I understand what you mean now that you actually explained it.

But looking back up at the original thread, there are quite a number of different dimensioning issues discussed. Originally, this thread was about dimensioning to objects inside groups. So, my response to your recent post, was correctly answered against the original question of this thread.

The official API issue tracking is done at the GitHub tracker, as you well know as this is where you filed the request to enhance API definition of dimensions:

It is probably better to discuss this feature there, where you already asked the question that popped into my mind whether LayOut dimensions could do what you desire.


I know you’ve been waiting 6 years for this feature. There are features we’ve been waiting 16 years for.

Thanks, Dan. Yeah, I lost track of all the places things are tracked. I bumped the thread over there.

It’s nice that they’ve improved the API for making LinearDimensions, but I’m still seeing a problem: Entities#add_dimension_linear() does not appear to accept Sketchup::Groups in the InstancePath parameters I try to hand it; only Sketchup::ComponentInstances are allowed to be on the InstancePath. Since I cannot control whether an InstancePath in a given model includes Groups or not, I seem to be stuck…?

Like daiku, I want to make Dimensions programmatically but it seems to be nearly impossible, except at the most basic level.

I just did it with a group and it seems to work OK ?
A group is just another kind of instance of a definition ?
How are you constructing the code ?

I’m trying to write a tool that replicates the native Dimension tool (before going on to do something with the resulting dimension), and am having trouble with the Point3d values for the start and end points of the dimension.

All’s well if I’m dimensioning at the model level. I get the InstancePath and Point3d I need for the start and end of the dimension from my tool’s InputPoints and the dimension gets properly made. I’m using this command: @dimension = Sketchup.active_model.active_entities.add_dimension_linear(start_array, end_array, offset_vector).

But when I enter a group and use the tool inside the group, weird stuff happens. I can place the dimension properly, but when I exit the group, the dimension changes to show that its start and end points are out in space somewhere. It looks like it’s trying to use the global coordinates of the start and end points instead of the group’s local coordinates.

When I re-enter the group, the dimension again displays correctly, but the group’s bounding box is still way out there, where the dimension (erroneously) showed its start and end points to be when I was in the model context. It’s really weird that the dimension’s start and end points jump around like this instead of staying where I put them.

It looks like I’m not properly transforming from local to global coordinates, but when I try to transform the start and end Point3d values by Sketchup.active_model.edit_transform.inverse, I get this error: #<ArgumentError: Make sure the point is correctly transformed from local to global space.>. I do not get this error when I’m using the tool in model space.

So what am I missing here? Is there a better way to transform the InputPoints that works better with LinearDimensions, perhaps?

The word for today is transformation.

If you look at the examples in the API documentation, you’ll see that from the top-level (outside the group or component) you need to transform the points because they are inside a nested coordinate system.

HOWEVER, the API is written in a way that as the user drills down into nested edit contexts, points are returned by API methods and expected by API methods to be in world coordinates. I.e., the SketchUp core is already doing the transformation.

So be aware of these methods:

Sketchup::Model#active_path
Sketchup::Model#edit_transform

So in your tool …

# get the points for the dimension
if model.active_path.nil?
  # it's nil, at top level, so transform your points
end
# Otherwise non-nil, you are within some edit context, so
# the points returned should already be in world coordinates

* Note, if you are still choosing points in a context below the edit context, you’ll have to transform at least into that lower level.


Here is another nifty method to help in certain nested situations:

Sketchup::InstancePath#transformation

The problem isn’t with making the dimension correctly, it’s what happens after I close the group.

While I’m still inside the group, the dimension displays correctly, right where I placed it with my tool. But when I exit the group (click outside of it), the dimension “jumps” to the aforementioned weird start and end points. If I re-enter the group (double-click into it), the dimension jumps back to the correct coordinates.

Obviously, this doesn’t happen with native dimensions. They stay put whether you’re inside the group or not. So what gives?

Are you still using SU 2023 per your profile?

No, I’m on SU 26 now. Sorry, but I forget to update profiles often.

I think I’ve just figured out what I was doing wrong, and it has as much to do with InstancePaths as with coordinates and transformations.

My hypothesis is: I was adding my dimension to Sketchup.active_model.active_entities, when I really need to add it to the specific entities collection of the definition of the group or instance my dimension resides in. Using Model#active_path should allow me to find the correct entities to use.

The jumping behavior is probably because active_entities changes when I exit the group/instance, and Sketchup refreshes the dimension using the new (incorrect) context.

Let me chew on this for a day or two, then I’ll reply again “for the record” if I have the solution.

model.active_path.last.definition.entities == model.active_entities
#=> true

Yes, that’s pretty much what I did. Works fine now.