All connected components

Hi friends,

I’m trying to search for all entities connected to an entity.
Basically, I have a wire connected to 2 components. I want to go through all wires and get the name of these 2 components.

Something like below but with the following piece of code:

if c == 'wire'
    connected_components = c.all_connected
    cp1 = connected_components[0].name
    cp2 = connected_components[1].name
end
model = Sketchup.active_model()
entities= model.entities
groups = entities.grep(Sketchup::ComponentInstance).find_all
circuitos = ["plug","light","wire"]
for c in circuitos
  count = 0
  puts c
  for e in groups 
    if (c == e.name.to_s)
      new_name = e.name.to_s + '_' + count.to_s
      e.name = new_name
      count += 1
      puts count, new_name
    end
  end 
end

I will appreciate any help.

-Cheers

Thanks for formatting your code nicely, that is a skill!


  • The conditional block’s body is only run when c equals the string "wire". But a string won’t accept the method all_connected.
  • The method all_connected returns entities (edges and faces to be precise). Since the term “components” is used within the API (not reserved, but it can cause confusion), you should better name your variable to what it actually is, like connected_entities.

Apart from that, I don’t know exactly what your question is. For each string in circuitos, the code iterates over all components and sets a unique name, but returns nothing. Do you have references/variables of the two components of which you want to get the name?

1 Like

Thank you Aerillius for your concerns.

I rewrote the code below to make me clear.
I agree that I was mixing two goals in this code than I just left the lines I need to get the wire’s information:

model = Sketchup.active_model()
ents= model.entities
wires = ents.find_all {|ent| ent.is_a?(Sketchup::ComponentInstance) && ent.layer=="wire"}
count = 0
for w in wires
    count += 1
    wire_name = 'wire_' + count.to_s                              # create the wire name
    connected_entities = w.all_connected                      # get the connected entities
    start_point = w.start_point                                         # start_point  
    end_point = w.end_point                                           # end_point  
    cp1 = connected_components[0].name                    # first connected entity cp1
    cp2 = connected_components[1].name                    # second connected entity cp2
    puts wire_name, start_point, end_point, cp1, cp2    # print the information out
end

I want to generate a table with this header:

wire_name | start(x,y,z) | end(x,y,z) | cp1_name | cp2_name

for all wires in a specific layer called “wire”

What kind of object is a “wire” in your model? That will affect what you can do with it. For example, #all_connected is defined only for Edges and Faces. Unless c is an Edge or Face, you will get a method not defined error.

In your model, what constitutes “connected to”? That is, when you draw one of your circuits, what do you do that means the wire is connected to something? Note that because a ComponentInstance or a Group by its nature isolates its contents, even if a “wire” is an Edge, #all_connected will never return either a CI or a Group, nor will it find any Edge or Face within a different Component or Group than the Edge or Face you invoked all_connected on.

When you do entities.grep(Sketchup::ComponentInstance) you name the result “groups”. This is just a name, but I hope you realize that a Group is not a ComponentInstance in the Ruby API despite technically sharing the same underpinnings! That grep will not return any Groups.

#find_all requires a code block that returns true/false to tell the Enumerable (here an Array returned by #grep) which objects to keep. This might be where you could select the CI’s that have connections, but not knowing what “connections” means I can’t suggest code to do it.

As @Aerilius noted, your code is renaming things, but it isn’t clear what use that will be. Maybe just to help you see the structure in the outliner? What if more than one “wire” connects to the same ComponentInstance?

As a picky point, any object in the SketchUp Ruby API that supports #name returns a String from that method. There is no need to apply to_s to something that is already a String. On the other hand, count is a number, so it will need the conversion. It would be more efficient to build the new name as

new_name = "#{e.name}_#{count}"

Edit: I wrote this before your revised code. I have to do other things now, but will look at this again later.

You may be interested in this plugin that allows snap points to be added to SketchUp components.
(It is not free. There is a fee. I have no interest in this product.) …

https://extensions.sketchup.com/en/content/snap-connector

I’m wondering if there is a conceptual problem with your understanding of how SketchUp works (I offer this as a theory, and won’t be insulted if you tell me I am completely off the mark).

Your process suggests to me that you may be thinking that SketchUp operates like a 2D diagramming tool, in that “snapping” one object to another results in them being “connected”. In general, that isn’t what SketchUp does, and if I am right you will need to rethink how you are going about the entire process (though maybe the extension @DanRathbun mentioned could help - I have never seen or used it).

In SketchUp, “connected” means “touching” or “sharing” in the sense that Edges use the same endpoints, Faces use Edges to define their perimeter, and Faces share an Edge between them. Whenever possible, SketchUp automatically causes new Edges or Faces to share whatever they can with pre-existing Edges and Faces. This intentional behavior is what causes SketchUp’s geometry to “stick” together and to intersect.

SketchUp’s Groups and Components exist for the purpose of breaking up this “stickiness”. The model and each Group or Component creates a separate editing “context” (technically an Entities collection). Each context is completely independent and can’t share anything with any other context. It is crucial to understand that “colocated” means “connected” only within a single context. For example, an Edge in one Group can’t share an endpoint with an Edge in some other Group even if they are at the same location in the model.

The #all_connected method starts with an Edge or a Face and follows these sharing relationships recursively until it can find no more connected Edges or Faces in the same context. It will never find Groups or ComponentInstances or anything inside them because they can’t share with an outside Edge or Face.

What may cause confusion is that SketchUp’s Inference Engine provides “snap” points by which you can align one Entity with another. This behavior seems like snapping to a connection in a diagramming tool. The Inference Engine will find snaps to Edges and Faces in a different context. But in SketchUp these are just helpers that let you select a location in the model accurately based on other existing geometry. Any actual connection occurs only if the new Edge or Face comes to satisfy SketchUp’s notion of sharing based on its location and context, not because the action of snapping to an inference point was somehow remembered as a “connection”.

So, for example, you can snap some point in a “wire” ComponentInstance to some point on a “box” ComponentInstance, and they will draw as if connected. But if you then move either of them, the other will not follow along as it would in a diagramming tool because the “connection” is just coincidental “co-location”; there is no actual sharing of geometry taking place.

1 Like

Yes, I agree this is what it seems the OP wishes to accomplish.

I believe SketchUp is unsuited for 3D electrical connectivity because it has no “line” objects that can be used as wires or cables. It has edges only. Shoehorning edges or even guidelines into a “wire” or “cable” component creates more problems then it will solve.

I think this workflow needs to wait until LayOut gets a “live” API with components that have customizable attributes. Then we’ll be able to create Visio-like diagrams with wire run tables, etc.

1 Like

Thank you, both, for the explanation.

It make the question clear for me.

Thank you for share this extension.

There is an extension called OOB Electrical that makes something familiar with this.

Ok, let’s thinking in some workaround for that Sketchup feature. Is it possible to get the end and start point for each wire and for each component, explode then and search for the same position for those points?

If a “wire” is an edge or guideline, YES.

NO, components do NOT have a start and end point.
They have a transformation, which has an origin point, rotation and scale factors.

There should be no good reason to explode components or groups. This is destructive.

SketchUp does not have collision detection. Searching for entities in one geometric context sharing the same global coordinates can be done, but it is complex. It would likely be slow as well.

It could be made easier, if you use the snap point sub-components from the plugin I pointed to (above).
It would be much easier to look for “wires” that had vertices that ended at these “snap points”.

OK. Let’s move forward.

Maybe the easy way to create a Tool to draw the Line and getting the start and end position with onMouseMove?

Creating a custom line tool is just adding MORE complication. It’s not getting the endpoints of an edge that is complex. It is matching those endpoints to a component. (Components do not have terminals or plugs or jacks, that “wires” can be plugged into.)

And IF you do use a custom tool, you would get the points using mouse button click callbacks. See the example LineTool in the Example Ruby Scripts extension.