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

    Automatically delete all inner polygons

    Scheduled Pinned Locked Moved PYTHON Development
    15 Posts 0 Posters 1.2k 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 30/11/2016 at 15:34, xxxxxxxx wrote:

      I don't think there's an easy way to determine whether a polygon is inside/outside based on topology.

      A possible strategy might be:
      List all polygons with edges connected to 3+ polygons.
      Shoot a ray from the center of those polygons in the normal direction, and the opposite of the normal direction.
      If it collides with another polygon in the same object in both directions, it's an interior polygon.
      Delete all interior polygons.

      That said, I can see that breaking down really quickly for any sort of complex convex geometries.

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

        On 01/12/2016 at 01:31, xxxxxxxx wrote:

        Hello,

        I'm not aware of any build-in command that can detect or delete inside faces. You probably would have to develop your own solution.

        But there is a command to split polygon groups into separate objects: Polygon Groups to Objects.

        This command can also be invoked using SendModelingCommand() with the command ID MCOMMAND_EXPLODESEGMENTS.

        best wishes,
        Sebastian

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

          On 01/12/2016 at 11:18, xxxxxxxx wrote:

          Hi,

          Thanks for your replys, I gives up the idea of removing the inner polygons, but I have another question.

          In my poroject I have an option with two choices.
          Choise 01 : allow to create a text with all cubes separed, where i use the command MCOMMAND_EXPLODESEGMENTS.
          Choise 02 : alow to connect all polygons, to obtain only one object. For that I have used Connect Object command then Optimize command (see the optimize setting below) :

          Steps :

          # ...          
          settings = c4d.BaseContainer()  
          settings[c4d.MDATA_OPTIMIZE_POLYGONS] = True  
          settings[c4d.MDATA_OPTIMIZE_UNUSEDPOINTS] = True  
          if fractured == 1 : # if Choise 1  
            settings[c4d.MDATA_OPTIMIZE_POINTS] = False  
          else : # if Choise 2  
            settings[c4d.MDATA_OPTIMIZE_POINTS] = True  
            settings[c4d.MDATA_OPTIMIZE_TOLERANCE] = 1 # Tested with several values.  
            
          c4d.utils.SendModelingCommand(c4d.MCOMMAND_OPTIMIZE,[polyobj],c4d.MODIFY_ALL,settings)  
          # ...
          

          The problem is : I obtain one object but her polygons are not all connected.
          Preview :

          How I can connect all polygons to obtain just a single block for each character?

          Thanks.

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

            On 01/12/2016 at 17:08, xxxxxxxx wrote:

            I think I have come up with a script that will delete the inner polygons for you.
            I've only tested it with a few cubes. But it seems to work.
            *This a specific script targeted to your specific task(combining cubes). And probably won't work for objects other than cubes.

            There is no error checking in this. So please be sure that you do this before running the script:
            1 - Converted all of the cubes to polygon type objects first
            2 - Have your cubes butted against each other properly so two polygons share the same position
            3 - Selected all of the cube objects you want to combine

            #This script combines all selected cube objects that are butted together into a single mesh  
            #Then it get's the center positions for all of the polygons  
            #Then it compares these positions to see if any two polygon's are in the same position (the inner polygons)  
            #Then it selects them if they are in the same position and deletes them  
            #Finally..it runs the optimize points command on the object's points  
              
            import c4d  
            def main() :  
                
              c4d.CallCommand(16768)   #Connect Objects + Delete  
                
              obj = doc.GetActiveObject()  
              objmg = obj.GetMg()  
              poly = obj.GetAllPolygons()  
              PolyS = obj.GetPolygonS()  
              centers = []  
                
              #Loop through the list of polygons to get their points  
              for p in poly:  
                  ptA = obj.GetPoint(p.a)  
                  ptB = obj.GetPoint(p.b)  
                  ptC = obj.GetPoint(p.c)  #These are local point values  
                  ptD = obj.GetPoint(p.d)  
                
                  polyCenterL = (ptA + ptB + ptC + ptD)/4 #This is the local Midpoint position  
                  polyCenterG = polyCenterL * objmg       #Convert it to a global position  
                  centers.append(polyCenterG)  
              
              #Find any two polygons that share the same center positions and select them    
              for i in xrange(len(centers)) :  
                for j in xrange(i + 1, len(centers)) :  
                  if centers[i] == centers[j]:  
                    PolyS.Select(i)  
                    PolyS.Select(j)  
                      
              #Delete the selected polygons  
              c4d.utils.SendModelingCommand(command=c4d.MCOMMAND_DELETE,  
                                            list=[obj],  
                                            mode=c4d.MODELINGCOMMANDMODE_POLYGONSELECTION,  
                                            doc=doc)            
                  
              #Optimize (weld) the object's points      
              bc = c4d.BaseContainer()  
              bc.SetData(c4d.MDATA_OPTIMIZE_TOLERANCE, 1.5)  
              bc.SetData(c4d.MDATA_OPTIMIZE_POINTS, True)  
              bc.SetData(c4d.MDATA_OPTIMIZE_UNUSEDPOINTS,True)  
              c4d.utils.SendModelingCommand(c4d.MCOMMAND_OPTIMIZE, list = [obj], mode = c4d.MODIFY_ALL, bc=bc, doc = doc)  
                
                
              c4d.EventAdd()  
                
            if __name__=='__main__':  
              main()
            

            -ScottA

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

              On 02/12/2016 at 08:58, xxxxxxxx wrote:

              Hi,

              Big Thanks! I don't know how to thank You for the help that you have given me.
              I have tested your script, that works at around 95%. see te screenshoot below:

              I was looking at the object again and again to understand why there is this problem and unsuccessfully.
              Here the object that i have used : PObject.c4d

              Thanks again!

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

                On 02/12/2016 at 09:15, xxxxxxxx wrote:

                I'm not really surprised it doesn't work 100%. Because I never really tested it much beyond a few simple cubes. Just something I bashed together in a  few minutes.
                Maybe adding a range option to it so the polygon centers don't need to be exactly at the same position to get selected & deleted will get those stingy ones?

                If I get time I'll see if I can improve it. But I'm a little bit busy at the moment. So no promises.
                Maybe someone else can improve upon it?

                -ScottA

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

                  On 02/12/2016 at 09:51, xxxxxxxx wrote:

                  No problem, Thank you so much for all you have done for me.

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

                    On 02/12/2016 at 10:50, xxxxxxxx wrote:

                    NP.
                    This does script not solve the problem. But it was quick for me to write. So I'll post it.
                    This one selects polygons using a distance value. But It's not 100% the same as the previous one.
                    Perhaps with these scripts you can come up with something that does work.

                    #This version selects polygons that are less than the distance value apart  
                    #With this code your cube's polygons don't have to touch each other exactly for it to work   
                    #Play around with the distance and MDATA_OPTIMIZE_TOLERANCE value depending on the cubes layout  
                      
                    import c4d  
                    def main() :  
                        
                      distance = 10  #<--- Change this as desired depending on how far away each cube is   
                        
                      c4d.CallCommand(16768) #Connect Objects + Delete  
                        
                      obj = doc.GetActiveObject()  
                      objmg = obj.GetMg()  
                      poly = obj.GetAllPolygons()  
                      PolyS = obj.GetPolygonS()  
                      centers = []  
                        
                      for p in poly:            #Loop thru the list of polygons   
                          ptA = obj.GetPoint(p.a)  
                          ptB = obj.GetPoint(p.b)  
                          ptC = obj.GetPoint(p.c)  #These are local point values  
                          ptD = obj.GetPoint(p.d)  
                        
                          polyCenterL = (ptA + ptB + ptC + ptD)/4 #This is the local Midpoint position  
                          polyCenterG = polyCenterL * objmg     #Convert it to a global position  
                          centers.append(polyCenterG)  
                            
                      for i in xrange(len(centers)) :  
                        for j in xrange(i + 1, len(centers)) :  
                            vec = centers[i] - centers[j]  
                            dist = abs(vec.GetLength())  
                            if dist < distance:  
                                PolyS.Select(i)  
                                PolyS.Select(j)    
                              
                      c4d.utils.SendModelingCommand(command=c4d.MCOMMAND_DELETE,  
                                                    list=[obj],  
                                                    mode=c4d.MODELINGCOMMANDMODE_POLYGONSELECTION,  
                                                    doc=doc)  
                              
                              
                      bc = c4d.BaseContainer()  
                      bc.SetData(c4d.MDATA_OPTIMIZE_TOLERANCE, distance)  
                      bc.SetData(c4d.MDATA_OPTIMIZE_POINTS, True)  
                      bc.SetData(c4d.MDATA_OPTIMIZE_UNUSEDPOINTS,True)  
                      c4d.utils.SendModelingCommand(c4d.MCOMMAND_OPTIMIZE, list = [obj], mode = c4d.MODIFY_ALL, bc=bc, doc = doc)  
                            
                      c4d.EventAdd()  
                        
                    if __name__=='__main__':  
                      main()
                    

                    -ScottA

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

                      On 02/12/2016 at 16:52, xxxxxxxx wrote:

                      Hi,
                      I tested the last script, but nothing happens. only the Optimize command that works.

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

                        On 02/12/2016 at 18:13, xxxxxxxx wrote:

                        You'll have to play around with the distance and MDATA_OPTIMIZE_TOLERANCE values.
                        They are set fairly high. And might not work on cubes if they are small and already touching each other.
                        So lowering them should produce better results in that case.

                        When I was lining up cubes. I noticed that it was sort of a pain to get their faces exactly touching in the same position. That's why I wrote the second distance version, so it would combine them even if they were a small distance apart depending on the distance value in the script.
                        Both scripts do the same thing. The second one just allows you to connect non touching cubes.
                        If your cubes are already touching. The second version won't be of any benefit.

                        -ScottA

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

                          On 02/12/2016 at 20:22, xxxxxxxx wrote:

                          The problem stems from this line :

                          dist = abs(distance)
                          
                          # ...  
                          for i in xrange(len(centers)) :  
                              for j in xrange(i + 1, len(centers)) :  
                                  vec = centers[i] - centers[j]  
                                  dist = vec.GetLength()  
                                  **#dist = abs(distance)   **          
                                  if dist < distance:  
                                      print dist                
                                      PolyS.Select(i)  
                                      PolyS.Select(j)  
                          # ...
                          

                          After disabling this line it worked at 100%.
                          Thank you very much and have a good day.

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

                            On 02/12/2016 at 21:21, xxxxxxxx wrote:

                            DOH! My fault.
                            I renamed things and I missed that one.😊

                            Although it's working for you. It might be possible to get negative numbers from dist without using abs. And that would make the distance value not work correctly.
                            I edited the code.
                            Glad that it's working for you.

                            -ScottA

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

                              On 03/12/2016 at 13:37, xxxxxxxx wrote:

                              Hi, again me. I have another question:

                              I want to add a option that allow to delete only the horizontal polygons or only the vertical polygons. or the both together (Inner Polygons).

                              The script below allow to select only the vertical polygons, but I dont know how I can apply it on the script above to delete only the vertical polygons for example.

                              poly = obj.GetAllPolygons()  
                              sel_polys = obj.GetPolygonS()  
                              index = 0  
                              for p in poly:  
                                ptA = obj.GetPoint(p.a)  
                                ptB = obj.GetPoint(p.b)  
                                if ptA.y == ptB.y :  
                                    sel_polys.Select(index)  
                                index += 1
                              
                              1 Reply Last reply Reply Quote 0
                              • H Offline
                                Helper
                                last edited by

                                On 03/12/2016 at 14:26, xxxxxxxx wrote:

                                I found a solution to delete only the horizontal polygons for example.

                                import c4d  
                                def main() :  
                                   
                                  distance = 10 #<--- Change this as desired depending on how far away each cube is   
                                    
                                  c4d.CallCommand(16768) #Connect Objects + Delete  
                                    
                                  obj = doc.GetActiveObject()  
                                  objmg = obj.GetMg()  
                                  poly = obj.GetAllPolygons()  
                                  PolyS = obj.GetPolygonS()  
                                  centers = []  
                                  **indexL = []  
                                  index = 0**  
                                  for p in poly:            #Loop thru the list of polygons   
                                      ptA = obj.GetPoint(p.a)  
                                      ptB = obj.GetPoint(p.b)  
                                      ptC = obj.GetPoint(p.c)  #These are local point values  
                                      ptD = obj.GetPoint(p.d)  
                                    
                                      polyCenterL = (ptA + ptB + ptC + ptD)/4 #This is the local Midpoint position  
                                      polyCenterG = polyCenterL * objmg     #Convert it to a global position  
                                      centers.append(polyCenterG)  
                                      **if ptA.y == ptB.y :  
                                ** **             ****indexL.append(index)  
                                ** **         ****index += 1**  
                                  
                                  for i in xrange(len(centers)) :  
                                      for j in xrange(i + 1, len(centers)) :  
                                          vec = centers[i] - centers[j]  
                                          dist = abs(vec.GetLength())  
                                          if dist < distance **and i in indexL** :  
                                              PolyS.Select(i)  
                                              PolyS.Select(j)    
                                          
                                  c4d.utils.SendModelingCommand(command=c4d.MCOMMAND_DELETE,  
                                                                list=[obj],  
                                                                mode=c4d.MODELINGCOMMANDMODE_POLYGONSELECTION,  
                                                                doc=doc)  
                                  
                                  bc = c4d.BaseContainer()  
                                  bc.SetData(c4d.MDATA_OPTIMIZE_TOLERANCE, distance)  
                                  bc.SetData(c4d.MDATA_OPTIMIZE_POINTS, True)  
                                  bc.SetData(c4d.MDATA_OPTIMIZE_UNUSEDPOINTS,True)  
                                  c4d.utils.SendModelingCommand(c4d.MCOMMAND_OPTIMIZE, list = [obj], mode = c4d.MODIFY_ALL, bc=bc, doc = doc)  
                                        
                                  c4d.EventAdd()  
                                    
                                if __name__=='__main__':  
                                  main()
                                
                                1 Reply Last reply Reply Quote 0
                                • First post
                                  Last post