% Convex Hull — Andrew's Monotone Chain
%
% Walks 8 sorted points left-to-right building the lower hull via
% stack + cross-product turn check, then (compressed) upper hull,
% then highlights the final hull polygon.
%
% Points (sorted by x):
% A(0,1) B(1,0) C(2,2) D(3,1) E(4,3) F(5,0) G(6,4) H(7,2)
%
% Expected result:
% Lower hull: A B F H Upper hull: H G A
% Full hull (CCW): A B F H G Interior: C D E
%
% Demonstrates the loop-to-step manual-unroll pattern (ruleset §2.1).
Step 1 / 23
Step 1 / 23
Andrew's monotone chain duyệt n điểm đã sắp theo x (ties by y)
và build lower hull via stack. Với mỗi điểm mới p: while top-2 của
stack plus p tạo right turn (cross product ≤0), pop. Sau đó
push p. Cross product:
cross(O,P,Q)=(Px−Ox)(Qy−Oy)−(Py−Oy)(Qx−Ox).
Sign >0: left turn (counterclockwise). Sign <0: right turn. Sign
=0: collinear.
Step 2 / 23
Process A(0,1). Stack rỗng, không có gì để check. Push A.
Step 3 / 23
Process B(1,0). Stack =[A], chỉ 1 phần tử nên không check turn.
Push B. Vẽ tentative segment A→B.
Step 4 / 23
Process C(2,2). Check triple (A,B,C):
cross(A,B,C)=(1−0)(2−1)−(0−1)(2−0)=1−(−2)=3>0.
Left turn — keep B on the stack.
Step 5 / 23
Push C. Stack =[A,B,C]. Vẽ tentative segment B→C.
Step 6 / 23
Process D(3,1). Check triple (B,C,D):
cross(B,C,D)=(2−1)(1−0)−(2−0)(3−1)=1−4=−3≤0.
Right turn — pop C from stack.
Step 7 / 23
C popped. Stack =[A,B]. Segment B→C dimmed (discarded,
nhưng giữ trên canvas để author thấy algorithm progression).
Now check triple (A,B,D):
cross(A,B,D)=(1−0)(1−1)−(0−1)(3−0)=0−(−3)=3>0.
Left turn — stop popping, push D.
Step 8 / 23
Stack =[A,B,D]. Vẽ segment B→D.
Step 9 / 23
Process E(4,3). Check triple (B,D,E):
cross(B,D,E)=(3−1)(3−0)−(1−0)(4−1)=6−3=3>0.
Left turn — push E.
Step 10 / 23
Stack =[A,B,D,E]. Vẽ segment D→E.
Step 11 / 23
Process F(5,0). Check triple (D,E,F):
cross(D,E,F)=(4−3)(0−1)−(3−1)(5−3)=−1−4=−5≤0.
Right turn — pop E.
Step 12 / 23
E popped. Stack =[A,B,D]. Check triple (B,D,F):
cross(B,D,F)=(3−1)(0−0)−(1−0)(5−1)=0−4=−4≤0.
Right turn again — pop D.
Step 13 / 23
D popped. Stack =[A,B]. Check triple (A,B,F):
cross(A,B,F)=(1−0)(0−1)−(0−1)(5−0)=−1−(−5)=4>0.
Left turn — stop popping, push F.
Step 14 / 23
Stack =[A,B,F]. Vẽ segment B→F. Hull đang hình thành
ở bottom — A, B, F đều là phần của final hull.
Step 15 / 23
Process G(6,4). Check triple (B,F,G):
cross(B,F,G)=(5−1)(4−0)−(0−0)(6−1)=20−0=20>0.
Left turn — push G.
Step 16 / 23
Stack =[A,B,F,G]. Vẽ segment F→G.
Step 17 / 23
Process H(7,2). Check triple (F,G,H):
cross(F,G,H)=(6−5)(2−0)−(4−0)(7−5)=2−8=−6≤0.
Right turn — pop G.
Step 18 / 23
G popped. Stack =[A,B,F]. Check triple (B,F,H):
cross(B,F,H)=(5−1)(2−0)−(0−0)(7−1)=8−0=8>0.
Left turn — push H.
Step 19 / 23
Stack =[A,B,F,H]. Vẽ segment F→H. Lower hull walk done.
Final lower hull: A→B→F→H.
Step 20 / 23
Lower hull complete. 4 points: A,B,F,H. Time complexity:
O(n) amortized cho stack walk (mỗi point push tối đa một lần và
pop tối đa một lần).
Step 21 / 23
Upper hull: walk tương tự nhưng reverse sorted (H,G,F,E,D,C,B,A).
Để ngắn gọn, mình skip the walk và show kết quả: upper hull có 3 điểm
H,G,A. G(6,4) giờ chính thức thuộc hull sau khi được reviewed từ
phía upper side — trước đó bị popped ở lower walk vì wrong direction.
Step 22 / 23
Convex hull hoàn chỉnh: 5 đỉnh {A,B,F,H,G} theo thứ tự
counterclockwise. 3 interior points {C,D,E} bị pop trong
quá trình walk. Total complexity: O(nlogn) cho sort + O(n)
amortized cho hai stack walks.
Step 23 / 23
Hull as filled polygon. Thuật toán Andrew's monotone chain ngắn gọn
hơn Graham scan (không cần sort theo angle, không cần pivot) và
robust với collinear points (chỉ cần thay ≤ bằng < trong
cross-product check nếu muốn giữ collinear points trên hull).