Untitled

mail@pastecode.io avatar
unknown
java
a year ago
5.4 kB
7
Indexable
Never
package com.epam.rd.autotasks.figures;

class Quadrilateral extends Figure {
    private Point _a;
    private Point _b;
    private Point _c;
    private Point _d;
    public Quadrilateral(Point a, Point b, Point c, Point d) {
        // Check if the points are not null
        if (a == null || b == null || c == null || d == null) {
            throw new IllegalArgumentException("Points cannot be null");
        }
        // Check if the points are not collinear
        if (collinear(a, b, c) || collinear(b, c, d) || collinear(c, d, a) || collinear(d, a, b)) {
            throw new IllegalArgumentException("Points cannot be collinear");
        }
        // Check if the quadrilateral is convex
        if (!isConvex(a, b, c, d)) {
            throw new IllegalArgumentException("Quadrilateral must be convex");
        }
        // Assign the points to the fields
        _a = a;_b = b;
        _c = c;_d = d;
    }
    public static boolean collinear(Point p1, Point p2, Point p3) {
        // Calculate the cross product of the vectors p1p2 and p1p3
        double cross = (p2.getX() - p1.getX()) *(p3.getY() - p1.getY()) - (p2.getY() - p1.getY())* (p3.getX() - p1.getX());
        // Check if the cross product is zero, which means the vectors are parallel
        return Math.abs(cross) < 1e-6; // Use a small tolerance to account for floating-point errors
    }

    @Override
    public Point centroid() {
        // Calculate the area of the quadrilateral using the shoelace formula
        double area = Math.abs((_a.getX()*_b.getY() - _b.getX()*_a.getY()) +
                (_b.getX()*_c.getY() - _c.getX()*_b.getY()) +
                (_c.getX()*_d.getY() - _d.getX()*_c.getY()) +
                (_d.getX()*_a.getY() - _a.getX()*_d.getY())) / 2.0;
        // Calculate the x and y coordinates of the centroid using the formula from https://en.wikipedia.org/wiki/Centroid#Of_a_polygon
        double x = (_a.getX() +_b.getX()) *(_a.getX()* _b.getY() -_b.getX() *_a.getY()) +
                (_b.getX() +_c.getX())*(_b.getX()*_c.getY() -_c.getX()*_b.getY()) +
                (_c.getX() +_d.getX())*(_c.getX()*_d.getY() -_d.getX()*_c.getY()) +
                (_d.getX() +_a.getX())*(_d.getX()*_a.getY() -_a.getX()*_d.getY());
        x = x / (6.0*area);
        double y = (_a.getY() +_b.getY())*(_a.getX()*_b.getY() -_b.getX()*_a.getY()) +
                (_b.getY() +_c.getY())*(_b.getX()*_c.getY() -_c.getX()*_b.getY()) +
                (_c.getY() +_d.getY())*(_c.getX()*_d.getY() -_d.getX()*_c.getY()) +
                (_d.getY() +_a.getY())*(_d.getX()*_a.getY() -_a.getX()*_d.getY());
        y = y / (6.0*area);
        // Return a new point with the calculated coordinates
        return new Point(-x, -y);
    }

    @Override
    public boolean isTheSame(Figure figure) {
        // Check if the figure is not null and is a quadrilateral
        if (figure == null || !(figure instanceof Quadrilateral)) {
            return false;
        }
        // Cast the figure to a quadrilateral
        Quadrilateral quad = (Quadrilateral) figure;
        // Define a small tolerance value for comparing doubles
        double epsilon = 1e-6;
        // Check if the four points of this quadrilateral are equal to the four points of the other quadrilateral
        // Note: order of the vertices does not matter
        return (equals(this._a, quad._a, epsilon) || equals(this._a, quad._b, epsilon) || equals(this._a, quad._c, epsilon) || equals(this._a, quad._d, epsilon)) &&
                (equals(this._b, quad._a, epsilon) || equals(this._b, quad._b, epsilon) || equals(this._b, quad._c, epsilon) || equals(this._b, quad._d, epsilon)) &&
                (equals(this._c, quad._a, epsilon) || equals(this._c, quad._b, epsilon) || equals(this._c, quad._c, epsilon) || equals(this._c, quad._d, epsilon)) &&
                (equals(this._d, quad._a, epsilon) || equals(this._d, quad._b, epsilon) || equals(this._d, quad._c, epsilon) || equals(this._d, quad._d, epsilon));
    }

    // A helper method to check if two points are equal using a tolerance value
    private boolean equals(Point p1, Point p2, double epsilon) {
        // Check if the x and y coordinates of the points are within the tolerance range
        return Math.abs(p1.getX() - p2.getX()) <= epsilon && Math.abs(p1.getY() - p2.getY()) <= epsilon;
    }


    // A helper method to check if a quadrilateral is convex using the cross product of consecutive edges
    private boolean isConvex(Point a, Point b, Point c, Point d) {
        // Calculate the vectors of the four edges
        Point ab = new Point(b.getX() - a.getX(), b.getY() - a.getY());
        Point bc = new Point(c.getX() - b.getX(), c.getY() - b.getY());
        Point cd = new Point(d.getX() - c.getX(), d.getY() - c.getY());
        Point da = new Point(a.getX() - d.getX(), a.getY() - d.getY());
        // Calculate the cross products of the consecutive edges
        double cross1 = ab.getX() *bc.getY() - ab.getY()* bc.getX();
        double cross2 = bc.getX() *cd.getY() - bc.getY()* cd.getX();
        double cross3 = cd.getX() *da.getY() - cd.getY()* da.getX();
        double cross4 = da.getX() *ab.getY() - da.getY()* ab.getX();
        // Check if the signs of the cross products are the same
        return (cross1 > 0 && cross2 > 0 && cross3 > 0 && cross4 > 0) ||
                (cross1 < 0 && cross2 < 0 && cross3 < 0 && cross4 < 0);
    }
}