Thứ Tư, 27 tháng 8, 2025

Phép nghịch đảo với mp-geom2d

Trong gói mp-geom2d có toàn bộ công cụ vẽ hình học phẳng, đặc biệt tích hợp sẵn phép nghịch đảo (Inverse). Ta sử dụng chúng như sau:
  1. Tạo một file $\rm Lua\LaTeX$:
    \documentclass[border=5mm]{standalone}
    \usepackage{luamplib}
    \begin{document}
    \mplibtextextlabel{enable}
    \begin{mplibcode}
    input geom2d;
     beginfig(1);
     % nội dung 
     Window(-1,-1,5.5,6);
    endfig;
    \end{mplibcode}
    \end{document}
        
  2. Ảnh của một điểm. Ta xác định một phép nghịch đảo cực $A(2;2)$, đường tròn nghịch đảo là đường tròn tâm $A$ bán kính $2$, nghĩa là phương tích nghịch đảo $k=R^2=4$. Viết đoạn code sau đây ngay sau beginfig(1);
    A = Point(2,2);
    C = Circle(A,2);
    gddDraw C withcolor Cyan withpen pencircle scaled 1bp;
    gddMark.rt "A";
    d = Segment(A,B);
    gddDraw d withcolor Gray withpen pencircle scaled 1bp;
     
    Biên dịch bằng LuaLaTeX có kết quả như ở dưới. Phần phía trên của hình vẽ còn trống: là do ta chọn Window(-1,-1,5.5,6) để còn có thể vẽ thêm hình vào file này.
  3. Ảnh của môt đường tròn.
  4. Ta biết rằng một đường tròn không đi qua cực nghịch đảo sẽ biến thành một đường tròn. Tâm của đường tròn nguồn không biến thành tâm của đường tròn ảnh, nhưng hai tâm thẳng hàng với cực nghịch đảo.

    Rất tiếc cũng giống như pstricks, phép nghịch đảo của mp-geom2d không biến được đường tròn thành đường tròn một cách chính xác.
    E = Point(3,1);
    CE = Circle(E,0.5);
    gddDraw CE  withcolor Gray withpen pencircle scaled 1bp;
    gddMark.rt "E";
    iCE = Inverse(CE,C);
    F = Center(iCE);
    gddMark.rt "F";
    gddDraw iCE  withcolor red withpen pencircle scaled 1.5bp;


    Hình vẽ dưới đây phép nghich đảo biến đường tròn $(E)$ xám (Gray) thành đường tròn đỏ $(F)$ , nhưng đó không là ảnh của đường tròn $(E)$. Nguyên nhân có thể dự đoán được là nó lấy một tập hợp hữu hạn các điểm của đường tròn $(E)$, lấy ảnh của từng điểm rồi nối lại, kết quả nối sai.

    Sau hình vẽ ở dưới là cách khắc phục.

    Khắc phục.
    • Viết một hàm đặt trong một file metapost (ví dụ invert.mp ) xác định ảnh của đường tròn qua phép nghịch đảo, tất nhiên đường tròn nguồn không đi qua cực.
      % Hàm tính ảnh đường tròn qua phép nghịch đảo
      vardef invert_circle(expr input_circle, inversion_circle) =
          save cen, r, xcen, ycen, X, Y, Z, iX, iY, iZ;
          cen = Center(input_circle);
          r = Radius(input_circle);
          xcen = Xcoordinate(cen);
          ycen = Ycoordinate(cen);
          
          % Chọn 3 điểm trên đường tròn (cách đều 120 độ)
          X = Point(xcen + r*cos(0), ycen + r*sin(0));
          Y = Point(xcen + r*cos(120), ycen + r*sin(120));
          Z = Point(xcen + r*cos(240), ycen + r*sin(240));
          
          % Tính ảnh của 3 điểm qua phép nghịch đảo
          iX = Inverse(X, inversion_circle);
          iY = Inverse(Y, inversion_circle);
          iZ = Inverse(Z, inversion_circle);
          
          % Tạo đường tròn mới từ 3 điểm ảnh
          CircleThreePoints(iX, iY, iZ)
      enddef;
      
    • Sau đây là file $\rm \TeX$ sử dụng mp-geom2d.mpinvert.mp

      \documentclass[border=5mm]{standalone}
      \usepackage{luamplib}
      \begin{document}
      \mplibtextextlabel{enable}
      \begin{mplibcode}
      input geom2d;
      input invert;
      
      beginfig(1);
      
      % Đường tròn nghịch đảo
      A = Point(2,4);
      C = Circle(A,2);
      gddDraw C withcolor Cyan withpen pencircle scaled 1bp;
      gddMark.rt "A";
      
      % Vẽ nhiều đường tròn và ảnh nghịch đảo của chúng, 
      % chọn upto 0 để lấy 1 đường tròn.  
      for i = 0 upto 0:
      save E, CE, invCE, F;  % Khai báo biến cục bộ
      E = Point(3 + i*0.7, 3 + i*0.3);
      CE = Circle(E, 0.5 + i*0.1);
          
      % Vẽ đường tròn gốc
      gddDraw CE withcolor (0.2, 0.6, 0.2) withpen pencircle scaled 1bp;
      gddMark.rt "E";
          
      % Tính và vẽ ảnh nghịch đảo
      invCE = invert_circle(CE, C);
      gddDraw invCE withcolor (0.8, 0.2, 0.2) withpen pencircle scaled 1bp;
          
      % Đánh dấu tâm đường tròn ảnh
      F = Center(invCE);
      gddMark.rt "F";
      endfor
      
      % Thiết lập khung hiển thị
      FrameMinMax(0, 6, 0, 6, 1, 1);
      drawoptions(withcolor LightGrey);
      FrameGrid;
      
      endfig;
      \end{mplibcode}
      \end{document}


    • Kết quả chính xác:
  5. Ảnh của đường thẳng. Qua phép nghịch đảo một đường thẳng không đi qua cực nghịch đảo sẽ biến thành một đường tròn đi qua cực nghịch đảo. Vì phép nghịch đảo có tính chất đối hợp nên một đường tròn đi qua cực nghịch đảo sẽ biến thành một đường thẳng.
    d = Line((3,3),(4,2));
    gddDraw d withcolor Gray withpen pencircle scaled 1bp;;
    Cd = Inverse(d,C);
    gddDraw Cd withcolor Red withpen pencircle scaled 1.5bp;


THỰC HÀNH


  1. Tạo một file $\rm Lua\LaTeX$, khai báo ba điểm $A, B, C$ có tọa độ như ghi trong file.
    \documentclass[border=5mm]{standalone}
    \usepackage{luamplib}
    \begin{document}
    \mplibtextextlabel{enable}
    \begin{mplibcode}
    input geom2d;
    input invert;
    beginfig(1);
    d = 10;
    A = Point(0,0);
    C = Point(d,0);
    B= Point(3*d/4,0); 
    % nội dung sẽ viết ở đây
    Window(-1,-14,14,14);
    % Thiết lập khung hiển thị
    FrameMinMax(0, 18, 0, 20, 1, 1);
    drawoptions(withcolor LightGrey);
    FrameGrid;
    endfig;
    \end{mplibcode}
    \end{document}
  2. Viết vào sau dòng 12:
    gddMark.lft "A";
    gddMark.llft "B";
    gddMark.rt "C";
    gddDraw Segment(A,C) withcolor Cyan withpen pencircle scaled 1bp;
    U = CircleCP(A,C);
    gddDraw U withcolor Cyan withpen pencircle scaled 1bp;
    X = CircleD(A,B);
    gddDraw X withcolor Gray withpen pencircle scaled 1bp;
    Y = CircleD(A,C);
    gddDraw Y withcolor Gray withpen pencircle scaled 1bp;

    3 dòng đầu tiên hiển thị các điểm $A, B, C$.
    Dòng thứ 4 vẽ đoạn thẳng $AC$.
    Dòng thứ 5 và dòng thứ 6 xác định và vẽ đường tròn tâm $A$ và đi qua $C$, chính là đường tròn nghich đảo, chọn màu rất nhạt.
    Dòng thứ 7 và dòng thứ 8 xác định và vẽ đường tròn đường kính $AB$.
    Dòng thứ 9 và dòng thứ 10 xác định và vẽ đường tròn đường kính $AC$.

  3. Bây giờ ta bắt đầu sẽ chuỗi đường tròn Pappus. Trước hết ta vẽ đường tròn chuẩn, đó là đường tròn đường kính $BC$

    Thêm dòng code
    Z := CircleD(B,C);
    gddDraw Z withcolor Gray withpen pencircle scaled 1bp;

  4. Dùng phép nghịch đảo cực $A$, phương tích $k=AC^2$, tức là đường tròn nghịch đảo $U$ là đường tròn bán kính $AC$. Dùng phép nghich đảo này biến đường tròn các đường kính $AB$ và $AC$ đi qua cực nghịch đảo và tiếp xúc nhau thành thành các đường thẳng song song.

    Thêm 4 dòng lệnh
    iX = Inverse(X,U);
    gddDraw iX withcolor Gray withpen pencircle scaled 1.5bp;
    iY = Inverse(Y,U);
    gddDraw iY withcolor red withpen pencircle scaled 1.5bp;
  5. Không dùng phép nghịch đảo nói trên để tìm ảnh của đường tròn đường kính $BC$. Thay vào đó ta dùng phép nghịch đảo invert_circle trong file invert.mp để biến đường tròn đường kính $BC$ thành đường tròn, ta tạm gọi là (bleu). Đường tròn (blue) tiếp xúc với hai đường thẳng song song vì tạo ảnh của nó tiếp xúc với hai đường tròn $[AB]$ và $[AC]$.

    Thêm câu lệnh:
    invZ := invert_circle(Z, U);
    gddDraw invZ withcolor blue withpen pencircle scaled 1.5bp;
    D = Center(invZ);
    gddMark.bot "D";
    Rp = Radius(invZ);

    Dòng 1 và dòng 2 xác định và vẽ đường tròn nghịch đảo của đường tròn $[BC]$.
    Dòng 3 và dòng 4 xác định và hiển thị tâm, dòng 5 xác định bán kính của đường tròn nghịch đảo đó.
  6. Ta tịnh tiến tâm $D$ của đường tròn (blue) theo vectơ $(0,2*i*Rp)$ thành các điểm $E[i]$. Sau đó lấy $E[i]$ làm tâm và bán kính bằng bán kính của đường tròn (blue) để vẽ các đường tròn $C[i]$ tịnh tiến của đường tròn (blue).

    Thêm dòng code:
    for i:=-18 upto 18:
    E[i] = Addition(D,Point(0,2*i*Rp));
    C[i] := Circle(E[i],Rp);
    gddDraw C[i]  withcolor blue withpen pencircle scaled 1.5bp;
    endfor
  7. Dùng phép nghịch đảo invert_circle để xác định ảnh của các đường tròn $C[i]$ thành các đường tròn $D[i]$. Sau đó với 8 đường tròn xung quang (blue), hiển thị tâm của chúng, nối các đoạn thẳng đi từ cực nghich đảo $A$ đên các tâm của $C[i]$.

    Thêm dòng code:
    D[i] := invert_circle(C[i],U);
    gddDraw D[i]  withcolor red withpen pencircle scaled 1.5bp;


    sang vòng lặp khác để vẽ các đoạn thẳng $AC[i]$:

    for i:=-4 upto 4:
    T[i]  := Center(C[i]); gddDrawPoint T[i];
    K[i]  := Center(D[i]); gddDrawPoint K[i];
    gddDraw Segment(A,T[i])  withcolor LightGray withpen pencircle scaled  1bp;
    endfor


Code hoàn chỉnh của chuỗi đường tròn Pappus vẽ bằng mp-geom2d. Cần phải có 2 file geom2d.mp (thực ra là một thư mục) và file invert.mp

\documentclass[border=5mm]{standalone}
\usepackage{luamplib}
\begin{document}
\mplibtextextlabel{enable}
\begin{mplibcode}
input geom2d;
input invert;
beginfig(1);
d = 10;
A = Point(0,0);
C = Point(d,0);
B= Point(3*d/4,0); 
gddMark.lft "A";
gddMark.llft "B";
gddMark.rt "C";
gddDraw Segment(A,C) withcolor Cyan withpen pencircle scaled 1bp;
U = CircleCP(A,C);
gddDraw U withcolor Cyan withpen pencircle scaled 1bp;
X = CircleD(A,B);
gddDraw X withcolor Gray withpen pencircle scaled 1bp;
Y = CircleD(A,C);
gddDraw Y withcolor Gray withpen pencircle scaled 1bp;
iX = Inverse(X,U);
gddDraw iX withcolor Gray withpen pencircle scaled 1.5bp;
iY = Inverse(Y,U);
gddDraw iY withcolor red withpen pencircle scaled 1.5bp;
Z := CircleD(B,C);
gddDraw Z withcolor Gray withpen pencircle scaled 1bp;
invZ := invert_circle(Z, U);
gddDraw invZ withcolor blue withpen pencircle scaled 1.5bp;
D = Center(invZ);
gddMark.bot "D";
Rp = Radius(invZ);
for i:=-18 upto 18:
E[i] = Addition(D,Point(0,2*i*Rp));
C[i] := Circle(E[i],Rp);
gddDraw C[i]  withcolor blue withpen pencircle scaled 1.5bp;
D[i] := invert_circle(C[i],U);
gddDraw D[i]  withcolor red withpen pencircle scaled 1.5bp;
endfor
for i:=-4 upto 4:
T[i]  := Center(C[i]); gddDrawPoint T[i];
K[i]  := Center(D[i]); gddDrawPoint K[i];
gddDraw Segment(A,T[i])  withcolor LightGray withpen pencircle scaled
 1bp;
endfor
Window(-1,-14,14,14);
% Thiết lập khung hiển thị
FrameMinMax(0, 18, 0, 20, 1, 1);
drawoptions(withcolor LightGrey);
FrameGrid;
endfig;
\end{mplibcode}
\end{document}

Không có nhận xét nào:

Đăng nhận xét