Maxon Developers Maxon Developers
    • Documentation
      • Cinema 4D Python API
      • Cinema 4D C++ API
      • Cineware 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
    • Unread
    • Recent
    • Tags
    • Users
    • Login

    Data to Spline

    Cinema 4D SDK
    python c++
    4
    6
    1.2k
    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.
    • A
      allenrob
      last edited by ferdinand

      Hi everybody,

      My first post here so I really hope you tolerate my mistakes if I make any.

      I'm working on a path generation tool (for Windows and macOS) that creates paths with x and y coordinates of each points. I can easily covert them to SVG (using 'polyline' as it's more convenient than 'path' for my case). As far as I know, C4D doesn't support direct SVG import; it either needs to be *.dwg or *.dxf. Instead of expecting users to import the generated file into their scenes, I'd like to write a script that would do that with one click. Here are my questions:

      • Should I do that in Python or in C++? I'm not new to programming but I'm mostly a JAVA coder. I think I can give that a try on either of those languages.
      • What should be the data structure in the generated file? For what I have now, I'm getting values as [x,y] in floating point numbers like:
      540.3475, 417.24466
      541.6318, 417.6269
      544.0376, 417.85046
      548.4767, 417.7466
      

      How can I get those values from a *.txt file to create a spline in C4D? I can change the format of the values if needed. I just need to know the workaround (or a piece of script) to do that. Any help would be much appreciated.

      1 Reply Last reply Reply Quote 0
      • CairynC
        Cairyn
        last edited by

        Python can easily read lines from a file, split the line into partial strings, and convert the strings into float values.

        But for creating a spline from that, you will need to have a look at the class SplineObject and its parent PointObject:
        https://developers.maxon.net/docs/py/2023_2/modules/c4d/C4DAtom/GeListNode/BaseList2D/BaseObject/PointObject/SplineObject/index.html?highlight=spline#c4d.SplineObject

        C++ would require the huge project overhead so I can't really recommend this for such a simple script.

        1 Reply Last reply Reply Quote 0
        • A
          allenrob
          last edited by

          Hi Cairyn,

          I think I'm lost. I feel stuck. Is there way to get this done by paying somebody? I'm sorry, I know that's not the right place to list a job but python coders for C4D is extremely rare. 😕

          1 Reply Last reply Reply Quote 0
          • X
            x_nerve
            last edited by

            Hi:

            I think it might be faster to try to import the point location directly as an external library (.py). At the same time, C4D supports importing Illustrator files, and SVG can be processed in Illustrator before importing C4D. Here is a simple SplineObject code.

            import c4d
            
            def main():
                #The location of the point.
                Points = [c4d.Vector(0, 0, 0),c4d.Vector(0, 0, 2),c4d.Vector(0, 4, 4)]
                
                #Initializes the spline object.
                Spline = c4d.SplineObject(len(Points), c4d.SPLINETYPE_LINEAR
            )
                
                #Change the number of spline object segments, the number of points.
                Spline.ResizeObject(len(Points), 3)
                
                #Set the locations of all the points of the spline object.
                Spline.SetAllPoints(Points)
                
                #Set properties of the segment.
                Spline.SetSegment(0, len(Points), True)
                
                #Close the spline object.
                Spline[c4d.SPLINEOBJECT_CLOSED] = 1
                
                #Inserts the spline object into the current document.
                doc.InsertObject(Spline)
                
                #Update current document, routine code.
                c4d.EventAdd()
             
            if __name__=='__main__':
                main()
            
            1 Reply Last reply Reply Quote 0
            • ferdinandF
              ferdinand
              last edited by ferdinand

              Hi @allenrob,

              thank you for reaching out us. Also a big thank you @Cairyn and @x_nerve for the provided community support. I'll answer in bullet points:

              1. There is an importer plugin for SVG files for Cinema. I am not sure if it will fit your needs.
              2. When you want to have more control over the import process or use a custom file format, you can:
                a. Simply write your own interface as a script solution, I have provided a very simple example for the example data you did provide at the end of the posting. I just put your data into a txt file and read it in CSV style, but without using any special library. The example mostly demonstrates Python's very straight forward file object interface open.
                b. You can also use any of the standard library modules like json, csv, xml.etree.ElementTree to read in common data formats or use external libraries, e.g. pandas, to do so.
              3. Instead of just creating a script solution, like I did provide, you can also write a c4d.plugins.SceneLoaderData plugin. Read its documentation for details. You can do here basically anything you want and have a more natural user experience of loading in a file. Internally you would do mostly the same as in 2.a. or 2.b.

              I hope this helps,
              Ferdinand

              Your test data as a txt file to load in with the script below: points.txt

              """ Basic Python file IO to create a Cinema 4D linear spline from a CSV
              style file as discussed in:
              
                  https://developers.maxon.net/forum/topic/13065
              
              Run this file in Cinema 4D's script manager (Shift+F11). It will open a file
              dialog, where you should locate the provided example file 'points.txt',
              which ten will be loaded into the document as a linear spline.
              
              !THIS IS AN EXAMPLE AND NOT PRODCUTION READY CODE!
              """
              
              import c4d
              import decimal
              
              def read_spline_from_file(file_path):
                  """Reads one of your CSV style data structures into a single spline.
                  """
                  # The points of the spline we are going to build.
                  points = []
                  # Open a file object in read only text mode and read it line by line.
                  with open(file_path, "rt") as file:
                      for line in file.read().splitlines():
                          # Parse the line in a comma separated value style.
                          components = line.split(",")
                          if len(components) != 2:
                              raise RuntimeError("Parsing Error")
                          # Cast the components to floats. We need these gymnastics, because 
                          # Python's string type cannot implicitly be cast into a float and 
                          # Cinema does expect that type when instantiating a vector.
                          components = [float(decimal.Decimal(c)) for c in components]
                          # Create the vector and add it to our points list.
                          p = c4d.Vector(*components, 0)
                          points.append(p)
              
                  # Create a spline object with our points.
                  spline = c4d.SplineObject(pcnt=len(points), type=c4d.SPLINETYPE_LINEAR)
                  spline.SetAllPoints(points)
                  spline.Message(c4d.MSG_UPDATE)
                  # Insert it into the active document.
                  doc.InsertObject(spline)
                  # Tell Cinema to update.
                  c4d.EventAdd()
              
              def main():
                  """Entry point.
                  """
                  # Open a file dialog.
                  file_path = c4d.storage.LoadDialog(type=c4d.FILESELECTTYPE_ANYTHING, 
                                                     title="Select a file.", 
                                                     flags=c4d.FILESELECT_LOAD, 
                                                     force_suffix="", 
                                                     def_path="", 
                                                     def_file="")
                  # Read in the data as a single spline and insert into the scene.
                  read_spline_from_file(file_path)
              
              if __name__ == "__main__":
                  main()
              

              MAXON SDK Specialist
              developers.maxon.net

              1 Reply Last reply Reply Quote 0
              • ferdinandF
                ferdinand
                last edited by

                Hi,

                without further feedback, we will consider this thread as solved by Wednesday and flag it accordingly.

                Cheers,
                Ferdinand

                MAXON SDK Specialist
                developers.maxon.net

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