![](/img/trans.png)
[英]How to determine which points (x,y) out of million data points lie inside the area described by a rectangle (x1, x2, y1, y2)?
[英]In a file of 10,000 points of the form X1 y1 X2 y2 ,,, How to detect at least 4 which form a square ? java
我只用了4点尝试了这个示例,它适用于:
-1 -1
2 1
4 -2
1 -4
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
public class CarreSimple {
static int distance(Point point1, Point point2) {
int dist = (int) (Math.pow(point1.getX() - point2.getX(), 2) + Math.pow(point1.getY() - point2.getY(), 2));
dist = (int) Math.sqrt(dist);
return dist;
}
public static void main(String[] args) {
boolean EstCarre = false;
Point[] tb = new Point[10000];
int i = 0;
BufferedReader br = null;
try {
br = new BufferedReader(new FileReader("C:/Users/walid/Downloads/points.txt"));
String line;
while ((line = br.readLine()) != null) {
String[] parts = line.split(" ");
int part1 = Integer.parseInt(parts[0]);
int part2 = Integer.parseInt(parts[1]);
Point p = new Point(part1, part2);
tb[i] = p;
System.out.println("X " + tb[i].getX() + " y " + tb[i].getY());
i++;
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (br != null) {
br.close();
}
} catch (IOException ex) {
ex.printStackTrace();
}
}
int[] distances = new int[3];
distances[0] = distance(tb[0], tb[1]);
distances[1] = distance(tb[0], tb[2]);
distances[2] = distance(tb[0], tb[3]);
System.out.println(distances[0]);
int CoteEgal1 = -1;
int CoteEgal2 = -1;
int CotePasEgal = -1;
if (distances[0] == distances[1]) {
if (distances[0] != distances[2]) {
CoteEgal1 = 0;
CoteEgal2 = 1;
CotePasEgal = 2;
}
} else if (distances[1] == distances[2]) {
if (distances[1] != distances[0]) {
CoteEgal1 = 1;
CoteEgal2 = 2;
CotePasEgal = 0;
}
} else if (distances[0] == distances[2]) {
if (distances[0] != distances[1]) {
CoteEgal1 = 0;
CoteEgal2 = 2;
CotePasEgal = 1;
}
}
if (CoteEgal1 != -1) {
int coinOpposÈ = 0;
switch (CotePasEgal) {
case 0:
coinOpposÈ = distance(tb[2], tb[3]);
break;
case 1:
coinOpposÈ = distance(tb[1], tb[3]);
break;
case 2:
coinOpposÈ = distance(tb[1], tb[2]);
break;
default:
break;
}
if (coinOpposÈ == distances[CotePasEgal]) {
int diagonal = coinOpposÈ;
int adjacent = distances[CoteEgal1];
boolean stillOK = true;
for (int a = 0; a < 4; a++) {
int diagonalCount = 0;
int adjacentCount = 0;
for (int b = 0; b < 4; b++) {
if (a != b) {
int dist = distance(tb[a], tb[b]);
if (dist == diagonal) {
diagonalCount++;
} else if (dist == adjacent) {
adjacentCount++;
}
}
}
// est ce que on a 1 diagonal et 2 adjacents
if (!(diagonalCount == 1 && adjacentCount == 2)) {
stillOK = false;
break;
}
}
if (stillOK) {
EstCarre = true;
}
}
}
if (EstCarre) {
System.out.println("C'est un carre");
} else {
System.out.println("Ce n'est pas un carre");
}
}
}
要在10,000点的文件上循环并对4个点的每种组合进行测试,我发现太难了。
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
public class Square {
static int distance(Point point1, Point point2) {
int dist = (int) (Math.pow(point1.getX() - point2.getX(), 2) + Math.pow(point1.getY() - point2.getY(), 2));
dist = (int) Math.sqrt(dist);
return dist;
}
public static void main(String[] args) {
boolean EstCarre = false;
Point[] tb = new Point[10000];
int i = 0;
BufferedReader br = null;
try {
br = new BufferedReader(new FileReader("C:/Users/walid/Downloads/exercice.txt"));
String line;
while ((line = br.readLine()) != null) {
String[] parts = line.split(" ");
int part1 = Integer.parseInt(parts[0]);
int part2 = Integer.parseInt(parts[1]);
Point p = new Point(part1, part2);
tb[i] = p;
System.out.println("X " + tb[i].getX() + " y " + tb[i].getY());
i++;
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (br != null) {
br.close();
}
} catch (IOException ex) {
ex.printStackTrace();
}
}
for (int i2 = 0; i2 < 10000; i2++) {
for (int j = 0; j < 10000; j++) {
for (int k = 0; k < 10000; k++) {
for (int l = 0; l < 10000; l++) {
if (i2 != j && i2 != k && i2 != l && j != k && j != l && k != l) {
int[] distances = new int[10000000];
distances[i2] = distance(tb[i2], tb[j]);
distances[j] = distance(tb[i2], tb[k]);
distances[k] = distance(tb[i2], tb[l]);
int CoteEgal1 = -1;
int CoteEgal2 = -1;
int CotePasEgal = -1;
if (distances[i2] == distances[j]) {
if (distances[i2] != distances[k]) {
CoteEgal1 = i2;
CoteEgal2 = j;
CotePasEgal = k;
}
} else if (distances[i2] == distances[k]) {
if (distances[j] != distances[i2]) {
CoteEgal1 = j;
CoteEgal2 = k;
CotePasEgal = i2;
}
} else if (distances[i2] == distances[k]) {
if (distances[i2] != distances[j]) {
CoteEgal1 = i2;
CoteEgal2 = k;
CotePasEgal = j;
}
}
int coinOpposÈ = 0;
if (CoteEgal1 != -1) {
if (CotePasEgal == i2) {
coinOpposÈ = distance(tb[k], tb[l]);
} else if (CotePasEgal == j) {
coinOpposÈ = distance(tb[j], tb[l]);
} else if (CotePasEgal == k) {
coinOpposÈ = distance(tb[j], tb[k]);
}
if (coinOpposÈ == distances[CotePasEgal]) {
int diagonal = coinOpposÈ;
int adjacent = distances[CoteEgal1];
boolean stillOK = true;
for (int a = 0; a < 10000000; a++) {
int diagonalCount = 0;
int adjacentCount = 0;
for (int b = 0; b < 10000000; b++) {
if (a != b) {
int dist = distance(tb[a], tb[b]);
if (dist == diagonal) {
diagonalCount++;
} else if (dist == adjacent) {
adjacentCount++;
}
}
}
// est ce que on a 1 diagonal et 2 adjacents
if (!(diagonalCount == 1 && adjacentCount == 2)) {
stillOK = false;
break;
}
}
if (stillOK) {
EstCarre = true;
}
}
}
}
if (EstCarre) {
System.out.println("square found");
}
}
}
}
}
}
}
代码2:一对是需要两分的课程
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.Iterator;
import java.util.Map;
import java.util.HashMap;
import java.util.Set;
public class CarreP {
public static void main(String[] args) {
Point[] tb = new Point[10000];
int i = 0;
BufferedReader br = null;
try {
br = new BufferedReader(new FileReader("C:/Users/walid/Downloads/exercice.txt"));
String line;
while ((line = br.readLine()) != null) {
String[] parts = line.split(" ");
int part1 = Integer.parseInt(parts[0]);
int part2 = Integer.parseInt(parts[1]);
Point p = new Point(part1, part2);
tb[i] = p;
i++;
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (br != null) {
br.close();
}
} catch (IOException ex) {
ex.printStackTrace();
}
}
HashMap<Couple, Integer> hmap = new HashMap<Couple, Integer>();
int j = 0;
while (j < tb.length) {
for (int k = 0; k < tb.length; k++) {
int xcarre = (int) Math.pow(tb[j].getX() - tb[k].getX(), 2);
int ycarre = (int) Math.pow(tb[j].getY() - tb[k].getY(), 2);
int distance = (int) Math.sqrt(xcarre + ycarre);
Couple c = new Couple(tb[k], tb[k]);
hmap.put(c, distance);
Set set = hmap.entrySet();
Iterator iterator = set.iterator();
Iterator iterator2 = set.iterator();
int[] distances = new int[hmap.size()];
int s = 0;
while (iterator.hasNext()) {
Map.Entry mentry = (Map.Entry) iterator.next();
distances[s] = (int) mentry.getValue();
System.out.println(distances[s]);
s++;
}
int CoteEgal1 = -1;
int CoteEgal2 = -1;
int CoteInegal = -1;
for (int i1 = 0; i1 < distances.length; i1++) {
for (int i2 = 0; i2 < distances.length; i2++) {
for (int i3 = 0; i3 < distances.length; i3++) {
if (distances[i1] == distances[i2]) {
if (distances[i1] != distances[i3]) {
CoteEgal1 = i1;
CoteEgal2 = i2;
CoteInegal = i3;
}
} else if (distances[i2] == distances[i3]) {
if (distances[i2] != distances[i1]) {
CoteEgal1 = i2;
CoteEgal2 = i3;
CoteInegal = i1;
}
} else if (distances[i1] == distances[i3]) {
if (distances[i1] != distances[i2]) {
CoteEgal1 = i1;
CoteEgal2 = i3;
CoteInegal = i2;
}
}
}
}
}
}
}
}
}
总体思路如下:
假设我们有两个点:A和B。只有两种方法可以用此点构建一个正方形:ABCD和ABEF(请参见下图)。 现在,让我们考虑AB是一个向量。 我们可以将其顺时针旋转90度,得到点D。如果将其移动到点B,则将得到点C。类似地,我们可以将AB逆时针旋转90度,得到F和E。
现在我们只需要检查文件是否包含C和D点,或E和F点。如果是,则有一个正方形。 如果我们将所有点存储在哈希图中,则可以快速完成。
这是一个示例实现:
import java.util.HashSet;
import java.util.Set;
public class Main {
public static Set<Point> pointsSet = new HashSet<>();
public static void main(String[] args) {
//Suppose, that points are already parsed from file
Point[] points = new Point[]{
new Point(-1, -1),
new Point(2, 1),
new Point(4, -2),
new Point(1, -4)
};
//Fill hashset with points. Important: hashCode() and equals() methods are overrided in Point class
for (Point point : points) {
pointsSet.add(point);
}
Point point1;
Point point2;
Point suggested_point3;
Point suggested_point4;
//Consider every pair of points
for (int i = 0; i < points.length - 1; i++) {
point1 = points[i];
for (int j = i + 1; j < points.length; j++) {
point2 = points[j];
//Calculate vector coordinates for pair of points
Vector vector = new Vector(point2.getX() - point1.getX(), point2.getY() - point1.getY());
//Rotate vector clockwise by 90 degrees and calculate coordinates,
//where two more points should be to form a square with current pair of points
Vector clockwise_rotated_vector = rotateVector(vector, 90);
suggested_point3 = moveVectorToPoint(clockwise_rotated_vector, point1);
suggested_point4 = moveVectorToPoint(clockwise_rotated_vector, point2);
if (pointsSet.contains(suggested_point3) && pointsSet.contains(suggested_point4)) {
squareFound(point1, point2, suggested_point3, suggested_point4);
}
//Same for counterclockwise rotated vector
Vector counterclockwise_rotated_vector = rotateVector(vector, -90);
suggested_point3 = moveVectorToPoint(counterclockwise_rotated_vector, point1);
suggested_point4 = moveVectorToPoint(counterclockwise_rotated_vector, point2);
if (pointsSet.contains(suggested_point3) && pointsSet.contains(suggested_point4)) {
squareFound(point1, point2, suggested_point3, suggested_point4);
}
}
}
}
private static void squareFound(Point point1, Point point2, Point point3, Point point4) {
System.out.println(String.format("%s, %s, %s, %s", point1, point2, point3, point4));
}
private static Point moveVectorToPoint(Vector vector, Point point) {
double x = point.getX() + vector.getX();
double y = point.getY() + vector.getY();
return new Point(x, y);
}
private static Vector rotateVector(Vector original_vector, double degrees) {
double radians = Math.toRadians(degrees);
double x = original_vector.getX() * Math.cos(radians) - original_vector.getY() * Math.sin(radians);
double y = original_vector.getX() * Math.sin(radians) + original_vector.getY() * Math.cos(radians);
return new Vector(x, y);
}
}
课堂Point
:
import java.math.BigDecimal;
import java.util.Locale;
public class Point {
public Point(double x, double y) {
this.x = x;
this.y = y;
//Store decimal values with certain scale, which would later be used for hashCode() calculation
this.decimalX = new BigDecimal(x).setScale(DECIMAL_SCALE, BigDecimal.ROUND_HALF_EVEN);
this.decimalY = new BigDecimal(y).setScale(DECIMAL_SCALE, BigDecimal.ROUND_HALF_EVEN);
}
private static final int DECIMAL_SCALE = 3;
private double x;
public double getX() {
return x;
}
private double y;
public double getY() {
return y;
}
private BigDecimal decimalX;
private BigDecimal decimalY;
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Point point = (Point) o;
if (!decimalX.equals(point.decimalX)) return false;
return decimalY.equals(point.decimalY);
}
@Override
public int hashCode() {
//calculate for decimal values, so two very close enough points will have equal hash codes
int result = decimalX.hashCode();
result = 31 * result + decimalY.hashCode();
return result;
}
@Override
public String toString() {
return String.format(Locale.ENGLISH, "(%2f,%2f)", x, y);
}
}
类Vector
:
public class Vector {
public Vector(double x, double y) {
this.x = x;
this.y = y;
}
private double x;
public double getX() {
return x;
}
private double y;
public double getY() {
return y;
}
}
更新:正如评论中所提到的,有一些地方需要改进,因此我更新了代码。
要从10000个点中找到所有可能的正方形组合,将很难完成。
因此,您需要一种方法来查找可以组合成正方形的点,即共享X或Y坐标的点。
因此,将所有点加载到内存中,通过构建Map<Integer, Set<Integer>>
,将X坐标映射到Y坐标的集合来“索引”它们。 该值是一个Set
因此消除了重复的点,并提高了下面代码的性能。
现在出现了更强力的部分,但是它大大减少了,因此应该不会太糟。 像这样搜索(伪代码,因此您也必须做一部分) :
for eRight in xMap:
xRight = eKey.key
continue if eRight.value.size() == 1
for eLeft in xMap:
xLeft = eLeft.key
continue if xLeft >= xRight
continue if eLeft.value.size() == 1
// at this point we now have two distinct X coordinates
// with their corresponding collection of Y coordinates
for yTop : eLeft.value:
continue if ! eRight.value.contains(yTop)
for yBottom : eLeft.value:
continue if yBottom >= yTop // assuming (0,0) is lower-left
continue if ! eRight.value.contains(yBottom)
// at this point we now have two distinct Y coordinates
// that fit both X coordinates, i.e we have a rectangle
new Rectangle(xLeft, yTop, xRight, yBottom)
上面的代码查找矩形 ,而不是正方形 。 我将它留给您进行更改以找到正方形。
提示 : yBottom
(或yTop
)循环被计算替换。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.