અમે ત્રણ હાઇલાઇટર જ્યોમેટ્રી એન્જિનને સ્ટેમ્પ્સથી કેમ બદલ્યાં
વાસ્તવિક Apple Pencil ડેટાએ કૃત્રિમ પરીક્ષણોથી છૂટી ગયેલી ખામીઓ ઉજાગર કરી અને Lulucat Notesને ત્રણ આઉટલાઇન એન્જિનમાંથી MaLiang સ્ટેમ્પ મોડેલ સુધી પહોંચાડ્યું.
Lulucat Notesની શરૂઆત પરંપરાગત હાઇલાઇટર રેન્ડરરથી થઈ: સેમ્પલ કરેલા પાથની આસપાસ ભૌમિતિક આઉટલાઇન બનાવવી અને પછી તે આઉટલાઇનને અર્ધપારદર્શક રંગથી એક જ વાર ભરવી. એક જ ફિલ અર્ધપારદર્શક સેગમેન્ટ્સ એકબીજા પર ચડે ત્યારે દેખાતા ઘેરા પટ્ટાઓને ટાળે છે. તે દરેક જોડાણ, સેલ્ફ-ઇન્ટરસેક્શન, કૅપ અને ટૂંકા સ્ટ્રોકને પણ એક જ જ્યોમેટ્રી સમસ્યાની અંદર મૂકે છે.
કસ્ટમ જ્યોમેટ્રીની ત્રણ પેઢીઓએ દરેકે ખામીનો એક વર્ગ દૂર કર્યો અને ખામીનો બીજો વર્ગ બહાર લાવ્યો. હવે અમે જે રેન્ડરર મોકલીએ છીએ તે MaLiang પર આધારિત નરમ ગોળ સ્ટેમ્પ્સ વાપરે છે, જે Harley-xk દ્વારા બનાવાયેલું MIT-લાઇસન્સ ધરાવતું ઓપન-સોર્સ ડ્રોઇંગ ફ્રેમવર્ક છે. આઉટલાઇનની નિષ્ફળતાઓનો એક આખો વર્ગ દૂર કરવાના બદલામાં અમે ઘેરા સેલ્ફ-ઇન્ટરસેક્શન અને દબાણથી સાંકડા થતા છેડા સ્વીકાર્યા.

228% ઝૂમ પરનો મૂળ ડિવાઇસ સ્ક્રીનશૉટ. ઘણા સ્ટ્રોક્સના બંને છેડે નાના હૂક્સ દેખાય છે.
વાસ્તવિક હસ્તલેખનથી એવા હૂક્સ બન્યા જે કૃત્રિમ દૃશ્યોમાં બન્યા નહોતા
અમારા કૃત્રિમ દૃશ્યોમાં સીધી રેખાઓ, આર્ક્સ, ટૂંકા ટૅપ્સ, બૅકટ્રૅક્સ, દબાણમાં ફેરફાર અને તીક્ષ્ણ વળાંકો સામેલ હતા, અને તે બધું સ્વચ્છ રીતે રેન્ડર થયું. છતાં વાસ્તવિક ચીની હસ્તલેખનથી ઘણા સ્ટ્રોક્સની શરૂઆત અને અંતે લગભગ 1–3 પોઇન્ટ લાંબા હૂક્સ બનતા રહ્યા.
તેથી અમે ઍપમાં સેવ બટન ઉમેર્યું અને 29 સંપૂર્ણ સ્ટ્રોક્સ રેકોર્ડ કર્યા. દરેક સેમ્પલમાં તેનું સ્થાન, ત્રિજ્યા, દબાણ, અઝિમુથ, અલ્ટિટ્યુડ, ટાઇમસ્ટૅમ્પ અને UIKit estimation flags જળવાઈ રહ્યાં. એક ઑફલાઇન પ્રોગ્રામે તે JSON ડિકોડ કર્યું અને ઍપ વાપરે છે એ જ Stroke.swift, StrokeRenderer.swift અને HighlighterStrokeBuilder.swift ફાઇલો કમ્પાઇલ કરી. તેના આઉટપુટે હૂક્સ સહિત ડિવાઇસના સ્ક્રીનશૉટ સાથે સ્ટ્રોક-દર-સ્ટ્રોક બરાબર મેળ ખાધો.
ઑફલાઇન રેન્ડરરે માત્ર રેકોર્ડ કરેલા ઇનપુટમાંથી ખામી ફરી ઉત્પન્ન કરી હોવાથી તેનું કારણ ડિસ્પ્લેના વર્તનમાં નહીં, પણ સેમ્પલ્સ અને જ્યોમેટ્રીમાં હતું. હવે રેન્ડરમાં પ્રવેશેલા ચોક્કસ સેમ્પલ્સ અમે વાંચી શકતા હતા.
અમારી પહેલી ધારણાએ ટચડાઉન અને લિફ્ટ-ઑફ સમયે Pencilની અંદાજિત દિશાને દોષ આપ્યો. ડેટાએ આ ધારણા નકારી કાઢી. તમામ 29 સ્ટ્રોક્સમાં, પહેલા અને છેલ્લા આઠ સેમ્પલ્સની અંદર અઝિમુથમાં વધુમાં વધુ 0.09 રેડિયન અને અલ્ટિટ્યુડમાં વધુમાં વધુ 0.02 રેડિયનનો ફેરફાર થયો, અને તે iPad પર દરેક estimation flag false હતો. દબાણ અને દિશામાં તીવ્ર ફેરફાર થયા છતાં ઓરિએન્ટેશન સ્થિર રહ્યું.
ડેટામાં રહેલા સ્વચ્છ અંતરમાંથી દબાણની મર્યાદા મળી
રેકોર્ડ કરાયેલા દરેક સ્ટ્રોકના અંતિમ સેમ્પલનું દબાણ 0.000 હતું. લખાણના સેમ્પલ્સ 0.01 પર અથવા તેની ઉપર હતા, જ્યારે Pencil સપાટી છોડ્યા પછી રેકોર્ડ થયેલા સેમ્પલ્સ 0.002 પર અથવા તેની નીચે હતા. આ હવામાં રહેલા સેમ્પલ્સ ઘણી વાર 2–7 પોઇન્ટ સુધી ચાલુ રહ્યા અને 0.8–9.0 પોઇન્ટ સુધી આગળ વધ્યા; તેમની દિશા લખાયેલા સ્ટ્રોકથી લગભગ 90 ડિગ્રી જેટલી દૂર વળી શકતી હતી.
સ્ટ્રોક 2 આ રીત સમજાવે છે. તેનો મુખ્ય ભાગ 143 અને 180 ડિગ્રીની વચ્ચે પૂરો થયો. ત્યાર પછી ઓછી દબાણવાળી પૂંછડી −90 થી −67 ડિગ્રી તરફ વળી અને વધુ 8.5 પોઇન્ટ આગળ ગઈ. આઉટલાઇન રેન્ડરરે અંતિમ હવામાં રહેલા પોઇન્ટને અધિકૃત endpoint માન્યો, તેથી તેણે તે પોઇન્ટ તરફ જતી જ્યોમેટ્રીનો સાંકડો ભાગ ખેંચી દીધો.
માપેલા દબાણો લખાણ અને હવામાં થતી હિલચાલ વચ્ચે લગભગ એક ક્રમ જેટલું અંતર બતાવે છે, તેથી અમે cutoff એ અંતરની અંદર મૂક્યો:
private static let pressureFloor: CGFloat = 0.005
માત્ર બંને છેડાના ઓછા દબાણવાળા સેમ્પલ્સ દૂર થાય છે. સ્ટ્રોકની વચ્ચે આવેલો ઓછા દબાણવાળો સેમ્પલ તેનો ભાગ જ રહે છે. આ નિયમ માપેલી ઘટના-સીમાને અનુસરે છે અને લખાયેલા પાથમાં ફેરફાર કરતો નથી.

ટ્રિમિંગ પહેલાં રેન્ડરર કૅપને હવામાં રહેલા સેમ્પલ્સ સાથે એન્કર કરે છે. લીલા ટપકાં કાચા સેમ્પલ્સ છે; લાલ રેખા જનરેટ થયેલી આઉટલાઇન છે.

0.005 કરતાં ઓછા સેમ્પલ્સ ટ્રિમ કર્યા પછી કૅપ છેલ્લા લખાયેલા પોઇન્ટ પર પૂરી થાય છે. આ દબાણની મર્યાદા હાલના સ્ટેમ્પ રેન્ડરરમાં પણ જળવાઈ છે.
આ મર્યાદાએ લાંબા સમય સુધી ચાલતા હવામાં રહેલા હૂક્સ દૂર કર્યા. દબાણ 0.005 કરતાં ઉપર રહેલા ટૂંકા ટચડાઉન ડ્રૅગ્સ અને લિફ્ટ-ઑફ આર્ક્સ તેમાં ટકી રહ્યા, કારણ કે તે લખાયેલી હિલચાલ છે. આ હિલચાલને આઉટલાઇન મોડેલની અંદર સંભાળવાથી જ્યોમેટ્રીના આગળના તબક્કા આવ્યા.
ત્રણ જ્યોમેટ્રી એન્જિનોએ ખામીઓને એક જગ્યાએથી બીજી જગ્યાએ ખસેડી
પેઢી એક: એક આઉટલાઇન, એક ફિલ
પહેલા દબાણ-સંવેદનશીલ એન્જિને પરિચિત પાઇપલાઇન અનુસરી. તેણે એક સ્પાઇનને સ્મૂથ કરી, ડાબા અને જમણા ઑફસેટ્સ ગણ્યા, તેમને એક પોલિગનમાં જોડ્યા અને તે પોલિગનને એક જ વાર ભર્યો. નિબ Apple Pencilના અઝિમુથ અને અલ્ટિટ્યુડથી નિયંત્રિત થતું એલિપ્સ હતું, તેથી લખવાની દિશા સાથે તેનો ક્રોસ-સેક્શન બદલાતો. ટૂંકા ટૅપ્સ માટે અલગ આકાર હતો, અને ફ્લૅટ કૅપ્સમાં zero-winding pockets ટાળવા માટે નાની અસમાનતાઓ વપરાતી.
એક જ ફિલે સ્ટ્રોકની અંદર ઓપેસિટીના સંચયની સમસ્યા ઉકેલી, પરંતુ દરેક વળાંક પર માન્ય પોલિગનની જરૂરિયાત ઊભી કરી. ટચડાઉન ડ્રૅગ્સે કૅપ અને મુખ્ય ભાગ વચ્ચે વેજ બનાવ્યા. બૅકટ્રૅક્સથી સફેદ અર્ધચંદ્રાકાર ખિસ્સા બની શકતા. તીક્ષ્ણ વળાંકો અંદરની આઉટલાઇનને સેલ્ફ-ઇન્ટરસેક્ટ કરાવી શકતા અને ન ભરાયેલી ખાંચ છોડી શકતા.
પેઢી બે: છેડાની નજીકની આઉટલાઇનની મરામત
બીજા એન્જિને આઉટલાઇન જાળવી રાખીને સ્થાનિક મરામતો ઉમેરી: બૅકટ્રૅક ટ્રિમિંગ, શરૂઆતમાં અંદાજિત ગુણધર્મો માટે ડૅમ્પિંગ, endpoint સીધું કરવું, transient-direction ટ્રિમિંગ અને નાનું કૅપ એક્સટેન્શન. દરેક પૅચે ફરી ઉત્પન્ન થયેલી એક ખામી સંભાળી. સાથે મળીને તેમણે endpointનું વર્તન અનેક thresholds અને windows પર આધારિત બનાવી દીધું.
પછી વાસ્તવિક લખાણે આ windowsની બહારના કિસ્સા ઉત્પન્ન કર્યા. નિશ્ચિત 24-પોઇન્ટ straightening windowએ ટૂંકા સ્ટ્રોક્સમાં ઇરાદાપૂર્વક બનાવેલા હૂક્સ ભૂંસી નાખ્યા. adaptive windowએ એ હૂક્સ જાળવી રાખ્યા, છતાં લિફ્ટ-ઑફ આર્ક્સ દેખાતા ખૂણા બની શકતા. Direction-aware trimmingએ વધુ transient motion દૂર કરી, પરંતુ એક રેકોર્ડ કરેલા સ્ટ્રોકમાં ખરેખર વળાંકવાળી શરૂઆતના આશરે 2.5 પોઇન્ટ કાઢી નાખવાની કિંમત ચૂકવવી પડી.
દરેક પૅચે પોતાના લક્ષિત કિસ્સાને ઠીક કર્યો. તેમ છતાં તેમની નીચેનું મોડેલ ઘોંઘાટવાળા, વળાંકવાળા ઇનપુટ હેઠળ પણ માન્ય રહે તેવી કઠોર આઉટલાઇન પર આધારિત હતું.
પેઢી ત્રણ: ક્લિપ કરેલી ચોરસ કૅપ્સ સાથે coverage union
ત્રીજા એન્જિને એક જ contour બનાવવાનું બંધ કર્યું. તેણે દરેક સેગમેન્ટ માટે એક ટ્રેપેઝોઇડ અને દરેક આંતરિક સેમ્પલ પર એક ડિસ્ક ગ્રેસ્કેલ માસ્કમાં દોર્યાં, પછી તેમની coverage union લીધી અને અંતે હાઇલાઇટરનો રંગ એક જ વાર લાગુ કર્યો. બૅકટ્રૅક અર્ધચંદ્રાકારો, સેલ્ફ-ઇન્ટરસેક્શનથી થતી ઘેરાશ અને zero-winding holes અદૃશ્ય થઈ ગયાં, કારણ કે રેન્ડરર હવે પોલિગન winding પર આધારિત રહ્યો નહોતો.
આ યુનિયનથી છેડા ગોળ થઈ ગયા, તેથી અમે બે endpoint half-planes સામે coverage ક્લિપ કરીને ચોરસ કૅપ્સ પાછી લાવી. આ ક્લિપે સતત દબાણવાળી સીધી રેખાઓને ઠીક કરી, પરંતુ વધુ ગંભીર ખામી ઊભી કરી: વળાંકવાળા સ્ટ્રોકનો મુખ્ય ભાગ endpoint half-planeને કાયદેસર રીતે ઓળંગી શકે છે, અને પછી કૅપ ક્લિપ સ્ટ્રોકના મધ્યમાંથી એક ભાગ કાઢી નાખે છે. લાઇવ ઇનપુટ દરમિયાન endpointની દિશા બદલાતી રહેતી, તેથી ક્લિપ થયેલો વિસ્તાર ખસતો અને સ્ટ્રોક ઝબકતો.

વૈશ્વિક કૅપ constraint વળાંકવાળા સ્ટ્રોકના મુખ્ય ભાગમાંથી પસાર થાય છે.

કૅપ ક્લિપિંગને endpointથી એક half-widthની અંદરના primitives સુધી મર્યાદિત કરવાથી આ સ્ટ્રોક પાછો ઠીક થાય છે.
આર્ક-લંબાઈના ગેટે કૅપ ક્લિપિંગને સ્થાનિક બનાવ્યું અને દરેક રેકોર્ડ કરેલો કિસ્સો ઠીક કર્યો. એક અતિશય કૃત્રિમ હૂકે હજી પણ નાનો સફેદ notch બતાવ્યો, જ્યાં ઓછા દબાણવાળી ટોચ ક્લિપ કરેલી કૅપને મળતી હતી. ત્રીજા એન્જિને ફરી એક જ્યોમેટ્રી નિષ્ફળતાને બીજી સાથે બદલી હતી.
MaLiang કઠોર સીમા દૂર કરે છે
MaLiang એક બંધ આઉટલાઇનને બદલે વારંવાર મૂકાતા ટેક્સ્ચર સ્ટેમ્પ્સથી સ્ટ્રોક બનાવે છે. તેનું પાથ જનરેટર ક્વાડ્રેટિક Bézier સેગમેન્ટ્સ વાપરે છે, જે જોડાયેલા સેમ્પલ્સના મધ્યબિંદુઓમાંથી પસાર થાય છે, અને તેનું લાઇન રેન્ડરર આ પાથ પર નિયમિત અંતરે સ્ટેમ્પ્સ મૂકે છે. સ્ટ્રોક સાથે સ્ટેમ્પનું કદ, પરિભ્રમણ, રંગ અને ઓપેસિટી બધું બદલાઈ શકે છે.
નરમ સ્ટેમ્પમાં અલગ કૅપ, જોડાણ કે winding rule હોતો નથી. દિશામાં થતો તીક્ષ્ણ ફેરફાર ઓવરલેપ થતા નિશાનોની શ્રેણી તરીકે જ રહે છે. બૅકટ્રૅક્સ ખાલી પોલિગન ખિસ્સો બનાવી શકતા નથી, અને endpoint half-plane સ્ટ્રોકના મધ્યમાંથી કાપી શકતો નથી, કારણ કે આ મોડેલમાં endpoint clip જ નથી.
અમે કોડ નહીં, પરંતુ મોડેલ અપનાવ્યો. હાલનું HighlighterStrokeBuilder ચાર કામગીરી કરે છે:
- માત્ર એવા endpoint samples દૂર કરવા જેમનું દબાણ
0.005કરતાં ઓછું હોય. - midpoint quadratic Bézier સેગમેન્ટ્સથી સ્થાનોને સ્મૂથ કરવા.
- આર્ક-લંબાઈના દરેક પોઇન્ટ માટે એક ગોળ સ્ટેમ્પ મૂકવો.
- normalized pressure પરથી સ્ટેમ્પનો વ્યાસ નક્કી કરવો અને stampsને source-over alpha સાથે composite કરવા.
બિલ્ડર 686 લાઇન્સમાંથી ઘટીને 190 લાઇન્સનો રહી ગયો. અઝિમુથ, અલ્ટિટ્યુડ, આઉટલાઇન બનાવટ, યુનિયન માસ્ક્સ, endpoint direction windows, કૅપ એક્સટેન્શન અને કૅપ ક્લિપિંગ બધું હાઇલાઇટર પાથમાંથી દૂર થઈ ગયું. અમે Pencilની દિશા હજી રેકોર્ડ કરીએ છીએ, કારણ કે ઇનપુટ મોડેલ તેને સમર્થન આપે છે, પરંતુ હાઇલાઇટર પોતે હવે એ fields વાંચતું નથી.
MaLiangના દબાણના ફોર્મ્યુલા માટે ડિવાઇસ કૅલિબ્રેશન જરૂરી હતું
MaLiang સ્ટેમ્પનું કદ આ ફોર્મ્યુલા સમકક્ષ રીતે નક્કી કરે છે:
આ ફોર્મ્યુલા ધારે છે કે force 0 થી 1 વચ્ચેના રેન્જના ઉપયોગી ભાગનો ઉપયોગ કરે છે. અમારા ડિવાઇસના ડેટામાં એવું નહોતું. આશરે 3,400 Apple Pencil સેમ્પલ્સમાં મધ્યક દબાણ 0.047 અને મહત્તમ 0.178 હતું. આ મૂલ્યો સીધા ફોર્મ્યુલામાં આપતાં સામાન્ય લખાણ નામમાત્ર બ્રશના કદ કરતાં ઘણું પાતળું બનતું.
તેથી અમે જોવાયેલા મધ્યકની આસપાસ normalize કર્યું, પછી exponent લાગુ કર્યો અને પરિણામને clamp કર્યું:
હવે લખાણનું મધ્યક દબાણ નામમાત્ર 12-પોઇન્ટ વ્યાસમાં રૂપાંતરિત થાય છે. બહુ હળવો સંપર્ક નામમાત્ર કદના 35% પર દેખાતો રહે છે, જ્યારે ભારે દબાણ 120% પર વધવાનું બંધ કરે છે.
આ કૅલિબ્રેશન ઇનપુટ ડિવાઇસ અને બ્રશના વર્તન સાથે સંબંધિત છે, MaLiang સાથે નહીં. અમારા પોતાના દબાણ વિતરણને માપ્યા વિના મૂળ ફોર્મ્યુલા નકલ કરી હોત તો આર્કિટેક્ચર તો જળવાત, પરંતુ બ્રશ ખોટો બનત.
જાણીતી ઓવરલેપ સંખ્યાથી દરેક સ્ટેમ્પની alpha મળી
MaLiang ઓવરલેપ થતા અર્ધપારદર્શક સ્ટેમ્પ્સ માટે પ્રાયોગિક અભિવ્યક્તિ alpha ÷ overlapping × 2.5 વાપરીને ભરપાઈ કરે છે. અમારા બ્રશનો નામમાત્ર વ્યાસ 12 પોઇન્ટ અને સ્ટેમ્પ સ્ટેપ 1 પોઇન્ટનો નિશ્ચિત હોવાથી, તેની centerlineને આશરે 12 લેયર્સ મળે છે. અમારા કિસ્સામાં ઓવરલેપની સંખ્યા જાણીતી છે, તેથી ભરપાઈનો ઉકેલ અંદાજથી નહીં, સીધો કાઢી શકાય છે.
લક્ષિત સ્ટ્રોક ઓપેસિટી
તેથી એક સ્ટેમ્પ માટે જરૂરી છે

રેકોર્ડ કરેલા ડિવાઇસ પાથ્સને ફરી ચલાવતો અંતિમ રેન્ડરર. હૂક્સ, તિરછા કટ્સ અને સફેદ ખિસ્સા ગાયબ છે.
અમે સ્વીકારેલી બે કિંમતો
સેલ્ફ-ઇન્ટરસેક્શન વધુ ઘેરા બને છે. Source-over કમ્પોઝિશન દરેક સ્ટેમ્પની ગણતરી કરે છે, જેમાં એ જ વિસ્તારમાંથી અગાઉના પાસમાં મૂકાયેલા સ્ટેમ્પ્સ પણ સામેલ છે, અને coverage-union એન્જિને આ ટાળ્યું હતું. અમે આ ઘેરા ઓવરલેપને સ્વીકાર્યો, કારણ કે તે અનુમાનપાત્ર છે અને સ્ટ્રોકનો આકાર જાળવી રાખે છે.
દબાણ સાથે છેડા સાંકડા થાય છે. વાસ્તવિક લિફ્ટ-ઑફ દબાણ ઘટાડે છે, તેથી સ્ટેમ્પનો વ્યાસ ઘટે છે અને સ્ટ્રોક સંપૂર્ણ પહોળાઈની ચોરસ કૅપને બદલે ધીમે ધીમે સાંકડો થતો પૂરો થાય છે. ત્રણેય જ્યોમેટ્રી એન્જિનો દરમિયાન અમે એ ચોરસ કૅપને આવશ્યકતા માનતા હતા. તેને છોડતાં ઉપરની ઘણી નિષ્ફળતાઓ પાછળનું ક્લિપિંગ અને endpoint મશીનરી દૂર થઈ ગઈ, તેથી અમે સાંકડો થતો અંત સ્વીકાર્યો.
અમે જે મોડેલ મોકલીએ છીએ તે પહેલાંના મોડેલો કરતાં ઓછું કામ કરે છે. તે માપેલી લખાણ-ઘટનાને જાળવે છે, ડિવાઇસ કૅલિબ્રેશન પછી દબાણને પ્રતિસાદ આપે છે અને વૈશ્વિક રીતે માન્ય આઉટલાઇનની જરૂર વિના વળાંકવાળા તથા એકબીજાને કાપતા પાથ્સ રેન્ડર કરે છે. છીણી-આકારનું નિબ, સંપૂર્ણ ચોરસ કૅપ અને કાચા સેમ્પલ્સ વચ્ચેની ચોક્કસ પોલિલાઇન — આ માટે અમે છોડી દીધેલી વિશેષતાઓ છે.
આ તપાસમાંથી મળેલી બાબતોમાં દબાણની મર્યાદા બીજા પ્રોજેક્ટ્સમાં સૌથી સીધી રીતે લઈ જઈ શકાય છે. 0.005 મૂલ્ય વાસ્તવિક ઇનપુટના બે ક્લસ્ટરો વચ્ચેના અંતરમાંથી આવ્યું: 0.01 અને તેથી વધુ દબાણવાળું લખાણ, અને 0.002 તથા તેથી ઓછા દબાણવાળું હવામાં ટ્રૅકિંગ. એ જ રેકોર્ડ કરેલા સ્ટ્રોક્સે બતાવ્યું કે દરેક જ્યોમેટ્રી મરામત ક્યાં નિષ્ફળ થઈ. આ નિષ્ફળતાઓએ સ્ટેમ્પ મોડેલ અને તેની સાથે સ્વીકારેલી બે કિંમતો તરફ દોરી.