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
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?
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
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.) …
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.
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.
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?
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”.
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.