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

    Getting the full angle between faces

    Scheduled Pinned Locked Moved PYTHON Development
    12 Posts 0 Posters 1.1k 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 09/07/2016 at 18:36, xxxxxxxx wrote:

      I'm trying to get the true, full angle between two adjacent faces, by calculating the normals, getting the dot product and getting the ACOS of the result.
      But as soon as I go over 180°, the angle starts to get lower again, instead of going over 180°

      How can I get the real angle between faces?
      I want to be able to detect angles of more and less than 180°.
      Thank you very much in advance for any reply.

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

        On 10/07/2016 at 06:56, xxxxxxxx wrote:

        Try this and see if it gives what you want.

        #This code gets the angle for two sides of a polygon  
        #With point index# 0 as their origin (where the two sides meet)  
          
        import c4d  
        def main() :  
            
          obj = doc.GetActiveObject()      
          
          #Gets the vector from pt0 to pt1  
          v1_0 = obj.GetPoint(0)  
          v1_1 = obj.GetPoint(1)  
          vector1 = v1_0 - v1_1  
          
          #Gets the vector from pt0 to pt3  
          v2_0 = obj.GetPoint(0)  
          v2_1 = obj.GetPoint(3)  
          vector2 = v2_0 - v2_1  
          
          cross = vector1.Cross(vector2)      
          
          angle = c4d.utils.GetAngle(vector1, vector2)  
            
          #The angle in radians  
          Dot = vector1.Dot(vector2)  
            
          #The angle in degrees  
          degrees = int(c4d.utils.Deg(angle))  
          print degrees  
          
          c4d.EventAdd()  
          
        if __name__=='__main__':  
          main()
        

        -ScottA

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

          On 10/07/2016 at 07:49, xxxxxxxx wrote:

          Thank you for the code, Scott.
          But it still shows the same problem.
          Check out the video I made, showing it.
          It is using your code.

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

            On 10/07/2016 at 10:44, xxxxxxxx wrote:

            Oh I see.
            I've done this kind of thing a lot in 2d to get the 0-360 values for rotating a dial image. But I've never done this in 3d.

            I think you'll need to use atan2.
            I did a bit of Googling and managed to come up with a way to do it on a polygon without any joints.

            Create a polygon primitive object and then make it editable.
            Go into points mode and select all 4 points and rotate the object in a clockwise rotation around the X axis.
            Run this script to get the 0-360 rotation values for it

            import c4d  
            from math import atan2, pi  
              
            def main() :  
                
              obj = doc.GetActiveObject()      
                
              #point 1  
              x1 = obj.GetPoint(0).x  
              y1 = obj.GetPoint(0).y  
              z1 = obj.GetPoint(0).z  
              
              #point 2  
              x2 = obj.GetPoint(1).x  
              y2 = obj.GetPoint(1).y  
              z2 = obj.GetPoint(1).z  
              
              deltaX = x2 - x1      #Gets the X vector between the the two points  
              deltaY = y2 - y1      #Gets the Y vector between the the two points  
              deltaZ = z2 - z1      #Gets the Z vector between the the two points  
              
              angle_rad = atan2(deltaY,deltaZ)  
              angle_deg = angle_rad*180.0/pi + 90  
                
              if angle_deg > 90: angle_deg = 450 - angle_deg  
              else: angle_deg = 90 - angle_deg  
                
              print angle_deg  
                
              c4d.EventAdd()      
              
            if __name__=='__main__':  
              main()
            

            This doesn't work when the polygon is rotated with a joint though. So I don't know how helpful it is.
            Maybe someone else has a better idea?

            -ScottA

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

              On 10/07/2016 at 10:57, xxxxxxxx wrote:

              In my sample scene, I got the point coordinates from the mesh with a Point Xpresso node, taking deformed points into account.
              That is why the Joint worked.
              This example you provided only gives me the orientation of an edge in relation to the origin, right?
              What have you searched for in Google?
              When I search for "angle between faces" I get a lot of preset angles, between specific polygonal solids 😞

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

                On 10/07/2016 at 11:12, xxxxxxxx wrote:

                That code might work with joints if you use the polygon's normal as the vector rather using the polygon's edge.

                This is where I got the idea from
                http://stackoverflow.com/questions/1311049/how-to-map-atan2-to-degrees-0-360

                -ScottA

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

                  On 10/07/2016 at 11:50, xxxxxxxx wrote:

                  This is still not working properly but it really may have to do with atan2.
                  Since only the Y and Z components are being considered, this is performing a 2D calculation. As soon as I rotate the whole object, the angle seems to change when, in fact, the faces keep the same relative angle.
                  There must be some calculation that needs to be performed taking the adjoining edge between the faces into account.
                  This is proving to be much trickier that expected 😞

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

                    On 10/07/2016 at 12:11, xxxxxxxx wrote:

                    I think I may have found a way
                    I will have to cook dinner now, but I will test it out later.
                    I'll post the results here.

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

                      On 10/07/2016 at 15:36, xxxxxxxx wrote:

                      YES!!! It works.
                      I just checked if the angle is concave or convex by calculating the dot product between the normal of the first face and the vector between the centers of both faces. in the case that is convex, I adjust the angle to give me something over 180°.
                      This is the code:

                        
                      polys=obj.GetAllPolygons()   
                      points=obj.GetAllPoints()   
                        
                      poly1=polys[f1]   
                      poly2=polys[f2]   
                             
                      a1,b1,c1 = points[poly1.a],points[poly1.b],points[poly1.c]   
                      n1 = (b1 - a1).Cross(c1 - a1).GetNormalized()   
                      center1=(a1+b1+c1)*.3333   
                             
                      a2,b2,c2 = points[poly2.a],points[poly2.b],points[poly2.c]   
                      n2 = (b2 - a2).Cross(c2 - a2).GetNormalized()   
                      center2=(a2+b2+c2)*.3333   
                             
                      v2=(center2-center1).GetNormalized()   
                             
                      conc=v2.Dot(n1)   
                             
                      angle_rad = utils.GetAngle(n1,n2)   
                      angle_deg = 180-angle_rad*180.0/math.pi   
                             
                      if conc<0:   
                          angle_deg=360-angle_deg   
                      
                      1 Reply Last reply Reply Quote 0
                      • H Offline
                        Helper
                        last edited by

                        On 10/07/2016 at 16:28, xxxxxxxx wrote:

                        In a 2 poly object. That code works if you manually move the points in poly[1].
                        But if you move poly[1] using joints. The result of angle_deg is always 180.
                        I'm curious how are you getting that code to work when poly[1] is animated by a joint?

                        This is how I've done it by multiplying the poly's points by the joint's matrix.
                        Are you doing it a different way?

                        import c4d,math  
                        def main() :  
                            
                          obj = op.GetObject()       
                            
                          polys = obj.GetAllPolygons()  
                          points= obj.GetAllPoints()  
                          
                          poly1 = polys[0]  
                          poly2 = polys[1]  
                            
                          #The joint that is moving poly[1]  
                          joint = doc.SearchObject("Joint.2")  
                          mg = joint.GetMg()  
                          
                          a1,b1,c1 = points[poly1.a], points[poly1.b], points[poly1.c]  
                          norm1 = (b1 - a1).Cross(c1 - a1).GetNormalized()      
                          center1 = (a1+b1+c1)*.3333     
                            
                          a2,b2,c2 = points[poly2.a] * mg, points[poly2.b] * mg, points[poly2.c] * mg  
                          norm2 = (b2 - a2).Cross(c2 - a2).GetNormalized()  
                          center2 = (a2+b2+c2)*.3333  
                          
                          v2 = (center2-center1).GetNormalized()     
                          
                          conc = v2.Dot(norm1)  
                          
                          angle_rad = c4d.utils.GetAngle(norm1,norm2)  
                          angle_deg = 180-angle_rad*180.0/math.pi      
                          
                          if conc < 0:   
                              angle_deg = 360 - angle_deg  
                            
                          print angle_deg
                        

                        -ScottA

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

                          On 10/07/2016 at 16:36, xxxxxxxx wrote:

                          Oh, in this case, using just python, no.
                          I would have to calculate a CurrentStateToObject for that
                          It works with a joint if I use Xpresso to feed the normals and centers into a Python node and turn on the Use Deformed Points option.
                          But I just used the joint to test the concept. I need to check for angles in static meshes, in the script I'm creating.
                          Now that I have the code that returns an angle in the range 0 -> 2Pi, if I need to, I can always create an internal clone and apply the CurrentStateToObject.

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

                            On 10/07/2016 at 16:39, xxxxxxxx wrote:

                            Oops. Cross posted with you.
                            Look at my edited post.
                            The matrix stuff works when using joints to animate the poly. I was just wondering if you were doing it differently.

                            -ScottA

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