An algorithm to obtain integer points (lattice points) within a circle

Source: Internet
Author: User
Tags assert

This algorithm is used to enumerate the integer points in the circle, which can be used to enumerate the integer points within the ring.

But now only some special circumstances, not to generalize to the general. Restriction Condition: The center coordinate is an integer (can be converted to the center of origin) and the radius is a positive integer.

The language is C + +,

The data structure of the point is:

Stuct Vector2
{
    int x;
    int y;
};

The object of the algorithm is to insert all the integer points within the circle into the points points the container is std::vector<vector2>.



The circle is about axis symmetry and y=x and y=-x symmetry, so we just need to consider the lower right part of the first quadrant (one-eighth parts of the circle).

Set RADIUS to R


The first step is to add the original point. Because the center of the circle is on the original point.

In the second step, add the points on the axis. (1, 0) (2,0) ... (r, 0).

The third step, add y = x, y = point (1, 1) (2, 2). (⌊r/1.414⌋,⌊r/1.414⌋) Note that the last one is rounding down.

Fourth step, add the other points:

This last part is probably a fan:

Rays (2, 1)-> (3, 1) and Rays (2, 1)-> (3, 2) intersect with the circle.


Two facts were found by observation:

1. The y-coordinate of the lowest point in the region is 1, and the y-coordinate of the highest points is the y-coordinate of the ray (2, 1)-> (3, 2) to the point at which the circle intersects.

2. Because the radius of the circle is an integer, the point (R, 0) is on the circle. (r, 1) outside the circle. And there are quite a number of points (R-1, J) that are the rightmost integer points within the circle.


Based on these facts, we can divide this area into two parts: the coordinates of the left boundary of the lower half are (i + 1, i), and the x-coordinate of the right boundary lattice point is r-1. The top half is the remaining point.

The y-coordinate of the equation in which x = R-1 is brought into the circle is rounded down, which is the upper boundary of the lower part.

That means the lower part is a right angle trapezoid:


The midpoint A is the highest point in the lower half, and Point B is the top of the upper half.

The left boundary of the upper part is the same as the lower part, and the right boundary needs to be solved: bring the y-coordinate into the circle equation, find the X coordinate and take the whole downward, that is the right border.

This makes it possible to add the dots to the array by looping through the left and right ranges. Of course, remember that this is only one-eighth, you also need to transform the coordinates: x, y coordinate reversal, add negative sign and so on.


Here's the complete code:

#pragma once #include <cassert> #include <vector> #include "vector2.h" class Latticepoint {private:static
		void pushaxispoints (int x, std::vector<vector2<int>> &points) {points.push_back ({x, 0});
		Points.push_back ({-X, 0});
		Points.push_back ({0, x});
	Points.push_back ({0,-X}); } static void pushdiagonalpoints (int i, std::vector<vector2<int>> &points) {points.push_back ({i, I
		});
		Points.push_back ({i, i});
		Points.push_back ({i, i});
	Points.push_back ({i, i}); } static void pushquadrantspoints (int i, int J, std::vector<vector2<int>> &points) {Points.push_back
		({i, J});
		Points.push_back ({i,-j});
		Points.push_back ({i, J});

		Points.push_back ({i,-j});
		Points.push_back ({j, i});
		Points.push_back ({j, i});
		Points.push_back ({-j, i});
	Points.push_back ({-j, i}); Public://get lattice points in Circle: (0, 0) radius static void getfromcircle (int radius, STD::vector<vector2<int>> &points) {assert (RADIUS >= 0);
		Points.push_back ({0, 0});
		for (int i = 1; I <= radius; i++) {pushaxispoints (I, points);
		int x1 = Floor (radius/sqrt (2)), y1 = x1;
		for (int i = 1; I <= x1 i++) {pushdiagonalpoints (I, points);
		} if (RADIUS <= 2) return;
		x1++;
		if (x1 * x1 + y1 * y1 > Radius * radius) {y1--;
		int x2 = radius-1, y2 = Floor (sqrt (RADIUS * radius-x2 * x2)); for (int j = 1; J <= y2-1 + +) {for (int i = j + 1; I <= x2; i++) {pushquadrantspoints (I, J, points
			);
			for (int j = y2 J <= Y1; j +) {int XE = floor (sqrt (RADIUS * radius-j * j));
			for (int i = j + 1; I <= xe; i++) {pushquadrantspoints (I, J, points); }}//get lattice points in Circle: (0, 0) (Smallradius, Bigradius] static void getfromring (int bigradius, int smal Lradius, std::vector<vector2<int>> &points) {assert (Bigradius = = SmalLradius + 1 && smallradius >= 0);
		Pushaxispoints (Bigradius, points);
		int x1b = Floor (bigradius/sqrt (2));
		int x1s = Floor (smallradius/sqrt (2));
		int x1 = x1b, y1 = x1;
		if (x1b > X1s) pushdiagonalpoints (x1, points);
		if (Bigradius <= 2) return;
		x1++;
		if (x1 * x1 + y1 * y1 > Bigradius * bigradius) {y1--;
		int x2b = bigradius-1, y2b = Floor (sqrt Bigradius * bigradius-x2b * x2b));
		int x2s = smallradius-1, y2s = Floor (sqrt Smallradius * smallradius-x2s * x2s));
		for (int j = 1; J <= Y2s + +) {pushquadrantspoints (x2b, J, points);  for (int j = y2b > Y2s y2b:y2b + 1 J <= Y1; j +) {int xs = floor (sqrt Smallradius * smallradius-j *
			j)); xs = xs < j?
			J:xs;
			int XE = Floor (sqrt (Bigradius * bigradius-j * j));
			for (int i = xs + 1; I <= xe; i++) {pushquadrantspoints (I, J, points);

		}} static int getnumbleofcircle (double radius) {assert (RADIUS >= 0); Unsignedint r = (int) radius;

		unsigned int sigma = 0;
		for (unsigned int i = 1; I <= r i++) {sigma + (int) sqrt (RADIUS * radius-i * i);
	Return 1 + 4 * r + 4 * SIGMA; static int getnumberofring (double Bigradius, double Smallradius) {assert (Bigradius > Smallradius && SMA

		Llradius >= 0);
	Return Getnumbleofcircle (Bigradius)-getnumbleofcircle (Smallradius); }
};

How to use:

std::vector<vector2> list;
Latticepoint::getfromcircle (distance, list);

There are also functions that only count the integer points in a circle: int latticpoint::getnumberofcircle (RADIUS);


According to this method, I have also deduced a method to find the integer points within the ring, and the function is latticpoint::getfromring (). But notice is not exactly the usual ring: here is the distance from the origin to all the integer points of (R, R+1], note that this is the interval between the left and right closed. You can change it according to your own needs.

There is also a function to find the number of integer points in the ring: int latticpoint::getnumberofring (Bigradius, Smallradius); This is the same point in the left open right closed range, but the difference is that the radius of the circle is only larger than the small circle radius.


Finally, note that the two parameters of a function that are evaluated for an integer number of points can be decimal. And the two functions I proposed, the arguments need to be integers.


Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.