REQUEST: (for help) - Make a box in Ruby
-
Well - it's never as simple as that.
Using sketch_talk (can't find the post where it was mentioned, but the website where it lives is http://www.martinrinehart.com/models/tutorial/tutorial_11.html I managed to stitch together another program that can call sketch_talk, ask users for some inputs, create a box and a rectangle on the box based on the size of the box. (so many rectangles).
Let me begin by saying that I have never programmed in Ruby before (let alone any other language, really... a C++ class 10 years ago count?). Have mercy
This is the code in Sketch_Talk I can find related to creating a box and a rectangle.
def box( near, far, pushpull ) b = Box.new( near, far, pushpull ) b.draw() return b end # of box() def draw() Sketchup.active_model().active_view().invalidate() end def r( *args ) if args.length == 2 r = Rectangle.new( args[0], args[1] ) r.draw return r elsif args.length == 4 return face( args[0], args[1], args[2], args[3] ) else raise "Command r requires two or four points." end end # of r() class Box =begin A box is a rectangular parallelepiped; six faces, all rectangular, all meeting at right angles. A box is defined by near and far corners of a rectangle plus a distance to PushPull the rectangle, creating the box shape. If the rectangle is orthogonal, a positive PushPull is done toward the positive end of the perpendicular axis. All six faces of the box will face the outside of the box. =end attr_reader ;rectangle, ;pushpull_distance def initialize( near, far, pushpull_distance ) @rectangle = Rectangle.new( near, far ) @pushpull_distance = pushpull_distance end def draw @rectangle.draw() @rectangle.face().pushpull( pushpull_distance ) end end # of class Box class Rectangle =begin A Rectangle is created from a near corner and a far corner. The corners are [r,g,b] arrays. An orthogonal rectangle is created, if possible. The rectangle's @plane is one of 'rg', 'gb', 'br' or 'no' (Not Orthogonal). An orthogonal Rectangle's normal points toward the positive end of the perpendicular axis. A non-orthogonal Rectangle's outside face will face the positive end of the blue axis, except that Rectangles parallel to the blue axis face the positive end of the green axis. =end attr_reader ;near, ;far, ;plane, ;face, ;group def initialize( near, far ) r = 0; g = 1; b = 2; @near = near; @far = far if near[r] == far[r] @plane = 'gb' elsif near[g] == far[g] @plane = 'rb' elsif near[b] == far[b] @plane = 'rg' else @plane = 'no' end end # of initialize() def draw( *args ) # args == none or optional group corners = get_corners() if args.length == 1 corners.insert( 0, args[0] ) end @group = add_face_group( corners ) @face = find_face( @group.entities ) return @group end # of draw() def get_corners() r = 0; g = 1; b = 2; ret = [] ret[0] = @near ret[2] = @far if ( @plane == 'rg' ) || ( @plane == 'no' ) ret[1] = [ @near[r], @far[g], @far[b] ] ret[3] = [ @far[r], @near[g], @near[b] ] elsif @plane == 'gb' ret[1] = [ @near[r], @near[g], @far[b] ] ret[3] = [ @near[r], @far[g], @near[b] ] else # @plane == 'rb' ret[1] = [ @near[r], @near[g] ,@far[b] ] ret[3] = [ @far[r], @near[g], @near[b] ] end return ret end # get_corners() end # of class Rectangle
And here's what I was messing around with last night:
######################## # blackbox.rb ######################## require 'sketchup' load '/r/martins_sketch_talk2.rb' #unless file_loaded?("blackbox.rb") # mymenu = UI.menu('Plugins').add_submenu('Dereks #Plugin Collection') # mymenu.add_item('Black Box Creator') # {(Blackbox.new(true))} # file_loaded("blackbox.rb") #end def boxes() all del glazing_ratio = 0.5 building_height = 15.0 eW_NsRatio = 1.5 width = 25 inputs = [0,0,0] prompts = ['Glazing Ratio;', 'Building Height;', 'EW to NS ratio;'] defaults = [glazing_ratio, building_height, eW_NsRatio] inputs = UI.inputbox(prompts, defaults, 'blackbox') glazing_ratio = inputs[0].to_f building_height = 12*inputs[1].to_f eW_NsRatio = inputs[2].to_f width *= 12 #create initial box box ([0,0,0], [width,width/(eW_NsRatio),0], building_height) #add windows to front side based on glazing area area_front = building_height * width window_area_front = area_front * glazing_ratio window_ratio = width/building_height window_height = (window_area_front/window_ratio)**0.5 window_width = window_area_front/window_height r ([(width-window_width)/2,0,(building_height-window_height)/2],[(width+window_width)/2,0,(building_height+window_height)/2]) end # End of blackbox.rb
You'll note a bunch of things, I'm sure - but here are my most immediate questions:
The box and rectangle are each created as a group, but I can't understand from the code WHY they are created as a group. How would I change this? Even just exploding them after creation would be fine for me at this point...
I was trying to follow some other scripts to understand how one puts a plugin into the Plugins dropdown, but couldn't figure it out. Using the Ruby Code Editor plugin from this site - I got as far as you can see in the code above. But don't understand the {My_module::my_method} line (assume is has to do with "when you click on this - what is supposed to happen")
Finally - is there a way to set materials through a Ruby script? Let's say I wanted the box to be wood, but the rectangle to be glass, for instance
There you have it - I want to make a box with a window. Anyone feel like pointing a n00b in the right direction?
Great forum - btw.
Derek
-
Bit of an update:
I've hacked my "plugin" a bit more.
- Fixed the "menu" problem - the plugin now properly displays in the menu and will run when I tell it to.
- Fixed the "shapes as groups" problem with the exploder.rb plugin's recursiveExploder function
Can't figure out how to "paint" an object, though.
I want the initial rectangle to be translucent glass. The box doesn't need to have any special material assignment.
Any tips for assigning a material to an entity if that material is not in the model already?
And by creating the box after the "window" - will the translucency be lost?(TO DO: Learn how to create layers. Learn how to set entity attributes like layer.)
I'll keep tryingDerek
-
Hey Derek, are you still using Martin's plugin? I don't think any of us here know what his plugin does. It might very well force the creation of new objects to always be as components or groups. If you're going to be making your own plugin, I'd recommend not building it using his as a base. Plus it will be easier for us to help debug if you are just using the regular SketchUp API, instead of Martin's.
-
Make a reference to the model to avoid too much typing
model=Sketchup.active_model
Decide in which 'context' the box will be: there are several possibilities.
ents=model.entities
which is the model's entities even if you are currently inside a group-edit etc.
ents=model.active_entities
which is the entities that are 'current'; e.g. could still be the model's entities or if you're inside a group-edit it's the group's entities, or inside an component-instance-edit its the component's definition's entities.
or if you have reference to a group or definition it can be specified as that entities context thus:
ents=group.entities
or
ents=definition.entities
For this example we will make a group and add a box to it - there are very good reasons for this - as groups separate geometry so we won't affect anything existing as we work - we can explode it later if desired...
first make the empty group in the active_entities
group=model.active_entities.add_group()
then make a reference to its entities
ents=group.entities
Now lets specify the four coplanar points for the box's base
points=[[0,0,0], [1,0,0], [1,1,0], [0,1,0]]
Add a rectangle face (1" square)
face=ents.add_face(points)
Note - the direction you add the points to make the face affects whether it looks up or down... BUT for a face drawn at z=0 Sketchup always makes it looking down!
Now make a box from the face 1" high
face.pushpull(-1)
Note that a pushpull is in the direction of the face, so as it's looking down we use -1 to extrude it up in the other direction...You now have a box drawn inside a group.
To explode that group use
group.explode
This is a relatively simple thing to do - try with other shapes and face orientations...
Tips: if you make a face that is the 'wrong-way-round' use
face.reverse!
to flip it to look the other way OR change the +/- of the pushpull distance.
Any numbers are taken as inches, irrespective of the models units; however you can specify other units if desired - e.g.face.pushpull(-2.5**.cm**)
will make the box 2.5cm high etc... -
I knew it had to be easy.
Speaking of which - does anyone have recommendation for good learning resources, that I might at some point get to asking useful questions?
Thanks a bunch for all the help!
Derek
-
@unknownuser said:
Speaking of which - does anyone have recommendation for good learning resources, that I might at some point get to asking useful questions?
Well, this forum
Depending on your level of expertise, Automatic Sketchup is a good start.
-
@kybasche said:
:roflmao:
I knew it had to be easy.
Speaking of which - does anyone have recommendation for good learning resources, that I might at some point get to asking useful questions?
Thanks a bunch for all the help!
Derek
Have a look at the sticky thread in the Developers section. An important part to pay attention is wrapping your code in a module to avoid clashes with other scripts.
-
Well said thomthom...
My code snippets will work in the Ruby Console for testing...
BUT a typical format for simple code is
` module Kybasche
def self.box()box code in here
end
endThen
Kybasche.box()` draws a box
You add to it with extra code, like a dialog for its sizes or material[s]...
If you want to make a tool [class] where you pick points etc then this can be done inside the module too...
Advertisement