create a circular list by using a range of angles

2019-02-26 06:03发布

问题:

I have a list of lists which contains the lower and upper limit of sets of angles

something like

[[1,22],[2,24]...[359,15],[360,21]]

360 elements in total

Now I want to check for each angle from 1 to 360 the elements in the list that contains that angle

I was thinking about using the lower and upper limits to create all the elements of the list with range or np.arange(lower,upper) and check if the angle is contained, but np.arange generates empty list when lower is higher than upper

for i in range(1,361):
    sel=[]
    for coe in coef:
        if i in range(coe[0],coe[1]):
            sel.append(coe)

I tried also with itertools and cycle but i do not see how it can be applied in this case

回答1:

The standard way to do this is to use modulus. This answer by sschuberth shows how to do this in C/C++.

Here's a Python implementation and test. The code is simpler in Python, because in Python a % b always has the same sign as b.

The test code loops through all pairs of angles from 0 to 360 degrees in steps of 60, for a and b, testing all angles x from 0 to 360 degrees in steps of 30. The sector starts at a and sweeps through to b. Thus the sector (60, 120) contains 60°, but (120, 60) contains 300°.

If x is within the sector (including the endpoints) it gets added to the result list.

def in_angle_interval(x, a, b):
    return (x - a) % 360 <= (b - a) % 360

# test 

for a in range(0, 420, 60):
    for b in range(0, 420, 60):
        result = [x for x in range(0, 390, 30) if in_angle_interval(x, a, b)]
        print('{:3}-{:3} {}'.format(a, b, result))

output

  0-  0 [0, 360]
  0- 60 [0, 30, 60, 360]
  0-120 [0, 30, 60, 90, 120, 360]
  0-180 [0, 30, 60, 90, 120, 150, 180, 360]
  0-240 [0, 30, 60, 90, 120, 150, 180, 210, 240, 360]
  0-300 [0, 30, 60, 90, 120, 150, 180, 210, 240, 270, 300, 360]
  0-360 [0, 360]
 60-  0 [0, 60, 90, 120, 150, 180, 210, 240, 270, 300, 330, 360]
 60- 60 [60]
 60-120 [60, 90, 120]
 60-180 [60, 90, 120, 150, 180]
 60-240 [60, 90, 120, 150, 180, 210, 240]
 60-300 [60, 90, 120, 150, 180, 210, 240, 270, 300]
 60-360 [0, 60, 90, 120, 150, 180, 210, 240, 270, 300, 330, 360]
120-  0 [0, 120, 150, 180, 210, 240, 270, 300, 330, 360]
120- 60 [0, 30, 60, 120, 150, 180, 210, 240, 270, 300, 330, 360]
120-120 [120]
120-180 [120, 150, 180]
120-240 [120, 150, 180, 210, 240]
120-300 [120, 150, 180, 210, 240, 270, 300]
120-360 [0, 120, 150, 180, 210, 240, 270, 300, 330, 360]
180-  0 [0, 180, 210, 240, 270, 300, 330, 360]
180- 60 [0, 30, 60, 180, 210, 240, 270, 300, 330, 360]
180-120 [0, 30, 60, 90, 120, 180, 210, 240, 270, 300, 330, 360]
180-180 [180]
180-240 [180, 210, 240]
180-300 [180, 210, 240, 270, 300]
180-360 [0, 180, 210, 240, 270, 300, 330, 360]
240-  0 [0, 240, 270, 300, 330, 360]
240- 60 [0, 30, 60, 240, 270, 300, 330, 360]
240-120 [0, 30, 60, 90, 120, 240, 270, 300, 330, 360]
240-180 [0, 30, 60, 90, 120, 150, 180, 240, 270, 300, 330, 360]
240-240 [240]
240-300 [240, 270, 300]
240-360 [0, 240, 270, 300, 330, 360]
300-  0 [0, 300, 330, 360]
300- 60 [0, 30, 60, 300, 330, 360]
300-120 [0, 30, 60, 90, 120, 300, 330, 360]
300-180 [0, 30, 60, 90, 120, 150, 180, 300, 330, 360]
300-240 [0, 30, 60, 90, 120, 150, 180, 210, 240, 300, 330, 360]
300-300 [300]
300-360 [0, 300, 330, 360]
360-  0 [0, 360]
360- 60 [0, 30, 60, 360]
360-120 [0, 30, 60, 90, 120, 360]
360-180 [0, 30, 60, 90, 120, 150, 180, 360]
360-240 [0, 30, 60, 90, 120, 150, 180, 210, 240, 360]
360-300 [0, 30, 60, 90, 120, 150, 180, 210, 240, 270, 300, 360]
360-360 [0, 360]

And here's a test using the data in the question.

coef = [[1,22], [2,24], [359,15], [360,21]]
print(coef)
for x in range(0, 361):
    sel = [coe for coe in coef if in_angle_interval(x, coe[0], coe[1])]
    if sel:
        print('{:3} {}'.format(x, sel))

output

[[1, 22], [2, 24], [359, 15], [360, 21]]
  0 [[359, 15], [360, 21]]
  1 [[1, 22], [359, 15], [360, 21]]
  2 [[1, 22], [2, 24], [359, 15], [360, 21]]
  3 [[1, 22], [2, 24], [359, 15], [360, 21]]
  4 [[1, 22], [2, 24], [359, 15], [360, 21]]
  5 [[1, 22], [2, 24], [359, 15], [360, 21]]
  6 [[1, 22], [2, 24], [359, 15], [360, 21]]
  7 [[1, 22], [2, 24], [359, 15], [360, 21]]
  8 [[1, 22], [2, 24], [359, 15], [360, 21]]
  9 [[1, 22], [2, 24], [359, 15], [360, 21]]
 10 [[1, 22], [2, 24], [359, 15], [360, 21]]
 11 [[1, 22], [2, 24], [359, 15], [360, 21]]
 12 [[1, 22], [2, 24], [359, 15], [360, 21]]
 13 [[1, 22], [2, 24], [359, 15], [360, 21]]
 14 [[1, 22], [2, 24], [359, 15], [360, 21]]
 15 [[1, 22], [2, 24], [359, 15], [360, 21]]
 16 [[1, 22], [2, 24], [360, 21]]
 17 [[1, 22], [2, 24], [360, 21]]
 18 [[1, 22], [2, 24], [360, 21]]
 19 [[1, 22], [2, 24], [360, 21]]
 20 [[1, 22], [2, 24], [360, 21]]
 21 [[1, 22], [2, 24], [360, 21]]
 22 [[1, 22], [2, 24]]
 23 [[2, 24]]
 24 [[2, 24]]
359 [[359, 15]]
360 [[359, 15], [360, 21]]


回答2:

Maybe using a customized compare function?

    def compare(angle, lower, upper):
        if lower <= upper:
            return lower <= angle and angle <= upper
        else:
            return ((angle >= lower and angle <= 360)
                    or (angle <= upper and angle >= 1))

Then test if the angle is in any of the intervals:

    >>> angle
    3
    >>> intervals
    [[1,22],[2,24]...[359,15],[360,21]]
    >>> any([compare(angle, *interval) for interval in intervals])
    True