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

Үндсэн геометр

Энэ өгүүлэлд бид бүхэл аналитик геометрийн суурийг бүрдүүлдэг Евклидийн орон зай дахь цэгүүд дээрх үндсэн үйлдлүүдийг авч үзнэ. Бид цэг $\mathbf r$ бүрийн хувьд $\mathbf 0$-ээс $\mathbf r$ рүү чиглэсэн $\vec{\mathbf r}$ векторыг авч үзнэ. Цаашид бид $\mathbf r$ ба $\vec{\mathbf r}$-г ялгахгүй бөгөөд цэг гэсэн нэр томьёог вектор-ын ижил утгатай үгээр хэрэглэнэ.

Шугаман үйлдэл

2 хэмжээст ба 3 хэмжээст цэгүүд аль аль нь шугаман орон зай үүсгэдэг ба энэ нь тэдгээрийн хувьд цэгүүдийн нийлбэр ба цэгийг ямар нэг тоогоор үржүүлэх үйлдэл тодорхойлогдсон гэсэн үг юм. 2 хэмжээстийн хувьд эдгээр үндсэн хэрэгжүүлэлт энд байна:

struct point2d {
    ftype x, y;
    point2d() {}
    point2d(ftype x, ftype y): x(x), y(y) {}
    point2d& operator+=(const point2d &t) {
        x += t.x;
        y += t.y;
        return *this;
    }
    point2d& operator-=(const point2d &t) {
        x -= t.x;
        y -= t.y;
        return *this;
    }
    point2d& operator*=(ftype t) {
        x *= t;
        y *= t;
        return *this;
    }
    point2d& operator/=(ftype t) {
        x /= t;
        y /= t;
        return *this;
    }
    point2d operator+(const point2d &t) const {
        return point2d(*this) += t;
    }
    point2d operator-(const point2d &t) const {
        return point2d(*this) -= t;
    }
    point2d operator*(ftype t) const {
        return point2d(*this) *= t;
    }
    point2d operator/(ftype t) const {
        return point2d(*this) /= t;
    }
};
point2d operator*(ftype a, point2d b) {
    return b * a;
}
Мөн 3 хэмжээст цэгүүд:
struct point3d {
    ftype x, y, z;
    point3d() {}
    point3d(ftype x, ftype y, ftype z): x(x), y(y), z(z) {}
    point3d& operator+=(const point3d &t) {
        x += t.x;
        y += t.y;
        z += t.z;
        return *this;
    }
    point3d& operator-=(const point3d &t) {
        x -= t.x;
        y -= t.y;
        z -= t.z;
        return *this;
    }
    point3d& operator*=(ftype t) {
        x *= t;
        y *= t;
        z *= t;
        return *this;
    }
    point3d& operator/=(ftype t) {
        x /= t;
        y /= t;
        z /= t;
        return *this;
    }
    point3d operator+(const point3d &t) const {
        return point3d(*this) += t;
    }
    point3d operator-(const point3d &t) const {
        return point3d(*this) -= t;
    }
    point3d operator*(ftype t) const {
        return point3d(*this) *= t;
    }
    point3d operator/(ftype t) const {
        return point3d(*this) /= t;
    }
};
point3d operator*(ftype a, point3d b) {
    return b * a;
}

Энд ftype нь координатад ашиглагдах ямар нэг төрөл бөгөөд ихэвчлэн int, double эсвэл long long байна.

Скаляр үржвэр

Тодорхойлолт

$\mathbf a$ ба $\mathbf b$ векторуудын скаляр үржвэр $\mathbf a \cdot \mathbf b$-г ижил утгатай хоёр аргаар тодорхойлж болно. Геометрийн хувьд энэ нь эхний векторын урт ба хоёр дахь векторын эхний вектор дээрх проекцын уртын үржвэр юм. Доорх зургаас харахад энэ проекц нь $|\mathbf a| \cos \theta$-ээс өөр юу ч биш, энд $\theta$ нь $\mathbf a$ ба $\mathbf b$-ийн хоорондох өнцөг юм. Тиймээс $\mathbf a\cdot \mathbf b = |\mathbf a| \cos \theta \cdot |\mathbf b|$.

Скаляр үржвэр хэд хэдэн онцлох шинж чанартай:

  1. $\mathbf a \cdot \mathbf b = \mathbf b \cdot \mathbf a$
  2. $(\alpha \cdot \mathbf a)\cdot \mathbf b = \alpha \cdot (\mathbf a \cdot \mathbf b)$
  3. $(\mathbf a + \mathbf b)\cdot \mathbf c = \mathbf a \cdot \mathbf c + \mathbf b \cdot \mathbf c$

Өөрөөр хэлбэл энэ нь хоёр аргументийн аль алины хувьд шугаман байх коммутатив функц юм. Нэгж векторуудыг дараах байдлаар тэмдэглэе

$$\mathbf e_x = \begin{pmatrix} 1 \\ 0 \\ 0 \end{pmatrix}, \mathbf e_y = \begin{pmatrix} 0 \\ 1 \\ 0 \end{pmatrix}, \mathbf e_z = \begin{pmatrix} 0 \\ 0 \\ 1 \end{pmatrix}.$$

Энэ тэмдэглэгээгээр бид $\mathbf r = (x;y;z)$ векторыг $r = x \cdot \mathbf e_x + y \cdot \mathbf e_y + z \cdot \mathbf e_z$ гэж бичиж болно. Мөн нэгж векторуудын хувьд

$$\mathbf e_x\cdot \mathbf e_x = \mathbf e_y\cdot \mathbf e_y = \mathbf e_z\cdot \mathbf e_z = 1,\\ \mathbf e_x\cdot \mathbf e_y = \mathbf e_y\cdot \mathbf e_z = \mathbf e_z\cdot \mathbf e_x = 0$$

байдаг тул $\mathbf a = (x_1;y_1;z_1)$ ба $\mathbf b = (x_2;y_2;z_2)$-ийн хувьд координатаар илэрхийлбэл дараах нь биелэхийг бид харж болно

$$\mathbf a\cdot \mathbf b = (x_1 \cdot \mathbf e_x + y_1 \cdot\mathbf e_y + z_1 \cdot\mathbf e_z)\cdot( x_2 \cdot\mathbf e_x + y_2 \cdot\mathbf e_y + z_2 \cdot\mathbf e_z) = x_1 x_2 + y_1 y_2 + z_1 z_2$$

Энэ нь мөн скаляр үржвэрийн алгебрийн тодорхойлолт юм. Үүнээс бид түүнийг тооцоолох функцүүдийг бичиж болно.

ftype dot(point2d a, point2d b) {
    return a.x * b.x + a.y * b.y;
}
ftype dot(point3d a, point3d b) {
    return a.x * b.x + a.y * b.y + a.z * b.z;
}

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

Шинж чанарууд

Бид скаляр үржвэрээр дамжуулан олон геометрийн шинж чанарыг тодорхойлж болно. Жишээ нь

  1. $\mathbf a$-ийн норм (уртын квадрат): $|\mathbf a|^2 = \mathbf a\cdot \mathbf a$
  2. $\mathbf a$-ийн урт: $|\mathbf a| = \sqrt{\mathbf a\cdot \mathbf a}$
  3. $\mathbf a$-ийн $\mathbf b$ дээрх проекц: $\dfrac{\mathbf a\cdot\mathbf b}{|\mathbf b|}$
  4. Векторуудын хоорондох өнцөг: $\arccos \left(\dfrac{\mathbf a\cdot \mathbf b}{|\mathbf a| \cdot |\mathbf b|}\right)$
  5. Өмнөх зүйлээс харахад тэдгээрийн хоорондох өнцөг хурц бол скаляр үржвэр эерэг, мохоо бол сөрөг, ортогональ буюу тэгш өнцөг үүсгэж байвал тэгтэй тэнцүү байна.

Эдгээр бүх функц хэмжээсийн тооноос хамаардаггүй тул 2 хэмжээст ба 3 хэмжээст тохиолдолд ижил байхыг анхаарна уу:

ftype norm(point2d a) {
    return dot(a, a);
}
double abs(point2d a) {
    return sqrt(norm(a));
}
double proj(point2d a, point2d b) {
    return dot(a, b) / abs(b);
}
double angle(point2d a, point2d b) {
    return acos(dot(a, b) / abs(a) / abs(b));
}

Дараагийн чухал шинж чанарыг харахын тулд бид ямар нэг тогтмол $C$-ийн хувьд $\mathbf r\cdot \mathbf a = C$ байх $\mathbf r$ цэгүүдийн олонлогийг авч үзэх хэрэгтэй. Энэ цэгүүдийн олонлог нь яг $\mathbf a$ дээрх проекц нь $C \cdot \dfrac{\mathbf a}{|\mathbf a| ^ 2}$ цэг байх цэгүүдийн олонлог бөгөөд тэдгээр нь $\mathbf a$-д ортогональ гиперхавтгай үүсгэдгийг та харж болно. Доорх зурган дээр 2 хэмжээст орон зайд $\mathbf a$ вектор ба түүнтэй ижил скаляр үржвэртэй хэд хэдэн ийм векторыг харж болно:

a вектортой ижил скаляр үржвэртэй векторууд

2 хэмжээст орон зайд эдгээр вектор шулуун үүсгэх ба 3 хэмжээст орон зайд хавтгай үүсгэнэ. Энэ үр дүн нь бидэнд 2 хэмжээст орон зайд шулууныг $\mathbf r\cdot \mathbf n=C$ эсвэл $(\mathbf r - \mathbf r_0)\cdot \mathbf n=0$ гэж тодорхойлох боломж олгодгийг анхаарна уу, энд $\mathbf n$ нь шулуунд ортогональ вектор, $\mathbf r_0$ нь шулуун дээр аль хэдийн байгаа дурын вектор ба $C = \mathbf r_0\cdot \mathbf n$. Үүнтэй адилаар 3 хэмжээст орон зайд хавтгайг тодорхойлж болно.

Вектор үржвэр

Тодорхойлолт

Доорх зурган дээрх шиг параллелепипед үүсгэн нийлсэн 3 хэмжээст орон зай дахь $\mathbf a$, $\mathbf b$, $\mathbf c$ гэсэн гурван вектор байна гэж үзье:

Гурван вектор

Түүний эзэлхүүнийг хэрхэн тооцоолох вэ? Сургуулиас бид суурийн талбайг өндрөөр үржүүлэх ёстойг мэднэ, өндөр нь $\mathbf a$-ийн суурьт ортогональ чиглэл дээрх проекц юм. Энэ нь хэрэв бид $\mathbf b \times \mathbf c$$\mathbf b$ ба $\mathbf c$-ийн аль алинд нь ортогональ бөгөөд урт нь $\mathbf b$ ба $\mathbf c$-ийн үүсгэсэн параллелограммын талбайтай тэнцүү вектор гэж тодорхойлбол $|\mathbf a\cdot (\mathbf b\times\mathbf c)|$ нь параллелепипедийн эзэлхүүнтэй тэнцүү байна гэсэн үг юм. Бүрэн байдлын үүднээс бид $\mathbf b\times \mathbf c$ нь $\mathbf b\times \mathbf c$-ийн үзүүрээс харахад $\mathbf b$ векторооос $\mathbf c$ вектор руу эргэх эргэлт үргэлж цагийн зүүний эсрэг байхаар чиглэсэн байна гэж хэлнэ (доорх зургийг үз).

вектор үржвэр

Энэ нь $\mathbf b$ ба $\mathbf c$ векторуудын вектор үржвэр $\mathbf b\times \mathbf c$, мөн $\mathbf a$, $\mathbf b$, $\mathbf c$ векторуудын холимог үржвэр $\mathbf a\cdot(\mathbf b\times \mathbf c)$-г тодорхойлно.

Вектор ба холимог үржвэрийн зарим онцлох шинж чанар:

  1. $\mathbf a\times \mathbf b = -\mathbf b\times \mathbf a$
  2. $(\alpha \cdot \mathbf a)\times \mathbf b = \alpha \cdot (\mathbf a\times \mathbf b)$
  3. Дурын $\mathbf b$ ба $\mathbf c$-ийн хувьд дурын $\mathbf a$ векторын хувьд $\mathbf a\cdot (\mathbf b\times \mathbf c) = \mathbf a\cdot\mathbf r$ байх яг нэг $\mathbf r$ вектор оршино.
    Үнэндээ хэрэв ийм хоёр вектор $\mathbf r_1$ ба $\mathbf r_2$ байвал бүх $\mathbf a$ векторын хувьд $\mathbf a\cdot (\mathbf r_1 - \mathbf r_2)=0$ болох ба энэ нь зөвхөн $\mathbf r_1 = \mathbf r_2$ үед л боломжтой.
  4. $\mathbf a\cdot (\mathbf b\times \mathbf c) = \mathbf b\cdot (\mathbf c\times \mathbf a) = -\mathbf a\cdot( \mathbf c\times \mathbf b)$
  5. $(\mathbf a + \mathbf b)\times \mathbf c = \mathbf a\times \mathbf c + \mathbf b\times \mathbf c$. Үнэндээ бүх $\mathbf r$ векторын хувьд дараах тэгшитгэлүүдийн гинж биелнэ:

    $$\mathbf r\cdot( (\mathbf a + \mathbf b)\times \mathbf c) = (\mathbf a + \mathbf b) \cdot (\mathbf c\times \mathbf r) = \mathbf a \cdot(\mathbf c\times \mathbf r) + \mathbf b\cdot(\mathbf c\times \mathbf r) = \mathbf r\cdot (\mathbf a\times \mathbf c) + \mathbf r\cdot(\mathbf b\times \mathbf c) = \mathbf r\cdot(\mathbf a\times \mathbf c + \mathbf b\times \mathbf c)$$

    Энэ нь 3 дугаар зүйлийн улмаас $(\mathbf a + \mathbf b)\times \mathbf c = \mathbf a\times \mathbf c + \mathbf b\times \mathbf c$-г батална.

  6. $|\mathbf a\times \mathbf b|=|\mathbf a| \cdot |\mathbf b| \sin \theta$, энд $\theta$ нь $\mathbf a$ ба $\mathbf b$-ийн хоорондох өнцөг, учир нь $|\mathbf a\times \mathbf b|$ нь $\mathbf a$ ба $\mathbf b$-ийн үүсгэсэн параллелограммын талбайтай тэнцүү.

Энэ бүхнийг болон нэгж векторуудын хувьд дараах тэгшитгэл биелэхийг харгалзан

$$\mathbf e_x\times \mathbf e_x = \mathbf e_y\times \mathbf e_y = \mathbf e_z\times \mathbf e_z = \mathbf 0,\\ \mathbf e_x\times \mathbf e_y = \mathbf e_z,~\mathbf e_y\times \mathbf e_z = \mathbf e_x,~\mathbf e_z\times \mathbf e_x = \mathbf e_y$$

бид $\mathbf a = (x_1;y_1;z_1)$ ба $\mathbf b = (x_2;y_2;z_2)$-ийн вектор үржвэрийг координатын хэлбэрээр тооцоолж болно:

$$\mathbf a\times \mathbf b = (x_1 \cdot \mathbf e_x + y_1 \cdot \mathbf e_y + z_1 \cdot \mathbf e_z)\times (x_2 \cdot \mathbf e_x + y_2 \cdot \mathbf e_y + z_2 \cdot \mathbf e_z) =$$
$$(y_1 z_2 - z_1 y_2)\mathbf e_x + (z_1 x_2 - x_1 z_2)\mathbf e_y + (x_1 y_2 - y_1 x_2)\mathbf e_z$$

Үүнийг мөн илүү дэгжин хэлбэрээр бичиж болно:

$$\mathbf a\times \mathbf b = \begin{vmatrix}\mathbf e_x & \mathbf e_y & \mathbf e_z \\ x_1 & y_1 & z_1 \\ x_2 & y_2 & z_2 \end{vmatrix},~a\cdot(b\times c) = \begin{vmatrix} x_1 & y_1 & z_1 \\ x_2 & y_2 & z_2 \\ x_3 & y_3 & z_3 \end{vmatrix}$$

Энд $| \cdot |$ нь матрицын тодорхойлогчийг илэрхийлнэ.

2 хэмжээст тохиолдолд ч мөн нэг төрлийн вектор үржвэрийг (тухайлбал псевдоскаляр үржвэрийг) хэрэгжүүлж болно. Хэрэв бид $\mathbf a$ ба $\mathbf b$ векторуудын үүсгэсэн параллелограммын талбайг тооцоолохыг хүсвэл $|\mathbf e_z\cdot(\mathbf a\times \mathbf b)| = |x_1 y_2 - y_1 x_2|$-г тооцоолно. Ижил үр дүнг авах өөр нэг арга бол $|\mathbf a|$-г (параллелограммын суурь) өндрөөр үржүүлэх явдал бөгөөд өндөр нь $\mathbf b$ векторын $90^\circ$-аар эргүүлсэн $\mathbf a$ вектор дээрх проекц бөгөөд энэ нь эргээд $\widehat{\mathbf a}=(-y_1;x_1)$ болно. Өөрөөр хэлбэл $|\widehat{\mathbf a}\cdot\mathbf b|=|x_1y_2 - y_1 x_2|$-г тооцоолох явдал юм.

Хэрэв бид тэмдгийг харгалзан үзвэл $\mathbf a$-ээс $\mathbf b$ рүү эргэх эргэлт ($\mathbf e_z$-ийн үзүүрээс харахад) цагийн зүүний эсрэг хийгдэж байвал талбай эерэг, эс бөгөөс сөрөг байна. Энэ нь псевдоскаляр үржвэрийг тодорхойлно. Энэ нь мөн $|\mathbf a| \cdot |\mathbf b| \sin \theta$-тэй тэнцүү болохыг анхаарна уу, энд $\theta$ нь $\mathbf a$-ээс $\mathbf b$ хүртэлх цагийн зүүний эсрэг тоолсон өнцөг (эргэлт цагийн зүүний дагуу бол сөрөг).

Энэ бүхнийг хэрэгжүүлье!

point3d cross(point3d a, point3d b) {
    return point3d(a.y * b.z - a.z * b.y,
                   a.z * b.x - a.x * b.z,
                   a.x * b.y - a.y * b.x);
}
ftype triple(point3d a, point3d b, point3d c) {
    return dot(a, cross(b, c));
}
ftype cross(point2d a, point2d b) {
    return a.x * b.y - a.y * b.x;
}

Шинж чанарууд

Вектор үржвэрийн хувьд энэ нь $\mathbf a$ ба $\mathbf b$ векторууд коллинеар (нийтлэг шулуун үүсгэдэг буюу параллель) байх үед л тэг вектортой тэнцүү байна. Холимог үржвэрийн хувьд ч мөн адил, энэ нь $\mathbf a$, $\mathbf b$, $\mathbf c$ векторууд компланар (нийтлэг хавтгай үүсгэдэг) байх үед л тэгтэй тэнцүү байна.

Үүнээс бид шулуун ба хавтгайг тодорхойлох универсал тэгшитгэлүүдийг гаргаж авч болно. Шулууныг түүний чиглүүлэгч вектор $\mathbf d$ ба эхлэлийн цэг $\mathbf r_0$-оор, эсвэл $\mathbf a$ ба $\mathbf b$ гэсэн хоёр цэгээр тодорхойлж болно. Энэ нь $(\mathbf r - \mathbf r_0)\times\mathbf d=0$ эсвэл $(\mathbf r - \mathbf a)\times (\mathbf b - \mathbf a) = 0$ гэж тодорхойлогдоно. Хавтгайн хувьд түүнийг $\mathbf a$, $\mathbf b$, $\mathbf c$ гэсэн гурван цэгээр $(\mathbf r - \mathbf a)\cdot((\mathbf b - \mathbf a)\times (\mathbf c - \mathbf a))=0$ гэж, эсвэл эхлэлийн цэг $\mathbf r_0$ ба энэ хавтгайд орших $\mathbf d_1$, $\mathbf d_2$ гэсэн хоёр чиглүүлэгч вектороор $(\mathbf r - \mathbf r_0)\cdot(\mathbf d_1\times \mathbf d_2)=0$ гэж тодорхойлж болно.

2 хэмжээст орон зайд псевдоскаляр үржвэрийг мөн хоёр векторын хоорондох чиглэлийг шалгахад ашиглаж болно, учир нь эхний вектороос хоёр дахь вектор руу эргэх эргэлт цагийн зүүний эсрэг бол эерэг, эс бөгөөс сөрөг байна. Мөн мэдээж үүнийг олон өнцөгтийн талбайг тооцоолоход ашиглаж болох ба үүнийг өөр өгүүлэлд тайлбарласан. 3 хэмжээст орон зайд холимог үржвэрийг ижил зорилгоор ашиглаж болно.

Дасгалууд

Шулуунуудын огтлолцол

2 хэмжээст орон зайд шулууныг тодорхойлох олон боломжит арга байдаг бөгөөд та тэдгээрийг хослуулахаас эргэлзэх хэрэггүй. Жишээ нь бидэнд хоёр шулуун байгаа ба бид тэдгээрийн огтлолцлын цэгүүдийг олохыг хүсэж байна. Эхний шулууны бүх цэгийг $\mathbf r = \mathbf a_1 + t \cdot \mathbf d_1$ гэж параметржүүлж болно гэж хэлж болно, энд $\mathbf a_1$ нь эхлэлийн цэг, $\mathbf d_1$ нь чиглэл, $t$ нь ямар нэг бодит параметр юм. Хоёр дахь шулууны хувьд түүний бүх цэг $(\mathbf r - \mathbf a_2)\times \mathbf d_2=0$-г хангах ёстой. Үүнээс бид $t$ параметрийг хялбархан олж болно:

$$(\mathbf a_1 + t \cdot \mathbf d_1 - \mathbf a_2)\times \mathbf d_2=0 \quad\Rightarrow\quad t = \dfrac{(\mathbf a_2 - \mathbf a_1)\times\mathbf d_2}{\mathbf d_1\times \mathbf d_2}$$

Хоёр шулууныг огтлолцуулах функцийг хэрэгжүүлье.

point2d intersect(point2d a1, point2d d1, point2d a2, point2d d2) {
    return a1 + cross(a2 - a1, d2) / cross(d1, d2) * d1;
}

Хавтгайнуудын огтлолцол

Гэвч заримдаа геометрийн зарим ойлголтыг ашиглахад хэцүү байж болно. Жишээ нь танд эхлэлийн цэг $\mathbf a_i$ ба чиглэл $\mathbf d_i$-ээр тодорхойлогдсон гурван хавтгай өгөгдсөн бөгөөд та тэдгээрийн огтлолцлын цэгийг олохыг хүсэж байна. Та зүгээр л дараах тэгшитгэлийн системийг бодох ёстойг анзаарч болно:

$$\begin{cases}\mathbf r\cdot \mathbf n_1 = \mathbf a_1\cdot \mathbf n_1, \\ \mathbf r\cdot \mathbf n_2 = \mathbf a_2\cdot \mathbf n_2, \\ \mathbf r\cdot \mathbf n_3 = \mathbf a_3\cdot \mathbf n_3\end{cases}$$

Геометрийн арга барилын талаар бодохын оронд та шууд гаргаж авч болох алгебрийн аргыг боловсруулж болно. Жишээ нь та цэгийн классыг аль хэдийн хэрэгжүүлсэн гэвэл холимог үржвэр нь векторуудыг багана болгон авсан матрицын тодорхойлогч тул та Крамерын дүрэм ашиглан энэ системийг бодоход хялбар байх болно:

point3d intersect(point3d a1, point3d n1, point3d a2, point3d n2, point3d a3, point3d n3) {
    point3d x(n1.x, n2.x, n3.x);
    point3d y(n1.y, n2.y, n3.y);
    point3d z(n1.z, n2.z, n3.z); 
    point3d d(dot(a1, n1), dot(a2, n2), dot(a3, n3));
    return point3d(triple(d, y, z),
                   triple(x, d, z),
                   triple(x, y, d)) / triple(n1, n2, n3);
}

Одоо та энэ бүхэнд дасахын тулд түгээмэл геометрийн үйлдлүүдийн аргуудыг өөрөө олохыг оролдож болно.