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
    • Unread
    • Recent
    • Tags
    • Users
    • Login

    Why are my Relative Transformation Values not 0?

    Cinema 4D SDK
    python r21
    4
    11
    898
    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 Former User
      last edited by

      Hello,
      I'm having an issue where I'm trying to compare an object's relative transformation Vectors to another Vector.

      As an example, if I print the values as such, I get a Vector with 0 values, just as can be seen in the Attributes Editor:

      print obj[c4d.ID_BASEOBJECT_REL_POSITION]
      #Vector(0, 0, 0)
      

      If I compare the relative Position to a Vector with 0 values, however, it returns as False.

      print obj[c4d.ID_BASEOBJECT_REL_POSITION] == c4d.Vector(0, 0, 0)
      #False
      

      If I print the Position.x it returns an unexpected number:

      print obj[c4d.ID_BASEOBJECT_REL_POSITION,c4d.VECTOR_X]
      #-3.552713678800501e-15
      

      Can anyone explain what is happening? My objects do have frozen transformation values, but it seems like the relative values should ignore these.

      c5ea6069-4cde-441e-96f9-8e5af2b9703d-image.png

      Thank you.

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

        @blastframe said in Why are my Relative Transformation Values not 0?:

        #-3.552713678800501e-15

        That is zero, at least as far as computer scientists programmers are concerned. That is a number with 14 zeros after the comma and then 3552 etc. The reason why this is happening is floating point precision.

        Cheers,
        zipit

        MAXON SDK Specialist
        developers.maxon.net

        ? 1 Reply Last reply Reply Quote 1
        • ?
          A Former User @ferdinand
          last edited by

          @zipit Thank you. So how do I compare it to 0? Currently it does not equate to zero.

          1 Reply Last reply Reply Quote 0
          • ?
            A Former User
            last edited by A Former User

            I found this solution on StackOverflow

            def isclose(a, b, rel_tol=1e-09, abs_tol=0.0):
                return abs(a-b) <= max(rel_tol * max(abs(a), abs(b)), abs_tol)
            

            This seems to address the issue.

            I am still confused as to why the Vectors do not compare equally though:

            print obj[c4d.ID_BASEOBJECT_REL_POSITION] == c4d.Vector(0, 0, 0)
            #False
            

            It seems like the floating point issues would be addressed in Vector.__eq__ and Vector.__ne__

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

              Hi,

              there is c4d.utils.CompareFloatTolerant(a, b) although the function is a bit of a black-box. You could also write your function, the problem here is that you might run into floating point precision problems depending on how accurate you want that function to be. The utils function is addressing that problem.

              COMPARE_DELTA = 1e-10
              
              a = 0
              b = 3.1415e-14
              
              print "a:", a, "b:", b
              print "a == b:", a == b
              
              tolerant_compare = lambda a, b: abs(a - b) <= COMPARE_DELTA
              
              print "tolerant compare:", tolerant_compare(a, b)
              
              a: 0 b: 3.1415e-14
              a == b: False
              tolerant compare: True
              

              edit: yes, the stack overflow snippet addresses your problem, it is a slightly fancier version of my lambda.

              FYI: If you are not interested only in a single component of a vector, you can also always evaluate the squared length of the difference vector of the two vectors you want to compare.

              Cheers,
              zipit

              MAXON SDK Specialist
              developers.maxon.net

              ? 1 Reply Last reply Reply Quote 1
              • ?
                A Former User @ferdinand
                last edited by A Former User

                @zipit Your lambda is working better for my current project than the StackOverflow function. I assume this is because of the tolerance? Regardless, thank you very much for your help!!

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

                  Jeah, mine is rather tolerant, it bascially ignores everything after the 9th digit. So use with care 😉

                  MAXON SDK Specialist
                  developers.maxon.net

                  ? 1 Reply Last reply Reply Quote 0
                  • ?
                    A Former User @ferdinand
                    last edited by

                    @zipit Will do. Thank you!

                    1 Reply Last reply Reply Quote 0
                    • M
                      m_adam
                      last edited by

                      Hi @blastframe just to clarify how c4d.utils.CompareFloatTolerant works, this actually performs a check based on the bit representation.
                      It's not 100% safe but would work in most of Cinema 4D case and it's way faster than a real comparison.

                      For more information about it, see .

                      Cheers,
                      Maxime.

                      MAXON SDK Specialist

                      Development Blog, MAXON Registered Developer

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

                        Hi,

                        what I meant with "is a bit of a black box" was, that it remains unclear to me, what the function considers "sufficiently close to each other". Does that mean it mimics the rounding behavior of the Cinema 4D app or does it mean that it analyzes the bit-patterns of the operands for avalanche patterns that indicate a precision error?

                        I did not want to imply that it is broken, because I never actually bothered using or testing it, because of the uncertainty of its description.

                        Cheers,
                        zipit

                        MAXON SDK Specialist
                        developers.maxon.net

                        1 Reply Last reply Reply Quote 0
                        • P
                          PluginStudent
                          last edited by

                          The source code of the C++ version of CompareFloatTolerant() is actually available in the frameworks\cinema.framework\source\ge_ieee.cpp and/or \frameworks\core.framework\source\maxon\general_math.cpp file of the C++ SDK. I assume the Python version just calls the C++ function.

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