Агуулгыг алгасах

Тойрог-шулууны огтлолцол

Тойргийн төвийн координат ба радиус, мөн шулууны тэгшитгэл өгөгдсөн үед та огтлолцлын цэгүүдийг олох шаардлагатай.

Шийдэл

Хоёр тэгшитгэлийн системийг бодохын оронд бид бодлогод геометрийн аргаар хандана. Ингэснээр бид тоон тогтвортой байдлын үүднээс илүү нарийвчлалтай шийд авна.

Бид ерөнхий чанараа алдалгүйгээр тойргийн төв эх цэгт байна гэж үзнэ. Хэрэв тийм биш бол бид түүнийг тийш зөөж, шулууны тэгшитгэл дэх $C$ тогтмолыг залруулна. Тэгэхээр бидэнд $(0,0)$ төвтэй $r$ радиустай тойрог ба $Ax+By+C=0$ тэгшитгэлтэй шулуун байна.

Эхлээд эх цэгт хамгийн ойр байх шулуун дээрх $(x_0, y_0)$ цэгийг олохоос эхэлье. Нэгдүгээрт, энэ нь дараах зайд байх ёстой

$$ d_0 = \frac{|C|}{\sqrt{A^2+B^2}} $$

Хоёрдугаарт, $(A, B)$ вектор шулуунд перпендикуляр тул цэгийн координат энэ векторын координаттай пропорциональ байх ёстой. Бид цэгээс эх цэг хүртэлх зайг мэдэж байгаа тул зөвхөн $(A, B)$ векторыг энэ урт руу масштаблахад л хангалттай бөгөөд бид дараахыг авна:

$$\begin{align} x_0 &= - \frac{AC}{A^2 + B^2} \\ y_0 &= - \frac{BC}{A^2 + B^2} \end{align}$$

Хасах тэмдгүүд илэрхий биш боловч $x_0$ ба $y_0$-г шулууны тэгшитгэлд орлуулснаар тэдгээрийг хялбархан шалгаж болно.

Энэ үе шатанд бид огтлолцлын цэгийн тоог тодорхойлж, бүр нэг эсвэл тэг цэг байх үед шийдийг олж чадна. Үнэндээ хэрэв $(x_0, y_0)$-ээс эх цэг хүртэлх $d_0$ зай нь $r$ радиусаас их бол хариулт нь тэг цэг байна. Хэрэв $d_0=r$ бол хариулт нь нэг цэг $(x_0, y_0)$ байна. Хэрэв $d_0<r$ бол огтлолцлын хоёр цэг байх ба одоо бид тэдгээрийн координатыг олох ёстой.

Тэгэхээр бид $(x_0, y_0)$ цэг тойргийн дотор байгааг мэдэж байна. Огтлолцлын хоёр цэг $(a_x, a_y)$ ба $(b_x, b_y)$ нь $Ax+By+C=0$ шулуунд харьяалагдах ёстой бөгөөд $(x_0, y_0)$-ээс ижил $d$ зайд байх ёстой, энэ зайг олоход амархан:

$$ d = \sqrt{r^2 - \frac{C^2}{A^2 + B^2}} $$

$(-B, A)$ вектор шулуунтай коллинеар болохыг анхаарна уу, тиймээс бид $d$ урт руу масштаблсан $(-B,A)$ векторыг $(x_0, y_0)$ цэг дээр нэмж, хасах замаар хайж буй цэгүүдийг олж болно.

Эцэст нь огтлолцлын хоёр цэгийн тэгшитгэл нь:

$$\begin{align} m &= \sqrt{\frac{d^2}{A^2 + B^2}} \\ a_x &= x_0 + B \cdot m, a_y = y_0 - A \cdot m \\ b_x &= x_0 - B \cdot m, b_y = y_0 + A \cdot m \end{align}$$

Хэрэв бид анхны тэгшитгэлийн системийг алгебрийн аргаар бодсон бол илүү их алдаатай өөр хэлбэрийн хариулт авах байсан байх. Энд тайлбарласан геометрийн арга илүү дүрслэг бөгөөд илүү нарийвчлалтай.

Implementation

As indicated at the outset, we assume that the circle is centered at the origin, and therefore the input to the program is the radius $r$ of the circle and the parameters $A$, $B$ and $C$ of the equation of the line.

double r, a, b, c; // given as input
double x0 = -a*c/(a*a+b*b), y0 = -b*c/(a*a+b*b);
if (c*c > r*r*(a*a+b*b)+EPS)
    puts ("no points");
else if (abs (c*c - r*r*(a*a+b*b)) < EPS) {
    puts ("1 point");
    cout << x0 << ' ' << y0 << '\n';
}
else {
    double d = r*r - c*c/(a*a+b*b);
    double mult = sqrt (d / (a*a+b*b));
    double ax, ay, bx, by;
    ax = x0 + b * mult;
    bx = x0 - b * mult;
    ay = y0 - a * mult;
    by = y0 + a * mult;
    puts ("2 points");
    cout << ax << ' ' << ay << '\n' << bx << ' ' << by << '\n';
}

Дасгал бодлогууд