All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.opentripplanner.visibility.VLPolygon Maven / Gradle / Ivy

package org.opentripplanner.visibility;

/**
 Ported by David Turner from Visilibity, by Karl J. Obermeyer
   
 
 This port undoubtedly introduced a number of bugs (and removed some features).
 
 Bug reports should be directed to the OpenTripPlanner project, unless they 
 can be reproduced in the original VisiLibity
 */

import java.util.ArrayList;
import java.util.List;

/**
 Ported by David Turner from Visilibity, by Karl J. Obermeyer


 This port undoubtedly introduced a number of bugs (and removed some features).

 Bug reports should be directed to the OpenTripPlanner project, unless they
 can be reproduced in the original VisiLibity
 */
public class VLPolygon {

    public ArrayList vertices;

    public VLPolygon() {

        vertices = new ArrayList();
    }

    double boundary_distance(VLPoint point_temp) {
        return point_temp.boundary_distance(this);
    }

    double boundary_distance(LineSegment line_segment) {
        return line_segment.boundary_distance(this);
    }

    public VLPolygon(List vertices_temp) {
        vertices = new ArrayList(vertices_temp);
    }

    public int n() {
        return vertices.size();
    }

    public VLPolygon(VLPoint point0, VLPoint point1, VLPoint point2) {
        vertices = new ArrayList();
        vertices.add(point0);
        vertices.add(point1);
        vertices.add(point2);
    }

    public int r() {
        int r_count = 0;
        if (vertices.size() > 1) {
            // Use cross product to count right turns.
            for (int i = 0; i <= n() - 1; i++)
                if ((get(i + 1).x - get(i).x) * (get(i + 2).y - get(i).y)

                - (get(i + 1).y - get(i).y) * (get(i + 2).x - get(i).x) < 0)
                    r_count++;
            if (area() < 0) {
                r_count = n() - r_count;
            }
        }
        return r_count;
    }

    public boolean is_simple(double epsilon) {

        if (n() == 0 || n() == 1 || n() == 2)
            return false;

        // Make sure adjacent edges only intersect at a single point.
        for (int i = 0; i <= n() - 1; i++)
            if (new LineSegment(get(i), get(i + 1)).intersection(
                    new LineSegment(get(i + 1), get(i + 2)), epsilon).size() > 1)
                return false;

        // Make sure nonadjacent edges do not intersect.
        for (int i = 0; i < n() - 2; i++)
            for (int j = i + 2; j <= n() - 1; j++)
                if (0 != (j + 1) % vertices.size()
                        && new LineSegment(get(i), get(i + 1)).distance(new LineSegment(get(j),
                                get(j + 1))) <= epsilon)
                    return false;

        return true;
    }

    public boolean is_in_standard_form() {
        if (vertices.size() > 1) // if more than one point in the polygon.
            for (int i = 1; i < vertices.size(); i++)
                if (vertices.get(0).compareTo(vertices.get(i)) > 0)
                    return false;
        return true;
    }

    public double boundary_length() {
        double length_temp = 0;
        if (n() == 0 || n() == 1)
            return 0;
        for (int i = 0; i < n() - 1; i++)
            length_temp += vertices.get(i).distance(vertices.get(i + 1));
        length_temp += vertices.get(n() - 1).distance(vertices.get(0));
        return length_temp;
    }

    public double area() {
        double area_temp = 0;
        if (n() == 0)
            return 0;
        for (int i = 0; i <= n() - 1; i++)
            area_temp += get(i).x * get(i + 1).y - get(i + 1).x * get(i).y;
        return area_temp / 2.0;
    }

    public VLPoint centroid() {
        assert (vertices.size() > 0);

        double area_temp = area();
        assert (area_temp != 0);
        double x_temp = 0;
        for (int i = 0; i <= n() - 1; i++)
            x_temp += (get(i).x + get(i + 1).x)
                    * (get(i).x * get(i + 1).y - get(i + 1).x * get(i).y);
        double y_temp = 0;
        for (int i = 0; i <= n() - 1; i++)
            y_temp += (get(i).y + get(i + 1).y)
                    * (get(i).x * get(i + 1).y - get(i + 1).x * get(i).y);
        return new VLPoint(x_temp / (6 * area_temp), y_temp / (6 * area_temp));
    }

    public double diameter() {
        // Precondition: nonempty Polygon.
        assert (n() > 0);

        double running_max = 0;
        for (int i = 0; i < n() - 1; i++) {
            for (int j = i + 1; j < n(); j++) {
                if (get(i).distance(get(j)) > running_max)
                    running_max = get(i).distance(get(j));
            }
        }
        return running_max;
    }

    public BoundingBox bbox() {
        // Precondition: nonempty Polygon.
        assert (vertices.size() > 0);

        BoundingBox bounding_box = new BoundingBox();
        double x_min = vertices.get(0).x, x_max = vertices.get(0).x, y_min = vertices.get(0).y, y_max = vertices
                .get(0).y;
        for (int i = 1; i < vertices.size(); i++) {
            if (x_min > vertices.get(i).x) {
                x_min = vertices.get(i).x;
            }
            if (x_max < vertices.get(i).x) {
                x_max = vertices.get(i).x;
            }
            if (y_min > vertices.get(i).y) {
                y_min = vertices.get(i).y;
            }
            if (y_max < vertices.get(i).y) {
                y_max = vertices.get(i).y;
            }
        }
        bounding_box.x_min = x_min;
        bounding_box.x_max = x_max;
        bounding_box.y_min = y_min;
        bounding_box.y_max = y_max;
        return bounding_box;
    }

    ArrayList random_points(int count, double epsilon) {
        // Precondition: nonempty Polygon.
        assert (vertices.size() > 0);

        BoundingBox bounding_box = bbox();
        ArrayList pts_in_polygon = new ArrayList(count);
        VLPoint pt_temp = new VLPoint(
                Util.uniform_random_sample(bounding_box.x_min, bounding_box.x_max),
                Util.uniform_random_sample(bounding_box.y_min, bounding_box.y_max));
        while (pts_in_polygon.size() < count) {
            while (!pt_temp.in(this, epsilon)) {
                pt_temp.set_x(Util.uniform_random_sample(bounding_box.x_min, bounding_box.x_max));
                pt_temp.set_y(Util.uniform_random_sample(bounding_box.y_min, bounding_box.y_max));
            }
            pts_in_polygon.add(pt_temp);
            pt_temp.set_x(Util.uniform_random_sample(bounding_box.x_min, bounding_box.x_max));
            pt_temp.set_y(Util.uniform_random_sample(bounding_box.y_min, bounding_box.y_max));
        }
        return pts_in_polygon;
    }

    public void enforce_standard_form() {
        int point_count = vertices.size();
        if (point_count > 1) { // if more than one point in the polygon.
            ArrayList vertices_temp = new ArrayList(point_count);
            // Find index of lexicographically smallest point.
            int index_of_smallest = 0;
            int i; // counter.
            for (i = 1; i < point_count; i++)
                if (vertices.get(i).compareTo(vertices.get(index_of_smallest)) < 0)
                    index_of_smallest = i;
            // Fill vertices_temp starting with lex. smallest.
            for (i = index_of_smallest; i < point_count; i++)
                vertices_temp.add(vertices.get(i));
            for (i = 0; i < index_of_smallest; i++)
                vertices_temp.add(vertices.get(i));
            vertices = vertices_temp;
        }
    }

    public void eliminate_redundant_vertices(double epsilon) {
        // Degenerate case.
        if (vertices.size() < 4)
            return;

        // Store new minimal length list of vertices.
        ArrayList vertices_temp = new ArrayList(vertices.size());

        // Place holders.
        int first = 0;
        int second = 1;
        int third = 2;

        while (third <= vertices.size()) {
            // if second is redundant
            if (new LineSegment(get(first), get(third)).distance(get(second)) <= epsilon) {
                // =>skip it
                second = third;
                third++;
            }
            // else second not redundant
            else {
                // =>add it
                vertices_temp.add(get(second));
                first = second;
                second = third;
                third++;
            }
        }

        // decide whether to add original first point
        if (new LineSegment(vertices_temp.get(0), vertices_temp.get(vertices_temp.size() - 1))
                .distance(vertices.get(0)) > epsilon)
            vertices_temp.add(vertices.get(0));

        // Update list of vertices.
        vertices = vertices_temp;
    }

    public void reverse() {
        int n = n();
        if (n > 2) {
            // reverse, leaving the first point in its place
            for (int i = 1; i < (n+1) / 2; ++i) {
                VLPoint temp = vertices.get(i);
                vertices.set(i, vertices.get((n - i)));
                vertices.set((n - i), temp);
            }
        }
    }

    public boolean equals(Object o) {
        if (!(o instanceof VLPolygon)) {
            return false;
        }
        VLPolygon polygon2 = (VLPolygon) o;
        if (n() != polygon2.n() || n() == 0 || polygon2.n() == 0)
            return false;
        for (int i = 0; i < n(); i++)
            if (!get(i).equals(polygon2.get(i)))
                return false;
        return true;
    }

    public int hashCode() {
        return vertices.hashCode() + 1;
    }

    public VLPoint get(int i) {
        return vertices.get(i % vertices.size());
    }

    boolean equivalent(VLPolygon polygon2, double epsilon) {
        if (n() == 0 || polygon2.n() == 0)
            return false;
        if (n() != polygon2.n())
            return false;
        // Try all cyclic matches
        int n = n();// =polygon2.n()
        for (int offset = 0; offset < n; offset++) {
            boolean successful_match = true;
            for (int i = 0; i < n; i++) {
                if (get(i).distance(polygon2.get(i + offset)) > epsilon) {
                    successful_match = false;
                    break;
                }
            }
            if (successful_match)
                return true;
        }
        return false;
    }

    double boundary_distance(VLPolygon polygon2) {
        assert (n() > 0 && polygon2.n() > 0);

        // Handle single point degeneracy.
        if (n() == 1)
            return get(0).boundary_distance(polygon2);
        else if (polygon2.n() == 1)
            return polygon2.get(0).boundary_distance(this);
        // Handle cases where each polygon has at least 2 points.
        // Initialize to an upper bound.
        double running_min = get(0).boundary_distance(polygon2);
        double distance_temp;
        // Loop over all possible pairs of line segments.
        for (int i = 0; i <= n() - 1; i++) {
            for (int j = 0; j <= polygon2.n() - 1; j++) {
                distance_temp = new LineSegment(get(i), get(i + 1)).distance(new LineSegment(
                        polygon2.get(j), polygon2.get(j + 1)));
                if (distance_temp < running_min)
                    running_min = distance_temp;
            }
        }
        return running_min;
    }

    public String toString() {
        String outs = "";
        for (int i = 0; i < n(); i++)
            outs += get(i) + "\n";
        return outs;
    }

    public boolean hasPointInside(VLPolygon container) {
        for (VLPoint point : vertices) {
            if (point.in(container)) {
                return true;
            }
        }
        return false;
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy