Lulucat

Zašto smo tri geometrijska motora markera zamijenili pečatima

Gaoge ZhangGaoge Zhang

Stvarni podaci s Apple Pencila otkrili su nedostatke koje su sintetički testovi propustili i odveli Lulucat Notes od triju motora konture do modela pečata MaLiang.

Ažurirano

Lulucat Notes započeo je konvencionalnim rendererom markera: izgraditi geometrijsku konturu oko uzorkovane putanje, a zatim tu konturu jednom ispuniti prozirnom bojom. Jedno ispunjavanje izbjegava tamnije trake koje se pojavljuju ondje gdje se prozirni segmenti preklapaju. Ono također smješta svaki spoj, samopresjek, završetak i kratki potez u isti geometrijski problem.

Tri generacije prilagođene geometrije uklonile su po jednu vrstu nedostatka i otkrile drugu. Renderer koji sada isporučujemo koristi meke kružne pečate temeljene na MaLiang, okviru za crtanje otvorenog koda s licencom MIT autora Harley-xk. Zauzvrat za uklanjanje cijele kategorije kvarova konture prihvatili smo tamnije samopresjeke i završetke sužene pritiskom.

Plavi rukopis markerom zabilježen na iPadu, s tankim kukicama vidljivima na počecima i krajevima nekoliko poteza.

Izvorna snimka zaslona uređaja pri povećanju od 228%. Male kukice pojavljuju se na oba kraja nekoliko poteza.

Stvarni je rukopis stvarao kukice koje sintetičke scene nisu

Naše su sintetičke scene obuhvaćale ravne crte, lukove, kratke dodire, povratne poteze, promjene pritiska i oštre zaokrete, a sve se renderiralo bez greške. Stvarni je kineski rukopis ipak na početku i kraju mnogih poteza proizvodio kukice duge oko 1–3 točke.

Zato smo u aplikaciju dodali gumb za spremanje i snimili 29 potpunih poteza. Svaki je uzorak zadržao svoj položaj, radijus, pritisak, azimut, elevaciju, vremensku oznaku i zastavice procjene UIKit. Izvanmrežni je program dekodirao taj JSON i kompajlirao iste datoteke Stroke.swift, StrokeRenderer.swift i HighlighterStrokeBuilder.swift koje aplikacija koristi. Njegov se izlaz podudarao sa snimkom zaslona uređaja potez po potez, uključujući kukice.

Budući da je izvanmrežni renderer reproducirao nedostatak samo iz snimljenog unosa, uzrok je bio u uzorcima i geometriji, a ne u ponašanju prikaza. Sada smo mogli pročitati točne uzorke koji su ušli u renderer.

Naša je prva hipoteza za to okrivila procijenjenu orijentaciju Pencila pri dodiru površine i odizanju. Podaci su je odbacili. U svih 29 poteza azimut se promijenio za najviše 0.09 radijana, a elevacija za najviše 0.02 radijana unutar prvih i posljednjih osam uzoraka, a svaka je zastavica procjene na tom iPadu bila false. Orijentacija je ostala stabilna dok su se pritisak i smjer naglo mijenjali.

Donji prag pritiska proizašao je iz čistog razmaka u podacima

Posljednji je uzorak svakog snimljenog poteza imao pritisak 0.000. Uzorci tijekom pisanja bili su na 0.01 ili iznad toga, dok su uzorci zabilježeni nakon što se Pencil odvojio od površine bili na 0.002 ili ispod toga. Ti su se uzorci u zraku često nastavljali još 2–7 točaka i prelazili 0.8–9.0 točaka, a njihov se smjer mogao okrenuti približno 90 stupnjeva od poteza pisanja.

Potez 2 pokazuje mehanizam. Tijelo mu je završavalo između 143 i 180 stupnjeva. Rep s niskim pritiskom zatim se okrenuo od −90 do −67 stupnjeva i prešao još 8.5 točaka. Renderer konture tretirao je posljednju točku u zraku kao mjerodavnu krajnju točku, pa je rastegnuo uzak komad geometrije prema toj točki.

Između izmjerenih vrijednosti pritiska pri pisanju i kretanju u zraku postoji razlika od gotovo jednog reda veličine, pa smo rez postavili unutar tog razmaka:

private static let pressureFloor: CGFloat = 0.005

Uklanjaju se samo uzorci niskog pritiska na dva kraja. Uzorak niskog pritiska u sredini poteza ostaje njegovim dijelom. Pravilo prati izmjerenu granicu događaja i ostavlja putanju pisanja neizmijenjenom.

Instrumentirani krupni plan prije obrezivanja: zeleni ulazni uzorci skreću od poteza dok crvena kontura tvori usku kukicu.

Prije obrezivanja renderer sidri završetak na uzorke u zraku. Zelene točke su sirovi uzorci; crvena crta je generirana kontura.

Instrumentirani krupni plan nakon obrezivanja: plava se ispuna završava na posljednjim uzorcima pisanja, a zeleni uzorci niskog pritiska ostaju izvan nje.

Nakon obrezivanja uzoraka ispod 0.005, završetak je na posljednjoj točki pisanja. Ovaj prag pritiska ostaje u trenutačnom rendereru pečata.

Prag je uklonio duge kukice u zraku. Kratka povlačenja pri dodiru i lukovi pri odizanju čiji je pritisak ostao iznad 0.005 ostali su jer su to pokreti pisanja. Obrada tih pokreta unutar modela konture dovela je do sljedećih iteracija geometrije.

Tri su geometrijska motora samo premještala nedostatke

Prva generacija: jedna kontura, jedno ispunjavanje

Prvi motor osjetljiv na pritisak slijedio je poznati cjevovod. Zaglađivao je središnju liniju, izračunavao lijeve i desne pomake, spajao ih u jedan poligon i jednom ispunjavao taj poligon. Vrh pisala bio je elipsa kojom su upravljali azimut i elevacija Apple Pencila, pa se njegov presjek mijenjao ovisno o smjeru pisanja. Kratki dodiri imali su zaseban oblik, a ravni završeci koristili su male asimetrije kako bi izbjegli džepiće nultog namotaja.

Jedno je ispunjavanje riješilo nakupljanje neprozirnosti unutar poteza, ali je zahtijevalo valjan poligon pri svakom zaokretu. Dodiri pri spuštanju stvorili su klinove između završetka i tijela. Povratni potezi mogli su stvoriti bijele džepove u obliku srpa. Oštri su zaokreti mogli učiniti da se unutarnja kontura samopresiječe i ostaviti neispunjeni urez.

Druga generacija: popravak konture blizu krajeva

Drugi je motor zadržao konturu i dodao lokalne popravke: obrezivanje povratnih poteza, prigušivanje ranih procijenjenih svojstava, izravnavanje krajnjih točaka, obrezivanje prolaznog smjera i malo produljenje završetka. Svaka se zakrpa bavila reproduciranim kvarom. Zajedno su učinile da ponašanje krajnjih točaka ovisi o nekoliko pragova i prozora.

Stvarno je pisanje potom proizvelo slučajeve izvan tih prozora. Fiksni prozor za izravnavanje od 24 točke brisao je namjerne kukice u kratkim potezima. Prilagodljivi je prozor sačuvao te kukice, a lukovi pri odizanju i dalje su mogli postati vidljivi kutovi. Obrezivanje koje uzima u obzir smjer uklonilo je više prolaznog kretanja, ali uz cijenu odbacivanja oko 2.5 točke doista zakrivljenog početka u jednom snimljenom potezu.

Svaka je zakrpa popravila svoj ciljani slučaj. Model ispod njih i dalje je zahtijevao čvrstu konturu koja ostaje valjana pri šumnom, zakrivljenom unosu.

Treća generacija: unija pokrivenosti s odrezanim kvadratnim završecima

Treći je motor prestao konstruirati jednu konturu. Crtao je trapez za svaki segment i disk na svakom unutarnjem uzorku u masku sivih tonova, uzeo njihovu uniju pokrivenosti, a zatim jednom primijenio boju markera. Povratni srpovi, potamnjenje samopresjeka i rupe zbog nultog namotaja nestali su jer renderer više nije ovisio o namotaju poligona.

Unija je zaoblila krajeve, pa smo vratili kvadratne završetke obrezivanjem pokrivenosti prema dvjema poluravninama krajnjih točaka. Taj je rez popravio ravne crte s konstantnim pritiskom i uveo ozbiljniji nedostatak: tijelo zakrivljenog poteza može legitimno prijeći preko poluravnine krajnje točke, a rez završetka tada ukloni dio sredine poteza. Tijekom unosa uživo smjer krajnje točke stalno se mijenjao, pa se odrezano područje pomicalo i potez je treperio.

Zakrivljeni plavi potez prije popravka reza završetka, s gornjim tijelom odrezanim duž dijagonalne crte; zelene točke pokazuju cijelu uzorkovanu putanju.

Globalno ograničenje završetka presijeca tijelo zakrivljenog poteza.

Isti zakrivljeni plavi potez nakon dodavanja lokalnog praga duljine luka, s obje grane vraćene oko zelene uzorkovane putanje.

Ograničavanje rezanja završetka na primitivne elemente unutar jedne polu-širine od krajnje točke vraća ovaj potez.

Prag duljine luka učinio je rez završetka lokalnim i popravio svaki zabilježeni slučaj. Ekstremna sintetička kukica i dalje je pokazala mali bijeli urez ondje gdje se vrh s niskim pritiskom susreo s odrezanim završetkom. Treći je motor ponovno zamijenio jedan geometrijski kvar drugim.

MaLiang uklanja tvrdu granicu

MaLiang gradi potez od ponovljenih teksturnih pečata, a ne od jedne zatvorene konture. Njegov generator putanje koristi kvadratne Bézierove segmente koji prolaze kroz sredine susjednih uzoraka, a renderer crte postavlja pečate u pravilnom koraku duž te putanje. Veličina, rotacija, boja i neprozirnost pečata mogu se mijenjati duž poteza.

Meki pečat nema zaseban završetak, spoj ni pravilo namotaja. Oštra promjena smjera ostaje niz preklapajućih otisaka. Povratni potezi ne mogu stvoriti prazan džep poligona, a poluravnina krajnje točke ne može odrezati sredinu poteza jer model ne sadrži rez krajnje točke.

Preuzeli smo model, a ne kod. Trenutačni HighlighterStrokeBuilder obavlja četiri operacije:

  1. Ukloniti samo krajnje uzorke čiji je pritisak ispod 0.005.
  2. Zagladiti položaje pomoću srednjih kvadratnih Bézierovih segmenata.
  3. Postaviti jedan kružni pečat po točki duljine luka.
  4. Postaviti promjer pečata prema normaliziranom pritisku i kompozitirati pečate alfa-kompozicijom source-over.

Builder se smanjio s 686 redaka na 190. Azimut, elevacija, izgradnja konture, maske unije, prozori smjera krajnjih točaka, produljenje završetka i rezanje završetka nestali su iz putanje markera. Orijentaciju Pencila i dalje bilježimo jer je model unosa podržava, ali sam marker više ne čita ta polja.

MaLiangova formula pritiska zahtijevala je kalibraciju uređaja

MaLiang određuje veličinu pečata formulom ekvivalentnom

koja pretpostavlja da force koristi koristan dio raspona od 0 do 1. Podaci s našeg uređaja nisu to potvrđivali. Među oko 3,400 uzoraka Apple Pencila, medijan pritiska bio je 0.047, a maksimum 0.178. Izravno ubacivanje tih vrijednosti u formulu učinilo je normalno pisanje mnogo tanjim od nominalne veličine kista.

Stoga normaliziramo oko uočenog medijana, zatim primjenjujemo eksponent i ograničavamo rezultat:

Medijan pritiska pri pisanju sada se preslikava na nominalni promjer od 12 točaka. Vrlo lagan dodir ostaje vidljiv na 35% nominalne veličine, dok se pri jakom pritisku rast zaustavlja na 120%.

Ova kalibracija pripada ulaznom uređaju i ponašanju kista, a ne MaLiangu. Kopiranje izvorne formule bez mjerenja vlastite raspodjele pritiska sačuvalo bi arhitekturu, ali proizvelo pogrešan kist.

Alfa po pečatu proizašla je iz poznatog broja preklapanja

MaLiang kompenzira preklapanje prozirnih pečata empirijskim izrazom alpha ÷ overlapping × 2.5. Naš kist ima fiksni nominalni promjer od 12 točaka i korak pečata od 1 točke, pa središnja linija prima oko 12 slojeva. U našem je slučaju broj preklapanja poznat, pa se kompenzacija može izračunati umjesto procijeniti.

Za ciljanu neprozirnost poteza i jednakih source-over slojeva, neprozirnost pečata daje

pa jedan pečat zahtijeva

Sa i , svaki pečat koristi neprozirnost od približno . Središte nakon ponovljene kompozicije doseže predviđenu boju, dok rub prima manje pečata i zadržava prijelaz omekšan na jednu ili dvije točke.

List raznolikih plavih poteza markera iscrtan konačnim modelom mekih pečata, uključujući petlje, kukice, kratke oznake i samopresjeke.

Konačni renderer ponovno iscrtava zabilježene putanje s uređaja. Kukice, dijagonalni rezovi i bijeli džepovi ne pojavljuju se.

Dva troška koja smo prihvatili

Samopresjeci postaju tamniji. Kompozicija source-over broji svaki pečat, uključujući pečate nanesene ranijim prolaskom kroz isto područje, a motor unije pokrivenosti to je izbjegavao. Prihvatili smo tamnije preklapanje jer je predvidljivo i ostavlja oblik poteza netaknutim.

Krajevi se sužavaju s pritiskom. Stvarno odizanje smanjuje pritisak, a time i promjer pečata, pa se potez sužava umjesto da završava kvadratnim završetkom pune širine. Taj smo kvadratni završetak kroz sva tri geometrijska motora smatrali zahtjevom. Njegovo uklanjanje uklonilo je rezanje i mehanizme krajnjih točaka koji su stajali iza nekoliko ranijih kvarova, pa smo prihvatili suženi kraj.

Model koji isporučujemo stoga radi manje od prethodnih. Čuva izmjereni događaj pisanja, reagira na pritisak nakon kalibracije uređaja i iscrtava zakrivljene putanje i putanje koje se same križaju bez potrebe za globalno valjanom konturom. Vrh u obliku dlijeta, savršeno kvadratni završetak i točna polilinija između sirovih uzoraka značajke su kojih smo se zbog toga odrekli.

Od svih rezultata ove analize, prag pritiska najizravnije se prenosi na druge projekte. Vrijednost 0.005 proizašla je iz razmaka između dvaju klastera u stvarnom unosu: pisanje na 0.01 i iznad, praćenje u zraku na 0.002 i ispod. Isti su snimljeni potezi zatim pokazali gdje je svaki popravak geometrije zakazao. Ti su neuspjesi doveli do modela pečata i dvaju troškova koje nosi.