繁体   English   中英

在X1 y1 X2 y2形式的10,000个点的文件中,如何检测至少四个正方形? 爪哇

[英]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 )循环被计算替换。

我有一个与上面的Marat Safin相似的答案,除了我认为我们必须注意以下事实:浮点算法不精确,并且必须小心,经过一些计算步骤,像3.1415926这样的浮点数可能会变成3.1415927 (只是相差1E-7)。 解决方案是,我们还必须声明一个参数epsilon (公差),该参数允许我们对两个浮点数(例如double )“近似相等”。

我的答案还包含测试输入,可用于验证程序。

您可以在点列表中检测方的另一篇SO帖子中找到我的答案

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM