In over my head?
-
Ok, so before I try to dive into things, I figured I'd try to run this script idea by people far more knowledgeable than I.
Say i have a set of data points, and want to import them into sketchup (like Cloudv6).
however instead of attempting to triangulate the points to make a sheet, is it possible to instead connect the points sequentially with lines.
Also, would there be a way to separate sets of data points within the file such that a script would know to begin a new set of lines?What I am hoping to get to is to say, have 3 sets of data points on a single file defining 3 different shapes. Import one set of data points, use them to draw a set of lines,turn it into a group, then import the next set, draw the lines...etc, etc. automatically.
My motivation for trying to build this script is I've been working on an aircraft wing design, and pretty much have all the shapes defined mathematically (ribs, spars, etc.. I'd like to be able to model the points, to see what the math is coming out to, and be able to change and remodel quicker than it's been taking me to do it so far.
lol its a little late, so I apologize for rambling on a bit. I hope I got my idea across clear enough, and look forward to your thoughts.
Thanks,
Mike -
Yes it all sounds reasonably do-able.
In what format are you trying to import the points? As a CSV file? I think that might be easiest to parse in SketchUp.
Then I think the idea would be to export all groups of points as a single file. Then write a ruby that takes that file, defines all the points, and then connects them. It would be helpful if you provided the connection order in the CSV file too. Or if they were ordered in the CSV by connection. So then you jsut connect them as you import them.
Do you have a file of exported points to play with?
Chris
-
As Chris says... A CSV file (comma-separated-variable') which can be exported from Excel et al (or a TSV file == same but tabbed) can easily be read in.
If the values are in the order you want them connected then simply read the first and second values and use them as the start/end of a line, then the second and third for the next line etc until the list is done. You then have a set of lines drawn between the points...
Of course there are various sophistications like setting the units that the file uses, and grouping these lines so they are kept separate from existing geometry...
Give us some example data... -
yeah all my data points are in .csv format, that's been the easy part,lol I even have a cheesy little C++ program to generate them for me. I'd planned on using that format, though wasn't sure if there was a way to distinguish between different sets of points within a single file. (one set for a cube, one set for a sphere for example)
That's good to hear that the concept is doable.lol the trick now is to learn Ruby enough to accomplish it.
If you want I can upload an example data point sheet this evening. (don't have it on this computer)
thanks,
Mike -
I the individual parts of the file refer to separate 3D objects you could devise a separator line e.g. ###
So a series of comma separated lines, then ###, then a series of comma separated lines, then ### etc
Your reader reads the points and makes lines given in the file from one to the next until it finds the ###... then it starts again on the next point set...I seize the night and cherish the day... but I'm semi-nocturnal...
-
I wrote this earlier this year for a very similar application.
It can't detect different object, but may give you a starting point.
-
sweet, thank you Jim, that plugin was a great help to get me started.
runnign it a couple times, I see that it is actually a great starting point for the script that I'd like to write (if you don't mind me using it ).
Going through the code I'm pretty sure I understand how it works. However I do have a couple questions.
what exactly does "rescue =>e" do?and how does
@unknownuser said:
pts.each_with_index do |pt, i|
Sketchup.status_text = "Plotting point #{i} of #{point_count}"
Sketchup.active_model.entities.add_line(first_pt, pt)
first_pt = pt
endpull the next point out of the array pts and store it as pt? I figured out how First_pt was generated, though the second part eludes me a bit.
thanks again for your help everyone
Mike
-
Hi Mike.
@mike ravenwolf said:
what exactly does "rescue =>e" do?
It is part of an exception handling block
begintry this
rescue => e
an exception is caught and put in a variable e
end
It would actually catch more types of exceptions (all in fact) written as:
rescue Exception => e
@mike ravenwolf said:
pull the next point out of the array pts and store it as pt?
each_with_index
is called an iterator. Its job is to visit each member of the array and pass the value to|pt, i|
- a couple of loop variables.each_with_index
is is a relative of the more commoneach
method, but I wanted to show the progress by showing the index.What I think you'll want to do is insert some token in the .csv file that can be picked up in the readlines loop. The token will mark when the Group is complete and a new one created.
-
Thanks again Jim,
here is a quick and dirty tryout of the script.
I seriously doubt in its current form it would work (especially my attempt at creating a group)
but here goes anywaysUI.menu('Plugins').add_item('Plot Data File') do file = UI.openpanel("Select Data File") if file.is_a? String object_set=[] point_set = [] line_count = 0 IO.readlines(file).each do |line| line_count += 1 line.chomp! next if line.empty? if line='$$$' object_set.push(point_set) next end #defines the point_set elements array = line.split(/[;|,|\s]+/).map!{|e| e.to_f} if array.length == 2 array.push(0) end if ary.length != 3 raise UI.messagebox("Couldn't parse data file line;#{line_count}") end begin point = Geom;;Point3d.new(array) rescue => e raise UI.messagebox("Couldn't create point from;#{array.inspect}\ndata file line;#{line_count}\nerror;#{e}") end point_set.push(point) Sketchup.status_text = "Reading line; #{line_count}" end end if object_set.length < 1 rasie UI.messagebox("No data points found.") end #build object object_count=object_set.length object_set.each_with_index do |point_set,i1| start_point= point_set.shift group=sketchup.active_model.entities.add_group if (group) UI.messagebox group else UI.messagebox "Failure" end point_count=point_set.length point_set.each_with_index do |point, i2| Sketchup.status_text = "Plotting point #{i2} of #{point_count} in Point_set #{i1}" group.add_line(start_point, point) start_point = point end end end end
I know i need to do better at commenting the code but that will deffinitly be in the 'final' version. but lemme know what you think.
BIG thanks to Jim, whose code comprises the core of this script.
Mike
-
It looks pretty good, Mike. I do see a couple of problems, though (most of which are quickly found by having the Ruby console open when you try to run it it's really easy to use with Jim's Ruby Toolbar: http://forums.sketchucation.com/viewtopic.php?f=180&t=1542
-
A typo: "rasie" instead of raise.
-
In that same if block, you should probably abort the rest of the script if there are no point sets... Just put in a "return" with an optional value.
-
On the same topic, you may want to replace all the message boxes with "puts" statements and use the console. I find it much less annoying than all the clicking
-
In both "each_with_index" statements, you reuse the name of a local variable for an iterator. This is probably okay, I just like to nit-pick .
-
Finally, if you ever want to debug by reloading just the script (rather than SU itself), you'll start filling up your "Plugins" menu with "Plot Data File" items. Better to define this in its own method (preferably in its own Module) and point to it with a menu inside a block, like so:
require 'sketchup' module YourModule def self.plot_points . . . end end # Module unless file_loaded? ( File;;basename( __FILE__ ) ) UI.menu('Plugins').add_item('Plot Data File') { YourModule.plot_points } file_loaded File;;basename( __FILE__ ) end
One last thing: Can I have a ride in your plane when you get the wings sorted out?
-
-
Thanks runner, I'll give some of those a shot,
not sure how to implement the puts, though and seeing as how all the message boxes are for error, i dont think it'll bother me to much. At least i'll know my code was doing something...lolI'm working on going through, and cleaning up/commenting the code, and will give it a shot and post it later this eve.
also, i'm not entirely sure this line is correct
IO.readlines(file).each do |line|
mostly i get the feeling that the 'IO." is the wrong prefix. is that a correct assumption?thanks again everyone. Oh, and runner.. If I ever manage to get this thing built and flying, I'll deffinitly give you a ride
-
Mike,
I found 3 things that would give you problems.
- There was an extra
end
statement - if line
=
'$$$' - this is assignment, comparison is if line==
'$$$' group.add_line
(start_point, point) - should begroup.entities.add_line
( ... ), not group.add_line
- There was an extra
-
Yeah i noticed a few of those, as well as some other problems
Was having alot of issues trying to get it even to run a few parts of it the other night. Been reading the programming Ruby book found on the ruby-doc.org website. going to have to go through the code and tear it apart piece by piece over the course of this week, and hopefully have something workable by this weekend.
Hopefully.
Advertisement