#include #include //#include /// po co nam to? uzywamy gdzies, bo jak nie, to tylko miejsce zajmuje #include #include #include #include #include #include #include #include "draw.h" #include "surface.h" #define PI 3.14159265 //#define EPSI 0.00000000000001 double funkcja(double x) { // double result = pow(x, 2); // double result = sin(x+3)-cos(x); // double result = pow((x-1), 2) + pow((x+2), 3); // double result = (x+1) * pow(2.72, x - 1) - 10; //sin((x*x)*PI/180) - pow(2.72, x+2); double result = pow(x, 3) - pow(x, 2) - 2 * x + 1; //double result = (x + 1) * (x - 1); //cout << "x: " << x << " : " << result << endl; return result; } double pochodna(double x) { // return cos(x+3)+sin(x); // return -2 + 2 * x + 3 * pow ((x+2), 2); // return cos(x); // return 2 * x; return 3 * pow(x, 2) - 2 * x - 2; return pow(2.72, x - 1) + (x + 1) * pow(2.72, x - 1); } double druga(double x) { // return -sin(x+3)+cos(x); // return 14 + 6 * x; // return -1 * sin(x); // return 2; return 6 * x - 2; return 2 * pow(2.72, x - 1) + (x + 1) * pow(2.72, x - 1); } double przybliz(double start) { cout << "przyblizam" << endl; return start - funkcja(start) / pochodna(start); } string zamien(double liczba) { ostringstream napis; if (!(napis << liczba)) { cout << "Blad przy konwersji liczby do napisu!" << endl; return "ERROR"; } return napis.str(); } bool sprawdz_czy_double_by_janis(double wartosc) { // cout << "Wprowadz wartosc double: "; // cin >> wartosc; // pobieramy wartosc z wejscia do zmiennej double, zatem wszystko musi przejsc poprawnie, poniewaz obiekt cin juz sam o to dba. w przypadku, gdy na pierwszym miejscu jest bledna dana (np. znak alfa), cin.peek() zwraca -1 - dzieje sie tak, poniewaz na obiekcie cin powinna zostac ustawiona flaga bledu // cout << "Wprowadzona wartosc to: " << wartosc << endl; // pokazanie wartosci, oczywiscie bez formatowania wyjscia, ktorego nigdy mi sie nie chce robic char znaczek = cin.peek(); // podgladamy kolejny znak w strumieniu // cout << "Kod kolejnego znaku to: " << int(znaczek) << ", czyli '" << znaczek << "'." << endl; // wyjscie testowe if (znaczek != 10 || cin.fail()) { // wejscie zostalo skonwertowane poprawnie wtedy i tylko wtedy, gdy do zmiennej double przez cin zostala wciagnieta cala linia - oznacza to, ze w strumieniu jako pierwszy znak do wczytania bedzie CR, czyli 10 (0x0A) (trzeba by sprawdzic wersje pod windowsy - tam jest CR/LF, czyli 10/13 cin.clear(); cin.ignore(); // wywalamy wszystko z wejscia cin.get(); // cerr << "Wyglada na to, ze system niepoprawnie odczytal wprowadzona wartosc." << endl; //Sprobuj jeszcze raz." << endl; // pokazujemy stosowny komunikat return false; } //else { // cout << "Konwersja przeprowadzona pomyslnie." << endl; // hurra, udalo sie! // } return true; } void rysuj_uklad(Surface *surf, int VWIDTH, int VHEIGHT, double a, double b, double resh, double resv, double min) { /// TODO: tutaj tez zmieniamy int na double dla a i b - odpowiednie zmiany w kodzie cout << "jestem 1" << endl; surf->setColor(0xff, 0xff, 0); cout << "jestem q" << endl; surf->moveTo(0, int(VHEIGHT + min * resv)); cout << "jestem w" << endl; cout << "vw: " << VWIDTH << endl << "h: " << VHEIGHT + min * resv << endl << "resv: " << resv << endl << "resh: " << resh << endl; surf->lineTo(VWIDTH, int(VHEIGHT + min * resv)); cout << "jestem e" << endl; double wyniczek, jednosteczka; cout << "jestem 8" << endl; if ( a < 0 & b > 0 ) { cout << "start: (" << (-1 * a * resh) << ", 0) - (" << (-1 * a * resh) << ", " << VHEIGHT << ")" << endl; surf->moveTo(int(-1 * a * resh), 0); surf->lineTo(int(-1 * a * resh), VHEIGHT - 1); } cout << "jestem 9" << endl; if ( a < -1 ) { cout << "op1" << endl; wyniczek = resh / 2; jednosteczka = (a + b) / 2; } else if ( a == -1 ) { cout << "op2" << endl; wyniczek = int((a + 3) * resh); jednosteczka = 1; } else if ( a > -1 && a < 0 ) { cout << "op3" << endl; wyniczek = int(-1 * (-1 + a) * resh); jednosteczka = 1; } else { cout << "op4" << endl; wyniczek = resh / 2; jednosteczka = (a + b) / 2; } cout << "jestem a" << endl; int dol = VHEIGHT + min * resv - 5; if (dol < 0) { dol = 0; } surf->moveTo(wyniczek, dol); cout << "jestem f" << endl << "(" << wyniczek << ", " << int((VHEIGHT + min * resv) + 0) << ")" << endl; surf->lineTo(wyniczek, int((VHEIGHT + min * resv) + 0)); // FIXME: resv do poprawki SDL_Color kolor; kolor.r = 0xff; kolor.g = 0xff; kolor.b = 0; cout << "jestem b" << endl; SDL_Rect rect; SDL_Surface *surfT; if ( TTF_Init() != 0 ) { cout << "Nie udalo sie zainicjowac TTF" << endl; return; }/* else { cout << "TTF zainicjowany poprawnie" << endl; }*/ cout << "jestem 7" << endl; TTF_Font* font = TTF_OpenFont("/usr/share/fonts/truetype/msttcorefonts/Courier_New.ttf", 12); if ( !font ) { cout << "Nie udalo sie pobrac pliku z czcionka" << endl; return; } /*else { cout << "Pobralem fonta" << endl; }*/ surfT = TTF_RenderText_Solid(font, zamien(jednosteczka).c_str(), kolor); // Sint16 pozycja_x = Sint16(fabs((a + 1) * resh )); Sint16 pozycja_x = int(wyniczek); Sint16 pozycja_y = Sint16(VHEIGHT + min * resv + 6); rect.x = ( pozycja_x == 0 ) ? Sint16( 2 * resh ) : pozycja_x; // cout << "rect.x = " << rect.x << endl; // cout << "pozycja = " << pozycja << endl << "VHEIGHT = " << VHEIGHT << endl << "surfT->h = " << surfT->h << endl << "VHEIGHT-surfT->h = " << VHEIGHT-surfT->h << endl; rect.y = ( pozycja_y >= (VHEIGHT - surfT -> h) ) ? VHEIGHT - 22 : pozycja_y; // cout << "rect.y = " << rect.y << endl; rect.w = surfT -> w; /// formatowanie stosujemy jednolite, przypomnij mi, zebym odnalazl code beautyfier rect.h = surfT -> h; SDL_BlitSurface(surfT, NULL, surf->getSurface(), &rect); surf->updateSurface(); SDL_Event event; bool running = true; while ( running ) { SDL_Delay ( 1 ); SDL_WaitEvent(&event); if (event.type == SDL_KEYDOWN & event.key.keysym.sym == SDLK_ESCAPE ) { /// wyjatkowy popis niejednolitego formatowania SDL_Quit(); running = false; } } } void oblicz_wart_fun(vector *fwart, double &min, double &max, double a, double b, double resh) { min = funkcja(a), max = funkcja(a); // cout << "\toblicz_wart_fun():\n\t\tresh: " << resh << "\n\t\ta: " << a << "; a*resh: " << a * resh << "\n\t\tb: " << b << "; b*resh: " << b * resh << endl; for (int i = a * resh; i < b * resh; i++) { fwart->push_back(funkcja(i/resh)); if (fwart->back() < min) min = fwart->back(); if (fwart->back() > max) max = fwart->back(); } } double licz_resv(int VHEIGHT, double min, double max) { return double(double(VHEIGHT - 1) / (max - min)); } void rysuj_wykres(Surface *surf, int VHEIGHT, int VWIDTH, double min, double max, vector *fwart) { /// vector przekazujemy przez wskazanie, nie przez wartosc - inaczej mamy dwukrotna zajetosc pamieci surf->setColor(0xff, 0, 0); cout << "rw1" << endl; const double resv = double(double(VHEIGHT) / (max - min)); cout << "rw2" << endl; surf->moveTo(0, int(VHEIGHT - (fwart->front() - min) * resv)); cout << "rw3" << endl; for (int i = 0; i < VWIDTH; i++) { int pikselik = VHEIGHT - 1 - (fwart->at(i) - min) * resv; //cout << "pikselik(" << i << "): " << pikselik << endl; surf->lineTo(i, pikselik); // * (VHEIGHT/2 - 1) + (VHEIGHT/2)); } cout << "rw4" << endl; surf->updateSurface(); cout << "rw5" << endl; } void metoda(double a, double b, double resv, double epsi) { int it = 0; double start = (((druga(a) > 0 && funkcja(a) > 0) || (druga(a) < 0 && funkcja(a) < 0)) ? a : b);// / resv; cout << "\tzaczynam od miejsca: " << start << endl << "\tpochodna w tym miejscu: " << pochodna(start) << endl; double f = funkcja(start); while (fabs(funkcja(start)) > epsi && it < 1200) { start = przybliz(start); f = funkcja(start); it++; cout << it << ": dla miejsca " << start << " funkcja ma wartosc " << funkcja(start) << endl; } cout << "miejsce zerowe: " << start << ", wartosc fcji w tym miejscu: " << funkcja(start) << endl << "liczba iteracji: " << it << endl; } int main_menu() { system("clear"); cout << "Co chcesz zrobic?" << endl; cout << "\t1 : Narysuj wykres funkcji" << endl; cout << "\t2 : Policz miejsce zerowe" << endl; cout << "\t3 : Zakoncz" << endl << endl; cout << "Twoj wybor to: "; char wybor = 10; while (wybor == 10) { cin.get(wybor); } cout << endl << endl; if (wybor < 49 || wybor > 51) { system("clear"); return main_menu(); } else { return (int(wybor) - 48); } } bool sprawdz_a_b(double a, double b) { if (a < b) { return true; } return false; } int main(int argc, char *argv[]) { const int VWIDTH = 550; const int VHEIGHT = 700; double epsi; double a, b; int znaczek = 0; double min, max, resv, resh; bool przedzial_ok; while (znaczek != 3) { znaczek = main_menu(); if (cin.peek() == 10) { cin.get(); } switch ( znaczek ) { case 1: { przedzial_ok = false; while (!przedzial_ok) { cout << "Podaj poczatek i koniec przedzialu (a, b), na ktorym chcesz narysowac wykres:" << endl; cout << "\ta = "; cin >> a; while(!(sprawdz_czy_double_by_janis(a))) { cout << "Nie podales poprawnej wartosci! Wprowadz ja jeszcze raz: flagi: " << cin.good() << endl; cout << "\ta = "; cin >> a; } cout << "\tb = "; cin >> b; while(!(sprawdz_czy_double_by_janis(b))) { cout << "Nie podales poprawnej wartosci! Wprowadz ja jeszcze raz:" << endl; cout << "\tb = "; cin >> a; } przedzial_ok = sprawdz_a_b(a, b); if (!przedzial_ok) { cout << endl << "Podales bledne konce przedzialu." << endl; } } resh = double(double(VWIDTH) / (b - a)); cout << "resh: " << resh << endl; vector fwart; cout << "jestem 1" << endl; fwart.reserve(int(resh * b - resh * a) + 1); /// dzieki statycznej inicjalizacji w bloku mozemy skorzystac z domyslnego destruktora wywolywanego po zakonczeniu zasiego zmiennej, a wiec robi sie ten blok wielokrotnego uzytku. // TODO: ustawic rozmiar statycznie - wielokrotnie przyspieszy program, zaoszczedzimy mnostwo kopiowan w nowe miejsce w pamieci; cout << "jestem 2" << endl; oblicz_wart_fun(&fwart, min, max, a, b, resh); if (min > 0) { min = -1; } if (max < 0) { max = 1; } cout << "jestem 3" << endl; cout << "min: " << min << endl << "max: " << max << endl; Surface surf( VWIDTH, VHEIGHT, "Draw_demo" ); surf.clearScreen(); //clear screen surf.updateSurface(); surf.setBackgroundColor ( 0x00, 0x00, 0x00 ); //set background to black cout << "jestem 4" << endl; resv = licz_resv(VHEIGHT, min, max); cout << "jestem 4a" << endl; rysuj_wykres(&surf, VHEIGHT, VWIDTH, min, max, &fwart); cout << "jestem 5" << endl; rysuj_uklad(&surf, VWIDTH, VHEIGHT, a, b, resh, resv, min); cout << "jestem 6" << endl; break; } case 2: { przedzial_ok = false; while (!przedzial_ok) { cout << "Podaj poczatek i koniec przedzialu (a, b), na ktorym chcesz wyznaczyc miejsce zerowe:" << endl; cout << "\ta = "; cin >> a; while(!(sprawdz_czy_double_by_janis(a))) { cout << "Nie podales poprawnej wartosci! Wprowadz ja jeszcze raz:" << endl; cout << "\ta = "; cin >> a; } cout << "\tb = "; cin >> b; while(!(sprawdz_czy_double_by_janis(b))) { cout << "Nie podales poprawnej wartosci! Wprowadz ja jeszcze raz:" << endl; cout << "\tb = "; cin >> a; } przedzial_ok = sprawdz_a_b(a, b); if (!przedzial_ok) { cout << endl << "Podales bledne konce przedzialu." << endl; } } resh = double(double(VWIDTH) / (b - a)); vector fwart; fwart.reserve(int(resh * b - resh * a) + 1); oblicz_wart_fun(&fwart, min, max, a, b, resh); if (((max > 0) && (min > 0)) || ((max < 0) && (min < 0))) { cerr << "Blad! funkcja nie ma miejsca zerowego w tym przedziale lub ma ich wiecej niz jedno!" << endl; cin.ignore(); break; } cout << "Podaj z jaka dokladnoscia mam wyznaczyc miejsce zerowe:" << endl; cout << "\tepsilon = "; cin >> epsi; resv = licz_resv(VHEIGHT, min, max); metoda(a, b, resv, epsi); cin.ignore(); break; } // case 3: // cout << "koniec" << endl; // petla = false; // break; // default: // cout << "cos innego" << endl; // cout << "1 - rysuj wykres" << endl << "2 - policz miejsce zerowe" << endl; // cin >> znaczek; // break; } if (znaczek != 3) { cout << "Nacisnij ENTER, zeby powrocic do menu" << endl; cin.ignore(); } } /* cout << "podaj zakres" << endl << "a = "; cin >> a; cout << "b = "; cin >> b; cout << "podaj z jakim przyblizeniem chcesz oszacowac miejsce zerowe" << endl << "epsi = "; cin >> epsi;*/ // int it = 0; // const Point center ( VWIDTH/2, VHEIGHT/2 ); //center of screen //rysowanie wykresu /* cout << " !! POCHODNA: " << pochodna(miejsce) << endl; for (int i = 0; i < VWIDTH; i++) { surf.lineTo(i, pochodna(miejsce) * i + funkcja(miejsce)); } */ //obliczanie miejsca zerowego //surf.setColor(0x30, 0x30, 0x30); //SDL_Delay ( 5000 ); //display 10 seconds before exit return 0; }