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

    Draw Bezier is confusing!

    Scheduled Pinned Locked Moved PYTHON Development
    5 Posts 0 Posters 486 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 13/05/2015 at 17:41, xxxxxxxx wrote:

      I've managed to draw complex bezier curves despite the completely confusing docs:

      GeUserArea.DrawBezier(sx, sy, p, closed, filled)

      • sx  (float) – X coordinate of the upper left corner of the drawn curve.
      • sy  (float) – Y coordinate of the upper left corner of the drawn curve.
      • p  (array of float) –
        An array with the bezier curves points.
        The following values ease the initialization of the points array:
      DRAWBEZIER_BX X coordinate of the second curve point.
      DRAWBEZIER_BY Y coordinate of the second curve point.
      DRAWBEZIER_CX X coordinate of the third curve point.
      DRAWBEZIER_CY Y coordinate of the third curve point.
      DRAWBEZIER_DX X coordinate of the fourth curve point.
      DRAWBEZIER_DY Y coordinate of the fourth curve point.

      _<_t_>_

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

        On 13/05/2015 at 17:44, xxxxxxxx wrote:

        Here are my notes that make it more understandable.
        Where is says 'point' in the docs, it isn't always a curve point.  Some of them are tangent handles.

          
        # Drawing beziers on a user area differs from creating splines in the 3D view.
        # The start coords (sx, sy) are the first knot.
        # A point array is then passed with 6 entries (3 x,y positions); These are: previous knot out-tan, next knot in-tan, next knot.
          
                            
        # Format:
        # points[c4d.DRAWBEZIER_BX+0] = Out-tangent x
        # points[c4d.DRAWBEZIER_BY+0] = Out-tangent y
        # points[c4d.DRAWBEZIER_CX+0] = Next Knot In-Tangent x
        # points[c4d.DRAWBEZIER_CY+0] = Next Knot In-Tangent y
        # points[c4d.DRAWBEZIER_DX+0] = Next Knot x
        # points[c4d.DRAWBEZIER_DY+0] = Next Knot y
        

        If you try try to pass an array with a number of entries that are not a multiple of 6, you get a warning that it must be a multiple of 6.  That sounds like you are allowed to set up arrays with more than 6 entries to draw multiple curve segments.  But, when I try to pass more than 6, the point after the first 6 goes shooting off the UserArea in a straight line.

        I've only managed to draw complex shapes by repeatedly calling the function with sx, sy, and a 6 entry array.

        This obviously makes it impossible to draw a filled complex shape.

        Am I doing something wrong with trying to pass an array with more than 6 entries?
        How do you draw a filled shape with lots of points?

        Thanks,

        Chris

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

          On 13/05/2015 at 18:22, xxxxxxxx wrote:

          Could someone post an example drawing a circle, 4 points with 2 tangent handles each, in a single array?

          Thanks

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

            On 15/05/2015 at 04:12, xxxxxxxx wrote:

            Hi Chris,

            The documentation for GeUserArea.DrawBezier() isn't accurate but your notes are exact 🙂.

            There seem to have an issue passing an array for multiple splines. It only works as expected passing an array for one spline only.
            So we can currently only draw one spline at a time (start/ending points + in/out control points/tangents).

            To draw an approximation of a circle with bezier splines the best solution is to draw 4 bezier splines and use magic numbers 0.55228475 or 0.551784 to calculate the influence points.

            Here's the code to use inside GeUserArea.DrawMsg():

            width = x2
            height = y2
              
            diameter = height-1
              
            # Create an array for 6 float values (3 points with x+y coordinates each)
            points = array.array('f', xrange(6))
              
            # Calculate 4 points for circle bezier spline approximation
            p0 = c4d.Vector(diameter/2.0, diameter, 0.0)
            p1 = c4d.Vector(diameter, diameter/2.0, 0.0)
            p2 = c4d.Vector(diameter/2.0, 0.0, 0.0)
            p3 = c4d.Vector(0.0, diameter/2.0, 0.0)
              
            # Draw lower right bezier spline
            points[c4d.DRAWBEZIER_BX] = p0.x + (p0.x * 0.551784)
            points[c4d.DRAWBEZIER_BY] = p0.y
            points[c4d.DRAWBEZIER_CX] = p1.x
            points[c4d.DRAWBEZIER_CY] = p1.y + (p1.y * 0.551784)
            points[c4d.DRAWBEZIER_DX] = p1.x
            points[c4d.DRAWBEZIER_DY] = p1.y
            self.DrawBezier(p0.x, p0.y, points, False, False)
              
            # Draw upper right bezier spline
            points[c4d.DRAWBEZIER_BX] = p1.x
            points[c4d.DRAWBEZIER_BY] = p1.y - (p1.y * 0.551784)
            points[c4d.DRAWBEZIER_CX] = p2.x + (p2.x * 0.551784)
            points[c4d.DRAWBEZIER_CY] = p2.y
            points[c4d.DRAWBEZIER_DX] = p2.x
            points[c4d.DRAWBEZIER_DY] = p2.y
            self.DrawBezier(p1.x, p1.y, points, False, False)
              
            # Draw upper left bezier spline
            points[c4d.DRAWBEZIER_BX] = p2.x - (p2.x * 0.551784)
            points[c4d.DRAWBEZIER_BY] = p2.y
            points[c4d.DRAWBEZIER_CX] = p3.x
            points[c4d.DRAWBEZIER_CY] = p3.y - (p3.y * 0.551784)
            points[c4d.DRAWBEZIER_DX] = p3.x
            points[c4d.DRAWBEZIER_DY] = p3.y
            self.DrawBezier(p2.x, p2.y, points, False, False)
              
            # Draw lower left bezier spline
            points[c4d.DRAWBEZIER_BX] = p3.x
            points[c4d.DRAWBEZIER_BY] = p3.y + (p3.y * 0.551784)
            points[c4d.DRAWBEZIER_CX] = p0.x - (p0.x * 0.551784)
            points[c4d.DRAWBEZIER_CY] = p0.y
            points[c4d.DRAWBEZIER_DX] = p0.x
            points[c4d.DRAWBEZIER_DY] = p0.y
            self.DrawBezier(p3.x, p3.y, points, False, False)
            

            See this paper for the surprisingly simple maths behind this code and magic numbers  0.55228475  or  0.551784.

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

              On 15/05/2015 at 19:22, xxxxxxxx wrote:

              Yannick,

              Thanks for taking a look.
              I thought there must be something wrong, I spent hours trying to make it draw correctly while passing multiples of 6 in the array.

              So there is no way to draw a filled shape with multiple segments then?

              If not, if I report this as a bug, will they fix it?
              This has been here since R14.

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