*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