Newbie: Drawing state diagrams with Ruby - would this work?
-
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