Опубликован: 27.09.2006 | Уровень: для всех | Доступ: свободно
Лекция 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());
        }
    }
}
Анастасия Халудорова
Анастасия Халудорова
подавляющее большиство фукций на пространстве последовательостей?
екатерина яковлева
екатерина яковлева
как получить сертификат,что для этого нужно?
Дмитрий Карпов
Дмитрий Карпов
Россия, Нижний Новгород
Антон Никитин
Антон Никитин
Россия, Хабаровск