Newbie: Drawing state diagrams with Ruby - would this work?
-
Thanks for your support. I have guessed 1 month for it.
I have googled around a bit and have read through some script examples, so I understand a bit more now.
Some questions I have so far for the connection between boxes:- is there a way to bind a group (line+text) to a box, so when a box is moved, the line is stretched and the text is moved?
- How do I then find the line connection between the boxes? Do I have to investigate on coordinates or is there some kind of relation between box and the line+text group?
- If I have a group of lines (polygon) + text, how do I then get there?
Best regards
Peter -
Hi Peter and welcome.
This is not really "Newbie" stuff so I am moving the topic to the Developers Forum (down the road, next to the Corner Bar) before we scare away other newbies.
Chris (and others) will continue helping there (me not as ruby is Greek to me). Have fun!
-
I'm guessing the appeal of SketchUp to you is that it's scriptable using Ruby. But what else appeals to you? Does SketchUp have the look and feel for the type of diagram you have in mind? Do the state diagrams really require a 3D view? Do you expect to be able to manipulate geometry in SketchUp and update your data? (You can.)
SketchUp does not have any libraries or algorithms built in for you to use. (There's a few helper method in the Geom module.) SketchUp has some intelligence when it comes to connected geometry, but it's almost certainly not what you want.
SketchUp has just a handful of Entity types, and they are fairly basic objects. Vertices have positions, Edges are made of 2 Vertices, Faces have 3 or more Edges. Curves are a colletion of Edges (and as such are not "real" curves.) Groups/Components are containers of the basic Entities, and have position, scale, and rotation (via a Transformation matrix.) This is the low-level sort of thing you'll be dealing with.
However, Entities have uniq id's (as any Ruby object) and can also have user defined attributes. So labeling and finding Entities using attributes is easy, which I think you'll find useful.
If you want to be able to use the mouse to select objects in order to make connections, you're going to need to write a Tool.
SketchUp's inputbox implementation has 2 widgets - textbox and dropdown menu. If you need anything more sophisticated than that you'll need to use a WebDialog which inlvolved knowing a minimal amount of html and javascript.
For entities to be dynamic (move) SketchUp has an Amination class, or a simple timer-based animation can be used. If an Entity needs to change in other ways you may be better of deleting it and re-creating a new version.
But to answer your question, yes it can be achieved to some degree.
So group, was that a fair assessment?
-
I wonder.. if a Ruby bridge exists for OpenOffice.org OpenDraw (it's sort of a Visio clone.)
If no Ruby bridge, you'd be stuck using OpenBasic (StarBasic,) or another lang.
http://api.openoffice.org/
The page list them as: C++, Java, Python, CLI, StarBasic, JavaScript, & OLENow.. IF Google Layout was connected to a Ruby API .. I'd say that it would be better to work in Layout for 'smart' 2D diagrams. But we are all still waiting for that to happen.
-
@stony999 said:
Thanks for your support. I have guessed 1 month for it.
I have googled around a bit and have read through some script examples, so I understand a bit more now.
Some questions I have so far for the connection between boxes:- is there a way to bind a group (line+text) to a box, so when a box is moved, the line is stretched and the text is moved?
- How do I then find the line connection between the boxes? Do I have to investigate on coordinates or is there some kind of relation between box and the line+text group?
- If I have a group of lines (polygon) + text, how do I then get there?
Best regards
Peter
To move one object with another you need to link them with paired attributes...
I useid=Time.now.to_f+rand
as it's likely to always return a unique value.
Do we have box1, a line that starts at box1, and then ends on box2.
Let's assume each 'box' is an instance of a component.
Each 'box' has a unique attribute 'id' set when it's created usingbox1.set_attribute("Diagram", "id", id)
When you draw a line from a 'box' your tool reads the box's id withbox1_id=box1.get_attribute("Diagram", "id", nil)
.
Unfortunately an object's data-base id is not kept across sessions so an enduring attribute one needs to be made...
If there is a box1_id then the new line you added is given two attributesline.set_attribute("Diagram","start",box1_id)
for it's start and then you read the id of box2 and useline.set_attribute("Diagram","end",box2_id)
...
Now the two boxes and the line are linked behind the scenes.
Next you need to make an observer that loads at startup and is applied to all suitable objects [you also need to catch it on a new skp opening etc - there are examples in some of my recent tools].
Let's assume this 'entity' observer attaches to instances of certain types of component [like 'box'] - [you would also have another observer watching the appropriate definitions themselves to ensure any new instances of them will get the observer attached as they are added to the model - as they get their 'id' too.]. This observer watches to see if the instance [entity] 'changes' - if it does then it kicks in code that reads its 'id', the model.entities are searched for edges with matching start/end attributes and the start/end vertex of the edge is moved with the box to suit using something likeentities.tranform_entities(box.transformation, edge.start)
This is an outline only but is how I would approach coding this... -
Here's a quick half-baked example of making box components and linking them with a line that stretches as a box moves
=begin (c) TIG 2011 =end require 'sketchup.rb' ### def linkedgetoboxes() model=Sketchup.active_model model.start_operation("linkedgetoboxes") defs=model.definitions ents=model.active_entities cbox=defs.add("Box") cbox.entities.add_edges([1,0,0],[0,1,0],[-1,0,0],[0,-1,0],[1,0,0]) tr=Geom;;Transformation.new(ORIGIN) box1=ents.add_instance(cbox,tr) id=Time.now.to_f+rand box1.set_attribute("Diagram","id",id) box1.add_observer($boxEntityObserver) tr=Geom;;Transformation.new(Geom;;Point3d.new(100,0,0)) box2=ents.add_instance(cbox,tr) id=Time.now.to_f+rand box2.set_attribute("Diagram","id",id) box2.add_observer($boxEntityObserver) edge=ents.add_line(box1.transformation.origin, box2.transformation.origin) edge.set_attribute("Diagram","start", box1.get_attribute("Diagram","id",nil)) edge.set_attribute("Diagram","end", box2.get_attribute("Diagram","id",nil)) model.commit_operation end ### adds a new component 'Box', places 2 instances, links them with an edge, ### if you move a box and the line stretches with it... ### ### Obsever for boxes class BoxEntityObserver < Sketchup;;EntityObserver def onChangeEntity(box) return if not box or not id=box.get_attribute("Diagram","id",nil) org=box.transformation.origin model=Sketchup.active_model ents=model.active_entities ents.to_a.each{|edge| next if not edge.class==Sketchup;;Edge if id==edge.get_attribute("Diagram","start",nil) v=edge.start vec=v.position.vector_to(org) ents.transform_by_vectors([v], [vec]) if vec.length!=0 end#if if id==edge.get_attribute("Diagram","end",nil) v=edge.end vec=v.position.vector_to(org) ents.transform_by_vectors([v], [vec]) if vec.length!=0 end#if } end end ### def makeBoxEntityObserver() $boxEntityObserver = BoxEntityObserver.new if not $boxEntityObserver end makeBoxEntityObserver() ###
-
A few of issues:
(1) "Connectors" are likely to cross one another. You need to ensure that when they do, that the crossed line is not broken.
(2) How will multi-segment connectors be manipulated (edited.) In AutoCAD, these kind of lines are Polyline entities. Clicking on them, causes "vertice handles" to appear, allowing them to be edited, by grabbing a vertex and simply dragging it to another location. Also (in acad,) the Stretch (by Window Select,) will stretch any polyline that the selection window crossed (if you select by lower-right corner and move the mouse to the upper left.. resulting in a dotted selection window.)
(3) Could these "connectors" in Sketchup, themselves be a Dynamic Component ?
(4) I assume the diagram will be drawn in Top view, on the XY plane ?
-
Another muse:
In Visio and/or OpenDraw, the boxes have "connection points" called (I think,) "glue points" where the "connector lines" snap to.
I wonder if in Sketchup, we could create a "glue point" Component or Dynamic Component, that could be embedded as a nested entity, of the Box components, lying along an edge. If a Box edge has only 1 "gluepoint" on an edge, the "gluepoint" would position itself at the edge's midpoint. If there are 2 per edge, the "gluepoints" would space themselves at 1/3 divisons along the edge, and so forth.
-
The simplest form of connectors could be clines - these are not 'sticky' like 'edges'... OR they could be 1" component lines that scale to suit the distance - requires a different 'resizing' code set but doable... In face all parts 'node-boxes' and 'connecting-lines' [that way you could incorporate text or 'arrowheads' etc] could all be components... that move/stretch together.
-
Also, what happens if you have a repeating pattern? Say two boxes are connected in such a way, and the user copies and pastes this pattern a number of times. You would need to be able to re-assign id's to each group of components, in order to maintain referential integrity.
This is an interesting application for SU, I can certainly think of a number of uses for it.
--
Karen -
As posted, I saw the benefit in using sketchup in using the programming language Ruby, which I know best of all languages.
I understand now that a lot more has to be done in oder to achieve my goals. So maybe some kind of programmable Visio-like stuff would be better.I think I will give OOO Draw and OOO-Basic a try and see how far I will get with that.
Thanks to all for your support.
-
I was looking forward to Bezier-based leaders, arrows, and text tags, actually. Maybe I could have been more encouraging.
-
Why don't you just send the data through JSON to a htmlpage and use that combined with existing chart creator?
Like this one: http://www.anychart.com/products/anychart/overview/Should be pretty simple.
-
@pout said:
Why don't you just send the data through JSON to a htmlpage and use that combined with existing chart creator?
Like this one: http://www.anychart.com/products/anychart/overview/Should be pretty simple.
Are you in the correct topic, Pout?
AnyChart does not produce diagrams, it produces charts.
And yes it's a minimum of 500 dollars "simple".Jim had some success using GraphViz, which actually has two examples of state diagrams:
Advertisement