Let's implement the condition that the circumference and the inside of the Ougi shape are included in Java [Part 1]

1. 1. Introduction

I had been playing a game called Metal Gear Solid for the first time in a while, but suddenly I was wondering what kind of algorithm the player-controlled character would be visible to the surveillance cameras and enemy soldiers. So, I decided to actually make it myself, as well as studying programming. In this article, I wrote how to implement it, how to crush bugs, and what lessons I learned. For those who have begun to study programming, the content is like a teacher, on the other hand, "Be careful not to make such a mistake."

2. Problem setting

Let's assume the following specifications.

player

There is one player on the coordinate plane. The player stays still and does not move. ~~ It's troublesome to move. ~~ The player's body can be regarded as a point, and the coordinates of that point are ($ p_x $, $ p_y $).

Surveillance camera

Surveillance cameras are installed in $ N $ units on the coordinate plane. $ N $ is an integer greater than or equal to 1. The surveillance camera is still and does not move. ~~ When it moves (omitted) ~~ The lens of each surveillance camera can be regarded as a point, and the coordinates of that point are ($ x_i $, $ y_i $). However, $ i $ is an integer of 1 or more and $ N $ or less, which indicates the number of the surveillance camera.

Visible range of each surveillance camera

The distance that each surveillance camera can see the player is $ d_i $ ($ d_i $> 0). Let $ e_i $ be the angle representing the direction of the lens of each surveillance camera, and $ f_i $ be the angle representing the field of view of the camera. $ e_i $ is the angle between the straight line representing the direction of the camera and the positive direction of the $ x $ axis, and both $ e_i $ and $ f_i $ are 0 ° or more and less than 360 °. That is, the range in which each surveillance camera can see the player is the circumference and the inside of the goose shape with a radius of $ d_i $ and a central angle of $ f_i $ as shown in the following figure. quiita_おうぎ形 - コピー.png

Parameter input / output

Input the parameters from the console in the following format.      p_x p_y      N      x_1 y_1 d_1 e_1 f_1 (Omitted)      x_i y_i d_i e_i f_i (Omitted)      x_N y_N d_N e_N f_N The parameters of each line shall be separated by a half-width space. In addition, each time the information of each surveillance camera is input, it is determined whether or not the surveillance camera can see the player, and if it can be seen, it is output as "visible", and if it cannot be seen, it is output as "not visible". And.

3. 3. Data structure implementation

First of all, I would like to say that this time, the purpose is to consider the condition that the circumference and the inside of the gourd shape include points, so it is not possible to strictly implement encapsulation or object orientation. I won't __. I can't say ~~. ~~ There may be many other points that cannot be reached, but please forgive me.

First, create a class Player that handles the player's location information. The class Player has $ x $ and $ y $ coordinates and has the ability to return their values as needed. In addition, it may not be necessary to make the player a class, but if this is system development, it is possible to assume a situation where there are many players, so "Anyway, the player is hidden. I will clarify the __idea __ that it has the information and functions of Kajika. Also, the class Player is just a idea (an abstract concept of an object in a complicated way), and we will create a __player (an entity in a complicated way) that exists in the true sense. For example, is it a feeling that there is an abstract concept of human beings, and that I and you exist as the substance?

class Player {
	private double x; //Player x coordinate
	private double y; //Player y coordinate

	public Player(double x, double y) {
		this.x = x;
		this.y = y;
	}
	public double getX() {
		return this.x;
	}
	public double getY() {
		return this.y;
	}
}

Since it's a big deal, I'll explain a little about encapsulation. In class Player, the values are stored in double type variables x and y, but the person who writes the program (not always me. May collaborate with someone or throw it to someone. In a situation where variable values can be referenced and assigned in a disorderly manner (!), There is a risk of writing a process (bug) that is not what was originally expected. Therefore, in order to clarify the processing that the program writer (s) can do for the class Player, the above code defines as follows.

--Variable x does not directly rewrite the value! ⇒ Write private before the type declaration. Then, it becomes impossible to write "x = 100;" that directly assigns a value to the variable x (it causes an error). --I want to substitute the x coordinate for the variable x when creating a real player! ⇒ Assign the argument value to the variable x in the constructor (method with the same name as the class. The method is a summary of the processing flow) that is always called when creating an existing player. --I want to be able to refer to the value of variable x later! ⇒Create a dedicated method getX (). If you write public before the type declaration, you can call it from various places. --The same applies to the variable y.

In this way, a class or encapsulation is a mechanism that summarizes necessary information and processing and prevents it from being rewritten randomly. It takes a little more work to write a program, but Java provides a mechanism to reduce the risk of creating bugs instead. The larger the scale of development, the more important such a mechanism becomes.

Next, create a class Camera that handles surveillance camera information. Class Cameras have x, y coordinates, visible distances, and angles that represent orientation and viewing angle. It has a minimal configuration now, but as we implement the process in the future, we will add more methods.

class Camera {
	private double x;	//X coordinate of surveillance camera
	private double y;	//Y coordinate of surveillance camera
	private double distance;	//Distance visible to surveillance cameras
	private double dirAngle;	//Direction of surveillance camera(direction)Angle representing
	private double viewAngle;	//Viewing angle of surveillance camera

	public Camera(double x, double y, double d, double e, double f) {
		this.x = x;
		this.y = y;
		this.distance = d;
		this.dirAngle = e;
		this.viewAngle = f;
	}
}

4. Algorithm implementation

input

Now that we have decided where and what kind of information to store, we will finally describe the processing flow. First, from the main method. Whenever you run a Java program, the main method is called first. Therefore, you have to write only one main method in the whole program. For the time being, I will create only the part that reads the numerical value entered from the console.

class CameraTest {
	public static void main(String[] args) {
		//input
		Scanner sc = new Scanner(System.in);
		//player
		double px = sc.nextDouble();	//Player x coordinate
		double py = sc.nextDouble();	//Player y coordinate
		Player player = new Player(px, py);
		//Surveillance camera
		int N = sc.nextInt();		//Number of surveillance cameras
		for (int n = 0; n < N; n ++) {
			//Input / processing for each surveillance camera
			double x = sc.nextDouble();	//X coordinate of surveillance camera
			double y = sc.nextDouble();	//Y coordinate of surveillance camera
			double d = sc.nextDouble();	//Distance visible to surveillance cameras
			double e = sc.nextDouble();	//Direction of surveillance camera(direction)Angle representing
			double f = sc.nextDouble();	//Viewing angle of surveillance camera
			Camera camera = new Camera(x, y, d, e, f);
		}
		sc.close();
	}
}

It's kind of like static, Scanner, nextDouble, nextInt, etc., but if you start explaining these, it will derail the purpose of this article, so I will omit the explanation. Anyway, at the time of creating the above, the numerical value entered according to the specifications can be read without any problem.

Can surveillance cameras see the player?

Of course, just reading the numbers is meaningless, so let's add a process to determine if the camera can actually see the player. In the Camera class created earlier, let's create a method findPlayer that reads the player's position information and determines whether the player can be visually recognized. This method is the key to this article.

//Add to Camera class
public boolean findPlayer(Player player) {
	double px = player.getX();
	double py = player.getY();

	//Judgment by distance
	double d = Math.sqrt(Math.pow(this.x - px, 2) + Math.pow(this.y - py, 2));
	if (d > this.distance) {
		return false;
	}

	//Judgment by angle
	double a = Math.toDegrees(Math.atan2(py - this.y, px - this.x));
	double aMin = this.dirAngle - this.viewAngle/2;
	double aMax = this.dirAngle + this.viewAngle/2;
	if (a < aMin || aMax < a) {
		return false;
	}

	return true;
}

Now, let's briefly explain the processing flow. There are two keywords, "distance" and "angle". First of all, "distance", as the name implies, determines whether the distance between the surveillance camera and the player is smaller than the visible distance of the surveillance camera. The distance between two points ($ x_i $, $ y_i ), ( p_x $, $ p_y $)

\sqrt{(x_i - p_x)^2 + (y_i - p_y)^2}

Is required at. If this is less than the viewing distance $ d_i $, it may be visible, but if it is larger than $ d_i $, it is out of the question. Therefore, in the part that judges by distance, in the latter case, false is returned suddenly so that unnecessary processing after that is not necessary. Next, regarding the processing of "angle" after clearing the condition of "distance", the function $ \ arctan $ (high school mathematics) that calculates the size of the angle between the straight line and the x-axis from the slope of the straight line passing through the two points. "Trigonometric function" and "inverse function") can be used, so by combining these for two points ($ x_i $, $ y_i ), ( p_x $, $ p_y $)

\arctan{\frac{y_i - p_y}{x_i - p_x}}

You can find it at. Also, the range of angles that the camera can see is represented by $ e_i-\ frac {f_i} {2} $ or more and $ e_i + \ frac {f_i} {2} $ or less, so the angle obtained from the tilt is this range. Returns true if there is, false if not.

output

At this point, it's almost complete. The method findPlayer created earlier returns a boolean type value, so it only outputs the result according to that value. Then, I will post the completed (?) Program.

import java.util.Scanner;

class CameraTest {
	public static void main(String[] args) {
		//input
		Scanner sc = new Scanner(System.in);
		//player
		double px = sc.nextDouble();	//Player x coordinate
		double py = sc.nextDouble();	//Player y coordinate
		Player player = new Player(px, py);
		//Surveillance camera
		int N = sc.nextInt();		//Number of surveillance cameras
		for (int n = 0; n < N; n ++) {
			//Input / processing for each surveillance camera
			double x = sc.nextDouble();	//X coordinate of surveillance camera
			double y = sc.nextDouble();	//Y coordinate of surveillance camera
			double d = sc.nextDouble();	//Distance visible to surveillance cameras
			double e = sc.nextDouble();	//Direction of surveillance camera(direction)Angle representing
			double f = sc.nextDouble();	//Viewing angle of surveillance camera
			Camera camera = new Camera(x, y, d, e, f);
			if (camera.findPlayer(player)) {
				System.out.println("I was able to see");
			} else {
				System.out.println("I couldn't see");
			}
		}
		sc.close();
	}
}

class Player {
	private double x; //Player x coordinate
	private double y; //Player y coordinate

	public Player(double x, double y) {
		this.x = x;
		this.y = y;
	}
	public double getX() {
		return this.x;
	}
	public double getY() {
		return this.y;
	}
}

class Camera {
	private double x;	//X coordinate of surveillance camera
	private double y;	//Y coordinate of surveillance camera
	private double distance;	//Distance visible to surveillance cameras
	private double dirAngle;	//Direction of surveillance camera(direction)Angle representing
	private double viewAngle;	//Viewing angle of surveillance camera

	public Camera(double x, double y, double d, double e, double f) {
		this.x = x;
		this.y = y;
		this.distance = d;
		this.dirAngle = e;
		this.viewAngle = f;
	}
	public boolean findPlayer(Player player) {
		double px = player.getX();
		double py = player.getY();
	
		//Judgment by distance
		double d = Math.sqrt(Math.pow(this.x - px, 2) + Math.pow(this.y - py, 2));
		if (d > this.distance) {
			return false;
		}
	
		//Judgment by angle
		double a = Math.toDegrees(Math.atan2(py - this.y, px - this.x));
		double aMin = this.dirAngle - this.viewAngle/2;
		double aMax = this.dirAngle + this.viewAngle/2;
		if (a < aMin || aMax < a) {
			return false;
		}
		
		return true;
	}
}

5. Execution, and ...

It's finally time to check the performance of the surveillance cameras. As a test, let's test using three surveillance cameras with the coordinates where the player is (10, 10). First of all, I will try to input until the process of the first unit is advanced.

10 10
3
10 0 12 90 30
I was able to see

The situation below shows the entered information in a diagram. You can see the player perfectly. The tension has risen. quiita_おうぎ形2.png

Let's go to the second one.

10 5 10 180 90
I couldn't see

I couldn't see the second one, but it's not a problem at all. This is because the situation is as shown in the figure below. I was able to clear the distance condition, but the direction of the surveillance camera was bad. The judgment is perfect this time as well! quiita_おうぎ形3.png

Then, let's go to the finale with the third last car.

10 16 8 270 120
I couldn't see

quiita_おうぎ形4.png

At the end, I could see the stupid player right in front of the surveillance camera ... __ I couldn't do it __. In terms of a shooting game, it's like a frontal placement! (Throwing)

6. And to debug ...

That's the beginning of fun debugging work, but this time I'd like to cut it here and continue to the second part. If you're wondering, "Why isn't it?" Like I used to be, please think about it before reading the second part. __ Why couldn't the third surveillance camera see the player even though he could see it? Also, how should I modify the program? __

Recommended Posts

Let's implement the condition that the circumference and the inside of the Ougi shape are included in Java [Part 2]
Let's implement the condition that the circumference and the inside of the Ougi shape are included in Java [Part 1]
This and that of the implementation of date judgment within the period in Java
[Android 9.0 Pie Java] Implement setOnTouchListener in the margin of RecyclerView and close the soft keyboard
[Java] What to do if the contents saved in the DB and the name of the enum are different in the enum that reflects the DB definition
A program (Java) that outputs the sum of odd and even numbers in an array
Shout Java at the heart of technology-Themes and elemental technologies that Java engineers should pursue in 2017-
JSON in Java and Jackson Part 1 Return JSON from the server
[Java] Get the dates of the past Monday and Sunday in order
Let's consider the meaning of "stream" and "collect" in Java's Stream API.
Let's create a TODO application in Java 5 Switch the display of TODO
Specify the order in which configuration files and classes are loaded in Java
The problem that the contents of params are completely displayed in the [Rails] view
The story of forgetting to close a file in Java and failing
Let's think about what declarative programming is in Java and Elm (Part 1)
Sample program that returns the hash value of a file in Java
Find the maximum and minimum of the five numbers you entered in Java
Review of "strange Java" and Java knowledge that is often forgotten in Java Bronze
[Java] Implement a function that uses a class implemented in the Builder pattern
[Introduction to Computer Science Part 1: Let's try machine learning] Let's implement k-means clustering in Java-About the concept of coordinates-
Get the result of POST in Java
What are the updated features of java 13
The story of writing Java in Emacs
Discrimination of Enums in Java 7 and above
I received the data of the journey (diary application) in Java and visualized it # 001
[Java] Where is the implementation class of annotation that exists in Bean Validation?
10 barrages of drawing with ● or ■ that are likely to appear in training (Java)