d3 svg techniques

170 views
Skip to first unread message

theta theta

unread,
Dec 27, 2012, 9:39:06 AM12/27/12
to trib...@googlegroups.com
http://tributary.io/inlet/4388714/ using the ingress logo obtained from kilobyte-svg-challenge, to experiment with reusing path data to reduce the size of the resulting svg. Tributary is a great app for experimenting with this stuff. 

theta theta

unread,
Dec 27, 2012, 10:02:15 AM12/27/12
to trib...@googlegroups.com
This is probably another narrow use case, and might be a whole bunch slower to render to svg, but it can be handy to capture a repeating d3 procedure as a function: http://tributary.io/inlet/4388811/

theta theta

unread,
Dec 27, 2012, 1:30:19 PM12/27/12
to trib...@googlegroups.com
more rotation and minimizing an icon path: http://tributary.io/inlet/4389758/ (snowflake from wikipedia)

theta theta

unread,
Dec 27, 2012, 4:15:24 PM12/27/12
to trib...@googlegroups.com
tiny optimization of path: http://tributary.io/inlet/4391938/ (snowflake)

theta theta

unread,
Dec 28, 2012, 9:36:26 AM12/28/12
to trib...@googlegroups.com
many random snowflakes : 


Jeff Steward

unread,
Dec 28, 2012, 12:01:45 PM12/28/12
to theta theta, trib...@googlegroups.com
These are really cool... Snow crystals are formed from physical process, and I wonder if thinking about dendrites branches as being formed randomly between certain sets of numbers could lead to physically realistic snowflakes.  

This isn't just for looks, it turns out the shape of ice crystals has a big impact on microwave radiation coming from the earth.  The shape changes the multiple scattering of the signal detected by satellites such as the Tropical Rainfall Measuring Mission's Microwave Imager.  This satellite is used to look inside of storms such as hurricanes, and this data can be used to give the starting conditions for a hurricane forecast. Snowflakes actually occur high in the atmosphere even in hurricanes, and therefore have a big impact on the signal, so improving our understanding of ice crystals improves our ability to forecast hurricanes!  Cool huh?

Here is a classification of ice crystals based on the different types encountered in the wild.

--
You received this message because you are subscribed to the Google Groups "Tributary" group.
To unsubscribe from this group, send email to tributary+...@googlegroups.com.
Visit this group at http://groups.google.com/group/tributary?hl=en.
 
 

theta theta

unread,
Dec 28, 2012, 12:13:02 PM12/28/12
to trib...@googlegroups.com, theta theta
The implementation here is pretty brain dead and optimized for minimal amount of lines of code per flake. Perhaps after reading the link you provided I might implement a more elaborate routine. 

Thanks for the great read Jeff! 

theta theta

unread,
Dec 28, 2012, 2:56:57 PM12/28/12
to trib...@googlegroups.com, theta theta
some clarity for the thread:

As Jeff suggests, interesting results will come from attempting to model how snowflakes form. I can imagine a few abstractions of the physics involved.

Jeff Steward

unread,
Dec 28, 2012, 3:23:06 PM12/28/12
to theta theta, trib...@googlegroups.com, theta theta
The idea of abstracting the physics is a great one.  Deciding what level of detail you want I think is one of the most important parts of science...

I really like this painting by Picasso that shows his process of abstracting a bull down to just the essentials:

http://blog.teacollection.com/wp-content/uploads/2011/01/PicassosBullSeries.jpg

No need to represent things in an overwhelming amount of unnecessary detail: just capture the bull by the horns! :/)
--

theta theta

unread,
Dec 28, 2012, 5:21:40 PM12/28/12
to trib...@googlegroups.com, theta theta
http://tributary.io/inlet/4402047/ (produces slightly larger svg) I suppose next step is to mirror the dendrites using scale on X axis then radial array them around using use and "transform": "translate(-60*i)". Will be good practice :)
Message has been deleted

theta theta

unread,
Dec 29, 2012, 9:44:47 AM12/29/12
to trib...@googlegroups.com, theta theta
Using "visibility": "hidden" when using "xlink:href" with use it can be useful to place the template path to a hidden state. The reason for this can be obvious when trying to use a fill/stroke which isn't entirely opaque. Setting the copy attributes to include "visibility": "visible" makes the copies visible. 

for (i in d3.range(2, 6){ ..some loop..} . Will give i as [1,2,3,4] in the loop body.

The alternative was http://tributary.io/inlet/4407245/ (using parseInt(i) to bump up the radial multiplier, avoids using visibility settings.

theta theta

unread,
Dec 29, 2012, 12:58:08 PM12/29/12
to trib...@googlegroups.com, theta theta
not much of an update, but this http://tributary.io/inlet/4408287/ makes variables easier to control.

Ian Johnson

unread,
Dec 29, 2012, 3:08:33 PM12/29/12
to trib...@googlegroups.com
I've got to say this is pretty cool, and seeing it evolve over the course of the thread is inspiring! This is exactly one thing I hoped from this mailing list (including the cool segway into real snowflakes) and I love seeing the process.

Also, it's a lot of fun to scrub any of the numbers and see the snowflakes regenerate randomly.
now to just make them fall down the page ;)


On Sat, Dec 29, 2012 at 9:58 AM, theta theta <tet...@gmail.com> wrote:
not much of an update, but this http://tributary.io/inlet/4408287/ makes variables easier to control.

--
You received this message because you are subscribed to the Google Groups "Tributary" group.
To unsubscribe from this group, send email to tributary+...@googlegroups.com.
Visit this group at http://groups.google.com/group/tributary?hl=en.
 
 



--
Ian Johnson - 周彦

theta theta

unread,
Dec 29, 2012, 4:00:13 PM12/29/12
to trib...@googlegroups.com
I'm about to have a long hard stare at implementing L-systems, it's been on a todo-list for quite some time.

theta theta

unread,
Dec 30, 2012, 8:10:07 PM12/30/12
to trib...@googlegroups.com
L-systems.

Complex L-systems are based on a form of recursion done by grammar rules rewriting the original input.
http://mathforum.org/advanced/robertd/lsys2d.html is a light weight introduction to the topic and will guide the next few posts in this thread.

My favourite language is Python, the eventual code will be in js inside tributary.

input_string = "F+F--F+F"
rule = "F > F+F--F+F"

instructions = rule.split(' > ')[1]
iterations = 2

for i in range(iterations):
    instructions = instructions.replace('F', input_string)
    print(instructions)

Above represents a most basic parser, it produces the rewritten instructions given a defined amount of iterations. Notice the avoidance of a recursive function call for now. Also early on I will limit to one rule until drawing is implemented.

I expect drawing to be relatively light code, relying on the polar rotation / relative coordinate mini language in svg paths that is very similar to postscript and G-code.

Naively the idea is to convert every character of the resulting instructions into a command to move the 'pen' and draw relative to the previous coordinate. Easier done than explained. The minus symbol could mean - 30 degrees, + could be +30 degrees F could be move in that direction by 20 px.

More later,

theta theta

unread,
Dec 31, 2012, 10:03:27 AM12/31/12
to trib...@googlegroups.com
http://tributary.io/inlet/4420154/ is a short introduction to paths, but http://www.w3.org/TR/SVG11/paths.html describes entirely the mini language of paths. 

For debugging I will stick with the verbose comma separated notation as tributary lower-case L and 1 are too similar and prohibit squashed notation from being easy to read (stuff can always be squashed lateron). The make_path function will in the future translate the instructions. I'm thinking a state-machine would help keep track of angles and distances to project the pen.

Dealga McArdle

unread,
Dec 31, 2012, 11:18:34 AM12/31/12
to trib...@googlegroups.com
time to break out the trig. http://tributary.io/inlet/4420916/


On Mon, Dec 31, 2012 at 4:03 PM, theta theta <tet...@gmail.com> wrote:
http://tributary.io/inlet/4420154/ is a short introduction to paths, but http://www.w3.org/TR/SVG11/paths.html describes entirely the mini language of paths. 

For debugging I will stick with the verbose comma separated notation as tributary lower-case L and 1 are too similar and prohibit squashed notation from being easy to read (stuff can always be squashed lateron). The make_path function will in the future translate the instructions. I'm thinking a state-machine would help keep track of angles and distances to project the pen.

--

theta theta

unread,
Dec 31, 2012, 4:46:24 PM12/31/12
to trib...@googlegroups.com
something like this : http://tributary.io/inlet/4421006/ now for some testing and new years celebrations.

theta theta

unread,
Dec 31, 2012, 4:49:44 PM12/31/12
to trib...@googlegroups.com
OK, so preliminarily this looks interesting: http://tributary.io/inlet/4423022/


theta theta

unread,
Dec 31, 2012, 7:39:58 PM12/31/12
to trib...@googlegroups.com
Still far from mature, but this seems to work. It appears to benefit from forcing integer inputs using floor and don't go beyond 5 or 6 iterations, the browser will likely feel the pressure.

Notice the big similarity between javascript and python code for the grammar rewriter:
// apply rule to rewriting grammar
function rewrite(input_string){
  
  var rule = "F > F+F--F+F";
  var instructions = rule.split(' > ')[1];

  for (i in d3.range(iterations)){
  instructions = instructions.replace(/F/g, input_string)
  }
  return instructions
}

theta theta

unread,
Dec 31, 2012, 7:49:41 PM12/31/12
to trib...@googlegroups.com

Jeff Steward

unread,
Dec 31, 2012, 11:00:58 PM12/31/12
to theta theta, trib...@googlegroups.com
So awesome!  I couldn't wait so I started messing around.  :-)

Creating the whole string in memory could pretty easily crash the browser (try to set the iterations to 10, for example).

It's better to have a recursive make_path function.  This avoids unnecessary storage and can handle lots levels better (however, this is still is making one big string for the draw_path call - it'd be easier on the browser to just draw immediately without the path string). 


I also put in multiple rules like the Sierpinski system.  :-)

Happy New Year!

Best wishes,

Jeff

On Mon, Dec 31, 2012 at 4:49 PM, theta theta <tet...@gmail.com> wrote:

(experimentation) http://tributary.io/inlet/4424270/

theta theta

unread,
Jan 1, 2013, 7:45:11 AM1/1/13
to trib...@googlegroups.com, theta theta
Beautiful modifications Jeff, Thanks! 

recursion can make something look simple and complicated at the same time, depending on the point of view of the observer. Now to consider ways to generate a dendrite grammar. We'll get a hybrid of L-systems and simple radial array / mirroring.

Great! 
Breakfast and a slight hangover. 
Happy New Year! 
Message has been deleted
Message has been deleted

theta theta

unread,
Jan 1, 2013, 11:27:41 AM1/1/13
to trib...@googlegroups.com, theta theta
Here's a slightly safer version. It aims to reduce the chance of accidentally setting recursion levels too deep for the browser.

Don't radically change the i_max value beyond 10 or 12, as it might halt your device/browser entirely.

String replace was removed by Jeff, thus effectively this builds the resulting string on the fly -- My recursive solution would not have been this elegant so soon.

I think this is a good starting point for anyone interested in learning about L-systems by experimenting with the grammar and adding rules. 

Ian Johnson

unread,
Jan 1, 2013, 2:39:45 PM1/1/13
to theta theta, trib...@googlegroups.com
this is a lot of fun!

playing with the rules and the bend:



--
You received this message because you are subscribed to the Google Groups "Tributary" group.
To unsubscribe from this group, send email to tributary+...@googlegroups.com.
Visit this group at http://groups.google.com/group/tributary?hl=en.
 
 

Jeff Steward

unread,
Jan 1, 2013, 2:50:59 PM1/1/13
to trib...@googlegroups.com
So I played with adding "commands," which tell what to do when you hit the bottom of the tree - for example, should you draw, or move forward without drawing?  However, I decided that SVG was getting murdered, so with Ian's help I switched over to Canvas to see if it would be any better.  You can judge for yourself, it seems L-systems with deep recursion can just get really nasty no matter how you cook them up.  But you can just click "config" and switch between the two, with some minor code modifications...


--

theta theta

unread,
Jan 1, 2013, 3:29:52 PM1/1/13
to trib...@googlegroups.com
http://tributary.io/inlet/4429786/  ohm.

Being able to slide values is really cool, i imagine the pioneers of this stuff burnt through many hours attempting to find interesting rules. There is something beautifully convenient about the immediacy of tributary.

Ian Johnson

unread,
Jan 1, 2013, 3:52:04 PM1/1/13
to theta theta, trib...@googlegroups.com

"There is something beautifully convenient about the immediacy of tributary."

--
You received this message because you are subscribed to the Google Groups "Tributary" group.
To unsubscribe from this group, send email to tributary+...@googlegroups.com.
Visit this group at http://groups.google.com/group/tributary?hl=en.
 
 
Screen Shot 2013-01-01 at 12.51.06 PM.png

theta theta

unread,
Jan 1, 2013, 4:06:15 PM1/1/13
to trib...@googlegroups.com
it seems L-systems with deep recursion can just get really nasty no matter how you cook them up. 

Blind recursion (or whatever the sci-comp term is) are leaps of faith with no consideration for unmanageable outcomes. I expect there are ways to attempt to calculate the cost of hitting another recursive call. Seems like this stuff can hit exponential growth really fast.

while playing around the outcomes tend to look like protein folding, which is very very interesting :)

theta theta

unread,
Jan 2, 2013, 8:22:21 AM1/2/13
to trib...@googlegroups.com
any amount of playing around with L-systems in Tributary in real-time will result in 3 common (and avoidable) manual edits.

1) start_x and start_y
2) arm length
3) bend angle

I'll implement moving the start_x and _y via a mouse (or whatever pointer device), maybe with inertia for smooth transitions. Not immediately sure how to implement the other 2. Can tributary capture key combos when the display panel has focus?

Ian Johnson

unread,
Jan 2, 2013, 1:55:45 PM1/2/13
to theta theta, trib...@googlegroups.com
cool idea!
yes, you can do d3.select("svg").on("keyup") or any other event. for the canvas one you would select #display (altho you may run into a problem with that since the display div doesn't get recreated every edit, but more event handlers do...)


--
You received this message because you are subscribed to the Google Groups "Tributary" group.
To unsubscribe from this group, send email to tributary+...@googlegroups.com.
Visit this group at http://groups.google.com/group/tributary?hl=en.
 
 

Jeff Steward

unread,
Jan 2, 2013, 8:35:04 PM1/2/13
to theta theta, trib...@googlegroups.com
The question of how to set the arm length is really interesting.

Sierpinski: http://tributary.io/inlet/4439895/
Koch snowflake: http://tributary.io/inlet/4439937/
Cheshire cat smile (my own little invention):http://tributary.io/inlet/4439816/

If you look at the line where F is set, in order to keep the size on
the screen constant, you need to divide by the length of each arm by
x^n, where x is some characteristic number of the system and n is the
number of iterations.

Sierpinski is 2^n, Koch is 3^n, and the Cheshire cat smile is
somewhere around 2.4^n (but it is not quite 2.4). This has to do with
how much length is gained each time.

If you aren't doing thing at the moment, x for the Cheshire cat smile
isn't too hard to compute. Care to find it?

Have any ideas about how we can do this for arbitrary paths?? :-)

Jeff Steward

unread,
Jan 2, 2013, 8:44:05 PM1/2/13
to theta theta, trib...@googlegroups.com
Oops, here's a simpler but equivalent version of the Cheshire cat grin:

http://tributary.io/inlet/4440094/

theta theta

unread,
Jan 3, 2013, 7:51:19 AM1/3/13
to trib...@googlegroups.com, theta theta
Appending the <path> object to a <group> and scaling the group depending on the path boundaries seems more convenient than dragging the start x,y around manually or scaling the arm width. I've had little luck extracting this stuff, is it even possible without manually parsing the path? Off the top the head anyone?


theta theta

unread,
Jan 3, 2013, 11:35:03 AM1/3/13
to trib...@googlegroups.com, theta theta

theta theta

unread,
Jan 3, 2013, 12:22:08 PM1/3/13
to trib...@googlegroups.com, theta theta
http://tributary.io/inlet/4444761/ 

left me thinking about colour.


theta theta

unread,
Jan 4, 2013, 8:26:33 AM1/4/13
to trib...@googlegroups.com, theta theta
(from enjalot's email)
wow things are getting awesome!

I went ahead and did one way to implement mouse interaction, using d3 zoom and drag behaviors:
http://tributary.io/inlet/4450281/
 
i play with self referencing tributary functionality to save the state to a json file. this is headed in the direction of enabling control plugins, sort of the raw implementation of a drag/zoom control. 

These additions ease the exploration of L-Systems. It will take me a while to digest the accumulative changes in code. 

theta theta

unread,
Jan 4, 2013, 8:47:08 AM1/4/13
to trib...@googlegroups.com, theta theta

Maybe needless to say, but: wow :D

theta theta

unread,
Jan 4, 2013, 9:23:17 AM1/4/13
to trib...@googlegroups.com, theta theta
took a while, but finally it emerged: http://tributary.io/inlet/4452891/

Ian Johnson

unread,
Jan 4, 2013, 2:47:05 PM1/4/13
to theta theta, trib...@googlegroups.com
that's awesome! fun to zoom into the heart ;)


On Fri, Jan 4, 2013 at 6:23 AM, theta theta <tet...@gmail.com> wrote:
took a while, but finally it emerged: http://tributary.io/inlet/4452891/

--
You received this message because you are subscribed to the Google Groups "Tributary" group.
To unsubscribe from this group, send email to tributary+...@googlegroups.com.
Visit this group at http://groups.google.com/group/tributary?hl=en.
 
 

theta theta

unread,
Jan 5, 2013, 5:56:10 PM1/5/13
to trib...@googlegroups.com, theta theta
for later reference: svg hyperlink http://tributary.io/inlet/4464142/ ( the slow poke way)

theta theta

unread,
Jan 14, 2013, 7:45:13 AM1/14/13
to trib...@googlegroups.com, theta theta
http://tributary.io/inlet/4529764 Quite a lot of code for one link. 

here's the same but with the css done through d3js instead: http://tributary.io/inlet/4529798

theta theta

unread,
Jan 14, 2013, 12:42:09 PM1/14/13
to trib...@googlegroups.com, theta theta
still clunky : http://tributary.io/inlet/4530869  ( but allows multiple click-able links )

theta theta

unread,
Jan 15, 2013, 12:45:36 PM1/15/13
to trib...@googlegroups.com, theta theta
this attempts to adjust the width of the rect associated with the text for the link : http://tributary.io/inlet/4540413

Ian Johnson

unread,
Jan 15, 2013, 12:54:06 PM1/15/13
to theta theta, trib...@googlegroups.com

Nice! You may also want to experiment with the getBBox() function (which you can call on a dom node) like
text.each(function(d) {
  bbox = this.getBBox();
  //save it on data
  d.bbox = bbox;
})

I've had trouble with that on Firefox before tho, just thought it was appropriate to point out.

Also this thread is getting mighty long, I think each of your techniques could live in their own threads for easier searching/reference.

On Jan 15, 2013 9:45 AM, "theta theta" <tet...@gmail.com> wrote:
this attempts to adjust the width of the rect associated with the text for the link : http://tributary.io/inlet/4540413

--

theta theta

unread,
Jan 15, 2013, 1:29:06 PM1/15/13
to trib...@googlegroups.com, theta theta
I was looking for a way to get .clientWidth for the text object, as it seems to return the correct value. Also looked at a few examples found over at stackExchange and paper.js using a temporary span or div to wrap a string and get bounding box from that. 

like :
var tk = d3.select('text.rect_link1')
tk[0][0].clientWidth // 46

It seemed a little excessive to pollute the group with small experiments, but as each experiment has grown it is starting to make sense to create separate threads.

Nils Schlomann

unread,
Jan 15, 2013, 1:52:09 PM1/15/13
to trib...@googlegroups.com, theta theta
You can also use .getBoundingClientRect() which gives you a correct bounding box even I you applied transformations like "scale" on the element.

But be aware that getBoundingClientRect has a different output in terms of positioning compare to getBBox(), instead of x,y it returns top and left.
but the important part is that it, returns width and height.

Nils Schlomann

unread,
Jan 15, 2013, 1:55:03 PM1/15/13
to trib...@googlegroups.com, theta theta
Also we careful with clientWidth I think its works only in Chrome reliable, but I am not 100% sure.

theta theta

unread,
Jan 15, 2013, 3:13:39 PM1/15/13
to trib...@googlegroups.com, theta theta
Thanks Nils! I've continued this conversation in a new thread here in an attempt to give these concepts their own space.
Reply all
Reply to author
Forward
0 new messages