#include <stdio.h>
#include <math.h>
#include <Adafruit_GFX.h>
#include <Adafruit_ILI9341.h>
#define TFT_DC 2
#define TFT_CS 15
Adafruit_ILI9341 tft = Adafruit_ILI9341(TFT_CS, TFT_DC);
#define P1_PIN 35
#define P2_PIN 32
#define P3_PIN 33
#define P4_PIN 25
#define DEBUG 1
struct point {
double x;
double y;
};
struct cyrcle {
point center;
double radius;
};
point p1, p2;
point planeA, planeB, plane;
#define NN 4
cyrcle c[ NN ];
point pA[ NN * 3 ], pB[ NN * 3 ];
int cntA, cntB;
long time_calc, time_all;
void showStatus( int status );
void update_points();
int interception( cyrcle c1, cyrcle c2, point *p1, point *p2);
double distance(point a, point b);
void showResultPoints();
void setup() {
// put your setup code here, to run once:
Serial.begin(115200);
printf("\n");
setup_graphics();
c[0].center.x = 50;
c[0].center.y = 10;
c[0].radius = 30;
c[1].center.x = 35;
c[1].center.y = 9;
c[1].radius = 30;
c[2].center.x = -20;
c[2].center.y = 10;
c[2].radius = 70;
c[3].center.x = 85;
c[3].center.y = 5;
c[3].radius = 60;
cntA, cntB = 0;
calculate();
}
/////////////////////////////////////////////////
void calculate(){
time_all = micros();
for (int i = 0; i < NN - 1; i++ ) {
for (int m = i + 1; m < NN; m++) {
time_calc = micros();
int res = interception (c[i], c[m], &p1, &p2);
time_calc = micros() - time_calc;
if (res > 0) update_points( );
showStatus( res );
}
}
time_all = micros() - time_all;
showResultPoints();
showResultGraphics();
}
void update_points() {
if ( cntA == 0 ) {
pA[cntA++] = p1;
pB[cntB++] = p2;
}
else {
double d1 = distance(pA[0], p1);
double d2 = distance(pB[0], p1);
if (d1 < d2) {
pA[cntA++] = p1;
}
else {
pB[cntB++] = p1;
}
d1 = distance(pA[0], p2);
d2 = distance(pB[0], p2);
if (d1 < d2) {
pA[cntA++] = p2;
}
else {
pB[cntB++] = p2;
}
}
}
double distance(point a, point b) {
double dx = b.x - a.x;
double dy = b.y - a.y;
return sqrt(dx * dx + dy * dy);
}
void showResultPoints() {
double distA, distB, sumX, sumY = 0;
printf("Точки в хмарі А:\n");
for (int i = 0; i < cntA; i++) {
printf(" %u - (%.6f, %.6f)\n", i, pA[i].x, pA[i].y );
}
printf("Точки в хмарі B:\n");
for (int i = 0; i < cntB; i++) {
printf(" %u - (%.6f, %.6f)\n", i, pB[i].x, pB[i].y );
}
sumX = pA[cntA - 1].x; sumY = pA[cntA - 1].y;
for (int i = 0; i < cntA - 1; i++) {
for (int k = i + 1; k < cntA; k++) {
distA += distance(pA[i], pA[k]);
}
sumX += pA[i].x;
sumY += pA[i].y;
}
planeA.x = sumX / cntA;
planeA.y = sumY / cntA;
sumX = pB[cntB - 1].x; sumY = pB[cntB - 1].y;
for (int i = 0; i < cntB - 1; i++) {
for (int k = i + 1; k < cntB; k++) {
distB += distance(pB[i], pB[k]);
}
sumX += pB[i].x;
sumY += pB[i].y;
}
planeB.x = sumX / cntB;
planeB.y = sumY / cntB;
printf("Загальна дистанція в хмарі А %.6f\n", distA);
printf("Загальна дистанція в хмарі B %.6f\n", distB);
if (distA < distB) {
printf(" Точка літака A (%.6f, %.6f)\n", planeA.x, planeA.y );
plane = planeA;
}
else {
printf(" Точка літака B (%.6f, %.6f)\n", planeB.x, planeB.y );
plane = planeB;
}
printf("Загальний час розрахунку %.3f ms\n", time_all / 1000.0);
}
void showStatus( int status ) {
//printf("Result = %u\n", status);
switch (status) {
case -1:
printf("Кола не перетинаються!\n");
break;
case 1:
printf("Кола дотикаються в точці: (%.6f, %.6f)\n", p1.x, p1.y);
break;
case 2:
printf("Кола перетинаються в точках: (%.6f, %.6f) та (%.6f, %.6f) \n", p1.x, p1.y, p2.x, p2.y);
}
//printf("Час розрахунку в мkс - %u\n", time_calc);
}
void loop() {
cntA = 0;
cntB = 0;
c[0].radius = analogRead(P1_PIN)/16;
c[1].radius = analogRead(P2_PIN)/16;
c[2].radius = analogRead(P3_PIN)/16;
c[3].radius = analogRead(P4_PIN)/16;
calculate();
delay(5000); // this speeds up the simulation
}
int interception( cyrcle c1, cyrcle c2, point *p1, point *p2) {
double x1, y1, r1;
double x2, y2, r2;
x1 = c1.center.x;
y1 = c1.center.y;
r1 = c1.radius;
x2 = c2.center.x;
y2 = c2.center.y;
r2 = c2.radius;
p1->x = 0;
p1->y = 0;
p2->x = 0;
p2->y = 0;
double dx = x2 - x1;
double dy = y2 - y1;
double d = sqrt(dx * dx + dy * dy);
if (d > r1 + r2) {
printf("Кола не перетинаються (занадто далеко один від одного).\n");
return -1;
} else if (d < fabs(r1 - r2)) {
printf("Кола не перетинаються (одне коло всередині іншого).\n");
return -1;
} else if (d == 0 && r1 == r2) {
printf("Кола співпадають (безліч точок перетину).\n");
return -1;
} else {
// Обчислимо точку пересічення лінії центрів і точок перетину
double a = (r1 * r1 - r2 * r2 + d * d) / (2 * d);
double h = sqrt(r1 * r1 - a * a);
// Координати точки P на лінії між центрами
double x3 = x1 + a * (dx) / d;
double y3 = y1 + a * (dy) / d;
// Координати точок перетину
double rx = -dy * (h / d);
double ry = dx * (h / d);
double xi1 = x3 + rx;
double yi1 = y3 + ry;
double xi2 = x3 - rx;
double yi2 = y3 - ry;
if (h == 0) {
p1->x = x3;
p1->y = y3;
return 1;
} else {
p1->x = xi1;
p1->y = yi1;
p2->x = xi2;
p2->y = yi2;
return 2;
}
}
return 0;
}
void setup_graphics(){
tft.begin();
tft.setRotation(1);
tft.setTextColor(ILI9341_WHITE);
}
void showResultGraphics(){
tft.fillScreen(ILI9341_BLACK);
tft.setCursor(0, 0);
tft.print("(0,0)");
double koef=1, kx, ky, xmin=1e8, xmax=0, ymin=1e8, ymax=0, dx=1e8, dy=1e8;
printf("\n Before scale\n");
for (int i=0; i<NN; i++) {
printf("Circle %u (%.1f, %.1f, %.1f)\n", i, c[i].center.x, c[i].center.y, c[i].radius);
if ( c[i].center.x - c[i].radius < xmin ) xmin = c[i].center.x - c[i].radius;
if ( c[i].center.x + c[i].radius > xmax ) xmax = c[i].center.x + c[i].radius;
if ( c[i].center.y - c[i].radius < ymin ) ymin = c[i].center.y - c[i].radius;
if ( c[i].center.y + c[i].radius > ymax ) ymax = c[i].center.y + c[i].radius;
if (dx > c[i].center.x - c[i].radius ) dx = c[i].center.x - c[i].radius;
if (dy > c[i].center.y - c[i].radius ) dy = c[i].center.y - c[i].radius;
}
kx = 320 / (xmax - xmin);
ky = 240 / (ymax - ymin);
//koef = min(kx, ky);
printf("dx=%.1f dy=%.1f koef=%.2f xmin=%.1f xmax=%.1f ymin=%.1f ymax=%.1f\n", dx, dy, koef, xmin, xmax, ymin, ymax);
printf(" After scale\n");
for (int i=0; i<NN; i++) {
double x = (c[i].center.x-dx)*koef;
double y = (c[i].center.y-dy)*koef;
double r = c[i].radius*koef;
printf("Circle %u (%.1f, %.1f, %.1f)\n", i, x, y, r);
tft.drawCircle( x, y, r, ILI9341_WHITE);
}
tft.fillCircle( (plane.x-dx)*koef, (plane.y-dy)*koef, 2, ILI9341_RED);
for (int i=0; i<cntA; i++) tft.drawCircle((pA[i].x-dx)*koef, (pA[i].y-dy)*koef, 4, ILI9341_YELLOW);
for (int i=0; i<cntB; i++) tft.drawCircle((pB[i].x-dx)*koef, (pB[i].y-dy)*koef, 4, ILI9341_BLUE);
printf("\n\n\n\n");
}