You are given an array points, an integer angle, and your location, where location = [posx, posy] and points[i] = [xi, yi] both denote integral coordinates on the X-Y plane.

Initially, you are facing directly east from your position. You cannot move from your position, but you can rotate. In other words, posx and posy cannot be changed. Your field of view in degrees is represented by angle, determining how wide you can see from any given view direction. Let d be the amount in degrees that you rotate counterclockwise. Then, your field of view is the inclusive range of angles [d - angle/2, d + angle/2].


Your browser does not support the video tag or this video format.


You can see some set of points if, for each point, the angle formed by the point, your position, and the immediate east direction from your position is in your field of view.

There can be multiple points at one coordinate. There may be points at your location, and you can always see these points regardless of your rotation. Points do not obstruct your vision to other points.

Return the maximum number of points you can see.

&nbsp;
Example 1:

Input: points = [[2,1],[2,2],[3,3]], angle = 90, location = [1,1]
Output: 3
Explanation: The shaded region represents your field of view. All points can be made visible in your field of view, including [3,3] even though [2,2] is in front and in the same line of sight.


Example 2:

Input: points = [[2,1],[2,2],[3,4],[1,1]], angle = 90, location = [1,1]
Output: 4
Explanation: All points can be made visible in your field of view, including the one at your location.


Example 3:

Input: points = [[1,0],[2,1]], angle = 13, location = [1,1]
Output: 1
Explanation: You can only see one of the two points, as shown above.


&nbsp;
Constraints:


	1 &lt;= points.length &lt;= 105
	points[i].length == 2
	location.length == 2
	0 &lt;= angle &lt; 360
	0 &lt;= posx, posy, xi, yi &lt;= 100


class Solution:
    def visiblePoints(self, points: List[List[int]], angle: int, location: List[int]) -> int:

        arr, extra = [], 0
        xx, yy = location

        for x, y in points:
            if x == xx and y == yy:
                extra += 1
                continue
            arr.append(math.atan2(y - yy, x - xx))

        arr.sort()
        arr = arr + [x + 2.0 * math.pi for x in arr]
        angle = math.pi * angle / 180

        l = ans = 0
        for r in range(len(arr)):
            while arr[r] - arr[l] > angle:
                l += 1
            ans = max(ans, r - l + 1)

        return ans + extra
class Solution {
    public int visiblePoints(List<List<Integer>> points, int angle, List<Integer> location) {
        int overlap = 0;
        List<Double> list = new ArrayList<>(points.size());
        for (List<Integer> p : points) {
            if (p.get(0) == location.get(0) && p.get(1) == location.get(1)) {
                overlap++;
            } else {
                list.add(angle(p.get(1) - location.get(1),
                               p.get(0) - location.get(0)));
            }
        }
        Collections.sort(list);
        int max = 0;
        int n = list.size();
        int i2 = 0;
        // list.get(i1) is first angle leg
        // list.get(i2) is second angle leg
        for (int i1 = 0; i1 < n; i1++) {
            // let's grow i1-i2 angle as much as possible
            // edge case example: angle = 30, i1 = 350 degrees, i2 = 10 degrees
            // edge case handling: allow i2 to circle around and calculate second leg as (360 + list.get(i2 % n))
            // then i1 = 350, i2 = 370, delta = 20 degrees < 30 degrees
            while ((i2 < n && list.get(i2) - list.get(i1) <= angle) ||
                   (i2 >= n && 360 + list.get(i2 % n) - list.get(i1) <= angle)) {
                i2++;
            }
            // after i2 went as far as possible away from i1 under allowed limit - check if a new maximum found
            max = Math.max(max, i2-i1);
        }
        return max + overlap;
    }

    private double angle(int dy, int dx) {
        double a = Math.toDegrees(Math.atan2(dy, dx));
        return (a < 0 ? a + 360 : a);
    }
}
class Solution {
public:
    int visiblePoints(vector<vector<int>>& points, int angle, vector<int>& location) {
        vector<double> pa;
        int at_start=0;
        for(auto point:points)
        {
            if(point[0]==location[0] && point[1]==location[1])
                at_start++;
            else
            {
                double ang = atan2(point[1]-location[1], point[0]-location[0]) * 180.0 /M_PI;
                if(ang<0)
                    ang+=360;
                pa.push_back(ang);
            }
        }
        sort(pa.begin(), pa.end());
        int n=pa.size();   
        int l = 0, ret=0;
        for(int i=0; i<n; i++)
            pa.push_back(pa[i] + 360);
        for(int r=0; r<pa.size(); r++)
        {
            while((pa[r]-pa[l])>angle)
                l++;
            ret = max(ret, r-l+1);
        }
        return ret+at_start;
    }
};
// basically First i transform my points into degrees in regards to my location as the center
// I need to perform a sliding window to see how many points can fit within my window of length
// angle 
var visiblePoints = function(points, angle, location) {
    
    //Math.atan2(y,x) returns the ANGLE in RADIANS between the point (X,Y), the CENTER (0,0) and x'x
    // so Math.atan2(5,5) * (180/Math.pi) === 45 //transforms it from radians to degrees instead
    let [sx,sy]=location
    let onCenter=points.filter(([x,y])=>(x==sx&&y==sy)).length //if i m standing on a point i always count it

    points=points.filter(([x,y])=>!(x==sx&&y==sy)) //other than that i dont want it messing with my result

                 .map(([x,y])=>{
                    // i need to transform my center from (0,0) to location, hence (y-sy,x-sx)
                         return Math.atan2(y-sy,x-sx)*(180/Math.PI) //returns the degrees
                    })
                 .sort((a,b)=>a-b) 

    //I will now perform the circular array duplication trick in order to consider points from different view
    points=[...points,...points.map(d=>d+360)] 
    // so for example if a point is 340, it can go with a point that is 15
    // example : [0,60,230,250,359], angle=200
    // would become     [0,60,230,250,359,360,420,590,610,719]
    // would allow me to pick  *   *   *   *   * ,which is practically [230,250,359,0,60] 
    // (every element of my starting array), which are obviously visible with anangle fo 200 deg


    //now i will perform a sliding window that tracks the points visible from my current degree-my angle degrees
    let start=0,n=points.length,result=0
    for (let end = 0; end < n; end++) {
        while(start<end&&points[start]<points[end]-angle) //if the point of start is no bueno
            start++ // shrink the window until all the points are within angle degrees 
        result=Math.max(result,end-start+1)
    }
    return result+onCenter //the points i can see + the ones i ms tanding on

};
Maximum Number of Visible Points