How to use Ruby API
-
OK, now I can locate components, their name, and groups. How do I use the API to get information of the faces within a component, or group?
module WMY_putdxf def WMY_putdxf.main #main proc . model = Sketchup.active_model # make db of active model entities = model.active_entities selection = model.selection # make db of selections if model.selection.empty? entities = model.active_entities else entities = model.selection end #endif entities.each do |e| # do loop through database and # place entities in type array if e.is_a? Sketchup;;ComponentInstance stuff= e.definition.name WMY_putdxf.get_faces(stuff) #call procedure/function end #endif end #end loop .
And:
def WMY_putdxf.get_faces (stuff)# procedure or method # UI.messagebox(stuff)# used this to test # if component instance is selected # How do I use API to get component's face info end
Btw, please advise if I have redundant coding:-), or if my qusetions don't make sense.
-
group.entities
component_instance.definition.entities
That will give you a collection of the entities they contain - like
model.entities
. -
OK, so now all I have to do is search the new collection for faces? Lets see if I can figure that out:-)
-
This makes a 'list' called faces of all of the faces inside the group...
faces=[] ### *** note how the list must be defined outside of the {...} block group.entities.each{|e|faces<<e if e.class==Sketchup;;Face}
This approach can be adjusted to suit any type of 'entities' list and any type of 'class' of thing you want to extract from it - faces, edges, cpoints, clines, text...
Then of course you can loop through you faces for say a particular material (or any other property)...red_faces=[] ### *** faces.each{|f|red_faces<<f if f.material.name=="Red"}
red_faces now contains all of the group's faces that are "Red" etc etc...
PS: Note that the
.entities
method returns all of the entities associated with the specified object - i.e. model/group/definition... There is another list of entities:model.active_entities
that applies to the current set of entities available in the present edit session - this could equivalent ot themodel.entities
or if you are editing a group or component-definition the available entities within that - e.g.group.entities
... -
OK, I put:
if e.is_a? Sketchup;;ComponentInstance name=e.definition.name#e.typename faces=e.definition.entities WMY_putdxf.get_faces(name,faces) end
And:
def WMY_putdxf.get_faces(name,faces)# procedure or method faces.each do |e| info = e.typename if e.is_a? Sketchup;;Face UI.messagebox(name+"; "+info) end #endif end #end do end #end method
So, you declare a array=[], but a collection (something like an array) makes itself?
OK, how do I make a collection of the geometric imformation inside each face so that I can access it later? Wild guess to start below:def WMY_putdxf.get_faces(name,faces)# procedure or method faces.each do |e| #why do we use e; can I use f? info = e.typename if e.is_a? Sketchup;;Face facegeo=e.something #get face geo collection goes here? end #endif end #end do end #end method
-
@honoluludesktop said:
OK, I put:
I USE CAPITALS FOR EASE OF READING ONLY !!!
> if e.is_a? Sketchup;;ComponentInstance > name=e.definition.name#e.typename### NAME IS THE 'NAME' - LIKE 'BED' TYPENAME IS THE CLASS/KIND_OF ETC > faces=e.definition.entities### THERE WILL BE MORE THAN FACES IN ENTITIES - AT LEAST EDGES TO FORM THE FACES > WMY_putdxf.get_faces(name,faces)### IF YOU WANT TO PASS THE DEFINITION THEN PASS E.DEFINITION NOT ITS 'NAME' > ### REMEMBER THAT 'FACES' IS 'ENTITIES' THAT WILL INCLUDE FACES BUT NOT JUST FACES ALONE... > end >
And:
> ### START DEF WITH lowercase LETTERS !!! wmy_putdxf etc > ### THIS GETS YOU NOTHING EXCEPT A MESSAGE LISTING THE DEF'S NAME AND EACH FACE IN TURN... > def WMY_putdxf.get_faces(name,faces)# procedure or method > faces.each do |e| > info = e.typename > if e.is_a? Sketchup;;Face > UI.messagebox(name+"; "+info) > end #endif > end #end do > end #end method >
So, you declare a array=[], but a collection (something like an array) makes itself?
AN ARRAY FACES=[] IS A LIST
OK, how do I make a collection of the geometric imformation inside each face so that I can access it later? Wild guess to start below:### REMEMBER THE lowercase LETTERS TA THE START > def WMY_putdxf.get_faces(name,faces)# procedure or method > faces.each do |e| #why do we use e; can I use f? ### CAN USE ANY VARIBALE 'E' IS OFTEN USED FOR 'EntitY' > info = e.typename > if e.is_a? Sketchup;;Face > > facegeo=e.something #get face geo collection goes here? > > end #endif > end #end do > end #end method >
HERE IS MY GET FACE VERSION...
if object.class==Sketchup;;ComponentInstance faces=[] object.definition.entities.each{|entity| faces<< entity if entity.class==Sketchup;;Face } ### now do stuff to these faces... end#if
Done with sub-defs or anything... Tests if the object is an Instance and if so make an Array [list] of its Definition's Entities' Faces to process...
-
Thanks guys. Will work on this later tonight after I get home. About the lowercase, if the def is inside a module, will it make a difference?
This runs ok on my system:
require 'sketchup.rb' module WMY_putdxf def WMY_putdxf.main model = Sketchup.active_model # make db of active model entities = model.active_entities selection = model.selection # make db of selections if model.selection.empty? entities = model.active_entities else entities = model.selection end # test if selection made entities.each do |e| # do loop through database and place entities in type array if e.is_a? Sketchup;;ComponentInstance #comp_file_name=e.definition.name name=e.definition.name#e.typename faces=e.definition.entities WMY_putdxf.get_faces(name,faces) end end end # .main method def WMY_putdxf.get_faces(name,faces)# procedure or method faces.each do |e| info = e.typename if e.is_a? Sketchup;;Face UI.messagebox(name+"; "+info) end #ednif end #end do end end # WMY_putdxf module #----------------menu------------------ if !file_loaded?(__FILE__) #_FILE_ permits renaming the file UI.menu("Plugins").add_item("Yet Another Test") { WMY_putdxf.main } end file_loaded(__FILE__)
But with WMY_ as wmy_ this error message:
Error Loading File yet_another_script.rb
C:/PROGRA~1/Google/GO2494~1/Plugins/yet_another_script.rb:3: class/module name must be CONSTANTSorry for the uneven indenting, when I copy from notepad++ and paste, the indent spacing changes.
-
module names always must start with a capital letter. methods do not start with a cap. Classes start with a cap. That is the basic rule. Constants are variables that start with a capital letter, and should remain constant - like Pi.
Chris
-
@chris fullmer said:
module names always must start with a capital letter. methods do not start with a cap. Classes start with a cap. That is the basic rule. Constants are variables that start with a capital letter, and should remain constant - like Pi.
Chris
Normal convention is to type constants in all caps.
-
Sorry for the confusion
- I didn't realise there was an enclosing module / class. They need initial CAPITAL letter; whereas defs and variables need lowercase. Consonants ion caps e.g. ORIGIN...
-
OK I am stuck again. Problem is with the last box of code below:
This is the main proc, methods below are at the bottom of the code in this section:
model = Sketchup.active_model entities = model.active_entities selection = model.selection if model.selection.empty? entities = model.active_entities else entities = model.selection end entities.each do |e| if e.is_a? Sketchup;;ComponentInstance the_name=e.definition.name stuff=e.definition.entities counter=0 faces=[] stuff.each do |e| if e.is_a? Sketchup;;Face counter=counter+1 faces.push e end ###if end ###loop points=[] add_face_vert_to_file(faces,points) make_comp_face_file(the_name,faces,counter,model,points) end ###if end ###loop
Method to make a collection of face.vertices
###make vertices file of faces in component def add_face_vert_to_file(faces,points) faces.each do |e| points.push e.vertices end ###end loop end
Method to make empty text file, then (where I fail) to take the face.vertices and copy them as string to the text file.
###create file ComponentName.txt def make_comp_face_file(the_name,faces,counter,model,points) the_line=the_name+" ",counter," faces" UI.messagebox(the_line) model_filename = File.basename(model.path) path=File.dirname(model.path)+"\\" out_name=the_name+".txt" out_path=path+out_name $mesh_file=File.new(out_path,"w") #HERE is problem code. How do I take the collection #of face.vertices and copy as strings to the text file. points.each do |e| $mesh_file.puts(e.x.to_s) $mesh_file.puts(e.y.to_s) $mesh_file.puts(e.z.to_s) end ###loop end
Am writing with the Web Console, and having some problems. Saving seems to drop characters, and the indents are gone. Any ideas?
-
points.each do |e| $mesh_file.puts(e.x.to_s) $mesh_file.puts(e.y.to_s) $mesh_file.puts(e.z.to_s) end ###loop
Adds x/y/z into file on separate lines...
to test if it's at least getting the points values use plain puts so it appears in the consolepoints.each do |e| puts(e.x.to_s) puts(e.y.to_s) puts(e.z.to_s) end ###loop
To write an xyz line use
points.each do |e| $mesh_file.puts(e.x.to_s+","+e.y.to_s+","+e.z.to_s) end ###loop
Does
$mesh_file=File.new(out_path,"w")
actually make the file ?
You need to open the file for writing AND then close it after you are done writing to it.$mesh_file.close
perhaps it's still open and so a second [separate] attempt to write to it fails...
-
@thomthom said:
Normal convention is to type constants in all caps.
Oh yeah! I rarely intialize them. Thanks Thom,
Chris
-
TIG, Just got up, and finished reading at your post. Thanks I think I understand, and have a lot to work with.
$mesh_file=File.new(out_path,"w")
Made a 0 byte file that I can see in "My Computer". I assumed it was open, guess it wasn't:-). Looks like a lot of stuff to work on later today. Good advice about using "puts" to check output. I use the messagebox a lot but that is slow.
puts(e.x.to_s) prints Sketchup::Vertex:0xea24668 ?-(, Crossed this bridge once before, but don't recall how to get output as a number.
-
puts(e.x.to_s) should return a numerical "x" position if e is a Point3d object. if e is a vertex, it should return an error. If e is a vertex, you can do e.position.x and that will return the x position of the vertex.
That sounded confusing to me. A few more lines of your code and I could give a slightly more complete example.
Great job so far!
Chris
-
"oops: - I"
A little slow this morning, didn't get it until now. Thanks guys, lets see how far I can get with what I have before I, OOPS:-(, need help getting off the floor. Might not take too long.
Tig, I can now open, write to, and close files:-)
Chris above here is where I stumbled on the code.
It occurred to me that a "method", a "function" in other languages (I missed this one), was in my day know as a "procedure", having evolved from a "[C}all". Before this I did a Basic "sub routine", itself born out of "jump xxxx:xxxx, where xxxx:xxxx began a set of instruction that ended in "return". Before "Buddha" it was all 1111's and 0000's
-
Help! How do I get a number that repersents the location of a face vertices? The following is setup for Web Console. When I output to UI.messagebox(e.vertices), I get:
#Sketchup::Vertex:0xfc83800#Sketchup::Vertex:0xfc837e8#Sketchup::Vertex:0xfc837d0
The main proc is at the bottom, and the methods are above it.
model = Sketchup.active_model entities = model.active_entities selection = model.selection ### Test is selection made if model.selection.empty? entities = model.active_entities else entities = model.selection end ###create file ComponentName.txt def make_comp_face_file(the_name,faces,counter,model) the_line=the_name+" ",counter," faces" UI.messagebox(the_line) model_filename = File.basename(model.path) path=File.dirname(model.path)+"\\" out_name=the_name+".txt" out_path=path+out_name end ###make vertices collection of faces in component def add_face_vertices_collect(faces,points) faces.each do |e| points.push e.outer_loop end ### loop end ###make 3dpoint from vertex HELP HERE!!!! I think def print_vertices_collect(points) points.each do |e| UI.messagebox(e.vertices) ###puts to test will be ###$points_file.puts(e.vertices)###put here when works end end ###Get su;;component collection entities.each do |e| if e.is_a? Sketchup;;ComponentInstance the_name=e.definition.name stuff=e.definition.entities faces=[] counter=0 ###Locate faces in each component and make faces collection stuff.each do |e| if e.is_a? Sketchup;;Face counter=counter+1 faces.push e end ###if end ###loop make_comp_face_file(the_name,faces,counter,model)####Have to points=[] add_face_vertices_collect(faces,points) ####nest these print_vertices_collect(points) ####later $points_file.close end ###if end ###loop
-
The Vertex entity has a position.
point = vertex.position
The position will be relative to parent container, and not relative the SketchUp axes.
-
### points>>>vertices vertices.each do |vertex| $points_file.puts(vertex.vertices.point.to_a) ### FILE of VERTICES POINTS AS AN ARRAY ONE PER LINE... end
-
Hi guys, Thanks for your help. I stumbled on e.vertices.x.position after starting over. Now how do I read the SU Ruby API to make this easier to understand?-(
model = Sketchup.active_model entities = model.entities selection = model.selection if model.selection.empty? entities = model.active_entities else entities = model.selection end entities.each do |e| if e.is_a? Sketchup;;ComponentInstance ci_name=e.definition.name #UI.messagebox(ci_name) ci_collection=e.definition.entities #UI.messagebox(ci_collection) ci_collection.each do |e| ci_faces_collection=[] if e.is_a? Sketchup;;Face ci_faces_collection.push e ci_faces_collection.each do |e| faces_vertices_collection=[] if e.vertices faces_vertices_collection.push e puts(e.vertices.x.position) end end end end end end
Advertisement