Московский государственный индустриальный университет
Опубликован: 27.09.2006 | Доступ: свободный | Студентов: 3333 / 380 | Оценка: 4.17 / 3.79 | Длительность: 24:17:00
Специальности: Программист
Лекция 11:

Проект "Выпуклая оболочка"

Текст эталонного проекта

Данная секция содержит исходный текст программы, являющейся итогом работы над проектом "Выпуклая оболочка".

Эталонный проект

//Класс, описывающий точку (Point) на плоскости (R2).
class R2Point {
    private double x, y;

    public R2Point(double x, double y) {
        this.x = x; this.y = y;
    }
    public R2Point() throws Exception {
        x = Xterm.inputDouble("x -> ");
        y = Xterm.inputDouble("y -> ");
    }
    public static double dist(R2Point a, R2Point b) {
        return Math.sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
    }
    public static double area(R2Point a, R2Point b, R2Point c) {
        return 0.5*((a.x-c.x)*(b.y-c.y)-(a.y-c.y)*(b.x-c.x));
    }
    public static boolean equal(R2Point a, R2Point b) {
        return a.x==b.x && a.y==b.y;
    }
    public static boolean isTriangle(R2Point a, R2Point b, R2Point c) {
        return area(a, b, c) != 0.0;
    }
    public boolean inside(R2Point a, R2Point b) {
        return (a.x <= x && x <= b.x || a.x >= x && x >= b.x) &&
            (a.y <= y && y <= b.y || a.y >= y && y >= b.y);
    }
    public boolean light(R2Point a, R2Point b) {
        double s = area(a, b, this);
        return s < 0.0 || ( s == 0.0 && ! inside(a, b));
    }
}
// Непрерывная реализация дека.
class Deq {
    private final static int DEFSIZE = 16;
    private R2Point[] array;
    private int size, head, tail;
    private int forward(int index) {
        return ++index < array.length ? index : 0;
    }
    private int backward(int index) {
        return --index >= 0 ? index : array.length - 1;
    }

    public Deq(int size) {
        array = new R2Point[size];
        this.size = head = 0;
        tail = array.length - 1;
    }
    public Deq() {
        this(DEFSIZE);
    }
    public int length() {
        return size;
    }
    public void pushFront(R2Point p) {
        array[head=backward(head)] = p;
        size += 1;
    }
    public void pushBack(R2Point p) {
        array[tail=forward(tail)] = p;
        size += 1;
    }
    public R2Point popFront() {
        R2Point p = front();
        head = forward(head);
        size -= 1;
        return p;
    }
    public R2Point popBack() {
        R2Point p = back();
        tail = backward(tail);
        size -= 1;
        return p;
    }
    public R2Point front() {
        return array[head];
    }
    public R2Point back() {
        return array[tail];
    }
} 
// Интерфейс, задающий новый тип - фигуру.
interface Figure {
    public double perimeter();
    public double area();
    public Figure add(R2Point p);
}
// Класс "нульугольник", реализующий интерфейс фигуры.
class Void implements Figure {
    public double perimeter() {
        return 0.0;
    }
    public double area() {
        return 0.0;
    }
    public Figure add(R2Point p) {
        return new Point(p);
    }
}
// Класс "одноугольник", реализующий интерфейс фигуры.
class Point implements Figure {
    private R2Point p;

    public Point(R2Point p) {
        this.p = p;
    }
    public double perimeter() {
        return 0.0;
    }
    public double area() {
        return 0.0;
    }
    public Figure add(R2Point q) {
        if (!R2Point.equal(p,q)) return new Segment(p, q);
        else return this;
    }
} 
// Класс "двуугольник", реализующий интерфейс фигуры.
class Segment implements Figure {
    private R2Point p, q;
  
    public Segment(R2Point p, R2Point q) {
        this.p = p; this.q = q;
    }
    public double perimeter() {
        return 2.0 * R2Point.dist(p, q);
    }
    public double area() {
        return 0.0;
    }
    public Figure add(R2Point r) {
        if (R2Point.isTriangle(p, q, r))
            return new Polygon(p, q, r);
        if (q.inside(p, r)) q = r;
        if (p.inside(r, q)) p = r;
        return this;
    }
}
// Класс "многоугольник", реализующий интерфейс фигуры.
class Polygon extends Deq implements Figure {
    private double s, p;
    private void grow(R2Point a, R2Point b, R2Point t) {
        p -= R2Point.dist(a, b);
        s += Math.abs(R2Point.area(a, b, t));
    }
  
    public Polygon(R2Point a, R2Point b, R2Point c) {
        pushFront(b);
        if (b.light(a, c)) {
            pushFront(a); pushBack(c);
        } else {
            pushFront(c); pushBack(a);
        }
        p = R2Point.dist(a, b) + R2Point.dist(b, c)
            + R2Point.dist(c, a);
        s = Math.abs(R2Point.area(a, b, c));
    }
    public double perimeter() {
        return p;
    }
    public double area() {
        return s;
    }
    public Figure add(R2Point t) {
        int i;
	// Ищем освещенные ребра, просматривая их одно за другим.
        for (i=length(); i>0 && !t.light(back(),front()); i--)
            pushBack(popFront());
        // УТВЕРЖДЕНИЕ: либо ребро [back(),front()] освещено из t,
	//              либо освещенных ребер нет совсем.
        if (i>0) {
            R2Point x;
            grow(back(), front(), t);
            // Удаляем все освещенные ребра из начала дека.
            for (x = popFront(); t.light(x, front()); x = popFront())
                grow(x, front(), t );
            pushFront(x);
            // Удаляем все освещенные ребра из конца дека.
            for (x = popBack(); t.light(back(), x); x = popBack())
                grow(back(), x, t);
            pushBack(x);
            // Завершаем обработку добавляемой точки.
            p += R2Point.dist(back(), t) + R2Point.dist(t, front());
            pushFront(t);
        }
        return this;
    }
}
// Класс "выпуклая оболочка".
class Convex {
    private Figure fig;
       
    public Convex() {
        fig = new Void();
    }
    public void add(R2Point p) {
        fig = fig.add(p);
    }
    public double area() {
        return fig.area();
    }
    public double perimeter() {
        return fig.perimeter();
    }
}
// Тест для выпуклой оболочки.
class ConvexTest {
    public static void main(String[] args) throws Exception {
        Convex convex = new Convex();
        while (true) {
            convex.add(new R2Point());
            Xterm.println("S = " + convex.area() + " , P = "
                               + convex.perimeter());
        }
    }
}
Анастасия Халудорова
Анастасия Халудорова
екатерина яковлева
екатерина яковлева