Lulucat

Vì sao chúng tôi thay thế ba bộ máy hình học bút đánh dấu bằng các stamp

Gaoge ZhangGaoge Zhang

Dữ liệu Apple Pencil thực tế đã phơi bày các lỗi mà kiểm thử tổng hợp bỏ sót, đưa Lulucat Notes từ ba bộ máy đường bao đến mô hình stamp của MaLiang.

Đã cập nhật

Lulucat Notes bắt đầu với một bộ dựng bút đánh dấu theo cách thông thường: xây dựng một đường bao hình học quanh đường đi đã lấy mẫu, rồi tô đường bao đó một lần bằng màu bán trong suốt. Một lần tô giúp tránh các dải màu đậm hơn xuất hiện ở nơi những đoạn bán trong suốt chồng lên nhau. Cách này cũng đưa mọi điểm nối, giao nhau với chính nó, đầu nét và nét ngắn vào cùng một bài toán hình học.

Ba thế hệ bộ hình học tự xây dựng lần lượt loại bỏ một nhóm lỗi rồi lại làm lộ ra một nhóm khác. Bộ dựng chúng tôi hiện dùng các stamp hình tròn mềm dựa trên MaLiang, một framework vẽ mã nguồn mở được cấp phép MIT do Harley-xk phát triển. Đổi lại việc loại bỏ cả một nhóm lỗi đường bao, chúng tôi chấp nhận các vùng giao nhau với chính nó đậm hơn và các đầu nét thu nhỏ theo áp lực.

Nét chữ bút đánh dấu màu xanh được ghi lại trên iPad, với các móc nhỏ nhìn thấy ở đầu và cuối của một số nét.

Ảnh chụp màn hình gốc từ thiết bị ở mức thu phóng 228%. Các móc nhỏ xuất hiện ở cả hai đầu của một số nét.

Chữ viết thực tế tạo ra các móc nhỏ mà cảnh tổng hợp không có

Các cảnh tổng hợp của chúng tôi bao phủ đường thẳng, cung tròn, chạm ngắn, đi ngược nét, thay đổi áp lực và các lần đổi hướng gắt, tất cả đều được dựng sạch sẽ. Chữ viết tiếng Trung thực tế vẫn tạo ra các móc dài khoảng 1–3 point ở đầu và cuối của nhiều nét.

Vì vậy, chúng tôi thêm một nút lưu vào ứng dụng và ghi lại 29 nét hoàn chỉnh. Mỗi mẫu giữ nguyên vị trí, bán kính, áp lực, phương vị, độ cao, dấu thời gian và các cờ ước lượng của UIKit. Một chương trình ngoại tuyến giải mã JSON đó rồi biên dịch chính các tệp Stroke.swift, StrokeRenderer.swiftHighlighterStrokeBuilder.swift mà ứng dụng sử dụng. Kết quả của nó khớp với ảnh chụp màn hình trên thiết bị theo từng nét, bao gồm cả các móc nhỏ.

Vì bộ dựng ngoại tuyến tái tạo được lỗi chỉ từ dữ liệu đầu vào đã ghi, nguyên nhân nằm ở các mẫu và hình học chứ không phải ở hành vi hiển thị. Giờ đây chúng tôi có thể đọc chính xác các mẫu đã đi vào bộ dựng.

Giả thuyết đầu tiên của chúng tôi đổ lỗi cho hướng Apple Pencil được ước lượng lúc chạm xuống và nhấc lên. Dữ liệu bác bỏ giả thuyết đó. Trên cả 29 nét, phương vị thay đổi nhiều nhất 0.09 radian và độ cao nhiều nhất 0.02 radian trong tám mẫu đầu và cuối, đồng thời mọi cờ ước lượng trên chiếc iPad đó đều là false. Hướng vẫn ổn định trong khi áp lực và hướng chuyển động thay đổi mạnh.

Ngưỡng áp lực xuất phát từ một khoảng trống rõ ràng trong dữ liệu

Mẫu cuối của mọi nét được ghi lại đều có áp lực 0.000. Các mẫu khi đang viết có áp lực từ 0.01 trở lên, còn các mẫu được ghi lại sau khi Apple Pencil rời khỏi bề mặt có áp lực từ 0.002 trở xuống. Các mẫu đang ở trên không đó thường tiếp tục trong 2–7 point và di chuyển 0.8–9.0 point, còn hướng của chúng có thể rẽ khoảng 90 độ lệch khỏi nét đã viết.

Nét 2 cho thấy cơ chế này. Phần thân của nó kết thúc trong khoảng từ 143 đến 180 độ. Đuôi có áp lực thấp sau đó quay từ −90 đến −67 độ và đi thêm 8.5 point. Bộ dựng đường bao coi điểm cuối đang ở trên không là điểm kết thúc chính thức, nên kéo một mảnh hình học hẹp về phía điểm đó.

Các giá trị áp lực đo được để lại một khoảng gần một bậc độ lớn giữa chuyển động khi viết và khi ở trên không, vì vậy chúng tôi đặt ngưỡng cắt vào bên trong khoảng đó:

private static let pressureFloor: CGFloat = 0.005

Chỉ các mẫu áp lực thấp ở hai đầu bị loại bỏ. Một mẫu áp lực thấp ở giữa nét vẫn là một phần của nét. Quy tắc này bám theo ranh giới sự kiện đo được và để nguyên đường viết.

Ảnh cận cảnh đã đo đạc trước khi cắt: các mẫu đầu vào màu xanh lá rẽ khỏi nét trong khi đường bao màu đỏ tạo thành một móc hẹp.

Trước khi cắt, bộ dựng neo đầu nét vào các mẫu đang ở trên không. Các chấm xanh lá là mẫu thô; đường màu đỏ là đường bao được tạo ra.

Ảnh cận cảnh đã đo đạc sau khi cắt: phần tô màu xanh kết thúc ở các mẫu cuối cùng khi đang viết, còn các chấm xanh lá áp lực thấp nằm bên ngoài.

Sau khi cắt các mẫu dưới 0.005, đầu nét kết thúc tại điểm cuối cùng khi đang viết. Ngưỡng áp lực này vẫn được giữ trong bộ dựng stamp hiện tại.

Ngưỡng này loại bỏ các móc dài do chuyển động trên không. Các lần kéo ngắn lúc chạm xuống và các cung lúc nhấc lên có áp lực vẫn trên 0.005 được giữ lại, vì đó là chuyển động khi viết. Việc xử lý các chuyển động đó trong một mô hình đường bao đã dẫn đến những vòng hình học tiếp theo.

Ba bộ máy hình học chỉ di chuyển lỗi từ chỗ này sang chỗ khác

Thế hệ một: một đường bao, một lần tô

Bộ máy nhạy áp lực đầu tiên đi theo một quy trình quen thuộc. Nó làm mượt một đường sống, tính các độ lệch trái và phải, nối chúng thành một đa giác rồi tô đa giác đó một lần. Đầu bút là một ellipse được điều khiển bởi phương vị và độ cao của Apple Pencil, nên tiết diện của nó thay đổi theo hướng viết. Các lần chạm ngắn dùng một hình dạng riêng, còn đầu nét phẳng dùng những bất đối xứng nhỏ để tránh các vùng có số cuộn bằng không.

Một lần tô duy nhất giải quyết việc độ mờ tích lũy bên trong một nét, đồng thời đòi hỏi một đa giác hợp lệ ở mọi chỗ ngoặt. Các lần kéo lúc chạm xuống tạo ra những hình nêm giữa đầu nét và thân nét. Các lần đi ngược nét có thể tạo ra những vùng trắng hình lưỡi liềm. Những lần đổi hướng gắt có thể khiến đường bao phía trong tự giao nhau và để lại một khấc không được tô.

Thế hệ hai: sửa đường bao gần hai đầu

Bộ máy thứ hai giữ lại đường bao và thêm các sửa chữa cục bộ: cắt phần đi ngược nét, giảm chấn cho các thuộc tính được ước lượng sớm, làm thẳng đầu cuối, cắt hướng tạm thời và mở rộng đầu nét một chút. Mỗi bản vá sửa một lỗi đã tái tạo. Kết hợp lại, chúng khiến hành vi ở đầu nét phụ thuộc vào nhiều ngưỡng và cửa sổ.

Việc viết thực tế sau đó tạo ra những trường hợp nằm ngoài các cửa sổ đó. Cửa sổ làm thẳng cố định 24 point xóa mất các móc có chủ ý trong những nét ngắn. Cửa sổ thích ứng giữ được các móc đó, nhưng các cung lúc nhấc lên vẫn có thể biến thành những góc nhìn thấy được. Việc cắt có xét đến hướng loại bỏ nhiều chuyển động tạm thời hơn, nhưng phải đánh đổi bằng cách bỏ đi khoảng 2.5 point của một phần bắt đầu cong thực sự trong một nét được ghi lại.

Mỗi bản vá đều sửa được trường hợp mục tiêu của nó. Tuy nhiên, mô hình bên dưới vẫn yêu cầu một đường bao cứng luôn hợp lệ khi xử lý đầu vào nhiễu và cong.

Thế hệ ba: hợp nhất độ phủ với đầu nét vuông được cắt

Bộ máy thứ ba dừng việc tạo một đường bao duy nhất. Nó vẽ một hình thang cho mỗi đoạn và một hình tròn tại mỗi mẫu bên trong vào một mặt nạ thang độ xám, lấy hợp nhất độ phủ của chúng rồi áp màu bút đánh dấu một lần. Các vùng trắng hình lưỡi liềm do đi ngược nét, hiện tượng giao nhau với chính nó đậm hơn và các lỗ do số cuộn bằng không biến mất, vì bộ dựng không còn phụ thuộc vào số cuộn của đa giác.

Phép hợp nhất làm tròn hai đầu, và chúng tôi khôi phục đầu nét vuông bằng cách cắt độ phủ theo hai nửa mặt phẳng ở đầu cuối. Phép cắt đó sửa được các đường thẳng có áp lực không đổi nhưng lại tạo ra một lỗi nghiêm trọng hơn: thân của một nét cong có thể hợp lệ khi cắt qua một nửa mặt phẳng ở đầu cuối, và khi đó phép cắt đầu nét loại bỏ một phần giữa nét. Trong lúc nhập liệu trực tiếp, hướng ở đầu cuối liên tục thay đổi, nên vùng bị cắt di chuyển và nét bị nhấp nháy.

Một nét cong màu xanh trước khi sửa phép cắt đầu nét, với phần thân phía trên bị cắt theo một đường chéo; các chấm xanh lá cho thấy toàn bộ đường đi đã lấy mẫu.

Ràng buộc đầu nét toàn cục cắt xuyên qua thân của một nét cong.

Cùng nét cong màu xanh sau khi thêm bộ lọc độ dài cung cục bộ, với cả hai nhánh được khôi phục quanh đường đi đã lấy mẫu màu xanh lá.

Giới hạn phép cắt đầu nét vào các primitive nằm trong phạm vi một nửa bề rộng tính từ đầu cuối sẽ khôi phục nét này.

Một bộ lọc theo độ dài cung khiến phép cắt đầu nét trở nên cục bộ và sửa được mọi trường hợp đã ghi lại. Một móc tổng hợp cực đoan vẫn cho thấy một khấc trắng nhỏ nơi đầu có áp lực thấp gặp đầu nét đã cắt. Bộ máy thứ ba lại đánh đổi một lỗi hình học này lấy một lỗi khác.

MaLiang loại bỏ ranh giới cứng

MaLiang tạo một nét từ các stamp kết cấu lặp lại thay vì một đường bao khép kín duy nhất. Bộ tạo đường đi của nó dùng các đoạn Bézier bậc hai đi qua các trung điểm của những mẫu liền kề, còn bộ dựng nét đặt các stamp theo một bước đều dọc đường đi đó. Kích thước, góc xoay, màu và độ mờ của stamp đều có thể thay đổi dọc theo nét.

Một stamp mềm không có đầu nét, điểm nối hay quy tắc chiều cuộn riêng. Một thay đổi hướng gắt vẫn chỉ là một chuỗi các dấu chồng lên nhau. Các lần đi ngược nét không thể tạo ra một hốc đa giác rỗng, và một nửa mặt phẳng ở đầu cuối không thể cắt vào giữa nét, vì mô hình không chứa phép cắt đầu cuối.

Chúng tôi áp dụng mô hình này chứ không sao chép mã. HighlighterStrokeBuilder hiện tại thực hiện bốn thao tác:

  1. Chỉ loại bỏ các mẫu ở đầu cuối có áp lực dưới 0.005.
  2. Làm mượt vị trí bằng các đoạn Bézier bậc hai qua trung điểm.
  3. Đặt một stamp hình tròn cho mỗi điểm dọc theo độ dài cung.
  4. Đặt đường kính stamp dựa trên áp lực đã chuẩn hóa và hợp thành các stamp bằng alpha source-over.

Bộ dựng giảm từ 686 dòng xuống còn 190. Phương vị, độ cao, việc tạo đường bao, mặt nạ hợp nhất, các cửa sổ hướng ở đầu cuối, phần mở rộng đầu nét và phép cắt đầu nét đều bị loại khỏi đường đi của bút đánh dấu. Chúng tôi vẫn ghi lại hướng của Pencil vì mô hình đầu vào hỗ trợ nó, còn bản thân bút đánh dấu không còn đọc các trường đó.

Công thức áp lực của MaLiang cần hiệu chỉnh theo thiết bị

MaLiang tính kích thước stamp bằng một công thức tương đương với

công thức này giả định rằng force sử dụng một phần hữu ích của khoảng từ 0 đến 1. Dữ liệu thiết bị của chúng tôi không như vậy. Trong khoảng 3,400 mẫu Apple Pencil, áp lực trung vị là 0.047 và giá trị lớn nhất là 0.178. Đưa trực tiếp các giá trị đó vào công thức khiến nét viết thông thường mảnh hơn nhiều so với kích thước cọ danh nghĩa.

Vì vậy, chúng tôi chuẩn hóa quanh trung vị quan sát được, sau đó áp dụng số mũ và giới hạn kết quả:

Áp lực viết trung vị giờ đây ánh xạ tới đường kính danh nghĩa 12-point. Tiếp xúc rất nhẹ vẫn hiển thị ở 35% kích thước danh nghĩa, còn áp lực mạnh dừng tăng ở mức 120%.

Việc hiệu chỉnh này thuộc về thiết bị đầu vào và hành vi của cọ, chứ không thuộc về MaLiang. Sao chép công thức gốc mà không đo phân phối áp lực của chính mình sẽ giữ nguyên kiến trúc nhưng tạo ra một cây cọ sai.

Alpha của từng stamp bắt nguồn từ số lớp chồng lấn đã biết

MaLiang bù cho các stamp trong suốt chồng lên nhau bằng biểu thức thực nghiệm alpha ÷ overlapping × 2.5. Cọ của chúng tôi có đường kính danh nghĩa cố định 12-point và bước stamp 1-point, nên đường trung tâm nhận khoảng 12 lớp. Trong trường hợp của chúng tôi, số lớp chồng lấn đã biết, vì vậy có thể giải phép bù thay vì ước lượng.

Với độ mờ nét mục tiêu lớp source-over bằng nhau, một stamp có độ mờ sẽ tạo ra

vì vậy một stamp cần

Với , mỗi stamp dùng độ mờ khoảng . Phần trung tâm đạt màu mong muốn sau nhiều lần hợp thành, trong khi mép nhận ít stamp hơn và giữ lại một vùng chuyển tiếp mềm rộng một hoặc hai point.

Một tờ giấy với nhiều nét bút đánh dấu màu xanh đa dạng được dựng bằng mô hình stamp mềm cuối cùng, gồm các vòng, móc, nét ngắn và các vùng giao nhau với chính nó.

Bộ dựng cuối cùng phát lại các đường đi từ thiết bị đã ghi. Không còn móc, đường cắt chéo hay vùng trắng hình lưỡi liềm.

Hai cái giá chúng tôi chấp nhận

Các vùng giao nhau với chính nó trở nên đậm hơn. Phép hợp thành source-over tính mọi stamp, bao gồm cả các stamp được đặt trong lượt đi trước qua cùng một vùng, còn bộ máy hợp nhất độ phủ đã tránh được điều đó. Chúng tôi chấp nhận phần giao nhau đậm hơn vì nó có thể dự đoán và giữ nguyên hình dạng nét.

Hai đầu thu hẹp theo áp lực. Việc nhấc bút thật sự làm giảm áp lực, từ đó làm giảm đường kính stamp, nên nét thu nhỏ dần thay vì kết thúc bằng một đầu vuông đủ bề rộng. Chúng tôi đã coi đầu vuông đó là yêu cầu trong cả ba bộ máy hình học. Bỏ yêu cầu này giúp loại bỏ các phép cắt và bộ máy xử lý đầu cuối đứng sau một số lỗi ở trên, vì vậy chúng tôi chấp nhận đầu nét thu nhỏ dần.

Do đó, mô hình chúng tôi phát hành thực hiện ít hơn các mô hình trước. Nó giữ nguyên sự kiện viết đã đo được, phản hồi theo áp lực sau khi hiệu chỉnh thiết bị và dựng các đường đi cong cũng như tự giao nhau mà không cần một đường bao hợp lệ trên toàn cục. Đầu bút dạng đục, đầu nét vuông hoàn hảo và đường đa tuyến chính xác giữa các mẫu thô là những tính năng chúng tôi đã từ bỏ để đổi lấy điều đó.

Trong những gì cuộc điều tra cho thấy, ngưỡng áp lực là điều có thể chuyển giao trực tiếp nhất cho các dự án khác. Giá trị 0.005 xuất phát từ khoảng cách giữa hai cụm trong dữ liệu đầu vào thực tế: khi viết là 0.01 trở lên, còn theo dõi trên không là 0.002 trở xuống. Sau đó, chính những nét đã ghi lại cho thấy từng lần sửa hình học thất bại ở đâu; những thất bại đó đã dẫn đến việc thay đổi mô hình và xác định hai cái giá chúng tôi giữ lại.