Automatically delete all inner polygons



  • On 30/11/2016 at 12:02, xxxxxxxx wrote:

    Hello there,

    My text is composed of multiple cubes, then I connecte all cubes to obtain one object. Now I search a solution to delete all the inner polygons (see the picture below)

    Is it possible to do that automatically?

    Second question:
    Is it possible to automatically separate each character to one object (with all polygons connected). Even without deleting the inner polygons.

    Thanks!



  • 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.



  • 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



  • 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.



  • 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



  • 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!



  • 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



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

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



  • 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



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

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



  • 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



  • 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.



  • 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



  • 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
    


  • 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()
    

Log in to reply