Reading a file in Ruby
-
Set your
filepath
by usingUI.openpanel(...)
http://code.google.com/apis/sketchup/docs/ourdoc/ui.html#openpanel OR hard-code it in - if you get back-slashes in your path ..\folder\file.dat swap them for forward slashes for other ruby usefilepath.tr!("\\","/")
Then you open the file for reading...
lines=IO.readlines(filepath)
Now process the array oflines
to get the points as x/y values
points=[] lines.each{|line| x=line.split(",")[0].to_f y=line.split(",")[1].to_f pt=[x,y] points<< pt }
You now have an array of points.
To connect points with 'Lines' use
model=Sketchup.active_model ents=model.active_entities 0.upto(points.length-2) do |i| ents.add_line(points[i],points[i+1]) end#do
This is not tested but should form the basis for reading the lines in the file and listing the points and making consecutive points joined with lines...
-
TIG, your last bit there to add the lines from the points could be greatly simplified. Instead of adding each line separately with
.add_line
, you can use the.add_edges
. Replace the last chunk of code with this:model = Sketchup.active_model entities = model.active_entities entities.add_edges points
Chris
-
@chris fullmer said:
TIG, your last bit there to add the lines from the points could be greatly simplified. Instead of adding each line separately with
.add_line
, you can use the.add_edges
. Replace the last chunk of code with this:
model = Sketchup.active_model entities = model.active_entities entities.add_edges points
ChrisI know but I thought he might want to use the points in other ways to - e.g. close the 'loop'...
-
I had guesses you probably had a good reson for writing it the way you did. But I thought I'd mention just in case you had just forgotten
-
He could even do
face=ents.add_face(points) face.erase!
To get a loop quickly with no face ??? -
Dear TIG and Chris,
You both are geniuses and I can't thank you enough for your advice! I am attaching what I pieced together based on your inputs, and from info in the Ruby SketchUp programming examples. I put together a quick input file with the coordinates of a parabola just to test out the code, and it works just fine.
I am still not sure of some of the finer points of your discussion (e.g. edges versus lines), but this gets me started. Is there a good reference or tutorials for learning more about Ruby on SketchUp? I am experienced in Fortran and to a less extent C, but I can follow most of the the code. I am not sure what ".to_f" does in the loop to parse out the x,y points and would like to know more.
I will attach the simple input file in case you are interested.
First we pull in the standard API hooks.
require 'sketchup'
Show the Ruby Console at startup so we Can
see any programming errors we may make.
Sketchup.send_action "showRubyPanel:"
UI.menu("PlugIns").add_item("LinesFromFile") {
UI.messagebox("I'm about to import data")#Set your filepath by using
filepath = UI.openpanel("Open Data File", "/Users/sellers
", "*.txt")http://code.google.com/apis/sketchup/do ... #openpanel OR
hard-code it in - if you get back-slashes in your path ..\folder\file.dat
swap them for forward slashes for other ruby use filepath.tr!("\","/")
Then you open the file for reading...
lines=IO.readlines(filepath)
Now process the array of lines to get the points as x/y values
points=[]
lines.each{|line|
x=line.split(",")[0].to_f
y=line.split(",")[1].to_f
pt=[x,y]
points<< pt
}You now have an array of points.
To connect points with 'Lines' use
model=Sketchup.active_model
ents=model.active_entities0.upto(points.length-2) do |i|
ents.add_line(points[i],points[i+1])
end#do}
-
I put together a few videos on youtube that describe how I like to work in Ruby in SketchUp. It is designed mostly for people with no other programming knowledge like myself, but anyone can watch. Just don't be surprised if its a little basic - especially the first half of the first video.
Anyhow, it is the first 6 videos listed in my video page on Youtube here:
http://www.youtube.com/user/ChrisFullmer
The first one goes over how to get started and explains a little bit about how to quickyl test code in SketchUp, and it has one quick code example. Then the other ones all show how to perform various short, but useful tasks in ruby.
Chris
-
The 'lines' v. 'edges' is clouded by the "lines" of text read from the file too !
'Line' and 'Edge' have specific means in SUp's API.
The example code reads the file as 'lines' [of text] then processes each 'line' [of text].
It then makes an array [list] of points from these and then uses those toadd_line(p1,p2)
stepping through the array of points in pairs. Theents.add_line
method adds one 'Line' - or more correctly an 'Edge' - to the SUp entities collection. Chris pointed out that there is another methodents.add_edges(points)
where ALL of the Edges are processed en mass from the array of points.The 'Line' tool in SUp is actually an 'Edge' tool - draw a 'Line' and Select it, get Entity Info > 'Edge' !
The term 'Line' within the API has a specific meaning relating to an Edge -
edge.line
which returns a 2 item array of point and a vector - i.e. an Edge's "Line" tells you where the Edge starts and where it's heading to - which can be useful in getting intersections of an Edge's Line and a Plane etc...Another thing to note is that a 'Curve' in the API is not necessarily 'curved' ! An Arc or Circle is a Curve BUT any set of 'joined' Edges are technically a 'Curve' - a 'Polyline' in most other APIs ! There are free tools to join edges into Curves - e.g.
weld.rb
- which is useful in extruding smooth surfaces and essential with my EEby.. tools that need you to select Curves - if you are trying to use something other than an 'Arc'... -
@wsellers89 said:
I am experienced in Fortran and to a less extent C, but I can follow most of the the code.
In most modern languages there is a loop that loops over each member of a group without need for subscripting (and therefor without chance to mess up by going one too far or one too few). In Ruby it's
for member in group do process_member_here end
For non-trivial processing its
for member in group process_member_here end
Your job might go like this:
first = true for point in points create_edge( prev, point ) unless first prev = point first = false end
You'll see many Rubyists write that this way:
... points.each do |point| ... end
My tutorial, beginning in Chapter 11 teaches Ruby and the SketchUp API. It has "Topic" boxes for programming beginners. Programmers such as yourself who know coding essentials, but not Ruby, can just read the topic (for example, "Looping") and, if you know what the topic means, you skip over the box.
By the by, Chris's You Tube tutorials are a lot more fun.
-
Is there a SketchUp API command that would let you extract the beginning and end point (x,y,z) of a selected line or edge?
-
I think that I found my answer by digging into the SketchUp API documentation. Their examples show the following for the edge.start and the edge.end command. Don't know if there is a more elegant way.
edge = Sketchup.active_model.entities.add_line([0,0,0],[100,100,0])
vertex = edge.start
if (vertex)display a pointer to the Vertex
UI.messagebox vertex
else
UI.messagebox "Failure"
end
point = vertex.positionLet's get the Point3d of the vertex
if (point)
UI.messagebox point
else
UI.messagebox "Failure"
endvertex = edge.end
if (vertex)display a pointer to the Vertex
UI.messagebox vertex
else
UI.messagebox "Failure"
end
point = vertex.positionLet's get the Point3d of the vertex
if (point)
UI.messagebox point
else
UI.messagebox "Failure"
end -
Yup, that is one way to do it. Read all the methods available to the edge class:
http://code.google.com/apis/sketchup/docs/ourdoc/edge.html
You also have edge.vertices available which will return BOTH vertices in one shot.
edge = Sketchup.active_model.entities.add_line([0,0,0],[100,100,0]) vertices = edge.vertices position1 = vertices[0].position position2 = vertices[1].position
-
As well as getting the two vertices in order as Chris points out there is
vertex0 = edge.start vertex1 = edge.end point0 = vertex0.position point1 = vertex1.position
I made the 'vertices' just for clarity - of course you can miss defining the vertex and jump straight to the point likestart_point = edge.start.position
etc...
Also the edge.line defines its start thusstart_point = edge.line[0]
, the [1] would return its vector...
You can extract the x/y/z values direct from a point withx=point.x
or turn the point into an array withpoint.to_a
where you can still get the x/y/z or 0/1/2 items - points and 3-item arrays are somewhat interchangeable, but watch for traps - so methods require a point rather than an arrays of arrays are 'sortable' while arrays of points are not [but sets are ?]... -
@wsellers89 said:
Is there a good reference or tutorials for learning more about Ruby on SketchUp?
Advertisement