Word Cloud Idea with Python Generator

On 24/06/2015 at 16:04, xxxxxxxx wrote:

Wordcloud Idea

Hello I was playing with Python Generator Script by "tcastudios" and I tried to modify it (with a really limited - beginner level python knowledge :) ) in order to make a 3d wordcloud.
I think I have done something but it is extremely slow and if words amount less than points amount it gives out of index error. How would I make it limited to number of words in the list?
Here is my scene;

And here is code;

motexCLONE example tcastudios.com©2012

motexCLONE must have a MoText Object as a child for font control.

Add a UserData LinkField for Cloner/Matrix Object.

Tiny modification by M Sensoy :)

import c4d
from c4d import gui
from c4d.modules import mograph as mo

def MoCheck(obj) :
    global wordList,wl
    md = mo.GeGetMoData(obj)
    if md == None: return None,None,None
    clist  = []
    string = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc vitae augue ac enim facilisis mattis. Fusce et efficitur purus, eu ultricies enim. Nulla gravida aliquet risus, ac ornare augue mollis vulputate. Integer at nunc at dui lacinia vulputate ut id lacus. Sed lacinia finibus nibh id feugiat. Sed elementum dapibus metus, ac egestas sem rhoncus consectetur. Maecenas facilisis eget nunc ac venenatis. Curabitur nec molestie augue, sit amet blandit sem. Sed a rutrum nunc, in elementum sapien.Aliquam ut lorem massa. Aenean quis rhoncus velit. Maecenas commodo elementum libero et ullamcorper. Phasellus non urna id massa interdum egestas. Nulla porta augue eu sapien convallis, accumsan volutpat leo ullamcorper. Mauris ultricies, tellus et hendrerit ornare, lectus nisi gravida ligula, blandit fringilla augue turpis nec sapien. Suspendisse suscipit volutpat porta. Cras mattis ultricies enim quis tincidunt. Quisque ligula justo, tempus ut lacus quis, placerat commodo turpis. Duis in nisi volutpat turpis viverra consectetur. Cras lobortis sit amet tellus id volutpat. Cras bibendum malesuada nisi, a efficitur massa hendrerit id. Nam id pulvinar ante. Vestibulum a condimentum nunc, quis finibus odio. Cras euismod quis urna sit amet commodo. Nam tristique elit vel lobortis feugiat.'
    wordList = string.split()
    wl = len(wordList)
    marr   = md.GetArray(c4d.MODATA_MATRIX)
    farr   = md.GetArray(c4d.MODATA_FLAGS)
    ccount = len(marr) # Initial Clone count
    for i in xrange(ccount) :
        if ((farr _& (c4d.MOGENFLAG_CLONE_ON)) and (not (farr _& (c4d.MOGENFLAG_DISABLE)))) : #Only if the clone is visible
            clist.append(marr _) # Add Clone Matrix to the list
        else: ccount -= 1 # Adjust Clone count

return len(marr),ccount,clist

def main() :
    p     = c4d.BaseObject(c4d.Onull)
    cl    = op[c4d.ID_USERDATA,1] # <--- UserData LinkField for Cloner/Matrix Object
    if not cl or (not cl.CheckType(1018544) and not cl.CheckType(1018545)) :
        return p
    mot  = op.GetDown()
    if not mot or not mot.CheckType(1019268) :
        return p
    mot[c4d.PRIM_TEXT_TEXT] = ''

        pdata = MoCheck(cl)

        return p
    for i in xrange(pdata[1]) :
        nr = c4d.BaseObject(1019268)
        nr[c4d.PRIM_TEXT_FONT]          = mot[c4d.PRIM_TEXT_FONT]
        nr[c4d.PRIM_TEXT_ALIGN]         = mot[c4d.PRIM_TEXT_ALIGN]
        nr[c4d.PRIM_TEXT_HEIGHT]        = mot[c4d.PRIM_TEXT_HEIGHT]
        nr[c4d.PRIM_TEXT_TEXT] = wordList _
        nr.SetMg(pdata[2] _)
    return p

On 30/06/2015 at 03:37, xxxxxxxx wrote:


The Python generator is slow because it's recalculated every time it's called. In that case you can activate its Optimize Cache option. But in the case of this generator, it doesn't work well because a linked object in the user data is used as input and the Optimize Cache option doesn't check if it's been changed.
So to manually implement the optimize cache checks and verify the input linked object for changes:

At the beginning of the generator script add a global variable for the linked cloner/matrix object dirty count:

global clDirty
clDirty = 0

In main() :

global clDirty
p  = c4d.BaseObject(c4d.Onull)
cl = op[c4d.ID_USERDATA,1] # <--- UserData LinkField for Cloner/Matrix Object
if not cl or (not cl.CheckType(1018544) and not cl.CheckType(1018545)) :
  return p
dirty = op.CheckCache(hh) or op.IsDirty(c4d.DIRTYFLAGS_DATA) or (dirtyCount > clDirty)
if not dirty:
  return op.GetCache(hh)
clDirty = dirtyCount

About the index error if there are more points in the array than words in the string list, you can simply use a modulo on the number of words to loop through them:

for i in xrange(pdata[1]) :
  widx = i % wl
  nr[c4d.PRIM_TEXT_TEXT] = wordList[widx]

On 15/07/2015 at 06:10, xxxxxxxx wrote:

Thank you for your help,

I've done as you guided me here is my scene;

But still it's so slow, would you please check my scene if I have done it right?:nerd: