Axis Center Tool - python



  • On 13/11/2017 at 18:14, xxxxxxxx wrote:

    Hello,

    I was just wondering if someone can explain, how the axis center tool (ACT) functions, its such a useful tool and I would really like to use it in an automated manner on multiple objects. Is it originally a python script?

    e.g. I am especially interested in centering and aligning the object axis to a selected edge.

    Thanks!



  • On 14/11/2017 at 08:30, xxxxxxxx wrote:

    Hi NNenov, thanks for writing us.

    Actually the Axis Center Tool, does nothing fancy but simply compensate the space position and orientation of the points used in the mesh by a certain amount which is then back-compensated using a transformation matrix which places the mesh in the position it was supposed to be.

    I've prepared below a basic script which make this "wizardry" for selected points or selected edges. Basically from the selection I retrieve the new axis position (I basically compute the centroid starting from all the selected entities), then change the points position by this amount and, in the end, move the object back to the right position to compensate the displace I've forced on the vertexes.

      
    import c4d  
      
    def GetSelectedEdgesList(op) :  
      # check passed parameter  
      if op is None:  
          return None  
        
      # retrieve the polygons  
      polys = op.GetAllPolygons()  
      if polys is None:  
          return None  
        
      # evaluate the total number of polygons  
      polysCnt = len(polys)  
            
      # get the BaseSelect object responsible for  
      # storing the information on selected edges  
      edgeS = op.GetEdgeS()  
      if edgeS is None:  
          return None  
      
      # check the at least one edge is selected  
      if edgeS.GetCount() == 0:  
          return None  
        
      # return the list representing the selection status of an edge  
      return edgeS.GetAll(4 * polysCnt)  
      
    def GetSelectedPointsList(op) :  
      # check passed parameter  
      if op is None:  
          return None  
        
      # retrieve the points   
      points = op.GetAllPoints()  
      if points is None:  
          return None  
      
      # evaluate the total number of points  
      pointsCnt = len(points)  
            
      # get the BaseSelect object responsible for  
      # storing the information on selected points  
      pointS = op.GetPointS()  
      if pointS is None:  
          return None  
        
      # check that at least one point is selected  
      if pointS.GetCount() == 0:  
          return None  
        
      # return the list representing the selection status of a point  
      return pointS.GetAll(pointsCnt)  
      
    def CalcBaryFromSelectedEdges(selEdges, polys, points) :  
        
      # check the passed parameters  
      if selEdges is None or polys is None or points is None:  
          return None  
        
      # initialize samples count to compute the final avarage value and the centroid  
      i = 0  
      bary = c4d.Vector(0)  
        
      for index, poly in enumerate(polys) :  
          for j in range(0,4) :  
              # check the selected status of the edge  
              if selEdges[index*4+j] == 0: continue  
              # and in case sum the points representing the edge extremes   
              # to the variable used to store the centroid value  
              bary += points[poly.EdgePoints(j)[0]]  
              bary += points[poly.EdgePoints(j)[1]]  
              # increase the sample counter  
              i += 2       
                
      # compute the avarage values assuming that each sample has the same weight  
      bary = bary / i  
        
      return bary  
      
    def CalcBaryFromSelectedPoints(selPoints, points) :  
      # check the passed parameters  
      if selPoints is None or points is None:  
          return c4d.Vector(0)  
        
      # initialize samples count to compute the final avarage value and the centroid  
      i = 0  
      bary = c4d.Vector(0)  
            
      # loop through all the points  
      for index, selected in enumerate(selPoints) :  
          # check the selected status of the point  
          if not selected: continue  
          # and in case sum it to the variable used to store the centroid value  
          bary += points[index]  
          # increase the sample counter  
          i += 1  
        
      # compute the avarage values assuming that each sample has the same weight      
      bary = bary / i  
        
      return bary  
      
    def main() :  
      if op is None:  
          return  
        
      # retrieve points, polys and the current transformation matrix  
      points = op.GetAllPoints()      
      polys = op.GetAllPolygons()  
      currentMg = op.GetMg()  
      
      # retrieve the list representing the points selection status   
      selPoints = GetSelectedPointsList(op)  
        
      # retrieve the list representing the edges selection status  
      selEdges = GetSelectedEdgesList(op)  
        
      #init the centroid  
      bary = c4d.Vector(0)  
        
      # if points are selected use them to compute the new axis-position  
      if selPoints is not None:  
          bary = CalcBaryFromSelectedPoints(selPoints, points)  
      elif selEdges is not None:  
          bary = CalcBaryFromSelectedEdges(selEdges, polys, points)      
        
      # move the points by the amount represented by the new axis center  
      for index, point in enumerate(points) :  
          point -= bary  
          op.SetPoint(index, point)  
        
      # notify about the points repositioning  
      op.Message(c4d.MSG_UPDATE)  
            
      # adjust the matrix offset component accordingly  
      currentMg.off += bary  
        
      # reposition the object in the space  
      op.SetMg(currentMg)  
        
      c4d.EventAdd()  
        
        
    if __name__=='__main__':  
      main()  
    

    The code is far from being perfect (for example it doesn't consider re-orienting the axis) but extending the code to make it happen shouldn't be that complex.

    Best, Riccardo



  • On 14/11/2017 at 20:50, xxxxxxxx wrote:

    Thanks so much Ric,
    This is such a useful bit of code, I actually did something similar a few months ago but forgot it all, I remember you have to transform and then reverse transform as you said.
    What I knew in advance would really stump me is aligning the axis, e.g. getting the orientation( Alignment?) of a selected edge along a specific axis. But as you said I can probably figure it out if I look into it more thoroughly, I'm crap at maths!


Log in to reply