#include <Adafruit_GFX.h>
#include <Adafruit_GC9A01A.h>
#include <SPI.h>


#define TFT_DC 17
#define TFT_CS 16
/*
  SCL   --> 18 (SCK)
  SDA   --> 23 (MOSI)
  RST   --> EN
*/

Adafruit_GC9A01A tft(TFT_CS, TFT_DC);

// Константы координат смещения центра
const int CENTER_X = 120;
const int CENTER_Y = 120;
const float Z = 300.0; //от 100.0 до 1000.0 регулировка качества отрисовки пикселей с пропусками и без них
struct Point {
  float x, y;
  uint16_t color;
};
const int NUM_POINTS = 30; // Количество точек для диаграммы Вороного
Point points[NUM_POINTS];
long Y = 0; //

void setup() {
  // Инициализация генератора случайных чисел
  randomSeed(analogRead(32));
  tft.begin();
  tft.fillScreen(GC9A01A_BLACK);
  // tft.cp437(true);
  tft.setRotation(2);
  ran_Sait(3);
}

void loop() {
  if (millis() - Y > 90000ul) {//новый цикл роста узоров по условию каждые 90 секунд
    tft.fillScreen(GC9A01A_BLACK);
    Y = millis();
  }
  for (byte v = 1; v < 3; v++) {
    draw_RisSektor(v);
    delay(500);
  }
}
//////////////////////////////////////
//функция вычисления метрики (как вариант расстояния между двумя точками)
float dist(float x1, float y1, float x2, float y2, byte m) {
  if (m == 1) {
    return sqrt(pow(x1 - x2, 2) + pow(y1 - y2, 2)); //Евклидова метрика
  }
  if (m == 2) {
    return (abs(x1 - x2) + abs(y2 - y1)); //Манхэттенская метрика
  }
  if (m == 3) {
    return max(abs(x1 - x2), abs(y1 - y2)); // авторская метрика №1
  }

}
//////////////////////////////////////
// функция генерации точек (сайтов)для локусов диаграммы Вороного
void ran_Sait(byte variant) {
  for (int i = 0; i < NUM_POINTS; i++) {
    if (variant == 1 || variant == 3) {
      points[i].x = random(CENTER_X, CENTER_X + 120 );
      points[i].y = random(CENTER_Y, CENTER_Y + 60);
    }
    if (variant == 2 || variant == 3) {
      
       points[i].color = tft.color565(random(256), random(256), random(256));
      //варианты цветовых решений 
      //byte Gg=random(256);
      // points[i].color = tft.color565(random(Gg), Gg, random(Gg));
      
      // byte Bb = random(256);
      // points[i].color = tft.color565(random(Bb/1.2),Bb, Bb );
      
     // byte Rr = random(256);
     // points[i].color = tft.color565(Rr, random(Rr / 1.2) , random(Rr / 2.0));
    }
  }
}
//////////////////////////////////////
//функция вывода 12 отсимметриченных секторов узора по базовому сектору картинки
void draw_RisSektor(byte variant) {
  for (float f1 = 0.0; f1 <= PI / 6.0; f1 += PI / Z) {
    for (int r1 = 0; r1 <= 120 ; r1 += 1) {
      int x = CENTER_X + cos(f1) * r1;
      int y = CENTER_Y + sin(f1) * r1;
      int closestPoint = 0;
      float minDist = dist(x, y, points[0].x, points[0].y, variant );

      for (int i = 1; i < NUM_POINTS; i++) {
        float d = dist(x, y, points[i].x, points[i].y, variant );
        if (d < minDist) {
          minDist = d;
          closestPoint = i;
        }
      }

      for (float i = 0.01; i <= 2 * PI; i += PI / 3.0) {
        if (minDist > 12) {//условие роста степени заполнения элементов узора
          int x1 = CENTER_X + cos(f1 + i) * r1;
          int y1 = CENTER_Y + sin(f1 + i) * r1;
          tft.drawPixel(x1, y1, points[closestPoint].color);
          int x2 = CENTER_X + cos(2 * PI - f1 + i) * r1;
          int y2 = CENTER_Y + sin(2 * PI - f1 + i) * r1;
          tft.drawPixel(x2, y2, points[closestPoint].color );
        }
      }
    }
  }
  ran_Sait(3);
}
//////////////////////////////////////



