1. C++ / Говнокод #27990

    +1

    1. 01
    2. 02
    3. 03
    4. 04
    5. 05
    6. 06
    7. 07
    8. 08
    9. 09
    10. 10
    11. 11
    12. 12
    13. 13
    14. 14
    15. 15
    16. 16
    17. 17
    18. 18
    19. 19
    20. 20
    21. 21
    22. 22
    23. 23
    24. 24
    25. 25
    26. 26
    27. 27
    28. 28
    29. 29
    30. 30
    31. 31
    32. 32
    33. 33
    34. 34
    35. 35
    36. 36
    37. 37
    38. 38
    39. 39
    40. 40
    41. 41
    42. 42
    43. 43
    44. 44
    45. 45
    46. 46
    47. 47
    48. 48
    49. 49
    50. 50
    51. 51
    52. 52
    53. 53
    54. 54
    55. 55
    56. 56
    57. 57
    58. 58
    59. 59
    60. 60
    61. 61
    62. 62
    63. 63
    64. 64
    65. 65
    66. 66
    67. 67
    68. 68
    69. 69
    #include <iostream>
    using namespace std;
    void Brezenhem(char **z, int x0, int y0, int x1, int y1)
    {
      int A, B, sign;
      A = y1 - y0;
      B = x0 - x1;
      if (abs(A) > abs(B)) sign = 1;
      else sign = -1;
      int signa, signb;
      if (A < 0) signa = -1;
      else signa = 1;
      if (B < 0) signb = -1;
      else signb = 1;
      int f = 0;
      z[y0][x0] = '*';
      int x = x0, y = y0;
      if (sign == -1) 
      {
        do {
          f += A*signa;
          if (f > 0)
          {
            f -= B*signb;
            y += signa;
          }
          x -= signb;
          z[y][x] = '*';
        } while (x != x1 || y != y1);
      }
      else
      {
        do {
          f += B*signb;
          if (f > 0) {
            f -= A*signa;
            x -= signb;
          }
          y += signa;
          z[y][x] = '*';
        } while (x != x1 || y != y1);
      }
    }
    int main()
    {
      const int SIZE = 25; // размер поля
      int x1, x2, y1, y2;
      char **z;
      z = new char*[SIZE];
      for (int i = 0; i < SIZE; i++) 
      {
        z[i] = new char[SIZE];
        for (int j = 0; j < SIZE; j++)
          z[i][j] = '-';
      }
      cout << "x1 = ";     cin >> x1;
      cout << "y1 = ";     cin >> y1;
      cout << "x2 = ";     cin >> x2;
      cout << "y2 = ";    cin >> y2;
      Brezenhem(z, x1, y1, x2, y2);
      for (int i = 0; i < SIZE; i++) 
      {
        for (int j = 0; j < SIZE; j++)
          cout << z[i][j];
        cout << endl;
      }
      cin.get(); cin.get();
      return 0;
    }

    https://prog-cpp.ru/brezenham/

    спойлер: автор тян

    Запостил: digitalEugene, 04 Февраля 2022

    Комментарии (98) RSS

    • Автор -- Брезенхейм.
      Ответить
    • спойлер: автор тян

      Запостил: digitalEugene
      Ответить
    • Меня тут больше всего смешение крестов и сишки напрягает, на самом деле. Ну возьми ты вектор, раз на крестах пишешь, зачем все эти утечки с ручными new...

      А идея алгоритма вроде норм освоена.
      Ответить
      • А меня форматирование бесит.

        И вообще, лучше этот код переписать на «Nim».
        Ответить
      • Да тут вообще динамическая память нинужна.
        Ответить
        • Это правда.

          Ты заранее статически знаешь размер, и он равен 25. Даже если ты пишешь по 8086, тебе хватит стека.
          Ответить
      • >смешение крестов и сишки напрягает,
        бо нехуй студентам давать кресты

        Алгоритмы надо учить на чистой сишке.
        Ответить
        • согласен. перед изучением крестов нужен годик хотя бы няшной.
          Ответить
    • > спойлер: автор тян
      Поздравляю, digitalEugene!
      Ответить
      • Мдааа, сюда то это зачем? Мало того что друзья узнали, так теперь ещё пол страны. Эй сладкая попка) если ты читаешь выложи сюда его профиль вк и тел, коминг аут нужен человеку, поможем всей страной)
        Ответить
    • > спойлер: автор тян

      Привет, сестрёнка!
      Ответить
    • Хреновый алгоритм, он всегда на первом шаге увеличивает обе координаты

      -*-----------------------
      --**********************-
      -------------------------
      Ответить
    • > спойлер: автор тян
      Ня! (─‿‿─)
      Ответить
    • В deltaX (тут B) перепутаны местами x0 и x1, из-за этого пишем x -= signb, но y += signA
      Ответить
    • пофиксил
      https://ideone.com/Ndovg3
      void Brezenhem(char **z, int x0, int y0, int x1, int y1)
      {
        int A, B, sign;
        A = y1 - y0;
        B = x1 - x0;
        if (abs(A) > abs(B)) sign = 1;
        else sign = -1;
        int signa, signb;
        if (A < 0) signa = -1;
        else signa = 1;
        if (B < 0) signb = -1;
        else signb = 1;
        A = abs(A);
        B = abs(B);
        int f = 0;
        int x = x0, y = y0;
        if (sign == -1) 
        {
          do {
            z[y][x] = '*';
            f += A + 1;
            if (f >= B + 1) {
              f -= B + 1;
              y += signa;
            }
            x += signb;
          } while (x != x1 + signb);
        }
        else
        {
          do {
            z[y][x] = '*';
            f += B + 1;
            if (f >= A + 1) {
              f -= A + 1;
              x += signb;
            }
            y += signa;
          } while (y != y1 + signa);
        }
      }
      Кодстайл соблядён.
      Ответить
    • Перевёл на "Си":
      #include <stdio.h>
      #include <stdlib.h>
      
      void Brezenhem(int size, char z[][size], int x0, int y0, int x1, int y1)
      {
        int A, B, sign;
        A = y1 - y0;
        B = x1 - x0;
        if (abs(A) > abs(B)) sign = 1;
        else sign = -1;
        int signa, signb;
        if (A < 0) signa = -1;
        else signa = 1;
        if (B < 0) signb = -1;
        else signb = 1;
        A = abs(A) + 1;
        B = abs(B) + 1;
        int f = 0;
        int x = x0, y = y0;
        if (sign == -1) 
        {
          do {
            z[y][x] = '*';
            f += A;
            if (f >= B) {
              f -= B;
              y += signa;
            }
            x += signb;
          } while (x != x1 + signb);
        }
        else
        {
          do {
            z[y][x] = '*';
            f += B;
            if (f >= A) {
              f -= A;
              x += signb;
            }
            y += signa;
          } while (y != y1 + signa);
        }
      }
      int main()
      {
        #define SIZE 25 // размер поля
        int x1, x2, y1, y2;
        char z[SIZE][SIZE];
        for (int i = 0; i < SIZE; i++) {
          for (int j = 0; j < SIZE; j++) {
            z[i][j] = '-';
          }
        }
        printf("x1 = ");
        scanf("%d", &x1);
        printf("y1 = ");
        scanf("%d", &y1);
        printf("x2 = ");
        scanf("%d", &x2);
        printf("y2 = ");
        scanf("%d", &y2);
        Brezenhem(SIZE, z, x1, y1, x2, y2);
        for (int i = 0; i < SIZE; i++) 
        {
          for (int j = 0; j < SIZE; j++)
            putchar(z[i][j]);
          puts("");
        }
        return 0;
      }
      https://ideone.com/bThnq2

      > void Brezenhem(int size, char z[][size], int x0, int y0, int x1, int y1)
      Именно поэтому я за "Си"
      Ответить
      • А нейронка сможет дописать?
        Ответить
        • Долго искал нормальный вореант, устал, остановился на этом:
          #include <stdio.h>
          #include <stdlib.h>
          
          void Brezenhem(int size, char z[][size], int x0, int y0, int x1, int y1)
          {
            int A, B, sign;
            A = y1 - y0;
            B = x1 - x0;
            if (abs(A) > abs(B)) sign = 1;
            else sign = -1;
            int signa, signb;
            if (A < 0) signa = -1;
            else signa = 1;
            if (B < 0) signb = -1;
            else signb = 1;
            A = abs(A) + 1;
            B = abs(B) + 1;
            int f = 0;
            int x = x0, y = y0;
            if (sign == -1) 
            {
              do {
                z[y][x] = '*';
                f += A;
                if (f >= B) {
                  f -= B;
                  y += signa;
                }
                x += signb;
              } while (x != x1 + signb);
            }
            else
            {
              do {
                z[y][x] = '*';
                f += B;
                if (f >= A) {
                  f -= A;
                  x += signb;
                }
                y += signa;
              } while (y != y1 + signa);
            }
          }
          int main()
          {
            int size, x0, y0, x1, y1;
            printf("Size: ");
            scanf("%d", &size);
            printf("Size: ");
            scanf("%d", &x0);
            printf("Size: ");
            scanf("%d", &y0);
            printf("Size: ");
            scanf("%d", &x1);
            printf("Size: ");
            scanf("%d", &y1);
            char z[size][size];
            Brezenhem(size, z, x0, y0, x1, y1);
            for (int i = 0; i < size; i++)
            {
              printf("%c", z[i][0]);
            }
            return 0;
          }
          Ответить
          • А по сигнатуре дичь всякая генерится.
            Ответить
            • Потому что он не Brezenhem, а Bresenham.
              Ответить
            • #include <stdio.h>
              #include <stdlib.h>
              
              void Bresenham(int size, char z[][size], int x0, int y0, int x1, int y1)
              {
                  int dx = abs(x1-x0),
                      dy = abs(y1-y0),
                      d = dx+dy;
                  int i, j, ii = dx-1, jj = dy-1;
                  if (d==0) {
                      int r = dy / 2;
                      for (i=y0; i<=y1; i++)
                          Bresenham_x(size, z, x0+i, x0+y1, i, r, &j);
                  }
                  else if (d>0) {
                      int s = dx / 2;
                      for (i=x0; i<=x1; i++)
                          Bresenham_y(size, z, i, y0+i, i, s, &j);
                  }
                  else if (d<0) {
                      int s = -dy / 2;
                      for (i=x0; i<=x1; i++)
                          Bresenham_y(size, z, i, y0+i, i, s, &j);
                  }
              }
              
              int main()
              {
                  int size, i, j, k, n, m, i0, i1, j0, j1;
                  int x0, y0, x1, y1, x[1][size], y[1][size], a;
                  char z[size][size];
              
                  scanf("%d", &size);
                  for (i=0; i<size; i++)
                      for (j=0; j<size; j++)
                          scanf("%c", &z[i][j]);
              
                  Bresenham(size, z, x0, y0, x1, y1);
                  printf("n=%d m=%d\n", n, m);
                  a = x[0][0];
                  for (i=1; i<=n; i++) {
                      if (i<=m) {
                              x[i][0] = x0+i-1;
                          y[i][0] = a;
                      }
                      else
                          x[i][0] = x1+i-1;
                      for (j=1; j<=i; j++) {
                          x[i][j] = x[i][j-1]+y[i][j-1];
                          y[i][j] = a;
                      }
                      a = x[i][n-1];
                  }
                  for (i=0; i<size; i++) {
                      for (j=0; j<size; j++)
                          printf("%c", z[i][j]);
                      printf("\n");
                  }
                  return 0;
              }
              Ответить
    • Все 90-е люди такой хуйней в играх косые линии рисовали
      Ответить
      • Не все. Некоторые полагались на стандартную библиотеку (если игра не совсем рилтаймовая и пирфоманс не нужен, либо если картинка составлялась из готовых спрайтов).
        Ответить
        • Как-будто в стандартной либе что-то другое...
          Ответить
          • Да вроде другого ничего не было. Но это не надо было реализовывать, если полагаешься на готовую либу.

            Я вспомнил «Бейсик» на «Агате», в котором не было оператора CIRCLE, и окружность приходилось реализовывать самому. А синус эта гадость вычисляла невыносимо медленно, поэтому итерироваться по углу было нельзя.
            Ответить
            • Круг ведь тоже можно рисовать подобием брезенхейма.
              Ответить
            • > невыносимо медлено

              Ну представь как вычислять разложение в ряд (!) когда у тебя нету фпу (!), нету умножения (!) и даже складывать мантиссу приходится восьмибитными кусочками (!).

              Я помню у меня калькулятор тоже задумывался над синусами.
              Ответить
              • З.Ы. С другой стороны, конкретно синус можно и fixed'ами посчитать.

                CORDIC или как там его.
                Ответить
              • Используя признак Даламбера (см. статью Степенные ряды. Область сходимости ряда), легко проверить, что ряд сходится при любом «икс»: А что значит вообще «сходится»? По смыслу глагола – что-то куда-то идёт.
                Ответить
              • Именно по этому я за "таблитса синусов"
                Ответить
              • И правда, у 6502 из арифметики только сложение и вычитание. Ну ещё логические операции и сдвиги. Всё.

                Умножение и деление даже целых питухов разработчикам Бейсика пришлось пилить самостоятельно.

                А реализация плавающего — целое искусство.

                Регистры:
                A — аккумулятор, 8 бит;
                X, Y — индексные регистры, 8 бит;
                PC — счетчик команд, 16 бит;
                S — указатель стека, 8 бит;
                P — регистр состояния;

                Пи здесь.
                Ответить
              • У калькуляторов вообще всё интересно.

                Машинные регистры обычно четырёхбитные. Но их не видно даже на программируемых микрокалькуляторах. Их от пользователя скрывает микрокод.

                Аккумулятор X (который прибит к экрану) и «стековые регистры» — это, по всей вероятности, массивы из четырёхбитовых ячеек. То есть микрокод собирает из массива ячеек «макрорегистр».

                Числа обычно представлены как BCD. Одна четырёхбитовая ячейка — одна десятичная цифра. То есть на 8-разрядном микрокалькуляторе один «макрорегистр» состоит из восьми четырёхбитовых ячеек под мантиссу + несколько ячеек для хранения порядка и знака. При выводе на экран конвертировать число не нужно, представление уже готово. Ну почти готово. Нужно проверить порядок, если он небольшой, то вывести только мантиссу с нужным положением запятой, а если порядок огромный, то поставить запятую после первого знака мантиссы и вывести порядок.

                Погуглил...

                «Одно число с 8-разрядной мантиссой и 2-х разрядным порядком занимает 14 тетрад»

                Всё ещё интереснее:
                https://m.vk.com/@thntofff-vnedrenie-v-arhitekturu-sovetskih-programmiruemyh-kalkulyato

                Четырёхбитовые ячейки являются частью гигантского регистра.

                У некоторых микрокалькуляторов тригонометрию вычисляет отдельный сопроцессор, сидящий на той же шине, с собственным микрокодом.
                Ответить
              • К слову, синусы считаются не как ряд, а как многочлен.

                Для восьмиразрядного калькулятора хватит четырёх слагаемых формулы Тейлора. Пятое слагаемое уже выйдет за пределы разрядности.
                Ответить
                • Чем кусок ряда отличается от многочлена?
                  Ответить
                  • Ничем. Разве что в данном примере не нужно вычислять критерий остановки. Количество членов можно зафиксировать.
                    Ответить
                    • Ну ряды довольно часто обрубают до фиксированной длины, смирившись с погрешностью в каких-то случаях и лишними вычислениями в других.
                      Ответить
                    • А про CORDIC читал?
                      Ответить
                      • Нет, надо будет почитать.

                        Возможно, реализации каких-то частных случаев я уже видел...
                        Ответить
                      • Похоже, что калькуляторы как раз через CORDIC всё считают.
                        Ответить
            • > А синус эта гадость вычисляла невыносимо медленно, поэтому итерироваться по углу было нельзя.

              Для этой задачи синус нахуй не нужен
              https://wandbox.org/permlink/41wG3PdPotIwauSt

              Ну и да, можно по формуле y = sqrt((a-x)^2+(b-y)^2) найти кучу точек, и их соединить отрезками через брезенхейм
              Ответить
              • т.е. по формуле y = sqrt(r^2-x^2)
                Ответить
                • Именно через квадратный корень я и считал, когда мои одноклассники считали через синус.

                  Про обход по двум координатам не думал. Интересно. Квадрат считается быстрее корня. Хотя на больших размерах уже наверное будет не очень быстро.

                  Ещё есть вариант через дифференциальные уравнения:
                  (x - a)dx + (y - b)dy = 0. Но тут будут накапливаться погрешности и результат может оказаться заметно неровным.
                  Ответить
                  • А зачем вообще корни, синусы?

                    Для заполенного круга они не нужны.
                    If ((x*x)+(y*y) <= r*r) Then
                       Pset(x,y);
                    End If

                    А для незаполненного там тоже есть итеративный алгоритм без корней.
                    Ответить
                  • > Квадрат считается быстрее корня.

                    Смотря как он реализован. Если у тебя процессор без инструкций умножения, и если квадрат и корень реализован тупой таблицей поиска, считаться они будут одинаково по времени. Хотя корень может даже быстрее считаться, учитывая что под квадрат надо в два раза больше бит под результат

                    А если специальной таблицы поиска для квадратных корней нет, но есть таблица поиска для квадратов, для нахождения квадратного корня можно по ней ебнуть двоичным поиском, это конечно будет медленней
                    Ответить
                    • Ответить
                      • > На что получили ответ:
                        >> под квадрат надо в два раза больше бит под результат

                        > А под корень надо в два раза больше строчек в таблице.

                        Смотря с какой точностью какой интервал. Таблицу квадратов и корней еще можно всякими хитровыебаными методами зожимать. Можно еще воспользоваться формулой sqrt(a*b) = sqrt(a)*sqrt(b) из которой вытекает sqrt(a*2^(2*b)) = (2^b)*sqrt(a)

                        ну т.е. если надо посчитать квадратный корень из 70, используя инты, но получить сколько-то знаков после запятой, можно посчитать квадратный корень из 70 * pow(2, 2*n), и тогда будет n знаков после запятой
                        Ответить
                        • Можно сделать "логарифмическую линейку" и считать всё через логарифмы и экспоненты.

                          З.Ы. Блин, мы так CORDIC изобретём скоро.
                          Ответить
              • > соединить отрезками через брезенхейм

                Можно тупее: соединить вертикальными отрезками зеркальные точки:
                y1 = b + sqrt(r^2 - (x-a)^2)
                и
                y2 = b - sqrt(r^2 - (x- a)^2)

                Получим залитый круг.

                А если нужна окружность, сверху наложить круг чуть поменьше.

                Вот если нужно сохранять фон, тогда сложнее. Хотя всё равно брезенхейм не нужен. Просто берём единицу в качестве шага по x.
                Ответить
              • > отрезками

                Да там можно напрямую брезенхеймить. Алгоритм то довольно универсальный, любую f(x, y) = 0 можно обводить если получается быстро вычислить значение f в соседних точках.
                Ответить
        • Я полагался на uses graph и egavga.bgi, и у меня всё жутко тормозило, и я срал кирпичами, пока мне не объяснили старшие товарищи про геймлпуп, и как надо срать в память видеоадаптера, и флипать потом эту память

          хуй знает что можно написать на uses graph;
          Поле чудес?
          Ответить
          • Шахматы вполне норм получаются. Ну и что-нибудь ещё пошаговое и не графонистое.
            Ответить
            • Dwarf Fortress. На 486 как раз год генерации будет равен году реальному.
              Ответить
              • Там же буквы графонием рисуются, как бы не opengl...

                Хотя вроде был реально текстовый режим для игры по ssh.
                Ответить
            • Я Арканоид делал, работало норм. Затирал шарик чёрным, сдвигал координаты и рисовал новый.

              Правда не на 486-м, но мне кажется и на нём бы не тормозило.
              Ответить
              • Да много было игрушек на uses graph, которые на 486 работали сносно. Всё-таки 486 побыстрее предыдущих поколений.

                Шутер от первого лица а ля Дум, где нужно весь кадр перерисовывать, на uses graph не сделаешь, а вот игры с неподвижным фоном — вполне.
                Ответить
                • P.S. Я помню компьютерный класс из 386, где единственную машину 486 называли графической станцией, потому что на ней фоторедактор почти не тормозил.
                  Ответить
          • > срал кирпичами

            https://youtu.be/ZcbJEhE8dFY
            Ответить
          • vgafpga.bin небось нужен был чтобы плавно скроллить primary sruface (или как оно тогда называлось)
            Ответить
    • > автор тян

      Елена Вставская (Константинова), 1978-го года издания, Челябинск, доцент ЮУрГУ, замужем?
      Ответить
      • Не маловат ли ты для нее?
        Ответить
        • Вопрос риторический. Свиньи столько не живут. Я даже считать до такого числа не умею:

          https://sun9-29.userapi.com/sun9-17/IkiB_1wb_xMyPNzfuEYErf0svk_Y9JhT_e3n1Q/2ajObcm_i5g.jpg
          Ответить
          • Какая-то она не очень женственная.

            Ну с другой стороны, они уже замужем, ей уже всё равно.

            Считается, что крупные свиньи при сбалансированном питании и комфортной жизни запросто проживут порядка 35 лет.
            Ответить
            • На первой фотке норм:

              https://sun9-29.userapi.com/sun9-85/sN3BcKYVeadxDN7_oF6W4EWHBzP3PcvMdkomHg/6iAGqG6-PHE.jpg

              Но в целом вызывает ощущение типичного программиста.
              Ответить
              • Типичный программист -- это кто?

                Современный типичный программист имеет синие волосы, зеленую тату, оранжевые шорты, и макбук со смузи
                Ответить
    • да.
      Ответить
    • прикол в том что в отзывах к этой статье на сайте пишут:

      Спасибо, Елена, за понятное объяснение и элегантный код, очень всё упаковано, а ведь есть 8 вариантов знаков и отношений модулей A и B.

      и это явно не троллинг. судя по всему это те самые программисты по блок-схемам.
      Ответить
    • Mainz-Bretzenheim
      Ответить
    • Кстати, важный вопрос. Куда пропала HACmEHbKA?
      Ответить

    Добавить комментарий