Head In The (Word) Clouds

by Ali Lloyd on September 12, 2014 26 comments

The word “cloud” was much in evidence at the RunRevLive Conference this year. This was primarily because of LiveCloud, a cloud database for LiveCode, whose aesthetically pleasing t-shirts were donned in abundance, and whose capabilities were amply demonstrated by the official conference app. This pervasiveness stood in stark contrast to that of the San Diego sky, which staunchly refused to have anything whatsoever to do with clouds for the whole week-and-a-bit.

So perhaps it was with those LiveCloud t-shirts in mind that I, whilst putting the finishing touches to the demo stack to accompany my talk and contemplating compelling use-cases for the trueWord chunk, decided to code a word cloud creator.

Well, I say ‘decided to code’; first I checked if anyone had done one already that I could steal. No dice. Then, in case anyone else had even thought about it, I threw the question out to some of the team: “How easy would it be to get LiveCode to make word clouds?” We weren’t sure, and I needed something by the morning. So I gave it a go.

Initially I attempted to define an algorithm for word placement, keeping track of the current border and repeatedly traversing it to find the next available space. This quickly got too complicated, with many additional considerations to do with overhangs and such- a more heuristic approach was necessary.

The idea of a word cloud is not only that the size of a word is related to its frequency, but also that the distance of the word from the center is, on the whole, inversely related to frequency. So once you have the words in frequency order, the ideal path on which to try and position them is a spiral.

The spiral equation can be written parametrically as x = tsin(t), y = tcos(t), which means that at a given time t, the distance from the origin of a point on the spiral is also t, since x&#0178 + y&#0178 is t&#0178(sin&#0178t + cos&#0178t) = t&#0178. So when we search for positions to place words, we can search along the spiral for the next available position, knowing that we are uniformly increasing the distance from the center as we vary the angle.

Here’s the code for returning the location on the spiral at time pTime:

function spiralLoc pTime
   local tX, tY
   put pTime * sin(pTime) into tX
   put pTime * cos(pTime) into tY
   
   return (tX & comma & tY)
end spiralLoc

When following this strategy, we need a way of testing whether words are overlapping. Initially I had thought about taking a snapshot of a field containing the text and changing the alpha value of all the white pixels so that they would be transparent. Then I’d have an image to use for hit testing using LiveCode’s intersect command. It was pointed out to me, however, that the import snaphot command includes transparency data if you use the …of object form, and so this was as simple as the following:

on snapshotField pWord
   set the opaque of field pWord to false
   set the showborder of field pWord to false	
   import snapshot from rectangle (the rect of field pWord) of field pWord with effects
end snapshotField

Then to test if we can place a word, we just use LiveCode’s intersect command to check whether it intersects any previous word at the proposed position:

function canPlace pNum, pTime
   // we can always place the first word
   if pNum is 1 then return true
   if imageIntersects(pNum) is false then return true
   return false
end canPlace

We now have essentially all the ingredients for a LiveCode word cloud creator. First of all, a handler to generate the list of frequencies:

function listFrequencies pText
   local tArray, tList
   repeat for each trueWord tWord in pText
      add 1 to tArray[tWord]
   end repeat
   repeat for each key tKey in tArray
      put tKey & comma & tArray[tKey] & cr after tList
   end repeat
   sort tList descending numeric by item 2 of each
   return tList
end listFrequencies

Then a handler to create the image for a given word. The pWeight parameter is the frequency of the given word divided by the frequency of the most frequent word.

on createImage pWord, pWeight
   set the textSize of the templateField to pWeight*kMaxSize
   create field pWord
   set the text of field pWord to pWord
   set the height of field pWord to the formattedHeight of field pWord
   set the width of field pWord to the formattedWidth of field pWord
   snapshotField pWord
   delete field pWord
end createImage

Repeating this for each of the words we are using to create the cloud gives us the set of images to place. We then try to place each image horizontally (and if that fails vertically) on the spiral path:

on placeWord pNum
   local tVertical, tTime
   put 0 into tTime
   repeat while tTime < kLimit
      if sFilledTimes[tTime] is empty then 
         set the angle of image pNum to 0         
         set the loc of image pNum to spiralLoc(tTime)
         if canPlace(pNum) then
            put true into sFilledTimes[tTime] 
            exit placeWord
         else
            set the angle of image pNum to 90         
         end if
         if canPlace(pNum) then
            put true into sFilledTimes[tTime] 
            exit placeWord
         end if
      end if
      add kIncrement to tTime
   end repeat
   put ("couldn't place word" & pNum) after msg
end placeWord

Watch the placement routine in action in this slightly annoying gif

These handlers together give a relatively pleasing word cloud, although I wanted to make a few simple tweaks to improve it. First of all, word clouds tend not to be circular but elliptical, so I introduced a flattening factor of 0.5 to the spiral equation. Also I felt the word sizes were not contrasted starkly enough, so I used the square of the weights instead. Sometimes words were being placed too close together, requiring a small white outer glow on the text to make such words fail the intersection test. Initially coding them as constants, I allowed the user to input various parameters like maximum font size, spiral flatness, maximum number of words, minimum word length, etc.

Here is the word cloud of this blog post!

What’s more, this being LiveCode 7.0, I was able to put text of all sorts of different languages into the text input box and everything worked exactly as expected. Here’s one with some sample text from various languages.

 

 

A Unicode compatible word cloud creator in under 160 readable lines – not many other languages can boast that sort of economy. What’s more, it only took a few hours to achieve something which by all accounts is distinctly non-trivial.

Many thanks to Ben and David who came up with some useful suggestions while I was coding this. If you can come up with any improvements, particularly to speed, I would be interested to hear them in the comments. Perhaps surprisingly, taking a snapshot of the group each time instead of looping though all previous images to find the intersection seems to slow things down.

Download my word cloud stack here.

read more
Ali LloydHead In The (Word) Clouds

Koch Island: Fractal Basics with LiveCode

by Hanson Schmidt-Cornelius on August 22, 2014 11 comments

Have you ever thought it would be possible to create something that had an infinitely long edge in a confined area? Yes, it is theoretically possible. Math’s is full of this kind of stuff and even thinking about the very basics of this can be great fun.

Let us consider a little island that was discovered in 1904, not by an explorer or seafarer Helge von Koch, but the Swedish mathematician with that name. This island is a mathematical idea and is considered to be one of the first fractals. It starts out as a very basic geometric construct, an equilateral triangle, which is a triangle with equal angles and equal sides. This triangle is then reshaped by dividing each line into three equally long segments and then replacing the middle segment with another equilateral triangle. The base line of that new triangle is then removed, leaving a line with a pyramid in it. The algorithm can then be applied repeatedly on the new shape, again splitting each line segment into three segments and replacing the middle one with an equilateral triangle and then removing the base line of that new triangle. After only a few iterations, it becomes apparent that the curve surrounding the island becomes increasingly longer. In fact the length of the curve increases by one third at each iteration. At the same time, the island does not appear to grow excessively and take up much more area.

Now this is all great as a mind model and we can get the principal behind the process, but what is with the infinitely long edge in the confined area that we mentioned in the beginning? Well, we could consider drawing this kind of island on a sheet of paper and think about what that would entail. From a mathematical point of view, we can represent this, we have symbols to represent infinity and the LiveCode logo has one of these infinity symbols hidden in the fifth and sixth letters, but if we really wanted to draw such an island we would have to consider what infinite really means to us in the real world.

Regardless of how fast we could replace the line segments, if it took anything longer than infinitely quick, then it would take us infinitely long to draw the island. So that is a possible showstopper. Our pen would have to be able to draw lines that are very, very thin, in fact we would have to be able to draw lines that are infinitely thin. This would then also have an impact on visibility, as lines that are infinitely thin are hard to see or measure.

These circumstances are restrictive, but it should not stop us from considering such exercises and allow us to have fun with these kind of ideas that we can partially visualize with computers. The following LiveCode scripts allows you to draw what can only be considered the tip of the iceberg of Koch island.

You can create your LiveCode Koch Island generator as follows:

1. Create a new stack.

2. Create a button “New” and place script “New” into the button script.

3. Create a button “Iterate” and place script “Iterate” into the button script.

You now have your infinitely long island curve generator that draws the first few stages of this fractal. The code is intentionally short for the blog here and shortcuts were taken in order to get here. If you want to explore this concept in more detail and see how far you can dig into the fractal, then consider updating at least the following three areas:

1. Increase the accuracy by preventing rounding from real to integer numbers at each cycle.

2. Calculate the exact height of each new pyramid with a more accurate constant. You can get the exact value by using Pythagoras.

3. Filter out duplicate point entries from “the points of graphic “island””.

Hope you have fun with this simple fractal example!

********** Script “New” **********

on mouseUp
   if there is no graphic "island" then new graphic "island"
   set the style of graphic "island" to "polygon"
    set the points of graphic "island" to "100,100" & cr & "300,100" & cr & "200,273" & cr & "100,100"
 end mouseUp

********** Script “Iterate” **********

on mouseUp
   local tLastPoint, tCurrentPoint, tCurrentIsland, tNewIsland
   put empty into tLastPoint
   put empty into tNewIsland
   put the points of graphic "island" into tCurrentIsland
   repeat for each line tCurrentPoint in tCurrentIsland
      put calculateSegment (tLastPoint, tCurrentPoint) after tNewIsland
      put tCurrentPoint into tLastPoint
   end repeat
   put line 1 of tCurrentIsland after tNewIsland
    set the points of graphic "island" to tNewIsland
end mouseUp
 
function calculateSegment pP1, pP5
   local tP2, tP3, tP4, tTran, tHeight
   if pP1 is empty then return empty
   split pP1 by comma
   split pP5 by comma
   put pP1[1] - pP5[1] into tTran[1]
   put pP1[2] - pP5[2] into tTran[2]
   put pP1[1]-tTran[1]/3 into tP2[1]
   put pP1[2]-tTran[2]/3 into tP2[2]
   put (pP1[1]-tTran[1]/2) - tTran[2]/2.886 into tP3[1]
   put (pP1[2]-tTran[2]/2) + tTran[1]/2.886 into tP3[2]
   put pP5[1]+tTran[1]/3 into tP4[1]
   put pP5[2]+tTran[2]/3 into tP4[2]
      return pP1[1] & comma & pP1[2] & cr & tP2[1] & comma & tP2[2] & cr & tP3[1] & comma & tP3[2] & cr & tP4[1] & comma & tP4[2] & cr 
end calculateSegment

Koch

read more
Hanson Schmidt-CorneliusKoch Island: Fractal Basics with LiveCode

Are Conferences a Waste of Time?

by Heather Laine on August 20, 2014 5 comments

We live in a  digital age. I can sit at my computer all day and talk to people on the other side of the world, by email, chat or Skype. Online webinars make it possible to share training or ideas with larger groups of people without anyone leaving the comfort of their own office. Given that this is so, why do I need to get on a plane and fly 5,189 miles to San Diego, with all the jet lag, expense and inconvenience, in order to spend 4 days live with a group of people who are all as excited about LiveCode as I am?

jet plane

Of course you know that I’m not going to conclude that conferences are a waste of time. The clue is in that sentence “spend time with a group of people who are all as excited about LiveCode as I am”. But why not? How can we justify the huge investment of time, trouble and expense that live conferences represent? Besides the obvious opportunities for training and learning in formal sessions at these events, I think there are three areas where live conferences just cannot be replaced by digital events.

1) Personal interaction.

Accept no substitutes. You will always learn more in a face to face conversation with someone than you will over the phone/Skype. You can read their body language, pick up subtle nuances you would otherwise miss, not to mention that the conversation is going to flow far more smoothly that it does when you have to ask them to repeat every other sentence or reconnect three times when your Skype connection dies… As a moderator of several email lists I can tell you that an interaction via email can go pear shaped at the touch of an ill judged key. You just know that the group of people now engaged in a blazing flame war would get on like a house on fire if they were all sitting together in a bar, talking, instead of typing things at each other they will later regret.

 2) Networking.

There is a saying, “It’s not what you know but who”. You don’t know who you don’t know. You may find interesting people to interact with on forums, or during an online course, but there is just no better way to connect with the right people for you, your work, your educational needs or your business than attending a conference focussed on your area of interest. Unless you stay in your room and hide for the entire 4 days, you will meet interesting people who can help you at RunRevLive.14!

networkingRobert

3) Inspiration.

Life is not all about 1’s and 0’s. Yes, the mundane day to day tasks have to be done, plans need to be carried out, code must get written and so on and so forth. But where is your next big idea going to come from? A change of scene, a change of pace, and a new group of inspiring people to talk to might result in something you currently haven’t even begun to dream up. Technically, we could hold a conference in Dundee, in the rain, in a concrete/tin shed on an industrial estate somewhere. I suspect that a) not many people would come and b) it would not have the same inspiring atmosphere and potential as a conference held in beautiful surroundings with good weather, good food and plenty to see and do.

uglytinshed

Our next conference venue?

Personally, I’m hugely looking forward to seeing you all again, catching up on the gossip, meeting old friends and making new ones, and adding San Diego 2014 to my bag of happy memories. As far as whether it is worth it to attend goes, I’ll let an attendee from last year sum it up. He told me:

“That one to one meeting I just had with your developer was worth the entire cost of the conference to me! Thank you so much.”

 Have you been to one of our conferences? Or another conference? How did you find the experience, was it worth it to you?

read more
Heather LaineAre Conferences a Waste of Time?

HTML5: Next Steps

by Kevin Miller on August 8, 2014 9 comments

reprinted from revUp

Well, what an exciting ride that was! Thank you so much to everyone that helped make HTML5 deployment for LiveCode a reality. Together we made the total and we’re setting the wheels in motion.

 

Community Powered

This truly was a community driven project. From the first survey indicating the depth of feeling for HTML5 deployment, to the last pledge that put us over the line, its been you the users, powering the campaign all the way. It was a fascinating study in crowdfunding, and you might want to check out this blog post for a deeper analysis of what goes into a successful crowdfunded project. I feel privileged to work with such a dedicated, creative and enthusiastic community. Thank you all. You have entrusted us with this project, and we will work hard to bring you what you’ve asked for: an HTML5 capable version of LiveCode we can all be proud of.

Team Driven

I’ve thanked the community for your contribution. Thanks are also due to our small but dedicated marketing team that ran the campaign, engineered the page, raised awareness, answered your questions, and processed all the pledges. The last day especially was intense in terms of managing the last minute rush of queries and pledges. The upside of running the campaign on our own site instead of on Kickstarter was the additional flexiblity this allowed us, but this did mean we had to meet all the technical challenges ourselves. A very big Well Done to Steven, Heather and especially Arnaud for creating the highly complex webpage, making all the last minute changes demanded of him and keeping it up and running successfully through some very challenging traffic spikes.

Ramping it up

What’s next? We have some major plans to put into motion. Making the campaign total means we will secure the matchfunding, so we are now ploughing through the necessary paperwork and red tape for that. The HTML5 Dev Team needs put into place, trained and briefed. We’re working hard to ramp it all up. It’s a long runway, with our projected delivery date July/August next year, but thanks to you we are getting started! We’ll bring you more information in the coming weeks.

Why HTML5?

I’ve discussed the importance of this additional deployment platform a lot over the last few weeks. Being able to run your app straight in the browser, using the same natural language and drag/drop interface to create it widens the scope for LiveCode projects to a whole new audience. Schoolchildren gain greater accessibility, phone apps can be deployed without going through the app stores and the long tail of niche platforms that LiveCode doesn’t currently address can be supported via the browser. No plugin and no app to install removes barriers to adoption. Anywhere you can run an HTML5 capable browser, you will be able to run your app.

I’m really looking forward to the huge potential opened up by LiveCode HTML5!

read more
Kevin MillerHTML5: Next Steps

Thank You. HTML5 is coming to LiveCode

by LiveCode Team on July 31, 2014 No comments

WOW. We have done it. We are over 100% funded. HTML5 Web Deployment will be coming to LiveCode.

Your support over the last 30 days has been incredible and we can’t thank you enough for sharing our passion in delivering a better LiveCode.

Thank you to everyone who shared, commented, shouted and pledged on this campaign. Your support means a better LiveCode for you and for everyone.

THANK YOU

The LiveCode Team

read more
LiveCode TeamThank You. HTML5 is coming to LiveCode

This is One Powerful Crowd

by Steven Crighton on July 27, 2014 20 comments

Over the last 13 months since being with LiveCode the strength and loyalty of this community has never failed to amaze me. We are a bigger & stronger community than we have ever been and that is very powerful. It means that all of us together can control the future of our product.

In 2013 we ran our first Crowdfunding campaign on Kickstarter and this is where we stood up and showed the world that the LiveCode community is here to make a difference. We are here to make a better coding experience and we are not stopping until we achieve that.

A few months ago Kevin Miller LiveCode CEO (my boss) approached me about running a crowd funding campaign to bring HTML5 Web Output into LiveCode. My first thought was not worry or fear, it was excitement. I was so impressed that we were making a decision to go big, we were not sitting back on our 2013 success, we were saying, well we ain’t done yet, so let’s make a better LiveCode and let’s do it now. My second thought came in the form of about a million questions and I want to try and take you through that journey now.

read more
Steven CrightonThis is One Powerful Crowd