jonboy
jonboy

Reputation: 368

Count points within circle segments - Python

I'm trying to return a count of points within specified segments of a circle. The following df contains points at various timescales. The circle centre is designated by refX and refY. I'm hoping to split the circle into 4 even segments but re-orientate the segments based on the value provided by rotation_angle. Essentially, segment 1 is directly orientated by the rotation_angle and the following segments (2-4) go clockwise from this angle.

import pandas as pd
import numpy as np

df = pd.DataFrame({   
    'Time' : [1,1,1,1,2,2,2,2],             
    'id' : ['A','B','C','D','A','B','C','D'],                 
    'X' : [1,-1,-1,2,1,-1,-2,2],
    'Y' : [-2,-2,2,2,2,-2,-2,2],
    'refX' : [0,0,0,0,-1,-1,-1,-1],
    'refY' : [0,0,0,0,1,1,1,1],   
    'rotation_angle' : [-135,-135,-135,-135,0,0,0,0]                 
    })


def checkPoint(x, y, rotation_angle, refX, refY, radius = 5):

    section_angle_start = [(i + rotation_angle - 45) for i in [0, 90, 180, 270, 360]]

    Angle = np.arctan2(x-refX, y-refY) * 180 / np.pi
    Angle = Angle % 360

    for i in range(4):
        if section_angle_start[i] < Angle < section_angle_start[i+1]:
            break
    else:
        i = 0

    return i+1  

time = 1
tmp = []
result = []

for i, row in df.iterrows():
    seg = checkPoint(row.X, row.Y, row.rotation_angle, row.refY, row.refX)
    if row.Time == time:
        tmp.append(seg)
    else:
        result.append([time]+[tmp.count(i) for i in [1,2,3,4]])
        time += 1 
        tmp = []
        tmp.append(seg)

result.append([time]+[tmp.count(i) for i in [1,2,3,4]])

result = pd.DataFrame(result, columns=['Time', 'Seg1', 'Seg2', 'Seg3', 'Seg4'])

print(result)

Intended Output:

   Time  Seg1  Seg2  Seg3  Seg4
0     1     1     1     1     1
1     2     0     2     2     0

Upvotes: 0

Views: 726

Answers (1)

shimo
shimo

Reputation: 2285

You can check in which segment each point is, by determining the position and angle of the circle and axis. Note that axis refX,refY are 90deg rotated to xy axis. And the case points are on the axis is eliminated in this code.

# df is from your question...

def checkPoint(x, y, rotation_angle, refX, refY, radius = 5):
    import sys

    # check if is it inside circle
    if (y-refY)**2 + (x-refX)**2 > radius**2:
        print("outo of radius")
        sys.exit()

    section_angle_start = [(i + rotation_angle - 45) for i in [0, 90, 180, 270, 360]]

    Angle = np.arctan2(x-refX, y-refY) * 180 / np.pi
    Angle = Angle % 360

    # adjust range
    if Angle > section_angle_start[-1]:
        Angle -= 360
    elif Angle < section_angle_start[0]:
        Angle += 360

    for i in range(4):
        if section_angle_start[i] < Angle < section_angle_start[i+1]:
            break
    else:
        i = 0

    return i+1  # found segment


time = 1
tmp = []
result = []

for i, row in df.iterrows():
    seg = checkPoint(row.X, row.Y, row.rotation_angle, row.refX, row.refY)
    if row.Time == time:
        tmp.append(seg)
    else:
        result.append([time]+[tmp.count(i) for i in [1,2,3,4]])
        time += 1 
        tmp = []
        tmp.append(seg)

result.append([time]+[tmp.count(i) for i in [1,2,3,4]])


pd.DataFrame(result, columns=['Time', 'Seg1', 'Seg2', 'Seg3', 'Seg4'])

Upvotes: 1

Related Questions