Portál o technologiích a vývoji

Grafika – Lagrangeova křivka

Autor: Redakce ZdrojovyKod.cz Datum: 19.2.2011 Počet shlédnutí: 1 271 159x

Lagrangeova křivka patří k nejstarším pokusům o spojení bodů křivkou. Jedná se o interpolační křivku (narozdíl od Fergusonovi a Bezierovi křivky, které jsou aproximační), tzn. že prochází přímo zadanými body. V našem připadě dovolíme uživateli zadat libovolných, předem zadaný, počet bodů. Existuje i možnost vykreslovat křivku znovu pokaždé, kdy uživatel zadá další bod, tato úprava je velmi snadná a jistě ji zvládné dopsat do ukázaného algoritmu každý.

1. Nejprve necháme uživatele zadat počet bodů, po jejichž zadnaní se má křivka vykreslit, k tomu můžeme využít například komponentu jTextField. Následně v metodě mousePressed vykreslujeme body a ukládáme jejich souřadnice do ArrayListu.

Pro správné vykreslení křivky musí body splňovat podmínku že xi musí být menší než xi+1 (xi < xi+1) (toto zde pro jednoduchost neošetřuji, ale stačilo by přidat jednu podmínku, takto je správnost vykreslení z části ponechána na svědomí uživatele).

   private void formMousePressed(java.awt.event.MouseEvent evt) {
        Graphics g = getGraphics();
        int prumer = 5;
        g.setColor(Color.red);

        if (nakreslenoBodu < pocetBodu) {
            Point p = new Point(evt.getX(), evt.getY());
            body.add(p);
            g.drawOval(p.x - prumer / 2, p.y - prumer / 2, prumer, prumer);
            g.fillOval(p.x - prumer / 2, p.y - prumer / 2, prumer, prumer);
            g.drawString("P" + nakreslenoBodu, evt.getX() + 6, evt.getY() + 6);
            nakreslenoBodu++;
        }

        if (nakreslenoBodu == pocetBodu) {
            vykresliLagrange();
        }
    }

Pokud je počet nakreslených bodů shodný s počtem plánovaných bodů, zavoláme metodu, která vypočte a vykreslí křivku.

2. Nyní si představíme slíbenou metodu pro výpočet křivky, ten celý vychází ze vzorce pro výpočet Lagrangevova polynomu, který je zde uveden.

 public int vypoctiLagrange(double x) {
        double citatel, jmenovatel, soucet = 0.0;
        Point bod = new Point();

        for (int i = 0; i < body.size(); i++) {
            bod = body.get(i);
            citatel = 1.0;
            jmenovatel = 1.0;

            for (int j = 0; j < body.size(); j++) {
                if (i != j) {
                    citatel = citatel * (x - body.get(j).x);
                    jmenovatel = jmenovatel * (bod.x - body.get(j).x);
                }
            }
            soucet = soucet + bod.y * (citatel / jmenovatel);
        }
    return soucet;
}

3. Vykreslení křivky probíhá v metodě vykresliLagrange()

    Graphics g = getGraphics();
        int y;
        ArrayList bodyLagrang = new ArrayList();

        for (int x = 0; x < getWidth(); x++) {
            y = vypoctiLagrange(x);
            bodyLagrang.add(new Point(x, y));
        }

        int xpoints[] = new int[bodyLagrang.size()];
        int ypoints[] = new int[bodyLagrang.size()];

        for (int i = 0; i < bodyLagrang.size(); i++) {
            xpoints[i] = bodyLagrang.get(i).x;
            ypoints[i] = bodyLagrang.get(i).y;

        }

        g.drawPolyline(xpoints, ypoints, xpoints.length);
    }

Jak vidíte, nejprve jsme si vytvořili nový ArrayList kam budeme ukládat souřadnice výsledné křivky, následně generujeme tyto body v cyklu, do y přiřadíme výsledek metody vypoctiLagrange() a do x přiřazujeme index cyklu, který jede od začátku do samého konce kreslícího plátna. (Křivka není vodorovná úsečka, proto nebude "od kraje ke kraji", ale jedná se o ideální počet bodů pro správné vykreslení).

Samotnou křivku můžeme vykreslit takto:

  int xpoints[] = new int[bodyLagrang.size()];
        int ypoints[] = new int[bodyLagrang.size()];

        for (int i = 0; i < bodyLagrang.size(); i++) {
            xpoints[i] = bodyLagrang.get(i).x;
            ypoints[i] = bodyLagrang.get(i).y;

        }

g.drawPolyline(xpoints, ypoints, xpoints.length);

a nebo takto:

 for (int i = 0; i < bodyLagrang.size()-1; i++) {
           g.drawLine(bodyLagrang.get(i).x, bodyLagrang.get(i).y, bodyLagrang.get(i+1).x, bodyLagrang.get(i+1).y);

        }

Záleží čistě na vašich preferencích. Výsledek bude vypadat podobně jako na tomto obrázku (v závisloti na zadaných bodech):

Žádné komentáře

Poslat komentář

Vaše e-mailová adresa nebude zveřejněna.