How to get center of set of points using Python
Asked Answered
M

4

38

I would like to get the center point(x,y) of a figure created by a set of points.

How do I do this?

Martres answered 4/12, 2010 at 21:21 Comment(2)
Define "center". Center of gravity? Centroid? Something else?Ferebee
This is more like a math related question. I think in this exellent book: openbookproject.net/thinkcs I dont remember if in python or C++, there are some examples of what you are trying to achieve.Dorothydorp
C
46

If you mean centroid, you just get the average of all the points.

x = [p[0] for p in points]
y = [p[1] for p in points]
centroid = (sum(x) / len(points), sum(y) / len(points))
Cappuccino answered 4/12, 2010 at 21:27 Comment(3)
But be careful with integer division in Python 2.x: if every point has an integer x value, the x value of your centroid will be rounded down to an integer. Use from __future__ import division, explicitly convert to a float before division, or use Python 3.Talley
If points is a two-dimensional Numpy array, you can probably just use points.mean(0).Babirusa
that is not the centroid, is just the average of the points. If you want to compute the centroid, you have to use Green's theorem for discrete segments, as in en.wikipedia.org/wiki/Centroid#Centroid_of_polygonGinoginsberg
H
16

If the set of points is a numpy array positions of sizes N x 2, then the centroid is simply given by:

centroid = positions.mean(axis=0)

It will directly give you the 2 coordinates a a numpy array.

In general, numpy arrays can be used for all these measures in a vectorized way, which is compact and very quick compared to for loops.

Hamford answered 12/4, 2018 at 13:55 Comment(0)
D
10

I assume that a point is a tuple like (x,y), so you can use zip to join the x's and y's. Then using the min and max of x and y's, you can determine the center point.

x,y=zip(*points)
center=(max(x)+min(x))/2., (max(y)+min(y))/2.

Sample output

Points in an array : [(411, 148), (304, 148), (357, 241)]
x:(411, 304, 357)
y:(148, 148, 241)
center: (357.5, 194.5)
Dixiedixieland answered 4/12, 2010 at 21:32 Comment(4)
Shouldn't that be max + min, not max - min?Talley
trying to understand what this is doing... why do we 'add' the min to the max? The answer from @colin makes sense to me, but wasn't sure why this works too.Kazachok
you are using min max instead of subtraction and addition. As an example, if min was 10 and max was 40 - min is 10 and max is 40, so that is 50/2=25. You can arrive at the same answer with 10 + ((40-10)/2) - both work perfectly well.Pettifogger
Just another note: This center and the other answer are not the same center - for polygons there are multiple "center" formulas en.wikipedia.org/wiki/CentroidPettifogger
A
4

In this case the average of the points isn't the centroid. Generally speaking the center of area is the first moment of area. So you have to calculate the areas of the polygons that define the shape of your figure, then compute the first moment of area for each axis: sum((r_i * A_i), for i in range(N))/sum(A_i). So we can have a set of points lying on the contour of the figure:

Contents of data.dat:

x,y
0.99159,0.00467
0.97822,0.00828
0.96383,0.01237
0.94834,0.01703
0.93166,0.02231
0.91374,0.02816
0.89456,0.03443
0.87415,0.04092
0.85265,0.04755
0.83029,0.05426
0.80736,0.06099
0.78414,0.06766
0.76087,0.07423
0.73768,0.08064
0.71456,0.08687
0.69143,0.09294
0.6681,0.09886
0.64446,0.10469
0.62058,0.11041
0.59684,0.11598
0.57378,0.12127
0.55182,0.12613
0.53101,0.13048
0.51113,0.13432
0.49187,0.13766
0.47287,0.14054
0.4538,0.14301
0.43445,0.14514
0.4148,0.14694
0.39496,0.14844
0.37527,0.14964
0.3561,0.15051
0.33766,0.151
0.31999,0.15111
0.303,0.15081
0.28655,0.15011
0.27048,0.149
0.25467,0.14748
0.23907,0.14558
0.22372,0.14331
0.20869,0.14071
0.19411,0.13782
0.1801,0.1347
0.16677,0.13138
0.1542,0.12788
0.1424,0.12422
0.13136,0.12042
0.12106,0.1165
0.11142,0.11244
0.1024,0.10826
0.09391,0.10393
0.08588,0.09944
0.07824,0.09486
0.07098,0.0903
0.06412,0.08592
0.05772,0.08177
0.05182,0.07782
0.04641,0.07403
0.04142,0.07034
0.03683,0.06673
0.03258,0.0632
0.02864,0.05975
0.025,0.05637
0.02164,0.05307
0.01853,0.04985
0.01567,0.04669
0.01307,0.04357
0.01073,0.04047
0.00864,0.03735
0.00679,0.03423
0.00517,0.0311
0.00377,0.02798
0.00258,0.02487
0.00158,0.02177
0.00078,0.0187
0.00017,0.01565
-0.00025,0.01262
-0.00049,0.00962
-0.00055,0.00663
-0.00042,0.00367
-9.00E-05,0.00073
0.00043,-0.00218
0.00114,-0.00508
0.00206,-0.00793
0.00316,-0.01073
0.00447,-0.01346
0.00599,-0.0161
0.00772,-0.01865
0.00968,-0.02106
0.01188,-0.02333
0.01435,-0.02541
0.01711,-0.02728
0.02016,-0.02894
0.02351,-0.03043
0.02714,-0.03179
0.03101,-0.03309
0.03514,-0.03434
0.03955,-0.03555
0.04429,-0.03675
0.04937,-0.03795
0.05483,-0.03918
0.06069,-0.04048
0.06697,-0.0418
0.07372,-0.04312
0.081,-0.04436
0.0889,-0.0455
0.0976,-0.04653
0.10725,-0.04749
0.11801,-0.0484
0.13002,-0.04926
0.1434,-0.05007
0.15815,-0.05085
0.17419,-0.05161
0.19136,-0.05227
0.20955,-0.05274
0.22884,-0.05293
0.2494,-0.05286
0.27136,-0.05256
0.29473,-0.05206
0.3192,-0.05146
0.3442,-0.05081
0.36921,-0.05008
0.39401,-0.04924
0.41866,-0.04826
0.44342,-0.04713
0.46845,-0.04586
0.49376,-0.04447
0.51919,-0.04299
0.54445,-0.04142
0.56941,-0.03976
0.5941,-0.03796
0.61869,-0.036
0.64343,-0.03387
0.66852,-0.03162
0.69403,-0.0293
0.7199,-0.02698
0.74597,-0.02469
0.77207,-0.02242
0.79809,-0.02016
0.82397,-0.0179
0.84958,-0.01566
0.8746,-0.01347
0.8986,-0.01136
0.92114,-0.00939
0.94183,-0.00758
0.96037,-0.00596
0.97676,-0.00453
0.99124,-0.00326
1,-0.0025

Code: Calculate the first moment of area

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt

data = pd.read_table('data.dat',delim_whitespace=True,skiprows=[0],names=['x','y'],index_col=False)
x = data.x.to_numpy() 
y = data.y.to_numpy()

N = range(len(data)-1)
M = np.array([(x[i]-x[i+1])*(y[i]+y[i+1])/2 for i in N]) #Area of each trapezoid
My = np.array([(x[i]+x[i+1])/2 for i in N])*M #Moment of area (area*distance to centroid) with respect to the Y axis of each trapezoid
Mx = np.array([(y[i]+y[i+1])/4 for i in N])*M #Moment of area (area*distance to centroid) with respect to the X axis of each trapezoid
X = sum(My)/sum(M)
Y = sum(Mx)/sum(M)

centroid = [X , Y]

points_ave = data.mean(axis=0)

plt.plot(data.x, data.y, 'r',marker='.',markeredgecolor='black', markersize=3)
plt.plot(*centroid, 'blue', marker='o',markeredgecolor='black', markersize=7)
plt.plot(*points_ave, 'green', marker='o',markeredgecolor='black', markersize=7)
plt.axis('equal')
plt.xlim((-0.05, 1.05))
plt.legend(['GOE 383 AIRFOIL','Centroid','Average of points'])

In the following image you can very clearly see how the non-uniform point sampling skews the results. The average of points is only useful for point masses or concentrated properties.

Figure Centroid

Arlenearles answered 7/11, 2022 at 20:6 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.