• Categories
    • Overview
    • News & Information
    • Cinema 4D SDK Support
    • Cineware SDK Support
    • ZBrush 4D SDK Support
    • Bugs
    • General Talk
  • Unread
  • Recent
  • Tags
  • Users
  • Register
  • Login
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
  • Register
  • Login

How to select an Edge

Cinema 4D SDK
s22 python
3
8
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.
  • C
    chuanzhen
    last edited by Mar 26, 2022, 2:59 AM

    Hi,
    I know how to select a point / face, but I still don't know how to select an edge. Does each edge have a unique ID? For example, two quadrilateral faces have seven edges. If I choose an edge, I can know that its ID is 6.
    I have a picture below. I have marked the edges I want to choose, but I don't know what to do. Can have a simple code demonstration?问题.png
    Thanks for any help!

    相信我,可以的!

    1 Reply Last reply Reply Quote 0
    • C
      Cairyn
      last edited by Mar 26, 2022, 10:42 AM

      While points and polygons are objects in C4D that are identified by an index of an array (where the actual point/polygon data is stored), edges are not - they exist only as "inferred" data and will be described through the polygons they belong to, and an "edge index" within that polygon.

      If you look at the PolygonObject and the method GetEdgeS(), you will find the text:
      "The edges are indexed by 4 * polygon + edge where polygon is the polygon index and edge is the edge index between 0 and 3."
      (The docs don't tell, but it's kinda obvious: "edge index" 0 is between points a and b of the polygon, 1 between points b and c, 2 between points c and d, and 3 between points d and a.)
      This will result in an "encoded enumeration" (or an ID, if you want) for the edge. (But it's not an index in the sense of points and polygons, as there is no edge data that this index could point to.)

      Now, if you look at the first example and want to know what that edge's "ID" is, you may ask: Is that encoded through polygon 0 or polygon 1? Well, both. The simple code fragment

          bs = op.GetEdgeS()
          print(bs.GetCount())
      

      will result in the count 2 if you just select the middle edge.

      Looking at the full edge selection data:

      import c4d
      from c4d import gui
      
      def IterateSelected(selection, total):
          segments = selection.GetSegments()
          for seg in range(0, segments):
              minS, maxS = selection.GetRange(seg, total)
              for index in range(minS, maxS+1):
                  yield index
      
      
      def PrintSelectedEdgeIndex(obj):
          if op == None: return
          if op.GetType() != c4d.Opolygon: return
      
          total = op.GetPolygonCount() * 4
          selection = op.GetEdgeS()
          print ("Selected Edges:")
          for index in IterateSelected(selection, total):
              print ("Polygon:", index // 4, "Edge:", index % 4)
      
      
      def main():
          if op == None: return
          if op.GetType() != c4d.Opolygon: return
      
          PrintSelectedEdgeIndex(op)
      
      
      if __name__=='__main__':
          main()
      

      you will get

      Selected Edges:
      Polygon: 0 Edge: 0
      Polygon: 1 Edge: 1
      >>> 
      

      (well, since you didn't write the ABCD components of the polygons into your diagram, this is assuming that the polygons are 402- and 1043.) As you may guess, if you change the sequence of points in the polygon by "Change Point Order", the "ID" of the edge changes with it!

      So, an edge has as many "IDs" as there are polygons which share it. This requires care if you want to change the edge selection because you must ensure that all those "IDs" are selected, otherwise you get an inconsistent selection.

      If you go through the methods of a PolygonObject, you will find the additional ones: GetSelectedEdges and SetSelectedEdges, which make use of the Neighbor object. There, edges only have one "ID". I'm leaving you with the official documentation for this class though, since there are many examples and diagrams to see:
      https://developers.maxon.net/docs/py/2023_2/modules/c4d.utils/Neighbor/index.html#c4d.utils.Neighbor

      C 1 Reply Last reply Mar 27, 2022, 3:32 AM Reply Quote 0
      • C
        chuanzhen @Cairyn
        last edited by chuanzhen Mar 27, 2022, 4:30 AM Mar 27, 2022, 3:32 AM

        Hi @cairyn ,thanks for your help!
        I have made some progress, but there are still some problems!

        the image_1 show want wo select 2 edges.
        image_1:
        wenti2.png

        Through your reply, it seems that I have got 2 directions to solve my problem. I will show it in the following image_2.
        image_2:
        temp1.png

        use method 2 ,can select the edge show on gif_1.
        gif_1:
        method2.gif
        method 2 code:

        import c4d
        from c4d import gui
        
        
        def main():
            if op == None:
                return
            if op.GetType() != c4d.Opolygon:
                return
            
            bs = op.GetEdgeS()
            bs.DeselectAll()
            poly_cnt = op.GetPolygonCount()
            
            sel = bs.GetAll(poly_cnt * 4)
            
            
            edge_list = [(0,1),(0,4)]
            
        
            for poly_id in range(poly_cnt):
                poly = op.GetPolygon(poly_id)
                for edge in edge_list:
                    p1,p2 = edge
                    
                    edge_index = poly.FindEdge(p1,p2)
                    if edge_index != c4d.NOTOK:
                        sel[poly_id * 4  + edge_index] = 1
            
            bs.SetAll(sel)
                
            
            c4d.EventAdd()
        
        # Execute main()
        if __name__=='__main__':
            main()
        

        相信我,可以的!

        1 Reply Last reply Reply Quote 0
        • C
          Cairyn
          last edited by Mar 27, 2022, 10:05 AM

          Hi... not sure whether you see a problem in method 2, it seems fine to me (works, too).
          (Specifically, it works because FindEdge does not care about the direction of the edge, otherwise the middle edge might give you trouble because it runs 4-0 for poly 0, and 0-4 for poly 1. But you do not need to consider the directionality/normal of the polygon here.)
          (Also, border edges are only found once because there is only one polygon they belong to, but that is kinda obvious.)

          Now, the biggest issue seems to me that the algorithm needs to find the polygons the edges belong to. AFAIK the PolygonObject does not carry much permanent relationship data between points, polygons, and edges; only the polygon references its point indices. Everything else needs to be found by an existing method or by walking through the whole structure.

          The Neighbor class however must be initialized before usage, so in terms of speed, I wonder what is faster... Neighbor may internally initialize structures that you never use, but it is written in C++ so perhaps faster. Addressing the polygon object structure directly would be Python code, so slower, but more targeted. In case of large poly counts this may make a difference... I guess a Maxon person would be able to answer that. (I could measure runtimes directly and investigate, but I don't have the leisure to.)

          Let me just look whether I have a fitting example for Neighbor...

          1 Reply Last reply Reply Quote 0
          • C
            Cairyn
            last edited by Mar 27, 2022, 11:19 AM

            Okay, I cobbled together an example for Neighbor, but I found the class more disappointing that I remembered it.
            Neighbor doesn't seem to have many functions relating to the internal edge indices: notably, there is no method that returns the edge index for its two end points. This would make the algorithm very short (just look up all the neighbor edge indices for the given point pairs and create a BaseSelect from them).

            Instead, you can only use GetEdgePolys to find the (at most) two polygons bordering the edge given by two points. This saves you the explicit loop over all polygons... but from there, you still need to use GetPolygon to retrieve the CPolygon from the indices, then FindEdge to get the poly's edge index, then GetPolyInfo to finally get the edge's neighbor-internal index that you can use in the BaseSelect.

            It works, but unfortunately I am not convinced that it is faster or easier to read than method 2. meh

            import c4d
            from c4d import gui
            
            def IterateSelected(selection, total):
                segments = selection.GetSegments()
                for seg in range(0, segments):
                    minS, maxS = selection.GetRange(seg, total)
                    for index in range(minS, maxS+1):
                        yield index
            
            
            def PrintSelectedEdgeIndex(bs, total):
                print ("Selected Edges:")
                for index in IterateSelected(bs, total):
                    print ("Neighbor Edge:", index)
            
            
            def main():
                if op == None: return
                if op.GetType() != c4d.Opolygon: return
                ng = c4d.utils.Neighbor()
                ng.Init(op)
                print("# of edges:", ng.GetEdgeCount())
            
                # show currently selected edges
                bs = op.GetSelectedEdges(ng, c4d.EDGESELECTIONTYPE_SELECTION)
                total = op.GetPolygonCount() * 4
                PrintSelectedEdgeIndex(bs, total)
            
                # edge list as input for the selection
                edge_list = [(3,0),(0,4)]
            
                bsNew = c4d.BaseSelect()
                for edge in edge_list:
                    p1,p2 = edge
                    
                    for poly in ng.GetEdgePolys(p1, p2):
                        # print ("Poly:", poly)
                        if poly != -1:
                            pinf = ng.GetPolyInfo(poly)
                            edge_index = op.GetPolygon(poly).FindEdge(p1,p2)
                            if edge_index != c4d.NOTOK:
                                ng_edge_index = pinf["edge"][edge_index]
                                print ("Poly:", poly, 
                                            "Edge index:", edge_index, 
                                            "Neighbor edge index:", ng_edge_index)
                                bsNew.Select(ng_edge_index)
            
                op.SetSelectedEdges(ng, bsNew, c4d.EDGESELECTIONTYPE_SELECTION)
                c4d.EventAdd()
            
            
            if __name__=='__main__':
                main()
            

            (Also, I didn't catch any errors, and the code is not optimized in any way.)

            C 1 Reply Last reply Mar 28, 2022, 12:48 PM Reply Quote 0
            • C
              chuanzhen @Cairyn
              last edited by chuanzhen Mar 28, 2022, 12:51 PM Mar 28, 2022, 12:48 PM

              Hi @Cairyn
              Thanks for your help, I use method 2 to achieve my goal.
              This is a plug-in to mirror a selection of the same / different objects. Thank you for your help again,gif_2 show its work
              gif_2
              success.gif

              相信我,可以的!

              F 1 Reply Last reply Mar 29, 2022, 7:16 AM Reply Quote 0
              • F
                ferdinand @chuanzhen
                last edited by Mar 29, 2022, 7:16 AM

                Hello @chuanzhen,

                thank you for reaching out to us. And thank you @Cairyn for providing an answer. We do not have anything to addd here.

                Cheers,
                Ferdinand

                MAXON SDK Specialist
                developers.maxon.net

                C 1 Reply Last reply Mar 29, 2022, 9:47 AM Reply Quote 0
                • C
                  chuanzhen @ferdinand
                  last edited by Mar 29, 2022, 9:47 AM

                  @ferdinand Thanks your reply!

                  相信我,可以的!

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