На сегодняшний день можно найти техническую документацию, кучу теории и еще много всякого полезного. Но при попытках реализовать это все в коде, могут возникать ощущения, что чего-то не договорили
Программист должен мыслить забегая немного вперед, поэтому мой подход может казаться слегка осложненным, но на самом деле полагаю мой способ описания должен упростить разработку более больших проектов.
Изначально я решил разбить на отдельные функции разные участки кода, чтоб не сливать всё в одну кучу. При этом в качестве принимаемых параметров указал ссылки на переменные. Помню как меня сначала раздражало, что во многих примерах используют эти ссылки, не понимая зачем это нужно, но так как глобальные переменные желательно избегать, а возвращать более одного значения не слишком удобно (Из одной точки — Две касательные. = 2 точки соприкосновения. Для каждой точки по 2 значения. Итого 4 значения), то удобно использовать эти самые ссылки. Еще сразу предупрежу, что я обозначил центр окружности О1 и O2, что в коде можно спутать с нулем, но такое обозначения помогает легче ориентироваться при написании разных формул (сразу понятно — окружность)
Ладно, итак много букв написал, поэтому некоторые недостатки компенсирую позже, а сейчас переходим к коду:
Код С++ Координаты точек пересечения касательной и окружности
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 |
#include <stdlib.h> #include <iostream.h> #include <graphics.h> //Для работы с графическими функциями #include <math.h> //Для работы с математическими функциями /*ФУНКЦИЯ РАСЧЕТА КООРДИНАТ ТОЧЕК СОПРИКОСНОВЕНИЯ*/ void GetKas(pointtype O1,pointtype O2, double R1, double R2, pointtype &Kas1, pointtype &Kas2) { double D=sqrt((O1.x-O2.x)*(O1.x-O2.x)+(O1.y-O2.y)*(O1.y-O2.y)); double a=(R1*R1-R2*R2+D*D)/(2*D); double h=sqrt(R1*R1-a*a); double X=O1.x+a*(O2.x-O1.x)/D; double Y=O1.y+a*(O2.y-O1.y)/D; Kas1.x=X+h*(O2.y-O1.y)/D; Kas1.y=Y-h*(O2.x-O1.x)/D; Kas2.x=X-h*(O2.y-O1.y)/D; Kas2.y=Y+h*(O2.x-O1.x)/D; } /*ФУНКЦИЯ ВВОДА ПАРАМЕТРОВ*/ void input(pointtype &O1,pointtype &O2,double &R1, double &R2) { //Способ ввода легко изменить на нужный O1.x=getmaxx()>>1; O1.y=getmaxy()>>1; R1=50; O2.x=200; O2.y=200; R2=100; } void main() { system(“CLS”); int gd=DETECT,gm; initgraph(&gd,&gm,“”); //Инициализация для работы с графикой pointtype O1,O2; //Две переменные, обозначающие центры двух окружностей double R1,R2; //Переменные обозначающие радиусы двух окружностей input(O1,O2,R1,R2); //Вводим параметры и сразу запоминаем их circle(O1.x,O1.y,R1); //После ввода параметров чертим окружность // circle(O2.x,O2.y,R2); //Вспомогательная окружность pointtype Kas1,Kas2; //Точки касания GetKas(O1,O2,R1,R2,Kas1,Kas2); //Расчет точек касания setfillstyle(1,1); //Просто для наглядности чертим заполненные краской окружности fillellipse(Kas1.x,Kas1.y,5,5); //обозначающие точки касания fillellipse(Kas2.x,Kas2.y,5,5); system(“PAUSE”); closegraph(); return; } |
Чтобы сосредоточить внимание на самом нужном, я исключил проверку точки относительно окружности. Ведь существуют разные ситуации (Внутри окружности, на окружности, вне окружности). Я решил исходить, что окружности соприкасаются в двух точках. Если нужен более полноценный код, то стоит учитывать где находится точка и дописать код проверки самому (надеюсь это не сложно).
Еще хотелось бы в очередной раз быть повнимательнее. Я, например, при переписывании этого кода, перепутал участок, считающий большие X и Y. Они считаются по одной окружности, а я написал по разным и потом долго искал где не так.
Чуть не забыл пояснить, что весь алгоритм расчета строится на том, что если из точки провести окружность через центр другой окружности, то точки пересечения будут касательными, поэтому сделано так как сделано. Весь код не полноценен и требует доработки, но основная идея — помочь начать. Ведь многим непонятно как даже это делать.
Если кому-то интересно, то могу порекомендовать практическую задачу по построению касательной к окружности, используя этот материал и этот
Чувствую себя немного виноватым и что я многого не договорил, но знаю, что большинство не говорит даже о том, что я тут донес, поэтому надеюсь на то что всё, что я не написал вам не составит труда доделать
😎