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

    Get Point Positions of Selected N-Gon or Polygon

    General Talk
    5
    11
    2.5k
    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.
    • N
      noseman
      last edited by Manuel

      What's the simplest way to get all point positions of a selected Polygon (including N-Gons)?
      Cheers

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

        Hi,

        you forgot to tag your question, but from your history I assume this a Python question. There is PolygonObject. GetPolygonTranslationMap and PolygonObject.GetNGonTranslationMap which will allow you to translate between Ngon and Quads/Tri indices. Which in turn will you allow to infer the point indices.

        But note that there is no Ngon type in Python. Which means that interacting with them is quite limited. One workaround is to use SendModellingCommand to let Cinema's core do whatever you are trying to do with the Ngons.

        Cheers,
        zipit

        MAXON SDK Specialist
        developers.maxon.net

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

          Speaking of PolygonObject.GetNGonTranslationMap, the Python description seems to be wrong (copied from the C++ docs?). The doc says

          ngoncnt (int) – The number of N-gons. Pass the length of the list returned by GetPolygonTranslationMap(), not the value given by GetNgonCount().
          

          but the number needed here is not the length of the list (second return value), but the first return value of GetPolygonTranslationMap.

          For the return value, the doc explains

          The number of polygons in N-gon i is stored in list[i][0].
          Then the polygon indices are stored in list[i][j] where j goes from 1 to list[i][0].
          

          but the number of polygons is not stored at all. The sublists are simply the polygon indices, and the number must be inferred with the len() function.

          (Newest online docs, tested with R21)

          1 Reply Last reply Reply Quote 1
          • ManuelM
            Manuel
            last edited by Manuel

            hello,

            you have a old post explaining what are ngons here

            I've assumed the selected polygon or ngon are done by the user. If so, every polygon that compose a N-gon will be selected.
            Ngon doesn't exist in c4d, there's only tri and quads. Ngon are a group of tri or quads.

            In the object itself, we manage quads and tri.

            So you have to retrieve the selected polygon, convert that selection to points selection. Retrieves the coordinates of the selected points.

            This is the code without error check but it make it shorter and easier to understand.

            import c4d
            from c4d import gui
            # Welcome to the world of Python
            
            
            def ConvertFromPolyToPoint(obj):
                #Retrieves the selected polygons
                bs = obj.GetPolygonS()
                #Gets All Points and point count
                points = obj.GetAllPoints()
                pcnt = obj.GetPointCount()
                
                # Gets the Boolean array for every polygons
                selectedPolygon = bs.GetAll(pcnt)
                # Creates a BaseSelect for points (convert polygon selection to point selection)
                bsPoint = c4d.BaseSelect()
                
                # Checks all polygon to see if they are selected
                for i, selected in enumerate(selectedPolygon):
                    if selected:
                        # select all the points that belong to that polygon
                        cPoly = op.GetPolygon(i)
                        bsPoint.Select( cPoly.a)
                        bsPoint.Select( cPoly.b)
                        bsPoint.Select( cPoly.c)
                        bsPoint.Select( cPoly.d)
                # Retrieves the selected point as an array
                selectedPoint = bsPoint.GetAll(pcnt)
                return selectedPoint
               
            
            def GetSelectedPointPosition (obj):
                # Converts the selected polygon to an array of selected points
                selectedPoint = ConvertFromPolyToPoint(obj)
                # Retrieves all the points
                points = obj.GetAllPoints()
                
                pointsPosition = []
                for point, selected in zip(points, selectedPoint):
                    if selected:
                        pointsPosition.append(point)
                
                return pointsPosition
            # Main function
            def main():
                pointsPosition = GetSelectedPointPosition(op)
                print (len (pointsPosition), pointsPosition)
               
               
                # Execute main()
            if __name__=='__main__':
                main()
            

            Of course, if you want to retrieve the position of all the ngons of an object than you have to retrieves the ngon list first.

            @Cairyn
            you are absolutely right, i will update the documentation right now.

            Cheers,
            Manuel

            MAXON SDK Specialist

            MAXON Registered Developer

            1 Reply Last reply Reply Quote 0
            • N
              noseman
              last edited by

              Thank you everyone, and I'll make sure to tag my posts next time.

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

                HI:
                I found a way to get the global coordinates and indexes of all the points on N_gons.The Python script can select all N_gons faces, select points on all N_gons faces, and get the global coordinates and index of the points.

                Two Suggestions by the way:

                1.GetAllPoints() is used to get all the coordinates, but these are local coordinates, which need to be converted to global coordinates, and the results converted to global coordinates are usually correct.However, it is difficult to obtain the global coordinates of all points in the cache. Can you provide global coordinate parameters for all points?

                1. After the polygon object is baked as. ABC file, if the number of polygons is 0, the objects in the cache will change from polygons to blank objects.Can the cache still be a polygon object if the number of points is zero?

                The script code is as follows:

                import c4d
                from c4d import utils
                
                def main():
                    
                    Polygons = op.GetAllPolygons()
                
                    Selected_Polygon = op.GetPolygonS()
                    
                    #Determines whether n-gons edges exist on all polygon faces of the current object.
                    N_gons = op.GetNgonEdgesCompact()
                
                    Polygons_index  = [i for i,o in enumerate(Polygons)]
                    
                    #N-gons edge Numbers on all N-Gons faces.
                    N_gons_Edge_number = [h for h,z in enumerate(N_gons) if z > 0]
                
                    #select N-gons face.
                    Selected_Polygon.DeselectAll()
                    sele = [ Selected_Polygon.Select(ty) for ty in N_gons_Edge_number
                            if len(Polygons_index) == len(N_gons) ]
                    
                    #Toggle select mode.
                    bc = c4d.BaseContainer()
                    bc.SetData(c4d.MDATA_CONVERTSELECTION_LEFT, 2)        #ConvertSelection's Left "Polygons" option in memory
                    bc.SetData(c4d.MDATA_CONVERTSELECTION_RIGHT, 0)       #ConvertSelection's Right "Edges" option in memory
                    #bc.SetData(c4d.MDATA_CONVERTSELECTION_TOLERANT, True) #Select the selection->ConvertSelection's "Tolerant" option in memory
                    utils.SendModelingCommand(c4d.MCOMMAND_CONVERTSELECTION, 
                                                list = [op], 
                                                mode = c4d.MODELINGCOMMANDMODE_POLYGONSELECTION, 
                                                bc=bc, 
                                                doc = doc)
                
                    #Gets the global coordinates and index of the points on the N-gons plane.
                    All_Point = op.GetAllPoints()
                    PointS = op.GetPointS()
                    Pointe_Array = PointS.GetAll(op.GetPointCount())
                
                    All_posits = [(Arra,index) 
                                    for Arra,index in enumerate(All_Point)]
                                    
                    posit = [(Array,indexe) 
                            for Array,indexe in enumerate(All_Point) 
                            if Pointe_Array[Array] == 1]
                
                    #The global matrix of the current object.
                    op_matrix = op.GetMg()
                
                    matrix = []
                    for orientation in posit:
                        mt = c4d.Matrix()
                        mt.off = orientation[1]
                        m_mt = op_matrix * mt
                        matrix.append((orientation[0],m_mt))
                    
                    #Global coordinates and index of points on the N-GONS plane.
                    point_position = [(t[0],t[1].off) for t in matrix]
                    print point_position
                    
                    #Select all points on the N-gons side.
                    PointS.DeselectAll()
                    sele_point = [ PointS.Select(ty[0]) 
                                for ty in point_position]
                    
                    c4d.EventAdd()
                
                if __name__=='__main__':
                    main()
                N 1 Reply Last reply Reply Quote 0
                • N
                  noseman @x_nerve
                  last edited by

                  @x_nerve Thanks!

                  1 Reply Last reply Reply Quote 0
                  • ManuelM
                    Manuel
                    last edited by

                    @x_nerve said in Get Point Positions of Selected N-Gon or Polygon:

                    1.GetAllPoints() is used to get all the coordinates, but these are local coordinates, which need to be converted to global coordinates, and the results converted to global coordinates are usually correct.However, it is difficult to obtain the global coordinates of all points in the cache. Can you provide global coordinate parameters for all points?

                    2.After the polygon object is baked as. ABC file, if the number of polygons is 0, the objects in the cache will change from polygons to blank objects.Can the cache still be a polygon object if the number of points is zero?

                    1. yes i forgot it was local coordinate but global coordinates are just the matrix of the object * the local coordinates:
                        points = op.GetAllPoints()
                        mg = op.GetMg()
                        points = [mg * i for i in points]
                        print points
                    

                    If you retrieve the cache, you will retrieve a polygon object. So i don't understand why it will be difficult to retrieve the points's position. Retrieving an updated cache yes, it can sometimes be a kind of headache. Can you be a bit more clear about that ?

                    2- I didn't checked the result of the export alembic file (nor our code) but what do you mean "as blank objects" a null object ?
                    If you have a good argument for that, i will be happy to add a suggestion in our database and ping our devs to change that. Unless they have a really good reason to return a blank object they will be also happy to update it.

                    Cheers,
                    Manuel

                    MAXON SDK Specialist

                    MAXON Registered Developer

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

                      HI:
                      I found that if a polygon object has zero points on frame 0, using Alembic baking, it will only bake into blank objects.But as long as the initial number of points is not zero, the baking is normal.

                      The Python Tag script code is as follows, really just baking into blank objects.

                      
                      import c4d
                      
                      def main():
                      
                          obj = op.GetObject()
                          frame = doc.GetTime().GetFrame(doc.GetFps())
                      
                          if frame >= 25:
                              obj.ResizeObject(4,1)
                              points = [c4d.Vector(0, 0, 0),c4d.Vector(-100, 0, 0),
                                      c4d.Vector(-100, 100, 0),c4d.Vector(0, 100, 0)]
                      
                              obj.SetAllPoints(points)
                      
                              cpolygon = c4d.CPolygon(0,1,2,3)
                      
                              obj.SetPolygon(0,cpolygon)
                      
                              obj.Message(c4d.MSG_UPDATE)
                              c4d.EventAdd()
                      
                          else:
                              obj.ResizeObject(0, 0)
                              obj.Message(c4d.MSG_UPDATE)
                              c4d.EventAdd()
                      
                          if frame >= 65:
                              obj.ResizeObject(0, 0)
                              obj.Message(c4d.MSG_UPDATE)
                              c4d.EventAdd()
                      
                      if __name__=='__main__':
                          main()
                      1 Reply Last reply Reply Quote 0
                      • ManuelM
                        Manuel
                        last edited by

                        @x_nerve said in Get Point Positions of Selected N-Gon or Polygon:

                        I found that if a polygon object has zero points on frame 0, using Alembic baking, it will only bake into blank objects.But as long as the initial number of points is not zero, the baking is normal.

                        Thanks a lot for the feedback, I could reproduce that on S22 but not on R23, so it's seems to be already fixed.

                        If you found some other bugs, feel free to report them to our support team -> https://support.maxon.net/index.php?lang=en_US
                        This one in particular isn't related to our API so there's no need to report to us.

                        Cheers,
                        Manuel

                        MAXON SDK Specialist

                        MAXON Registered Developer

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

                          Hi:

                          This is a bit of a hassle, but can still be scripted, who CARES about an extra polygon.

                          import c4d
                          
                          def main():
                          
                              polygons = op.GetAllPolygons()
                              points = op.GetAllPoints()
                              point = [c4d.Vector(10000, 10000, 10000),c4d.Vector(9999, 10000,10000),
                                      c4d.Vector(9999, 10000, 10001),c4d.Vector(10000, 10000, 10001)]
                          
                              point_indexe = [[len(points) + i ,point[i]]
                                              for i in range(len(point))]
                          
                              op.ResizeObject(len(points) + len(point),len(polygons) + 1)
                          
                              set_point = [op.SetPoint(k[0], k[1])
                                              for k in point_indexe]
                          
                              op.Message(c4d.MSG_UPDATE)
                              c4d.EventAdd()
                          
                          if __name__=='__main__':
                              main()
                          1 Reply Last reply Reply Quote 0
                          • First post
                            Last post