Maxon Developers Maxon Developers
    • Documentation
      • Cinema 4D Python API
      • Cinema 4D C++ API
      • Cineware API
      • ZBrush Python API
      • ZBrush GoZ API
      • Code Examples on Github
    • Forum
    • Downloads
    • Support
      • Support Procedures
      • Registered Developer Program
      • Plugin IDs
      • Contact Us
    • Categories
      • Overview
      • News & Information
      • Cinema 4D SDK Support
      • Cineware SDK Support
      • ZBrush 4D SDK Support
      • Bugs
      • General Talk
    • Recent
    • Tags
    • Users
    • Login

    Word Cloud Idea with Python Generator

    Scheduled Pinned Locked Moved PYTHON Development
    3 Posts 0 Posters 332 Views
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • H Offline
      Helper
      last edited by

      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;
       https://www.dropbox.com/s/s59jphwf01qtkpb/wordcloud.c4d?dl=0

      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] = ''

      try:
              pdata = MoCheck(cl)

      except:
              return p
          
          for i in xrange(pdata[1]) :
              nr = c4d.BaseObject(1019268)
              nr[c4d.PRIM_TEXT_FONT]          = mot[c4d.PRIM_TEXT_FONT]
              nr[c4d.MGTEXTOBJECT_SPLINEMOVE] = mot[c4d.MGTEXTOBJECT_SPLINEMOVE]
              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] _)
              
              nr.InsertUnder(p)
              
          return p

      1 Reply Last reply Reply Quote 0
      • H Offline
        Helper
        last edited by

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

        Hi,

        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
          
        dirtyCount = cl.GetDirty(c4d.DIRTYFLAGS_MATRIX|c4d.DIRTYFLAGS_DATA|c4d.DIRTYFLAGS_CACHE|c4d.DIRTYFLAGS_CHILDREN)
          
        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]
        
        1 Reply Last reply Reply Quote 0
        • H Offline
          Helper
          last edited by

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

          Hello,
          Thank you for your help,

          I've done as you guided me here is my scene;
          https://www.dropbox.com/s/mi5g490eep2qmvh/wordcloud_v02.c4d?dl=0

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

          1 Reply Last reply Reply Quote 0
          • First post
            Last post