Lulucat

Miért cseréltük le a három kiemelő-geometriamotort stamp-lenyomatokra

Gaoge ZhangGaoge Zhang

Valódi Apple Pencil-adatok olyan hibákat tártak fel, amelyeket a szintetikus tesztek nem láttak, ezért a Lulucat Notes három körvonalmotorról MaLiang stamp-modellre váltott.

Frissítve

A Lulucat Notes hagyományos kiemelő-renderelővel indult: geometriai körvonalat épített a mintavételezett útvonal köré, majd ezt a körvonalat egyszer töltötte ki áttetsző színnel. Az egyszeri kitöltés elkerüli azokat a sötétebb sávokat, amelyek az áttetsző szakaszok átfedésekor jelennek meg. Ugyanakkor minden illesztést, önmetszést, végzárást és rövid vonást ugyanebbe a geometriai problémába helyez.

Mindhárom egyedi geometriageneráció egy-egy hibakategóriát szüntetett meg, és egy másikat tárt fel. A most szállított renderelő lágy, kör alakú stamp-lenyomatokat használ a MaLiang alapján, amely egy MIT-licencű, Harley-xk által készített nyílt forráskódú rajzolási keretrendszer. Egy teljes körvonalhibakategória eltávolításáért cserébe elfogadtuk a sötétebb önmetszéseket és a nyomással elkeskenyedő végeket.

Kék kiemelővel írt kézírás iPaden rögzítve; több vonás elején és végén vékony kampók láthatók.

Az eredeti eszköz-képernyőkép 228%-os nagyításban. Több vonás mindkét végén kis kampók jelennek meg.

A valódi kézírás kampókat hozott létre, a szintetikus jelenetek nem

Szintetikus jeleneteink lefedték az egyenes vonalakat, íveket, rövid érintéseket, visszakövetéseket, nyomásváltozásokat és éles kanyarokat, és mindegyik tisztán renderelődött. A valódi kínai kézírás ennek ellenére sok vonás elején és végén körülbelül 1–3 pontos kampókat hozott létre.

Ezért hozzáadtunk az alkalmazáshoz egy Mentés gombot, és 29 teljes vonást rögzítettünk. Minden minta megőrizte a pozícióját, sugarát, nyomását, azimutját, magassági szögét, időbélyegét és UIKit-becslési jelzőit. Egy offline program dekódolta a JSON-t, és lefordította ugyanazokat a Stroke.swift, StrokeRenderer.swift és HighlighterStrokeBuilder.swift fájlokat, amelyeket az alkalmazás használ. A kimenete vonásról vonásra megegyezett az eszköz képernyőképével, a kampókat is beleértve.

Mivel az offline renderelő önmagában a rögzített bemenetből reprodukálta a hibát, annak oka a mintákban és a geometriában, nem pedig a megjelenítés viselkedésében volt. Most már kiolvashattuk a renderelőbe ténylegesen bekerült pontos mintákat.

Első hipotézisünk a Pencil érintkezésekor és felemelésekor becsült tájolást tette felelőssé. Az adatok ezt elutasították. Mind a 29 vonásban az azimut legfeljebb 0.09 radiánnal, a magassági szög pedig legfeljebb 0.02 radiánnal változott az első és az utolsó nyolc minta során, és azon az iPaden minden becslési jelző false volt. A tájolás stabil maradt, miközben a nyomás és az irány élesen változott.

A nyomási küszöb egy tiszta adatrésből következett

Minden rögzített vonás utolsó mintájának nyomása 0.000 volt. Az írás közben rögzített minták értéke 0.01 vagy nagyobb volt, míg a Pencil felszínről való felemelése után rögzített mintáké 0.002 vagy kisebb. Ezek a levegőben lévő minták gyakran további 2–7 pontig folytatódtak, és 0.8–9.0 pontot tettek meg; irányuk pedig nagyjából 90 fokkal is elfordulhatott az írt vonástól.

A 2. vonás mutatja a mechanizmust. A teste 143 és 180 fok között ért véget. Az alacsony nyomású farok ezután −90 és −67 fok közé fordult, és még 8.5 pontot tett meg. A körvonal-renderelő a végső, levegőben lévő pontot tekintette mérvadó végpontnak, ezért egy keskeny geometriai darabot nyújtott ki e pont felé.

A mért nyomásértékek az írás és a levegőben végzett mozgás között csaknem egy nagyságrendnyi különbséget mutatnak, ezért a küszöböt ebbe a résbe tettük:

private static let pressureFloor: CGFloat = 0.005

Csak a két végén lévő alacsony nyomású mintákat távolítjuk el. Egy vonás közepén található alacsony nyomású minta továbbra is a vonás része marad. A szabály a mért eseményhatárt követi, és érintetlenül hagyja az írott útvonalat.

Műszerezett közeli kép vágás előtt: a zöld bemeneti minták elfordulnak a vonástól, miközben a piros körvonal keskeny kampót formál.

A vágás előtt a renderelő a végzárást a levegőben lévő mintákhoz rögzíti. A zöld pontok a nyers minták; a piros vonal a generált körvonal.

Műszerezett közeli kép vágás után: a kék kitöltés az utolsó írott mintáknál ér véget, az alacsony nyomású zöld pontok pedig kívül maradnak rajta.

A 0.005 alatti minták levágása után a végzárás az utolsó írott pontnál ér véget. Ez a nyomási küszöb a jelenlegi stamp-renderelőben is megmaradt.

A küszöb eltávolította a hosszú, levegőben rajzolt kampókat. A 0.005 fölött maradó rövid érintkezési húzások és felemelési ívek túlélték a vágást, mert írott mozgásról van szó. Ezeknek a mozgásoknak a körvonalmodellben való kezelése vezetett a geometria következő köreihez.

Három geometriamotor csak áthelyezte a hibákat

Első generáció: egy körvonal, egy kitöltés

Az első nyomásérzékeny motor egy ismerős folyamatot követett. Egy gerincvonalat simított, kiszámította a bal és jobb oldali eltolásokat, egyetlen sokszöggé kapcsolta őket, majd egyszer töltötte ki ezt a sokszöget. A tollhegy az Apple Pencil azimutja és magassági szöge által vezérelt ellipszis volt, ezért a keresztmetszete az írásirány szerint változott. A rövid érintésekhez külön alak tartozott, a lapos végzárások pedig kis aszimmetriákat használtak a nulla körüljárású üregek elkerülésére.

Az egyszeri kitöltés megoldotta az opacitás felhalmozódását egy vonáson belül, és minden fordulónál érvényes sokszöget igényelt. Az érintkezéskori húzások ékeket hoztak létre a végzárás és a test között. A visszakövetések fehér holdsarló alakú üregeket hozhattak létre. Az éles fordulókban a belső körvonal önmetszhetett, és kitöltetlen bevágást hagyhatott.

Második generáció: a körvonal javítása a végeknél

A második motor megtartotta a körvonalat, és helyi javításokat adott hozzá: visszakövetés-vágást, a korai becsült tulajdonságok csillapítását, végpont-kiegyenesítést, az átmeneti irány vágását és egy kis végzárás-hosszabbítást. Minden javítás egy reprodukált hibát kezelt. Együtt a végpontviselkedést több küszöbtől és ablaktól tették függővé.

A valódi írás ezután olyan eseteket produkált, amelyek kívül estek ezeken az ablakokon. A rögzített 24 pontos kiegyenesítési ablak kitörölte a rövid vonások szándékos kampóit. Az adaptív ablak megőrizte ezeket a kampókat, a felemelési ívek pedig továbbra is látható sarkokká válhattak. Az irányérzékeny vágás több átmeneti mozgást távolított el, cserébe az egyik rögzített vonás valóban görbült kezdetéből körülbelül 2.5 pontot eldobott.

Mindegyik javítás a saját célzott esetét oldotta meg. Az alattuk lévő modellnek továbbra is kemény körvonalra volt szüksége, amely zajos, görbült bemenet mellett is érvényes marad.

Harmadik generáció: fedettségi unió levágott négyzetes végzárásokkal

A harmadik motor felhagyott egyetlen kontúr felépítésével. Minden szakaszhoz trapézt, minden belső mintához pedig korongot rajzolt egy szürkeárnyalatos maszkba, egyesítette a fedettségüket, majd egyszer alkalmazta a kiemelő színét. A visszakövetésből adódó holdsarlók, az önmetszés sötétedése és a nulla körüljárású lyukak eltűntek, mert a renderelő többé nem függött a sokszög körüljárásától.

Az unió lekerekítette a végeket, ezért a fedettséget két végponti félsíkhoz igazítva visszaállítottuk a négyzetes végzárásokat. Ez a vágás kijavította az állandó nyomású egyenes vonalakat, és egy komolyabb hibát vezetett be: egy görbült vonás teste jogszerűen keresztezheti a végponti félsíkot, a végzárás vágása pedig eltávolíthatja a vonás közepének egy részét. Élő bevitel közben a végpont iránya folyamatosan változott, ezért a levágott terület mozgott, és a vonás villódzott.

Ívelt kék vonás a végzárás-vágás javítása előtt: felső teste egy átlós vonal mentén le van vágva; a zöld pontok a teljes mintavételezett útvonalat mutatják.

A globális végzárási korlát átvág a görbült vonás testén.

Ugyanaz az ívelt kék vonás egy helyi ívhossz-kapu hozzáadása után; mindkét ág visszaáll a zöld mintavételezett útvonal körül.

A végzárás vágásának a végponttól számított egy fél szélességen belüli primitívekre korlátozása helyreállítja ezt a vonást.

Az ívhossz-kapu helyivé tette a végzárás vágását, és minden rögzített esetet kijavított. Egy szélsőséges szintetikus kampó még mindig egy kis fehér bevágást mutatott ott, ahol az alacsony nyomású csúcs találkozott a levágott végzárással. A harmadik motor ismét egy geometriai hibát váltott egy másikra.

MaLiang eltávolítja a kemény határt

A MaLiang ismételt textúra-stamp-lenyomatokból épít fel egy vonást, nem pedig egyetlen zárt körvonalból. Az útvonal-generátora kvadratikus Bézier-szakaszokat használ, amelyek átmennek a szomszédos minták felezőpontjain, a vonalrenderelője pedig szabályos lépésközzel helyez el lenyomatokat az útvonalon. A lenyomat mérete, forgatása, színe és opacitása egyaránt változhat a vonás mentén.

Egy lágy stamp-lenyomatnak nincs külön végzárása, illesztése vagy körüljárási szabálya. Az éles irányváltozás átfedő jelek sorozataként marad meg. A visszakövetések nem hozhatnak létre üres sokszögüreget, és a végponti félsík sem vághatja át a vonás közepét, mert a modellben nincs végponti vágás.

A modellt vettük át, nem a kódot. A jelenlegi HighlighterStrokeBuilder négy műveletet hajt végre:

  1. Csak azokat a végponti mintákat távolítja el, amelyek nyomása 0.005 alatt van.
  2. A pozíciókat felezőpontos kvadratikus Bézier-szakaszokkal simítja.
  3. Az ívhossz minden pontjára egy kör alakú stamp-lenyomatot helyez el.
  4. A lenyomat átmérőjét normalizált nyomásból állítja be, és a lenyomatokat source-over alfával kompozitálja.

Az építő 686 sorról 190-re rövidült. Az azimut, a magassági szög, a körvonal felépítése, az uniómaszkok, a végpontirány-ablakok, a végzárás-hosszabbítás és a végzárás vágása mind kikerült a kiemelő útvonalából. A Pencil tájolását továbbra is rögzítjük, mert a bemeneti modell támogatja, de maga a kiemelő már nem olvassa ezeket a mezőket.

MaLiang nyomásformulája eszközkalibrációt igényelt

A MaLiang a stamp méretét egy ezzel ekvivalens formulával számítja:

Ez a formula azt feltételezi, hogy a force a 0 és 1 közötti tartomány hasznos részét használja. A mi eszközünk adatai nem ezt mutatták. Körülbelül 3,400 Apple Pencil-minta alapján a nyomás mediánja 0.047, a maximuma pedig 0.178 volt. Ha ezeket az értékeket közvetlenül adtuk a formulának, a normál írás sokkal vékonyabb lett a névleges ecsetméretnél.

Ezért a megfigyelt medián körül normalizálunk, majd alkalmazzuk a kitevőt és korlátozzuk az eredményt:

A medián írási nyomás most a névleges 12 pontos átmérőre képeződik le. A nagyon könnyű érintés a névleges méret 35%-án látható marad, míg az erős nyomás 120%-nál megáll.

Ez a kalibráció a bemeneti eszközhöz és az ecset viselkedéséhez tartozik, nem a MaLianghoz. Ha a saját nyomáseloszlásunk mérése nélkül másoltuk volna le az eredeti formulát, megőriztük volna az architektúrát, de rossz ecsetet kaptunk volna.

Az egyes stamp-ek alfája az ismert átfedésszámból következett

A MaLiang az egymást átfedő áttetsző stamp-eket az empirikus alpha ÷ overlapping × 2.5 kifejezéssel kompenzálja. A mi ecsetünknek fix 12 pontos névleges átmérője és 1 pontos stamp-lépésköze van, ezért a középvonala körülbelül 12 réteget kap. Esetünkben az átfedésszám ismert, így a kompenzáció becslés helyett kiszámítható.

Egy célopacitású, azonos source-over rétegből álló vonás esetén egy opacitású stamp ezt eredményezi:

tehát egyetlen stamphez ez szükséges:

és mellett minden stamp körülbelül opacitással dolgozik. A középvonal az ismételt kompozitálás után eléri a kívánt színt, a szélekre pedig kevesebb stamp jut, így megmarad az egy- vagy kétpontos, lágy átmenet.

A végső lágy-stamp-modellel renderelt, változatos kék kiemelővonásokból álló lap, hurkokkal, kampókkal, rövid jelekkel és önmetszésekkel.

A végső renderelő újrajátssza a rögzített eszközútvonalakat. Kampók, átlós vágások és fehér üregek nem jelennek meg.

A két költség, amelyet elfogadtunk

Az önmetszések sötétebbé válnak. A source-over kompozitálás minden stamp-et számításba vesz, beleértve azokat is, amelyeket ugyanazon területen egy korábbi áthaladás rakott le, miközben a fedettségi uniót használó motor ezt elkerülte. Elfogadtuk a sötétebb átfedést, mert kiszámítható, és érintetlenül hagyja a vonás alakját.

A végpontok a nyomással együtt elkeskenyednek. A valódi felemelés csökkenti a nyomást, ami csökkenti a stamp átmérőjét, így a vonás elkeskenyedik ahelyett, hogy teljes szélességű, négyzetes végzárással érne véget. Mindhárom geometriamotorban követelményként kezeltük ezt a négyzetes végzárást. Az elhagyása megszüntette a fenti hibák egy része mögött álló vágást és végponti gépezetet, ezért elfogadtuk az elkeskenyedő véget.

A most szállított modell ezért kevesebbet tesz, mint elődei. Megőrzi a mért írási eseményt, eszközkalibráció után reagál a nyomásra, és görbült, önmagukat keresztező útvonalakat renderel anélkül, hogy globálisan érvényes körvonalra lenne szüksége. A véső alakú tollhegy, a tökéletesen négyzetes végzárás és a nyers minták közötti pontos polivonal azok a jellemzők, amelyeket ezért feladtunk.

A vizsgálat eredményei közül a nyomási küszöb vihető át legközvetlenebbül más projektekbe. A 0.005 érték a valódi bemenet két klasztere közötti résből származott: az írás 0.01-en és fölötte, a levegőben végzett követés pedig 0.002-n és alatta történt. Ugyanezek a rögzített vonások mutatták meg azt is, hol vallottak kudarcot az egyes geometriai javítások. Ezek a kudarcok vezettek a stamp-modellhez és az ezzel járó két költséghez.