1<html> 2<head> 3<div height="0" hidden="true"> 4<div id="bug8380"> 5SkDCubic::ComplexBreak 6{{{126, 9.396100044250488281}, {125.6320571899414063, 9.295844078063964844}, {125.1227340698242188, 9.337338447570800781}, {124.6031646728515625, 9.379667282104492188}}}, 7inflectionsTs[0]=0.999997776 {{{126.1618761931709827, 9.252680507258252973}, {123.04446008475567, 9.506653492188940291}}}, 8SkDCubic::ComplexBreak 9{{{124.6031646728515625, 9.379667282104492188}, {124.1427383422851563, 9.417178153991699219}, {123.6742630004882813, 9.45534515380859375}, {123.28900146484375, 9.396100044250488281}}}, 10inflectionsTs[0]=4.14921088e-06 {{{125.984438133710114, 9.267135117035042668}, {123.2218797495565639, 9.492200381017113386}}}, 11maxCurvature[0]=0.0817322831 {{{125.8735553329735666, 9.277935394706121386}, {123.1067608854740314, 9.499713475347833835}}}, 12SkDCubic::ComplexBreak 13{{{126, 9.396200180053710938}, {125.305999755859375, 9.206999778747558594}, {124.1090011596679688, 9.522199630737304688}, {123.28900146484375, 9.396200180053710938}}}, 14inflectionsTs[0]=0.530286644 {{{127.5428560571536707, 9.140180090182106198}, {121.6628069847287179, 9.619260454379688241}}}, 15maxCurvature[0]=0.568563182 {{{127.4346914043237859, 9.15278490094694952}, {121.5456828946143446, 9.624913158409162506}}}, 16seg=1 {{{0, 353.891998f}, {126, 9.39610004f}}} 17seg=2 {{{126, 9.39610004f}, {125.632057f, 9.29584408f}, {125.122734f, 9.33733845f}, {124.603165f, 9.37966728f}}} 18seg=3 {{{124.603165f, 9.37966728f}, {124.142731f, 9.41717815f}, {123.674263f, 9.45534515f}, {123.289001f, 9.39610004f}}} 19seg=4 {{{123.289001f, 9.39610004f}, {118.119003f, 8.07219982f}}} 20seg=5 {{{118.119003f, 8.07219982f}, {8.17210007f, 104.212997f}}} 21seg=6 {{{8.17210007f, 104.212997f}, {0, 259.298737f}}} 22seg=7 {{{0, 259.298737f}, {0, 353.891998f}}} 23op sect 24seg=8 {{{8.17210007f, 104.212997f}, {-5.82350016f, 369.813995f}}} 25seg=9 {{{-5.82350016f, 369.813995f}, {126, 9.39620018f}}} 26seg=10 {{{126, 9.39620018f}, {125.631981f, 9.29586983f}, {125.12252f, 9.3373785f}, {124.602829f, 9.37972069f}}} 27seg=11 {{{124.602829f, 9.37972069f}, {124.142509f, 9.41722488f}, {123.674164f, 9.45538425f}, {123.289001f, 9.39620018f}}} 28seg=12 {{{123.289001f, 9.39620018f}, {118.119003f, 8.07219982f}}} 29seg=13 {{{118.119003f, 8.07219982f}, {8.17210007f, 104.212997f}}} 30debugShowLineIntersection wtTs[0]=1 {{{8.17210007,104.212997}, {-5.82350016,369.813995}}} {{-5.82350016,369.813995}} wnTs[0]=0 {{{-5.82350016,369.813995}, {126,9.39620018}}} 31debugShowLineIntersection wtTs[0]=0 {{{8.17210007,104.212997}, {-5.82350016,369.813995}}} {{8.17210007,104.212997}} wnTs[0]=1 {{{118.119003,8.07219982}, {8.17210007,104.212997}}} 32debugShowCubicLineIntersection wtTs[0]=0 {{{126,9.39620018}, {125.631981,9.29586983}, {125.12252,9.3373785}, {124.602829,9.37972069}}} {{126,9.39620018}} wnTs[0]=1 {{{-5.82350016,369.813995}, {126,9.39620018}}} 33debugShowCubicLineIntersection no intersect {{{124.602829,9.37972069}, {124.142509,9.41722488}, {123.674164,9.45538425}, {123.289001,9.39620018}}} {{{-5.82350016,369.813995}, {126,9.39620018}}} 34debugShowLineIntersection no intersect {{{-5.82350016,369.813995}, {126,9.39620018}}} {{{123.289001,9.39620018}, {118.119003,8.07219982}}} 35debugShowLineIntersection no intersect {{{-5.82350016,369.813995}, {126,9.39620018}}} {{{118.119003,8.07219982}, {8.17210007,104.212997}}} 36debugShowCubicIntersection wtTs[0]=1 {{{126,9.39620018}, {125.631981,9.29586983}, {125.12252,9.3373785}, {124.602829,9.37972069}}} {{124.602829,9.37972069}} wnTs[0]=0 {{{124.602829,9.37972069}, {124.142509,9.41722488}, {123.674164,9.45538425}, {123.289001,9.39620018}}} 37debugShowCubicLineIntersection wtTs[0]=1 {{{124.602829,9.37972069}, {124.142509,9.41722488}, {123.674164,9.45538425}, {123.289001,9.39620018}}} {{123.289001,9.39620018}} wnTs[0]=0 {{{123.289001,9.39620018}, {118.119003,8.07219982}}} 38debugShowLineIntersection wtTs[0]=1 {{{123.289001,9.39620018}, {118.119003,8.07219982}}} {{118.119003,8.07219982}} wnTs[0]=0 {{{118.119003,8.07219982}, {8.17210007,104.212997}}} 39debugShowLineIntersection no intersect {{{8.17210007,104.212997}, {-5.82350016,369.813995}}} {{{0,353.891998}, {126,9.39610004}}} 40debugShowLineIntersection wtTs[0]=0 {{{8.17210007,104.212997}, {-5.82350016,369.813995}}} {{8.17210007,104.212997}} wnTs[0]=1 {{{118.119003,8.07219982}, {8.17210007,104.212997}}} 41debugShowLineIntersection wtTs[0]=0 {{{8.17210007,104.212997}, {-5.82350016,369.813995}}} {{8.17210007,104.212997}} wtTs[1]=0.583904956 {{0,259.298737}} wnTs[0]=0 {{{8.17210007,104.212997}, {0,259.298737}}} wnTs[1]=1 42SkOpSegment::addT insert t=0.583904956 segID=8 spanID=27 43debugShowLineIntersection wtTs[0]=0.583904956 {{{8.17210007,104.212997}, {-5.82350016,369.813995}}} {{0,259.298737}} wnTs[0]=0 {{{0,259.298737}, {0,353.891998}}} 44debugShowLineIntersection wtTs[0]=0.0441765002 {{{-5.82350016,369.813995}, {126,9.39620018}}} {{0,353.891998}} wtTs[1]=1 {{126,9.39620018}} wnTs[0]=0 {{{0,353.891998}, {126,9.39610004}}} wnTs[1]=0.999999744 45SkOpSegment::addT insert t=0.0441765002 segID=9 spanID=28 46debugShowCubicLineIntersection no intersect {{{124.603165,9.37966728}, {124.142731,9.41717815}, {123.674263,9.45534515}, {123.289001,9.39610004}}} {{{-5.82350016,369.813995}, {126,9.39620018}}} 47debugShowLineIntersection no intersect {{{-5.82350016,369.813995}, {126,9.39620018}}} {{{118.119003,8.07219982}, {8.17210007,104.212997}}} 48debugShowLineIntersection no intersect {{{-5.82350016,369.813995}, {126,9.39620018}}} {{{8.17210007,104.212997}, {0,259.298737}}} 49debugShowLineIntersection wtTs[0]=0.0441765002 {{{-5.82350016,369.813995}, {126,9.39620018}}} {{0,353.891998}} wnTs[0]=1 {{{0,259.298737}, {0,353.891998}}} 50debugShowCubicLineIntersection wtTs[0]=0 {{{126,9.39620018}, {125.631981,9.29586983}, {125.12252,9.3373785}, {124.602829,9.37972069}}} {{126,9.39620018}} wnTs[0]=1 {{{0,353.891998}, {126,9.39610004}}} 51-1=(0.375,0.5) [-1] 52SkTSect::addForPerp addBounded span=-1 opp=-1 53-1=(0.5,0.625) [-1] 54SkTSect::addForPerp addBounded span=-1 opp=-1 55-1=(0.625,0.75) [-1] 56SkTSect::addForPerp addBounded span=-1 opp=-1 57-1=(0.75,0.8125) [-1] 58SkTSect::addForPerp addBounded span=-1 opp=-1 59-1=(0.8125,0.875) [-1] 60SkTSect::addForPerp addBounded span=-1 opp=-1 61-1=(0.875,0.9375) [-1] 62SkTSect::addForPerp addBounded span=-1 opp=-1 63SkTSect::addForPerp priorSpan=-1 t=0.937702598 opp=-1 64-1=(0.9375,1) [] 65SkTSect::addForPerp addBounded span=-1 opp=-1 66debugShowCubicIntersection wtTs[0]=0.307128906 {{{126,9.39620018}, {125.631981,9.29586983}, {125.12252,9.3373785}, {124.602829,9.37972069}}} {{125.624687,9.33981037}} wtTs[1]=0.9375 {{124.700119,9.37182617}} wnTs[0]=0.307191 {{{126,9.39610004}, {125.632057,9.29584408}, {125.122734,9.33733845}, {124.603165,9.37966728}}} wnTs[1]=0.937702598 67SkOpSegment::addT insert t=0.307128906 segID=10 spanID=29 68SkOpSegment::addT insert t=0.307190555 segID=2 spanID=30 69SkOpSegment::addT insert t=0.9375 segID=10 spanID=31 70SkOpSegment::addT insert t=0.937702598 segID=2 spanID=32 71debugShowCubicIntersection no intersect {{{126,9.39620018}, {125.631981,9.29586983}, {125.12252,9.3373785}, {124.602829,9.37972069}}} {{{124.603165,9.37966728}, {124.142731,9.41717815}, {123.674263,9.45534515}, {123.289001,9.39610004}}} 72debugShowCubicLineIntersection no intersect {{{124.602829,9.37972069}, {124.142509,9.41722488}, {123.674164,9.45538425}, {123.289001,9.39620018}}} {{{0,353.891998}, {126,9.39610004}}} 73-1=(0.125,0.1875) [-1] 74SkTSect::addForPerp addBounded span=-1 opp=-1 75-1=(0.1875,0.25) [-1] 76SkTSect::addForPerp addBounded span=-1 opp=-1 77-1=(0.25,0.375) [-1] 78SkTSect::addForPerp addBounded span=-1 opp=-1 79-1=(0.375,0.5) [-1] 80SkTSect::addForPerp addBounded span=-1 opp=-1 81-1=(0.5,0.625) [-1] 82SkTSect::addForPerp addBounded span=-1 opp=-1 83-1=(0.625,0.75) [-1] 84SkTSect::addForPerp addBounded span=-1 opp=-1 85debugShowCubicIntersection wtTs[0]=0.0625 {{{124.602829,9.37972069}, {124.142509,9.41722488}, {123.674164,9.45538425}, {123.289001,9.39620018}}} {{124.516449,9.38673687}} wtTs[1]=0.625 {{123.752594,9.4268837}} wnTs[0]=0.0627287 {{{124.603165,9.37966728}, {124.142731,9.41717815}, {123.674263,9.45534515}, {123.289001,9.39610004}}} wnTs[1]=0.625091708 86SkOpSegment::addT insert t=0.0625 segID=11 spanID=33 87SkOpSegment::addT insert t=0.0627286673 segID=3 spanID=34 88SkOpSegment::addT insert t=0.625 segID=11 spanID=35 89SkOpSegment::addT insert t=0.625091708 segID=3 spanID=36 90debugShowCubicLineIntersection no intersect {{{124.602829,9.37972069}, {124.142509,9.41722488}, {123.674164,9.45538425}, {123.289001,9.39620018}}} {{{123.289001,9.39610004}, {118.119003,8.07219982}}} 91debugShowLineIntersection no intersect {{{123.289001,9.39620018}, {118.119003,8.07219982}}} {{{0,353.891998}, {126,9.39610004}}} 92debugShowCubicLineIntersection wtTs[0]=0.999978653 {{{124.603165,9.37966728}, {124.142731,9.41717815}, {123.674263,9.45534515}, {123.289001,9.39610004}}} {{123.289001,9.39620018}} wnTs[0]=0 {{{123.289001,9.39620018}, {118.119003,8.07219982}}} 93debugShowLineIntersection wtTs[0]=4.65488731e-06 {{{123.289001,9.39620018}, {118.119003,8.07219982}}} {{123.289001,9.39610004}} wtTs[1]=1 {{118.119003,8.07219982}} wnTs[0]=0 {{{123.289001,9.39610004}, {118.119003,8.07219982}}} wnTs[1]=1 94debugShowLineIntersection wtTs[0]=1 {{{123.289001,9.39620018}, {118.119003,8.07219982}}} {{118.119003,8.07219982}} wnTs[0]=0 {{{118.119003,8.07219982}, {8.17210007,104.212997}}} 95debugShowLineIntersection no intersect {{{118.119003,8.07219982}, {8.17210007,104.212997}}} {{{0,353.891998}, {126,9.39610004}}} 96debugShowLineIntersection wtTs[0]=0 {{{118.119003,8.07219982}, {8.17210007,104.212997}}} {{118.119003,8.07219982}} wnTs[0]=1 {{{123.289001,9.39610004}, {118.119003,8.07219982}}} 97debugShowLineIntersection wtTs[0]=0 {{{118.119003,8.07219982}, {8.17210007,104.212997}}} {{118.119003,8.07219982}} wtTs[1]=1 {{8.17210007,104.212997}} wnTs[0]=0 {{{118.119003,8.07219982}, {8.17210007,104.212997}}} wnTs[1]=1 98debugShowLineIntersection wtTs[0]=1 {{{118.119003,8.07219982}, {8.17210007,104.212997}}} {{8.17210007,104.212997}} wnTs[0]=0 {{{8.17210007,104.212997}, {0,259.298737}}} 99debugShowCubicLineIntersection wtTs[0]=0 {{{126,9.39610004}, {125.632057,9.29584408}, {125.122734,9.33733845}, {124.603165,9.37966728}}} {{126,9.39610004}} wnTs[0]=1 {{{0,353.891998}, {126,9.39610004}}} 100debugShowCubicLineIntersection no intersect {{{124.603165,9.37966728}, {124.142731,9.41717815}, {123.674263,9.45534515}, {123.289001,9.39610004}}} {{{0,353.891998}, {126,9.39610004}}} 101debugShowLineIntersection no intersect {{{0,353.891998}, {126,9.39610004}}} {{{123.289001,9.39610004}, {118.119003,8.07219982}}} 102debugShowLineIntersection no intersect {{{0,353.891998}, {126,9.39610004}}} {{{118.119003,8.07219982}, {8.17210007,104.212997}}} 103debugShowLineIntersection no intersect {{{0,353.891998}, {126,9.39610004}}} {{{8.17210007,104.212997}, {0,259.298737}}} 104debugShowLineIntersection wtTs[0]=0 {{{0,353.891998}, {126,9.39610004}}} {{0,353.891998}} wnTs[0]=1 {{{0,259.298737}, {0,353.891998}}} 105debugShowCubicIntersection wtTs[0]=1 {{{126,9.39610004}, {125.632057,9.29584408}, {125.122734,9.33733845}, {124.603165,9.37966728}}} {{124.603165,9.37966728}} wnTs[0]=0 {{{124.603165,9.37966728}, {124.142731,9.41717815}, {123.674263,9.45534515}, {123.289001,9.39610004}}} 106debugShowCubicLineIntersection wtTs[0]=1 {{{124.603165,9.37966728}, {124.142731,9.41717815}, {123.674263,9.45534515}, {123.289001,9.39610004}}} {{123.289001,9.39610004}} wnTs[0]=0 {{{123.289001,9.39610004}, {118.119003,8.07219982}}} 107debugShowLineIntersection wtTs[0]=1 {{{123.289001,9.39610004}, {118.119003,8.07219982}}} {{118.119003,8.07219982}} wnTs[0]=0 {{{118.119003,8.07219982}, {8.17210007,104.212997}}} 108debugShowLineIntersection wtTs[0]=1 {{{118.119003,8.07219982}, {8.17210007,104.212997}}} {{8.17210007,104.212997}} wnTs[0]=0 {{{8.17210007,104.212997}, {0,259.298737}}} 109debugShowLineIntersection wtTs[0]=1 {{{8.17210007,104.212997}, {0,259.298737}}} {{0,259.298737}} wnTs[0]=0 {{{0,259.298737}, {0,353.891998}}} 110----------------x-x--x-x-------------- addExpanded 11100: coinSeg/Span/PtT=2/3/3 endSpan=30 oppSeg/Span/PtT=10/19/19 oppEndSpan=29 MissingCoin 11201: coinSeg/Span/PtT=3/36/36 endSpan=6 oppSeg/Span/PtT=11/35/35 oppEndSpan=22 MissingCoin 11302: coinSeg/Span/PtT=5/9/9 endSpan=10 oppSeg/Span/PtT=13/25/25 oppEndSpan=26 MissingCoin 11403: coinSeg/Span/PtT=2/3/3 endSpan=30 oppSeg/Span/PtT=10/19/19 oppEndSpan=29 MissingCoin 11504: coinSeg/Span/PtT=3/36/36 endSpan=6 oppSeg/Span/PtT=11/35/35 oppEndSpan=22 MissingCoin 11605: coinSeg/Span/PtT=5/9/9 endSpan=10 oppSeg/Span/PtT=13/25/25 oppEndSpan=26 MissingCoin 11706: coinSeg/Span/PtT=10/19/19 endSpan=29 oppSeg/Span/PtT=2/3/3 oppEndSpan=30 MissingCoin 11807: coinSeg/Span/PtT=11/35/35 endSpan=22 oppSeg/Span/PtT=3/36/36 oppEndSpan=6 MissingCoin 11908: coinSeg/Span/PtT=10/19/19 endSpan=29 oppSeg/Span/PtT=2/3/3 oppEndSpan=30 MissingCoin 12009: coinSeg/Span/PtT=11/35/35 endSpan=22 oppSeg/Span/PtT=3/36/36 oppEndSpan=6 MissingCoin 12110: coinSeg/Span/PtT=11/33/33 endSpan=6 oppSeg/Span/PtT=11/22/22 oppEndSpan=6 ExpandCoin 12211: coinSeg/Span/PtT=2/30/30 endSpan=19 oppSeg/Span/PtT=2/3/3 oppEndSpan=19 ExpandCoin 12312: seg/base=13/25 seg/base=5/9 MarkCoinStart 12413: seg/base=13/26 seg/base=5/10 MarkCoinEnd 12514: seg/base=4/7 seg/base=12/23 MarkCoinStart 12615: seg/base=4/8 seg/base=12/24 MarkCoinEnd 12716: seg/base=11/33 seg/base=3/34 MarkCoinStart 12817: seg/base=11/35 seg/base=3/36 MarkCoinEnd 12918: seg/base=2/30 seg/base=10/29 MarkCoinStart 13019: seg/base=2/32 seg/base=10/31 MarkCoinEnd 13120: seg/base=9/28 seg/base=1/1 MarkCoinStart 13221: seg/base=9/18 seg/base=1/2 MarkCoinEnd 13322: seg/base=8/15 seg/base=6/11 MarkCoinStart 13423: seg/base=8/27 seg/base=6/12 MarkCoinEnd 135SkOpSegment::debugShowActiveSpans id=8 (8.17210007,104.212997 -2.71619996e-07,259.298737) t=0 tEnd=0.583904956 windSum=? windValue=1 136SkOpSegment::debugShowActiveSpans id=8 (-2.71619996e-07,259.298737 -5.82350016,369.813995) t=0.583904956 tEnd=1 windSum=? windValue=1 137SkOpSegment::debugShowActiveSpans id=9 (-5.82350016,369.813995 7.26031715e-07,353.891998) t=0 tEnd=0.0441765002 windSum=? windValue=1 138SkOpSegment::debugShowActiveSpans id=9 (7.26031715e-07,353.891998 126,9.39620018) t=0.0441765002 tEnd=1 windSum=? windValue=1 139SkOpSegment::debugShowActiveSpans id=10 (126,9.39620018 125.886971,9.36538583 125.760599,9.34795095 125.624687,9.33981037) t=0 tEnd=0.307128906 windSum=? windValue=1 140SkOpSegment::debugShowActiveSpans id=10 (125.624687,9.33981037 125.345733,9.32310212 125.026588,9.34554777 124.700119,9.37182617) t=0.307128906 tEnd=0.9375 windSum=? windValue=1 141SkOpSegment::debugShowActiveSpans id=10 (124.700119,9.37182617 124.66775,9.37443162 124.63531,9.3770743 124.602829,9.37972069) t=0.9375 tEnd=1 windSum=? windValue=1 142SkOpSegment::debugShowActiveSpans id=11 (124.602829,9.37972069 124.574059,9.3820647 124.545259,9.38441166 124.516449,9.38673687) t=0 tEnd=0.0625 windSum=? windValue=1 143SkOpSegment::debugShowActiveSpans id=11 (124.516449,9.38673687 124.257155,9.40766372 123.997126,9.42685982 123.752594,9.4268837) t=0.0625 tEnd=0.625 windSum=? windValue=1 144SkOpSegment::debugShowActiveSpans id=11 (123.752594,9.4268837 123.589573,9.42689962 123.433437,9.41839421 123.289001,9.39620018) t=0.625 tEnd=1 windSum=? windValue=1 145SkOpSegment::debugShowActiveSpans id=12 (123.289001,9.39620018 118.119003,8.07219982) t=0 tEnd=1 windSum=? windValue=1 146SkOpSegment::debugShowActiveSpans id=13 (118.119003,8.07219982 8.17210007,104.212997) t=0 tEnd=1 windSum=? windValue=1 147SkOpSegment::debugShowActiveSpans id=1 (0,353.891998 126,9.39610004) t=0 tEnd=1 windSum=? windValue=1 148SkOpSegment::debugShowActiveSpans id=2 (126,9.39610004 125.886971,9.36530236 125.760605,9.34788101 125.624695,9.33975124) t=0 tEnd=0.307190555 windSum=? windValue=1 149SkOpSegment::debugShowActiveSpans id=2 (125.624695,9.33975124 125.345738,9.3230648 125.026588,9.34552196 124.700119,9.37180042) t=0.307190555 tEnd=0.937702598 windSum=? windValue=1 150SkOpSegment::debugShowActiveSpans id=2 (124.700119,9.37180042 124.667862,9.37439685 124.635532,9.37703031 124.603165,9.37966728) t=0.937702598 tEnd=1 windSum=? windValue=1 151SkOpSegment::debugShowActiveSpans id=3 (124.603165,9.37966728 124.574282,9.38202029 124.545364,9.3843762 124.516441,9.38671017) t=0 tEnd=0.0627286673 windSum=? windValue=1 152SkOpSegment::debugShowActiveSpans id=3 (124.516441,9.38671017 124.257145,9.40763418 123.997124,9.42681973 123.752594,9.42682648) t=0.0627286673 tEnd=0.625091708 windSum=? windValue=1 153SkOpSegment::debugShowActiveSpans id=3 (123.752594,9.42682648 123.589574,9.42683098 123.433439,9.41831153 123.289001,9.39610004) t=0.625091708 tEnd=1 windSum=? windValue=1 154SkOpSegment::debugShowActiveSpans id=4 (123.289001,9.39610004 118.119003,8.07219982) t=0 tEnd=1 windSum=? windValue=1 155SkOpSegment::debugShowActiveSpans id=5 (118.119003,8.07219982 8.17210007,104.212997) t=0 tEnd=1 windSum=? windValue=1 156SkOpSegment::debugShowActiveSpans id=6 (8.17210007,104.212997 0,259.298737) t=0 tEnd=1 windSum=? windValue=1 157SkOpSegment::debugShowActiveSpans id=7 (0,259.298737 0,353.891998) t=0 tEnd=1 windSum=? windValue=1 158----------------x-x--x-x-------------- move_multiples 15900: coinSeg/Span/PtT=2/3/3 endSpan=30 oppSeg/Span/PtT=10/19/19 oppEndSpan=29 MissingCoin 16001: coinSeg/Span/PtT=3/36/36 endSpan=6 oppSeg/Span/PtT=11/35/35 oppEndSpan=22 MissingCoin 16102: coinSeg/Span/PtT=5/9/9 endSpan=10 oppSeg/Span/PtT=13/25/25 oppEndSpan=26 MissingCoin 16203: coinSeg/Span/PtT=2/3/3 endSpan=30 oppSeg/Span/PtT=10/19/19 oppEndSpan=29 MissingCoin 16304: coinSeg/Span/PtT=3/36/36 endSpan=6 oppSeg/Span/PtT=11/35/35 oppEndSpan=22 MissingCoin 16405: coinSeg/Span/PtT=5/9/9 endSpan=10 oppSeg/Span/PtT=13/25/25 oppEndSpan=26 MissingCoin 16506: coinSeg/Span/PtT=10/19/19 endSpan=29 oppSeg/Span/PtT=2/3/3 oppEndSpan=30 MissingCoin 16607: coinSeg/Span/PtT=11/35/35 endSpan=22 oppSeg/Span/PtT=3/36/36 oppEndSpan=6 MissingCoin 16708: coinSeg/Span/PtT=10/19/19 endSpan=29 oppSeg/Span/PtT=2/3/3 oppEndSpan=30 MissingCoin 16809: coinSeg/Span/PtT=11/35/35 endSpan=22 oppSeg/Span/PtT=3/36/36 oppEndSpan=6 MissingCoin 16910: coinSeg/Span/PtT=11/33/33 endSpan=6 oppSeg/Span/PtT=11/22/22 oppEndSpan=6 ExpandCoin 17011: coinSeg/Span/PtT=2/30/30 endSpan=19 oppSeg/Span/PtT=2/3/3 oppEndSpan=19 ExpandCoin 17112: seg/base=13/25 seg/base=5/9 MarkCoinStart 17213: seg/base=13/26 seg/base=5/10 MarkCoinEnd 17314: seg/base=4/7 seg/base=12/23 MarkCoinStart 17415: seg/base=4/8 seg/base=12/24 MarkCoinEnd 17516: seg/base=11/33 seg/base=3/34 MarkCoinStart 17617: seg/base=11/35 seg/base=3/36 MarkCoinEnd 17718: seg/base=2/30 seg/base=10/29 MarkCoinStart 17819: seg/base=2/32 seg/base=10/31 MarkCoinEnd 17920: seg/base=9/28 seg/base=1/1 MarkCoinStart 18021: seg/base=9/18 seg/base=1/2 MarkCoinEnd 18122: seg/base=8/15 seg/base=6/11 MarkCoinStart 18223: seg/base=8/27 seg/base=6/12 MarkCoinEnd 183----------------x-x--x-x-------------- move_nearby 18400: coinSeg/Span/PtT=2/3/3 endSpan=30 oppSeg/Span/PtT=10/19/19 oppEndSpan=29 MissingCoin 18501: coinSeg/Span/PtT=3/36/36 endSpan=6 oppSeg/Span/PtT=11/35/35 oppEndSpan=22 MissingCoin 18602: coinSeg/Span/PtT=5/9/9 endSpan=10 oppSeg/Span/PtT=13/25/25 oppEndSpan=26 MissingCoin 18703: coinSeg/Span/PtT=2/3/3 endSpan=30 oppSeg/Span/PtT=10/19/19 oppEndSpan=29 MissingCoin 18804: coinSeg/Span/PtT=3/36/36 endSpan=6 oppSeg/Span/PtT=11/35/35 oppEndSpan=22 MissingCoin 18905: coinSeg/Span/PtT=5/9/9 endSpan=10 oppSeg/Span/PtT=13/25/25 oppEndSpan=26 MissingCoin 19006: coinSeg/Span/PtT=10/19/19 endSpan=29 oppSeg/Span/PtT=2/3/3 oppEndSpan=30 MissingCoin 19107: coinSeg/Span/PtT=11/35/35 endSpan=22 oppSeg/Span/PtT=3/36/36 oppEndSpan=6 MissingCoin 19208: coinSeg/Span/PtT=10/19/19 endSpan=29 oppSeg/Span/PtT=2/3/3 oppEndSpan=30 MissingCoin 19309: coinSeg/Span/PtT=11/35/35 endSpan=22 oppSeg/Span/PtT=3/36/36 oppEndSpan=6 MissingCoin 19410: coinSeg/Span/PtT=11/33/33 endSpan=6 oppSeg/Span/PtT=11/22/22 oppEndSpan=6 ExpandCoin 19511: coinSeg/Span/PtT=2/30/30 endSpan=19 oppSeg/Span/PtT=2/3/3 oppEndSpan=19 ExpandCoin 19612: seg/base=13/25 seg/base=5/9 MarkCoinStart 19713: seg/base=13/26 seg/base=5/10 MarkCoinEnd 19814: seg/base=4/7 seg/base=12/23 MarkCoinStart 19915: seg/base=4/8 seg/base=12/24 MarkCoinEnd 20016: seg/base=11/33 seg/base=3/34 MarkCoinStart 20117: seg/base=11/35 seg/base=3/36 MarkCoinEnd 20218: seg/base=2/30 seg/base=10/29 MarkCoinStart 20319: seg/base=2/32 seg/base=10/31 MarkCoinEnd 20420: seg/base=9/28 seg/base=1/1 MarkCoinStart 20521: seg/base=9/18 seg/base=1/2 MarkCoinEnd 20622: seg/base=8/15 seg/base=6/11 MarkCoinStart 20723: seg/base=8/27 seg/base=6/12 MarkCoinEnd 208----------------x-x--x-x-------------- correctEnds 20900: coinSeg/Span/PtT=2/3/3 endSpan=30 oppSeg/Span/PtT=10/19/19 oppEndSpan=29 MissingCoin 21001: coinSeg/Span/PtT=3/36/36 endSpan=6 oppSeg/Span/PtT=11/35/35 oppEndSpan=22 MissingCoin 21102: coinSeg/Span/PtT=5/9/9 endSpan=10 oppSeg/Span/PtT=13/25/25 oppEndSpan=26 MissingCoin 21203: coinSeg/Span/PtT=2/3/3 endSpan=30 oppSeg/Span/PtT=10/19/19 oppEndSpan=29 MissingCoin 21304: coinSeg/Span/PtT=3/36/36 endSpan=6 oppSeg/Span/PtT=11/35/35 oppEndSpan=22 MissingCoin 21405: coinSeg/Span/PtT=5/9/9 endSpan=10 oppSeg/Span/PtT=13/25/25 oppEndSpan=26 MissingCoin 21506: coinSeg/Span/PtT=10/19/19 endSpan=29 oppSeg/Span/PtT=2/3/3 oppEndSpan=30 MissingCoin 21607: coinSeg/Span/PtT=11/35/35 endSpan=22 oppSeg/Span/PtT=3/36/36 oppEndSpan=6 MissingCoin 21708: coinSeg/Span/PtT=10/19/19 endSpan=29 oppSeg/Span/PtT=2/3/3 oppEndSpan=30 MissingCoin 21809: coinSeg/Span/PtT=11/35/35 endSpan=22 oppSeg/Span/PtT=3/36/36 oppEndSpan=6 MissingCoin 21910: coinSeg/Span/PtT=11/33/33 endSpan=6 oppSeg/Span/PtT=11/22/22 oppEndSpan=6 ExpandCoin 22011: coinSeg/Span/PtT=2/30/30 endSpan=19 oppSeg/Span/PtT=2/3/3 oppEndSpan=19 ExpandCoin 22112: seg/base=13/25 seg/base=5/9 MarkCoinStart 22213: seg/base=13/26 seg/base=5/10 MarkCoinEnd 22314: seg/base=4/7 seg/base=12/23 MarkCoinStart 22415: seg/base=4/8 seg/base=12/24 MarkCoinEnd 22516: seg/base=11/33 seg/base=3/34 MarkCoinStart 22617: seg/base=11/35 seg/base=3/36 MarkCoinEnd 22718: seg/base=2/30 seg/base=10/29 MarkCoinStart 22819: seg/base=2/32 seg/base=10/31 MarkCoinEnd 22920: seg/base=9/28 seg/base=1/1 MarkCoinStart 23021: seg/base=9/18 seg/base=1/2 MarkCoinEnd 23122: seg/base=8/15 seg/base=6/11 MarkCoinStart 23223: seg/base=8/27 seg/base=6/12 MarkCoinEnd 233----------------x-x--x-x-------------- addEndMovedSpans 23400: coinSeg/Span/PtT=2/3/3 endSpan=30 oppSeg/Span/PtT=10/19/19 oppEndSpan=29 MissingCoin 23501: coinSeg/Span/PtT=3/36/36 endSpan=6 oppSeg/Span/PtT=11/35/35 oppEndSpan=22 MissingCoin 23602: coinSeg/Span/PtT=5/9/9 endSpan=10 oppSeg/Span/PtT=13/25/25 oppEndSpan=26 MissingCoin 23703: coinSeg/Span/PtT=2/3/3 endSpan=30 oppSeg/Span/PtT=10/19/19 oppEndSpan=29 MissingCoin 23804: coinSeg/Span/PtT=3/36/36 endSpan=6 oppSeg/Span/PtT=11/35/35 oppEndSpan=22 MissingCoin 23905: coinSeg/Span/PtT=5/9/9 endSpan=10 oppSeg/Span/PtT=13/25/25 oppEndSpan=26 MissingCoin 24006: coinSeg/Span/PtT=10/19/19 endSpan=29 oppSeg/Span/PtT=2/3/3 oppEndSpan=30 MissingCoin 24107: coinSeg/Span/PtT=11/35/35 endSpan=22 oppSeg/Span/PtT=3/36/36 oppEndSpan=6 MissingCoin 24208: coinSeg/Span/PtT=10/19/19 endSpan=29 oppSeg/Span/PtT=2/3/3 oppEndSpan=30 MissingCoin 24309: coinSeg/Span/PtT=11/35/35 endSpan=22 oppSeg/Span/PtT=3/36/36 oppEndSpan=6 MissingCoin 24410: coinSeg/Span/PtT=11/33/33 endSpan=6 oppSeg/Span/PtT=11/22/22 oppEndSpan=6 ExpandCoin 24511: coinSeg/Span/PtT=2/30/30 endSpan=19 oppSeg/Span/PtT=2/3/3 oppEndSpan=19 ExpandCoin 24612: seg/base=13/25 seg/base=5/9 MarkCoinStart 24713: seg/base=13/26 seg/base=5/10 MarkCoinEnd 24814: seg/base=4/7 seg/base=12/23 MarkCoinStart 24915: seg/base=4/8 seg/base=12/24 MarkCoinEnd 25016: seg/base=11/33 seg/base=3/34 MarkCoinStart 25117: seg/base=11/35 seg/base=3/36 MarkCoinEnd 25218: seg/base=2/30 seg/base=10/29 MarkCoinStart 25319: seg/base=2/32 seg/base=10/31 MarkCoinEnd 25420: seg/base=9/28 seg/base=1/1 MarkCoinStart 25521: seg/base=9/18 seg/base=1/2 MarkCoinEnd 25622: seg/base=8/15 seg/base=6/11 MarkCoinStart 25723: seg/base=8/27 seg/base=6/12 MarkCoinEnd 258----------------x-x--x-x-------------- expand 25900: coinSeg/Span/PtT=2/3/3 endSpan=30 oppSeg/Span/PtT=10/19/19 oppEndSpan=29 MissingCoin 26001: coinSeg/Span/PtT=3/36/36 endSpan=6 oppSeg/Span/PtT=11/35/35 oppEndSpan=22 MissingCoin 26102: coinSeg/Span/PtT=5/9/9 endSpan=10 oppSeg/Span/PtT=13/25/25 oppEndSpan=26 MissingCoin 26203: coinSeg/Span/PtT=2/3/3 endSpan=30 oppSeg/Span/PtT=10/19/19 oppEndSpan=29 MissingCoin 26304: coinSeg/Span/PtT=3/36/36 endSpan=6 oppSeg/Span/PtT=11/35/35 oppEndSpan=22 MissingCoin 26405: coinSeg/Span/PtT=5/9/9 endSpan=10 oppSeg/Span/PtT=13/25/25 oppEndSpan=26 MissingCoin 26506: coinSeg/Span/PtT=10/19/19 endSpan=29 oppSeg/Span/PtT=2/3/3 oppEndSpan=30 MissingCoin 26607: coinSeg/Span/PtT=11/35/35 endSpan=22 oppSeg/Span/PtT=3/36/36 oppEndSpan=6 MissingCoin 26708: coinSeg/Span/PtT=10/19/19 endSpan=29 oppSeg/Span/PtT=2/3/3 oppEndSpan=30 MissingCoin 26809: coinSeg/Span/PtT=11/35/35 endSpan=22 oppSeg/Span/PtT=3/36/36 oppEndSpan=6 MissingCoin 26910: coinSeg/Span/PtT=11/33/33 endSpan=6 oppSeg/Span/PtT=11/22/22 oppEndSpan=6 ExpandCoin 27011: coinSeg/Span/PtT=2/30/30 endSpan=19 oppSeg/Span/PtT=2/3/3 oppEndSpan=19 ExpandCoin 27112: seg/base=13/25 seg/base=5/9 MarkCoinStart 27213: seg/base=13/26 seg/base=5/10 MarkCoinEnd 27314: seg/base=4/7 seg/base=12/23 MarkCoinStart 27415: seg/base=4/8 seg/base=12/24 MarkCoinEnd 27516: seg/base=11/33 seg/base=3/34 MarkCoinStart 27617: seg/base=11/35 seg/base=3/36 MarkCoinEnd 27718: seg/base=2/30 seg/base=10/29 MarkCoinStart 27819: seg/base=2/32 seg/base=10/31 MarkCoinEnd 27920: seg/base=9/28 seg/base=1/1 MarkCoinStart 28021: seg/base=9/18 seg/base=1/2 MarkCoinEnd 28122: seg/base=8/15 seg/base=6/11 MarkCoinStart 28223: seg/base=8/27 seg/base=6/12 MarkCoinEnd 283------------------xx-x-x-------------- addExpanded 28400: coinSeg/Span/PtT=5/9/9 endSpan=10 oppSeg/Span/PtT=13/25/25 oppEndSpan=26 MissingCoin 28501: coinSeg/Span/PtT=5/9/9 endSpan=10 oppSeg/Span/PtT=13/25/25 oppEndSpan=26 MissingCoin 28602: seg/base=13/25 seg/base=5/9 MarkCoinStart 28703: seg/base=13/26 seg/base=5/10 MarkCoinEnd 28804: seg/base=4/7 seg/base=12/23 MarkCoinStart 28905: seg/base=4/8 seg/base=12/24 MarkCoinEnd 29006: seg/base=11/33 seg/base=3/34 MarkCoinStart 29107: seg/base=11/22 seg/base=3/6 MarkCoinEnd 29208: seg/base=3/36 MarkCoinInsert 29309: seg/base=11/35 MarkCoinInsert 29410: seg/base=2/3 seg/base=10/19 MarkCoinStart 29511: seg/base=2/32 seg/base=10/31 MarkCoinEnd 29612: seg/base=10/29 MarkCoinInsert 29713: seg/base=2/30 MarkCoinInsert 29814: seg/base=9/28 seg/base=1/1 MarkCoinStart 29915: seg/base=9/18 seg/base=1/2 MarkCoinEnd 30016: seg/base=8/15 seg/base=6/11 MarkCoinStart 30117: seg/base=8/27 seg/base=6/12 MarkCoinEnd 302------------------xx-x-x-------------- move_multiples 30300: coinSeg/Span/PtT=5/9/9 endSpan=10 oppSeg/Span/PtT=13/25/25 oppEndSpan=26 MissingCoin 30401: coinSeg/Span/PtT=5/9/9 endSpan=10 oppSeg/Span/PtT=13/25/25 oppEndSpan=26 MissingCoin 30502: seg/base=13/25 seg/base=5/9 MarkCoinStart 30603: seg/base=13/26 seg/base=5/10 MarkCoinEnd 30704: seg/base=4/7 seg/base=12/23 MarkCoinStart 30805: seg/base=4/8 seg/base=12/24 MarkCoinEnd 30906: seg/base=11/33 seg/base=3/34 MarkCoinStart 31007: seg/base=11/22 seg/base=3/6 MarkCoinEnd 31108: seg/base=3/36 MarkCoinInsert 31209: seg/base=11/35 MarkCoinInsert 31310: seg/base=2/3 seg/base=10/19 MarkCoinStart 31411: seg/base=2/32 seg/base=10/31 MarkCoinEnd 31512: seg/base=10/29 MarkCoinInsert 31613: seg/base=2/30 MarkCoinInsert 31714: seg/base=9/28 seg/base=1/1 MarkCoinStart 31815: seg/base=9/18 seg/base=1/2 MarkCoinEnd 31916: seg/base=8/15 seg/base=6/11 MarkCoinStart 32017: seg/base=8/27 seg/base=6/12 MarkCoinEnd 321------------------xx-x-x-------------- move_nearby 32200: coinSeg/Span/PtT=5/9/9 endSpan=10 oppSeg/Span/PtT=13/25/25 oppEndSpan=26 MissingCoin 32301: coinSeg/Span/PtT=5/9/9 endSpan=10 oppSeg/Span/PtT=13/25/25 oppEndSpan=26 MissingCoin 32402: seg/base=13/25 seg/base=5/9 MarkCoinStart 32503: seg/base=13/26 seg/base=5/10 MarkCoinEnd 32604: seg/base=4/7 seg/base=12/23 MarkCoinStart 32705: seg/base=4/8 seg/base=12/24 MarkCoinEnd 32806: seg/base=11/33 seg/base=3/34 MarkCoinStart 32907: seg/base=11/22 seg/base=3/6 MarkCoinEnd 33008: seg/base=3/36 MarkCoinInsert 33109: seg/base=11/35 MarkCoinInsert 33210: seg/base=2/3 seg/base=10/19 MarkCoinStart 33311: seg/base=2/32 seg/base=10/31 MarkCoinEnd 33412: seg/base=10/29 MarkCoinInsert 33513: seg/base=2/30 MarkCoinInsert 33614: seg/base=9/28 seg/base=1/1 MarkCoinStart 33715: seg/base=9/18 seg/base=1/2 MarkCoinEnd 33816: seg/base=8/15 seg/base=6/11 MarkCoinStart 33917: seg/base=8/27 seg/base=6/12 MarkCoinEnd 340------------------xx-x-x-------------- addExpanded 34100: coinSeg/Span/PtT=5/9/9 endSpan=10 oppSeg/Span/PtT=13/25/25 oppEndSpan=26 MissingCoin 34201: coinSeg/Span/PtT=5/9/9 endSpan=10 oppSeg/Span/PtT=13/25/25 oppEndSpan=26 MissingCoin 34302: seg/base=13/25 seg/base=5/9 MarkCoinStart 34403: seg/base=13/26 seg/base=5/10 MarkCoinEnd 34504: seg/base=4/7 seg/base=12/23 MarkCoinStart 34605: seg/base=4/8 seg/base=12/24 MarkCoinEnd 34706: seg/base=11/33 seg/base=3/34 MarkCoinStart 34807: seg/base=11/22 seg/base=3/6 MarkCoinEnd 34908: seg/base=3/36 MarkCoinInsert 35009: seg/base=11/35 MarkCoinInsert 35110: seg/base=2/3 seg/base=10/19 MarkCoinStart 35211: seg/base=2/32 seg/base=10/31 MarkCoinEnd 35312: seg/base=10/29 MarkCoinInsert 35413: seg/base=2/30 MarkCoinInsert 35514: seg/base=9/28 seg/base=1/1 MarkCoinStart 35615: seg/base=9/18 seg/base=1/2 MarkCoinEnd 35716: seg/base=8/15 seg/base=6/11 MarkCoinStart 35817: seg/base=8/27 seg/base=6/12 MarkCoinEnd 359------------------xx-x-x-------------- mark 36000: coinSeg/Span/PtT=5/9/9 endSpan=10 oppSeg/Span/PtT=13/25/25 oppEndSpan=26 MissingCoin 36101: coinSeg/Span/PtT=5/9/9 endSpan=10 oppSeg/Span/PtT=13/25/25 oppEndSpan=26 MissingCoin 36202: seg/base=13/25 seg/base=5/9 MarkCoinStart 36303: seg/base=13/26 seg/base=5/10 MarkCoinEnd 36404: seg/base=4/7 seg/base=12/23 MarkCoinStart 36505: seg/base=4/8 seg/base=12/24 MarkCoinEnd 36606: seg/base=11/33 seg/base=3/34 MarkCoinStart 36707: seg/base=11/22 seg/base=3/6 MarkCoinEnd 36808: seg/base=3/36 MarkCoinInsert 36909: seg/base=11/35 MarkCoinInsert 37010: seg/base=2/3 seg/base=10/19 MarkCoinStart 37111: seg/base=2/32 seg/base=10/31 MarkCoinEnd 37212: seg/base=10/29 MarkCoinInsert 37313: seg/base=2/30 MarkCoinInsert 37414: seg/base=9/28 seg/base=1/1 MarkCoinStart 37515: seg/base=9/18 seg/base=1/2 MarkCoinEnd 37616: seg/base=8/15 seg/base=6/11 MarkCoinStart 37717: seg/base=8/27 seg/base=6/12 MarkCoinEnd 378-------------------------------------- missing_coincidence 379-------------------------------------- expand 380-------------------------------------- expand 381-------------------------------------- apply 382SkOpSegment::markDone id=5 (118.119003,8.07219982 8.17210007,104.212997) t=0 [9] (118.119003,8.07219982) tEnd=1 newWindSum=? newOppSum=? oppSum=? windSum=? windValue=0 oppValue=0 383SkOpSegment::markDone id=12 (123.289001,9.39620018 118.119003,8.07219982) t=0 [23] (123.289001,9.39620018) tEnd=1 newWindSum=? newOppSum=? oppSum=? windSum=? windValue=0 oppValue=0 384SkOpSegment::markDone id=3 (124.603165,9.37966728 124.142731,9.41717815 123.674263,9.45534515 123.289001,9.39610004) t=0.0627286673 [34] (124.516441,9.38671017) tEnd=0.625091708 newWindSum=? newOppSum=? oppSum=? windSum=? windValue=0 oppValue=0 385SkOpSegment::markDone id=3 (124.603165,9.37966728 124.142731,9.41717815 123.674263,9.45534515 123.289001,9.39610004) t=0.625091708 [36] (123.752594,9.42682648) tEnd=1 newWindSum=? newOppSum=? oppSum=? windSum=? windValue=0 oppValue=0 386SkOpSegment::markDone id=10 (126,9.39620018 125.631981,9.29586983 125.12252,9.3373785 124.602829,9.37972069) t=0 [19] (126,9.39620018) tEnd=0.307128906 newWindSum=? newOppSum=? oppSum=? windSum=? windValue=0 oppValue=0 387SkOpSegment::markDone id=10 (126,9.39620018 125.631981,9.29586983 125.12252,9.3373785 124.602829,9.37972069) t=0.307128906 [29] (125.624687,9.33981037) tEnd=0.9375 newWindSum=? newOppSum=? oppSum=? windSum=? windValue=0 oppValue=0 388SkOpSegment::markDone id=1 (0,353.891998 126,9.39610004) t=0 [1] (0,353.891998) tEnd=1 newWindSum=? newOppSum=? oppSum=? windSum=? windValue=0 oppValue=0 389SkOpSegment::markDone id=6 (8.17210007,104.212997 0,259.298737) t=0 [11] (8.17210007,104.212997) tEnd=1 newWindSum=? newOppSum=? oppSum=? windSum=? windValue=0 oppValue=0 390-------------------------------------- findOverlaps 391SkOpSegment::debugShowActiveSpans id=8 (8.17210007,104.212997 -2.71619996e-07,259.298737) t=0 tEnd=0.583904956 windSum=? oppSum=? windValue=1 oppValue=1 392SkOpSegment::debugShowActiveSpans id=8 (-2.71619996e-07,259.298737 -5.82350016,369.813995) t=0.583904956 tEnd=1 windSum=? windValue=1 393SkOpSegment::debugShowActiveSpans id=9 (-5.82350016,369.813995 7.26031715e-07,353.891998) t=0 tEnd=0.0441765002 windSum=? windValue=1 394SkOpSegment::debugShowActiveSpans id=9 (7.26031715e-07,353.891998 126,9.39620018) t=0.0441765002 tEnd=1 windSum=? oppSum=? windValue=1 oppValue=1 395SkOpSegment::debugShowActiveSpans id=10 (124.700119,9.37182617 124.66775,9.37443162 124.63531,9.3770743 124.602829,9.37972069) t=0.9375 tEnd=1 windSum=? windValue=1 396SkOpSegment::debugShowActiveSpans id=11 (124.602829,9.37972069 124.574059,9.3820647 124.545259,9.38441166 124.516449,9.38673687) t=0 tEnd=0.0625 windSum=? windValue=1 397SkOpSegment::debugShowActiveSpans id=11 (124.516449,9.38673687 124.257155,9.40766372 123.997126,9.42685982 123.752594,9.4268837) t=0.0625 tEnd=0.625 windSum=? oppSum=? windValue=1 oppValue=1 398SkOpSegment::debugShowActiveSpans id=11 (123.752594,9.4268837 123.589573,9.42689962 123.433437,9.41839421 123.289001,9.39620018) t=0.625 tEnd=1 windSum=? oppSum=? windValue=1 oppValue=1 399SkOpSegment::debugShowActiveSpans id=13 (118.119003,8.07219982 8.17210007,104.212997) t=0 tEnd=1 windSum=? oppSum=? windValue=1 oppValue=1 400SkOpSegment::debugShowActiveSpans id=2 (126,9.39610004 125.886971,9.36530236 125.760605,9.34788101 125.624695,9.33975124) t=0 tEnd=0.307190555 windSum=? oppSum=? windValue=1 oppValue=1 401SkOpSegment::debugShowActiveSpans id=2 (125.624695,9.33975124 125.345738,9.3230648 125.026588,9.34552196 124.700119,9.37180042) t=0.307190555 tEnd=0.937702598 windSum=? oppSum=? windValue=1 oppValue=1 402SkOpSegment::debugShowActiveSpans id=2 (124.700119,9.37180042 124.667862,9.37439685 124.635532,9.37703031 124.603165,9.37966728) t=0.937702598 tEnd=1 windSum=? windValue=1 403SkOpSegment::debugShowActiveSpans id=3 (124.603165,9.37966728 124.574282,9.38202029 124.545364,9.3843762 124.516441,9.38671017) t=0 tEnd=0.0627286673 windSum=? windValue=1 404SkOpSegment::debugShowActiveSpans id=4 (123.289001,9.39610004 118.119003,8.07219982) t=0 tEnd=1 windSum=? oppSum=? windValue=1 oppValue=1 405SkOpSegment::debugShowActiveSpans id=7 (0,259.298737 0,353.891998) t=0 tEnd=1 windSum=? windValue=1 406-------------------------------------- calc_angles 407SkOpSegment::sortAngles [8] tStart=0 [15] 408SkOpSegment::sortAngles [8] tStart=0.583904956 [27] 409SkOpAngle::after [8/2] 5/5 tStart=0.583904956 tEnd=0 < [7/23] 23/23 tStart=0 tEnd=1 < [8/3] 21/21 tStart=0.583904956 tEnd=1 F 4 410SkOpAngle::afterPart {{{0,259.298737}, {8.17210034,104.212997}}} id=8 411SkOpAngle::afterPart {{{0,259.298737}, {0,353.891998}}} id=7 412SkOpAngle::afterPart {{{0,259.298737}, {-5.82349988,369.813995}}} id=8 413SkOpSegment::sortAngles [9] tStart=0.0441765002 [28] 414SkOpAngle::after [9/4] 21/21 tStart=0.0441765002 tEnd=0 < [7/24] 7/7 tStart=1 tEnd=0 < [9/5] 5/5 tStart=0.0441765002 tEnd=1 F 4 415SkOpAngle::afterPart {{{0,353.891998}, {-5.82350088,369.813995}}} id=9 416SkOpAngle::afterPart {{{0,353.891998}, {0,259.298737}}} id=7 417SkOpAngle::afterPart {{{0,353.891998}, {125.999999,9.39620018}}} id=9 418SkOpSegment::sortAngles [9] tStart=1 [18] 419SkOpSegment::sortAngles [10] tStart=0.9375 [31] 420SkOpAngle::after [10/7] 17/17 tStart=0.9375 tEnd=1 < [2/19] 17/17 tStart=0.937702598 tEnd=1 < [2/18] 1/1 tStart=0.937702598 tEnd=0.307190555 T 12 421SkOpAngle::afterPart {{{124.700119,9.37180042}, {124.66775,9.37440587}, {124.63531,9.37704855}, {124.602829,9.37969494}}} id=10 422SkOpAngle::afterPart {{{124.700119,9.37180042}, {124.667862,9.37439685}, {124.635532,9.37703031}, {124.603165,9.37966728}}} id=2 423SkOpAngle::afterPart {{{124.700119,9.37180042}, {125.026588,9.34552196}, {125.345738,9.3230648}, {125.624695,9.33975124}}} id=2 424SkOpSegment::sortAngles [11] tStart=0.0625 [33] 425SkOpAngle::after [11/8] 1/1 tStart=0.0625 tEnd=0 < [3/20] 1/1 tStart=0.0627286673 tEnd=0 < [11/9] 17/17 tStart=0.0625 tEnd=0.625 T 12 426SkOpAngle::afterPart {{{124.516441,9.38671017}, {124.545252,9.38438496}, {124.574051,9.382038}, {124.602821,9.37969398}}} id=11 427SkOpAngle::afterPart {{{124.516441,9.38671017}, {124.545364,9.3843762}, {124.574282,9.38202029}, {124.603165,9.37966728}}} id=3 428SkOpAngle::afterPart {{{124.516441,9.38671017}, {124.257148,9.40763702}, {123.997118,9.42683311}, {123.752586,9.42685699}}} id=11 429SkOpSegment::sortAngles [11] tStart=0.625 [35] 430SkOpSegment::sortAngles [11] tStart=1 [22] 431SkOpSegment::sortAngles [13] tStart=0 [25] 432SkOpSegment::sortAngles [13] tStart=1 [26] 433SkOpSegment::sortAngles [2] tStart=0 [3] 434SkOpSegment::sortAngles [2] tStart=0.307190555 [30] 435SkOpSegment::sortAngles [2] tStart=0.937702598 [32] 436SkOpSegment::sortAngles [3] tStart=0.0627286673 [34] 437SkOpSegment::sortAngles [4] tStart=0 [7] 438SkOpSegment::sortAngles [4] tStart=1 [8] 439SkOpSegment::sortAngles [7] tStart=0 [13] 440SkOpSegment::sortAngles [7] tStart=1 [14] 441coinSpan - id=13 t=0 tEnd=1 442coinSpan + id=5 t=0 tEnd=1 443coinSpan - id=4 t=0 tEnd=1 444coinSpan + id=12 t=0 tEnd=1 445coinSpan - id=11 t=0.0625 tEnd=1 446coinSpan + id=3 t=0.0627286673 tEnd=1 447coinSpan - id=2 t=0 tEnd=0.937702598 448coinSpan + id=10 t=0 tEnd=0.9375 449coinSpan - id=9 t=0.0441765002 tEnd=1 450coinSpan + id=1 t=0 tEnd=1 451coinSpan - id=8 t=0 tEnd=0.583904956 452coinSpan + id=6 t=0 tEnd=1 453SkOpSpan::sortableTop dir=kLeft seg=8 t=0.291952478 pt=(4.08605003,181.755859) 454SkOpSpan::sortableTop [0] valid=1 operand=1 span=15 ccw=0 seg=8 {{{8.17210007f, 104.212997f}, {-5.82350016f, 369.813995f}}} t=0.291952478 pt=(4.08605003,181.755859) slope=(-13.9956002,265.600998) 455SkOpSegment::markWinding id=8 (8.17210007,104.212997 -5.82350016,369.813995) t=0 [15] (8.17210007,104.212997) tEnd=0.583904956 newWindSum=1 newOppSum=1 oppSum=1 windSum=1 windValue=1 oppValue=1 456SkOpSegment::markWinding id=8 (8.17210007,104.212997 -5.82350016,369.813995) t=0 [15] (8.17210007,104.212997) tEnd=0.583904956 newWindSum=1 newOppSum=1 oppSum=1 windSum=1 windValue=1 oppValue=1 457SkOpSegment::markWinding id=13 (118.119003,8.07219982 8.17210007,104.212997) t=0 [25] (118.119003,8.07219982) tEnd=1 newWindSum=1 newOppSum=1 oppSum=? windSum=? windValue=1 oppValue=1 458SkOpSegment::markWinding id=4 (123.289001,9.39610004 118.119003,8.07219982) t=0 [7] (123.289001,9.39610004) tEnd=1 newWindSum=1 newOppSum=1 oppSum=? windSum=? windValue=1 oppValue=1 459SkOpSegment::markWinding id=11 (124.602829,9.37972069 124.142509,9.41722488 123.674164,9.45538425 123.289001,9.39620018) t=0.625 [35] (123.752594,9.4268837) tEnd=1 newWindSum=1 newOppSum=1 oppSum=? windSum=? windValue=1 oppValue=1 460SkOpSegment::markWinding id=11 (124.602829,9.37972069 124.142509,9.41722488 123.674164,9.45538425 123.289001,9.39620018) t=0.0625 [33] (124.516449,9.38673687) tEnd=0.625 newWindSum=1 newOppSum=1 oppSum=? windSum=? windValue=1 oppValue=1 461SkOpSegment::activeOp id=8 t=0.583904956 tEnd=0 op=sect miFrom=1 miTo=0 suFrom=1 suTo=0 result=1 462SkOpSegment::findNextOp simple 463SkOpSegment::markDone id=8 (8.17210007,104.212997 -5.82350016,369.813995) t=0 [15] (8.17210007,104.212997) tEnd=0.583904956 newWindSum=1 newOppSum=1 oppSum=1 windSum=1 windValue=1 oppValue=1 464bridgeOp current id=8 from=(-2.71619996e-07,259.298737) to=(8.17210007,104.212997) 465SkOpSegment::findNextOp simple 466SkOpSegment::markDone id=13 (118.119003,8.07219982 8.17210007,104.212997) t=0 [25] (118.119003,8.07219982) tEnd=1 newWindSum=1 newOppSum=1 oppSum=1 windSum=1 windValue=1 oppValue=1 467bridgeOp current id=13 from=(8.17210007,104.212997) to=(118.119003,8.07219982) 468path.moveTo(-2.71619996e-07,259.298737); 469path.lineTo(8.17210007,104.212997); 470SkOpSegment::findNextOp simple 471SkOpSegment::markDone id=4 (123.289001,9.39610004 118.119003,8.07219982) t=0 [7] (123.289001,9.39610004) tEnd=1 newWindSum=1 newOppSum=1 oppSum=1 windSum=1 windValue=1 oppValue=1 472bridgeOp current id=4 from=(118.119003,8.07219982) to=(123.289001,9.39610004) 473path.lineTo(118.119003,8.07219982); 474SkOpSegment::findNextOp simple 475SkOpSegment::markDone id=11 (124.602829,9.37972069 124.142509,9.41722488 123.674164,9.45538425 123.289001,9.39620018) t=0.625 [35] (123.752594,9.4268837) tEnd=1 newWindSum=1 newOppSum=1 oppSum=1 windSum=1 windValue=1 oppValue=1 476bridgeOp current id=11 from=(123.289001,9.39620018) to=(123.752594,9.4268837) 477path.lineTo(123.289001,9.39610004); 478path.cubicTo(123.433441,9.41839409, 123.589569,9.42689991, 123.752594,9.4268837); 479SkOpSegment::markWinding id=11 (124.602829,9.37972069 124.142509,9.41722488 123.674164,9.45538425 123.289001,9.39620018) t=0 [21] (124.602829,9.37972069) tEnd=0.0625 newWindSum=1 newOppSum=1 oppSum=? windSum=? windValue=1 oppValue=0 480SkOpSegment::markWinding id=10 (126,9.39620018 125.631981,9.29586983 125.12252,9.3373785 124.602829,9.37972069) t=0.9375 [31] (124.700119,9.37182617) tEnd=1 newWindSum=1 newOppSum=1 oppSum=? windSum=? windValue=1 oppValue=0 481SkOpSegment::markAngle last segment=10 span=31 windSum=1 482SkOpSegment::markWinding id=3 (124.603165,9.37966728 124.142731,9.41717815 123.674263,9.45534515 123.289001,9.39610004) t=0 [5] (124.603165,9.37966728) tEnd=0.0627286673 newWindSum=1 newOppSum=0 oppSum=? windSum=? windValue=1 oppValue=0 483SkOpSegment::markWinding id=2 (126,9.39610004 125.632057,9.29584408 125.122734,9.33733845 124.603165,9.37966728) t=0.937702598 [32] (124.700119,9.37180042) tEnd=1 newWindSum=1 newOppSum=0 oppSum=? windSum=? windValue=1 oppValue=0 484SkOpSegment::markAngle last segment=2 span=32 windSum=1 485SkOpSegment::findNextOp 486SkOpAngle::dumpOne [11/9] next=11/8 sect=17/17 s=0.0625 [33] e=0.625 [35] sgn=-1 windVal=1 windSum=1 oppVal=1 oppSum=1 operand 487SkOpAngle::dumpOne [11/8] next=3/20 sect=1/1 s=0.0625 [33] e=0 [21] sgn=1 windVal=1 windSum=1 oppVal=0 oppSum=1 operand 488SkOpAngle::dumpOne [3/20] next=11/9 sect=1/1 s=0.0627286673 [34] e=0 [5] sgn=1 windVal=1 windSum=1 oppVal=0 oppSum=0 489SkOpSegment::activeOp id=11 t=0.0625 tEnd=0 op=sect miFrom=1 miTo=1 suFrom=1 suTo=0 result=1 490SkOpSegment::findNextOp chase.append segment=10 span=31 windSum=1 491SkOpSegment::activeOp id=3 t=0.0627286673 tEnd=0 op=sect miFrom=1 miTo=0 suFrom=0 suTo=0 result=0 492SkOpSegment::markDone id=3 (124.603165,9.37966728 124.142731,9.41717815 123.674263,9.45534515 123.289001,9.39610004) t=0 [5] (124.603165,9.37966728) tEnd=0.0627286673 newWindSum=1 newOppSum=0 oppSum=0 windSum=1 windValue=1 oppValue=0 493SkOpSegment::markDone id=2 (126,9.39610004 125.632057,9.29584408 125.122734,9.33733845 124.603165,9.37966728) t=0.937702598 [32] (124.700119,9.37180042) tEnd=1 newWindSum=1 newOppSum=0 oppSum=0 windSum=1 windValue=1 oppValue=0 494SkOpSegment::findNextOp chase.append segment=2 span=32 windSum=1 495SkOpSegment::markDone id=11 (124.602829,9.37972069 124.142509,9.41722488 123.674164,9.45538425 123.289001,9.39620018) t=0.0625 [33] (124.516449,9.38673687) tEnd=0.625 newWindSum=1 newOppSum=1 oppSum=1 windSum=1 windValue=1 oppValue=1 496SkOpSegment::findNextOp from:[11] to:[11] start=-1132576784 end=-1353716568 497bridgeOp current id=11 from=(123.752594,9.4268837) to=(124.516449,9.38673687) 498path.cubicTo(123.997124,9.42685986, 124.257156,9.40766335, 124.516449,9.38673687); 499SkOpSegment::findNextOp simple 500SkOpSegment::markDone id=11 (124.602829,9.37972069 124.142509,9.41722488 123.674164,9.45538425 123.289001,9.39620018) t=0 [21] (124.602829,9.37972069) tEnd=0.0625 newWindSum=1 newOppSum=1 oppSum=1 windSum=1 windValue=1 oppValue=0 501bridgeOp current id=11 from=(124.516449,9.38673687) to=(124.602829,9.37972069) 502path.cubicTo(124.545258,9.38441181, 124.574059,9.38206482, 124.602829,9.37972069); 503SkOpSegment::markWinding id=2 (126,9.39610004 125.632057,9.29584408 125.122734,9.33733845 124.603165,9.37966728) t=0.307190555 [30] (125.624695,9.33975124) tEnd=0.937702598 newWindSum=1 newOppSum=-1 oppSum=? windSum=? windValue=1 oppValue=1 504SkOpSegment::markWinding id=2 (126,9.39610004 125.632057,9.29584408 125.122734,9.33733845 124.603165,9.37966728) t=0 [3] (126,9.39610004) tEnd=0.307190555 newWindSum=1 newOppSum=-1 oppSum=? windSum=? windValue=1 oppValue=1 505SkOpSegment::markWinding id=9 (-5.82350016,369.813995 126,9.39620018) t=0.0441765002 [28] (7.26031715e-07,353.891998) tEnd=1 newWindSum=-1 newOppSum=1 oppSum=? windSum=? windValue=1 oppValue=1 506SkOpSegment::markAngle last segment=9 span=28 windSum=-1 507SkOpSegment::findNextOp 508SkOpAngle::dumpOne [10/7] next=2/19 sect=17/17 s=0.9375 [31] e=1 [20] sgn=-1 windVal=1 windSum=1 oppVal=0 oppSum=1 operand 509SkOpAngle::dumpOne [2/19] next=2/18 sect=17/17 s=0.937702598 [32] e=1 [4] sgn=-1 windVal=1 windSum=1 oppVal=0 oppSum=0 done 510SkOpAngle::dumpOne [2/18] next=10/7 sect=1/1 s=0.937702598 [32] e=0.307190555 [30] sgn=1 windVal=1 windSum=1 oppVal=1 oppSum=-1 511SkOpSegment::activeOp id=2 t=0.937702598 tEnd=1 op=sect = result=1 512SkOpSegment::activeOp id=2 t=0.937702598 tEnd=0.307190555 op=sect miFrom=0 miTo=1 suFrom=1 suTo=0 result=0 513SkOpSegment::markDone id=2 (126,9.39610004 125.632057,9.29584408 125.122734,9.33733845 124.603165,9.37966728) t=0.307190555 [30] (125.624695,9.33975124) tEnd=0.937702598 newWindSum=1 newOppSum=-1 oppSum=-1 windSum=1 windValue=1 oppValue=1 514SkOpSegment::markDone id=2 (126,9.39610004 125.632057,9.29584408 125.122734,9.33733845 124.603165,9.37966728) t=0 [3] (126,9.39610004) tEnd=0.307190555 newWindSum=1 newOppSum=-1 oppSum=-1 windSum=1 windValue=1 oppValue=1 515SkOpSegment::markDone id=9 (-5.82350016,369.813995 126,9.39620018) t=0.0441765002 [28] (7.26031715e-07,353.891998) tEnd=1 newWindSum=-1 newOppSum=1 oppSum=1 windSum=-1 windValue=1 oppValue=1 516SkOpSegment::findNextOp chase.append segment=9 span=28 windSum=-1 517SkOpSegment::markDone id=10 (126,9.39620018 125.631981,9.29586983 125.12252,9.3373785 124.602829,9.37972069) t=0.9375 [31] (124.700119,9.37182617) tEnd=1 newWindSum=1 newOppSum=1 oppSum=1 windSum=1 windValue=1 oppValue=0 518SkOpSegment::findNextOp from:[10] to:[2] start=-1132576976 end=-1353719496 519bridgeOp current id=10 from=(124.602829,9.37972069) to=(124.700119,9.37182617) 520path.cubicTo(124.635307,9.37707424, 124.667747,9.37443161, 124.700119,9.37182617); 521SkOpSegment::markWinding id=7 (0,259.298737 0,353.891998) t=0 [13] (0,259.298737) tEnd=1 newWindSum=1 newOppSum=0 oppSum=? windSum=? windValue=1 oppValue=0 522SkOpSegment::markWinding id=9 (-5.82350016,369.813995 126,9.39620018) t=0 [17] (-5.82350016,369.813995) tEnd=0.0441765002 newWindSum=-1 newOppSum=0 oppSum=? windSum=? windValue=1 oppValue=0 523SkOpSegment::markWinding id=8 (8.17210007,104.212997 -5.82350016,369.813995) t=0.583904956 [27] (-2.71619996e-07,259.298737) tEnd=1 newWindSum=-1 newOppSum=0 oppSum=? windSum=? windValue=1 oppValue=0 524SkOpSegment::debugShowActiveSpans id=8 (-2.71619996e-07,259.298737 -5.82350016,369.813995) t=0.583904956 tEnd=1 windSum=-1 oppSum=0 windValue=1 oppValue=0 525SkOpSegment::debugShowActiveSpans id=9 (-5.82350016,369.813995 7.26031715e-07,353.891998) t=0 tEnd=0.0441765002 windSum=-1 oppSum=0 windValue=1 oppValue=0 526SkOpSegment::debugShowActiveSpans id=7 (0,259.298737 0,353.891998) t=0 tEnd=1 windSum=1 oppSum=0 windValue=1 oppValue=0 527SkOpSegment::activeOp id=7 t=1 tEnd=0 op=sect miFrom=1 miTo=0 suFrom=0 suTo=0 result=0 528SkOpSegment::markDone id=7 (0,259.298737 0,353.891998) t=0 [13] (0,259.298737) tEnd=1 newWindSum=1 newOppSum=0 oppSum=0 windSum=1 windValue=1 oppValue=0 529bridgeOp chase.append id=7 windSum=1 530SkOpSegment::debugShowActiveSpans id=8 (-2.71619996e-07,259.298737 -5.82350016,369.813995) t=0.583904956 tEnd=1 windSum=-1 oppSum=0 windValue=1 oppValue=0 531SkOpSegment::debugShowActiveSpans id=9 (-5.82350016,369.813995 7.26031715e-07,353.891998) t=0 tEnd=0.0441765002 windSum=-1 oppSum=0 windValue=1 oppValue=0 532SkOpSegment::activeOp id=8 t=0.583904956 tEnd=1 op=sect miFrom=0 miTo=0 suFrom=1 suTo=0 result=0 533SkOpSegment::markDone id=8 (8.17210007,104.212997 -5.82350016,369.813995) t=0.583904956 [27] (-2.71619996e-07,259.298737) tEnd=1 newWindSum=-1 newOppSum=0 oppSum=0 windSum=-1 windValue=1 oppValue=0 534SkOpSegment::markDone id=9 (-5.82350016,369.813995 126,9.39620018) t=0 [17] (-5.82350016,369.813995) tEnd=0.0441765002 newWindSum=-1 newOppSum=0 oppSum=0 windSum=-1 windValue=1 oppValue=0 535</div> 536 537 538 539 </div> 540 541<script type="text/javascript"> 542 543 var testDivs = [ 544 bug8380, 545 ]; 546 547var decimal_places = 3; // make this 3 to show more precision 548 549var tests = []; 550var testLines = []; 551var testTitles = []; 552var testIndex = 0; 553var ctx; 554 555var xmin, xmax, focusXmin, focusXmax; 556var ymin, ymax, focusYmin, focusYmax; 557var scale; 558var mouseX, mouseY; 559var srcLeft, srcTop; 560var screenWidth, screenHeight; 561var drawnPts, drawnLines, drawnQuads, drawnConics, drawnCubics; 562var curveT = 0; 563 564var pt_labels = 2; 565var collect_bounds = false; 566var control_lines = 0; 567var curve_t = false; 568var debug_xy = 1; 569var focus_enabled = false; 570var focus_on_selection = false; 571var step_limit = 0; 572var draw_active = false; 573var draw_add = false; 574var draw_angle = 0; 575var draw_coincidence = false; 576var draw_deriviatives = 0; 577var draw_direction = false; 578var draw_hints = false; 579var draw_id = false; 580var draw_intersection = 0; 581var draw_intersectT = false; 582var draw_legend = true; 583var draw_log = false; 584var draw_mark = false; 585var draw_midpoint = false; 586var draw_op = 0; 587var draw_sequence = false; 588var draw_sort = 0; 589var draw_top = false; 590var draw_path = 3; 591var draw_computed = 0; 592var retina_scale = !!window.devicePixelRatio; 593 594var activeCount = 0; 595var addCount = 0; 596var angleCount = 0; 597var coinCount = 0; 598var opCount = 0; 599var sectCount = 0; 600var sortCount = 0; 601var topCount = 0; 602var markCount = 0; 603var activeMax = 0; 604var addMax = 0; 605var angleMax = 0; 606var coinMax = 0; 607var sectMax = 0; 608var sectMax2 = 0; 609var sortMax = 0; 610var topMax = 0; 611var markMax = 0; 612var opMax = 0; 613var stepMax = 0; 614var lastIndex = 0; 615var hasPath = false; 616var hasAlignedPath = false; 617var hasComputedPath = false; 618var angleBetween = false; 619var afterIndex = 0; 620 621var firstActiveSpan = -1; 622var logStart = -1; 623var logRange = 0; 624 625var SPAN_ID = 0; 626var SPAN_X1 = SPAN_ID + 1; 627var SPAN_Y1 = SPAN_X1 + 1; 628var SPAN_X2 = SPAN_Y1 + 1; 629var SPAN_Y2 = SPAN_X2 + 1; 630 631var SPAN_L_TX = SPAN_Y2 + 1; 632var SPAN_L_TY = SPAN_L_TX + 1; 633var SPAN_L_OTHER = SPAN_L_TY + 1; 634var SPAN_L_OTHERT = SPAN_L_OTHER + 1; 635var SPAN_L_OTHERI = SPAN_L_OTHERT + 1; 636var SPAN_L_SUM = SPAN_L_OTHERI + 1; 637var SPAN_L_VAL = SPAN_L_SUM + 1; 638var SPAN_L_OPP = SPAN_L_VAL + 1; 639 640var SPAN_X3 = SPAN_Y2 + 1; 641var SPAN_Y3 = SPAN_X3 + 1; 642 643var SPAN_Q_TX = SPAN_Y3 + 1; 644var SPAN_Q_TY = SPAN_Q_TX + 1; 645var SPAN_Q_OTHER = SPAN_Q_TY + 1; 646var SPAN_Q_OTHERT = SPAN_Q_OTHER + 1; 647var SPAN_Q_OTHERI = SPAN_Q_OTHERT + 1; 648var SPAN_Q_SUM = SPAN_Q_OTHERI + 1; 649var SPAN_Q_VAL = SPAN_Q_SUM + 1; 650var SPAN_Q_OPP = SPAN_Q_VAL + 1; 651 652var SPAN_K_W = SPAN_Y3 + 1; 653var SPAN_K_TX = SPAN_K_W + 1; 654var SPAN_K_TY = SPAN_K_TX + 1; 655var SPAN_K_OTHER = SPAN_K_TY + 1; 656var SPAN_K_OTHERT = SPAN_K_OTHER + 1; 657var SPAN_K_OTHERI = SPAN_K_OTHERT + 1; 658var SPAN_K_SUM = SPAN_K_OTHERI + 1; 659var SPAN_K_VAL = SPAN_K_SUM + 1; 660var SPAN_K_OPP = SPAN_K_VAL + 1; 661 662var SPAN_X4 = SPAN_Y3 + 1; 663var SPAN_Y4 = SPAN_X4 + 1; 664 665var SPAN_C_TX = SPAN_Y4 + 1; 666var SPAN_C_TY = SPAN_C_TX + 1; 667var SPAN_C_OTHER = SPAN_C_TY + 1; 668var SPAN_C_OTHERT = SPAN_C_OTHER + 1; 669var SPAN_C_OTHERI = SPAN_C_OTHERT + 1; 670var SPAN_C_SUM = SPAN_C_OTHERI + 1; 671var SPAN_C_VAL = SPAN_C_SUM + 1; 672var SPAN_C_OPP = SPAN_C_VAL + 1; 673 674var ACTIVE_LINE_SPAN = 1; 675var ACTIVE_QUAD_SPAN = ACTIVE_LINE_SPAN + 1; 676var ACTIVE_CONIC_SPAN = ACTIVE_QUAD_SPAN + 1; 677var ACTIVE_CUBIC_SPAN = ACTIVE_CONIC_SPAN + 1; 678 679var ADD_MOVETO = ACTIVE_CUBIC_SPAN + 1; 680var ADD_LINETO = ADD_MOVETO + 1; 681var ADD_QUADTO = ADD_LINETO + 1; 682var ADD_CONICTO = ADD_QUADTO + 1; 683var ADD_CUBICTO = ADD_CONICTO + 1; 684var ADD_CLOSE = ADD_CUBICTO + 1; 685var ADD_FILL = ADD_CLOSE + 1; 686 687var PATH_LINE = ADD_FILL + 1; 688var PATH_QUAD = PATH_LINE + 1; 689var PATH_CONIC = PATH_QUAD + 1; 690var PATH_CUBIC = PATH_CONIC + 1; 691 692var INTERSECT_LINE = PATH_CUBIC + 1; 693var INTERSECT_LINE_2 = INTERSECT_LINE + 1; 694var INTERSECT_LINE_NO = INTERSECT_LINE_2 + 1; 695var INTERSECT_QUAD_LINE = INTERSECT_LINE_NO + 1; 696var INTERSECT_QUAD_LINE_2 = INTERSECT_QUAD_LINE + 1; 697var INTERSECT_QUAD_LINE_NO = INTERSECT_QUAD_LINE_2 + 1; 698var INTERSECT_QUAD = INTERSECT_QUAD_LINE_NO + 1; 699var INTERSECT_QUAD_2 = INTERSECT_QUAD + 1; 700var INTERSECT_QUAD_NO = INTERSECT_QUAD_2 + 1; 701var INTERSECT_CONIC_LINE = INTERSECT_QUAD_NO + 1; 702var INTERSECT_CONIC_LINE_2 = INTERSECT_CONIC_LINE + 1; 703var INTERSECT_CONIC_LINE_NO = INTERSECT_CONIC_LINE_2 + 1; 704var INTERSECT_CONIC_QUAD = INTERSECT_CONIC_LINE_NO + 1; 705var INTERSECT_CONIC_QUAD_2 = INTERSECT_CONIC_QUAD + 1; 706var INTERSECT_CONIC_QUAD_3 = INTERSECT_CONIC_QUAD_2 + 1; 707var INTERSECT_CONIC_QUAD_4 = INTERSECT_CONIC_QUAD_3 + 1; 708var INTERSECT_CONIC_QUAD_NO = INTERSECT_CONIC_QUAD_4 + 1; 709var INTERSECT_CONIC = INTERSECT_CONIC_QUAD_NO + 1; 710var INTERSECT_CONIC_2 = INTERSECT_CONIC + 1; 711var INTERSECT_CONIC_NO = INTERSECT_CONIC_2 + 1; 712var INTERSECT_SELF_CUBIC = INTERSECT_CONIC_NO + 1; 713var INTERSECT_SELF_CUBIC_NO = INTERSECT_SELF_CUBIC + 1; 714var INTERSECT_CUBIC_LINE = INTERSECT_SELF_CUBIC_NO + 1; 715var INTERSECT_CUBIC_LINE_2 = INTERSECT_CUBIC_LINE + 1; 716var INTERSECT_CUBIC_LINE_3 = INTERSECT_CUBIC_LINE_2 + 1; 717var INTERSECT_CUBIC_LINE_NO = INTERSECT_CUBIC_LINE_3 + 1; 718var INTERSECT_CUBIC_QUAD = INTERSECT_CUBIC_LINE_NO + 1; 719var INTERSECT_CUBIC_QUAD_2 = INTERSECT_CUBIC_QUAD + 1; 720var INTERSECT_CUBIC_QUAD_3 = INTERSECT_CUBIC_QUAD_2 + 1; 721var INTERSECT_CUBIC_QUAD_4 = INTERSECT_CUBIC_QUAD_3 + 1; 722var INTERSECT_CUBIC_QUAD_NO = INTERSECT_CUBIC_QUAD_4 + 1; 723var INTERSECT_CUBIC = INTERSECT_CUBIC_QUAD_NO + 1; 724var INTERSECT_CUBIC_2 = INTERSECT_CUBIC + 1; 725var INTERSECT_CUBIC_3 = INTERSECT_CUBIC_2 + 1; 726var INTERSECT_CUBIC_4 = INTERSECT_CUBIC_3 + 1; 727// FIXME: add cubic 5- 9 728var INTERSECT_CUBIC_NO = INTERSECT_CUBIC_4 + 1; 729 730var SORT_UNARY = INTERSECT_CUBIC_NO + 1; 731var SORT_BINARY = SORT_UNARY + 1; 732 733var OP_DIFFERENCE = SORT_BINARY + 1; 734var OP_INTERSECT = OP_DIFFERENCE + 1; 735var OP_UNION = OP_INTERSECT + 1; 736var OP_XOR = OP_UNION + 1; 737 738var MARK_LINE = OP_XOR + 1; 739var MARK_QUAD = MARK_LINE + 1; 740var MARK_CONIC = MARK_QUAD + 1; 741var MARK_CUBIC = MARK_CONIC + 1; 742var MARK_DONE_LINE = MARK_CUBIC + 1; 743var MARK_DONE_QUAD = MARK_DONE_LINE + 1; 744var MARK_DONE_CONIC = MARK_DONE_QUAD + 1; 745var MARK_DONE_CUBIC = MARK_DONE_CONIC + 1; 746var MARK_UNSORTABLE_LINE = MARK_DONE_CUBIC + 1; 747var MARK_UNSORTABLE_QUAD = MARK_UNSORTABLE_LINE + 1; 748var MARK_UNSORTABLE_CONIC = MARK_UNSORTABLE_QUAD + 1; 749var MARK_UNSORTABLE_CUBIC = MARK_UNSORTABLE_CONIC + 1; 750var MARK_SIMPLE_LINE = MARK_UNSORTABLE_CUBIC + 1; 751var MARK_SIMPLE_QUAD = MARK_SIMPLE_LINE + 1; 752var MARK_SIMPLE_CONIC = MARK_SIMPLE_QUAD + 1; 753var MARK_SIMPLE_CUBIC = MARK_SIMPLE_CONIC + 1; 754var MARK_SIMPLE_DONE_LINE = MARK_SIMPLE_CUBIC + 1; 755var MARK_SIMPLE_DONE_QUAD = MARK_SIMPLE_DONE_LINE + 1; 756var MARK_SIMPLE_DONE_CONIC = MARK_SIMPLE_DONE_QUAD + 1; 757var MARK_SIMPLE_DONE_CUBIC = MARK_SIMPLE_DONE_CONIC + 1; 758var MARK_DONE_UNARY_LINE = MARK_SIMPLE_DONE_CUBIC + 1; 759var MARK_DONE_UNARY_QUAD = MARK_DONE_UNARY_LINE + 1; 760var MARK_DONE_UNARY_CONIC = MARK_DONE_UNARY_QUAD + 1; 761var MARK_DONE_UNARY_CUBIC = MARK_DONE_UNARY_CONIC + 1; 762var MARK_ANGLE_LAST = MARK_DONE_UNARY_CUBIC + 1; 763 764var COMPUTED_SET_1 = MARK_ANGLE_LAST + 1; 765var COMPUTED_SET_2 = COMPUTED_SET_1 + 1; 766 767var ANGLE_AFTER = COMPUTED_SET_2 + 1; 768var ANGLE_AFTERPART = ANGLE_AFTER + 1; 769 770var ACTIVE_OP = ANGLE_AFTERPART + 1; 771 772var COIN_MAIN_SPAN = ACTIVE_OP + 1; 773var COIN_OPP_SPAN = COIN_MAIN_SPAN + 1; 774 775var FRAG_TYPE_LAST = COIN_OPP_SPAN; 776 777var REC_TYPE_UNKNOWN = -1; 778var REC_TYPE_PATH = 0; 779var REC_TYPE_PATH2 = 1; 780var REC_TYPE_SECT = 2; 781var REC_TYPE_ACTIVE = 3; 782var REC_TYPE_ADD = 4; 783var REC_TYPE_SORT = 5; 784var REC_TYPE_OP = 6; 785var REC_TYPE_MARK = 7; 786var REC_TYPE_COMPUTED = 8; 787var REC_TYPE_COIN = 9; 788var REC_TYPE_ANGLE = 10; 789var REC_TYPE_ACTIVE_OP = 11; 790var REC_TYPE_AFTERPART = 12; 791var REC_TYPE_TOP = 13; 792var REC_TYPE_COINCIDENCE = 14; 793var REC_TYPE_ALIGNED = 15; 794var REC_TYPE_LAST = REC_TYPE_ALIGNED; 795 796function strs_to_nums(strs) { 797 var result = []; 798 for (var idx = 1; idx < strs.length; ++idx) { 799 var str = strs[idx]; 800 var num = parseFloat(str); 801 if (isNaN(num)) { 802 result.push(str); 803 } else { 804 result.push(num); 805 } 806 } 807 return result; 808} 809 810function filter_str_by(id, str, regex, array) { 811 if (regex.test(str)) { 812 var strs = regex.exec(str); 813 var result = strs_to_nums(strs); 814 array.push(id); 815 array.push(result); 816 return true; 817 } 818 return false; 819} 820 821function construct_regexp2(pattern) { 822 var escape = pattern.replace(/[-/\\^$*+?.()|[\]{}]/g, '\\$&'); 823 escape = escape.replace(/UNSORTABLE/g, "\\*\\*\\* UNSORTABLE \\*\\*\\*"); 824 escape = escape.replace(/CUBIC_VAL/g, "\\(P_VAL P_VAL P_VAL P_VAL\\)"); 825 escape = escape.replace(/CONIC_VAL/g, "\\(P_VAL P_VAL P_VAL W_VAL\\)"); 826 escape = escape.replace(/QUAD_VAL/g, "\\(P_VAL P_VAL P_VAL\\)"); 827 escape = escape.replace(/LINE_VAL/g, "\\(P_VAL P_VAL\\)"); 828 escape = escape.replace(/FILL_TYPE/g, "SkPath::k[a-zA-Z]+_FillType"); 829 escape = escape.replace(/PTR_VAL/g, "0x[0-9A-F]+"); 830 escape = escape.replace(/PT_VAL/g, "\\(P_VAL\\)"); 831 escape = escape.replace(/P_VAL/g, "(-?\\d+\\.?\\d*(?:e[+-]?\\d+)?)[Ff]?, ?(-?\\d+\\.?\\d*(?:e[+-]?\\d+)?)[Ff]?"); 832 escape = escape.replace(/T_VAL/g, "(-?\\d+\\.?\\d*(?:e[+-]?\\d+)?)"); 833 escape = escape.replace(/W_VAL/g, "(-?\\d+\\.?\\d*(?:e[+-]?\\d+)?)[Ff]?"); 834 escape = escape.replace(/PATH/g, "pathB?"); 835 escape = escape.replace(/IDX/g, "(-?\\d+)"); 836 escape = escape.replace(/NUM/g, "(-?\\d+)"); 837 escape = escape.replace(/OPT/g, "(\\?|-?\\d+)"); 838 return new RegExp(escape, 'i'); 839} 840 841function construct_regexp2c(pattern) { 842 var escape = pattern.replace(/[-/\\^$*+?.()|[\]{}]/g, '\\$&'); 843 escape = escape.replace(/UNSORTABLE/g, "\\*\\*\\* UNSORTABLE \\*\\*\\*"); 844 escape = escape.replace(/CUBIC_VAL/g, "(?:\\$\\d = )?\\{\\{\\{P_VAL\\}, \\{P_VAL\\}, \\{P_VAL\\}, \\{P_VAL\\}\\}\\}"); 845 escape = escape.replace(/CONIC_VAL/g, "(?:\\$\\d = )?\\{\\{\\{\\{P_VAL\\}, \\{P_VAL\\}, \\{P_VAL\\}\\}\\}, W_VAL\\}"); 846 escape = escape.replace(/QUAD_VAL/g, "(?:\\$\\d = )?\\{\\{\\{P_VAL\\}, \\{P_VAL\\}, \\{P_VAL\\}\\}\\}"); 847 escape = escape.replace(/LINE_VAL/g, "(?:\\$\\d = )?\\{\\{\\{P_VAL\\}, \\{P_VAL\\}\\}\\}"); 848 escape = escape.replace(/FILL_TYPE/g, "SkPath::k[a-zA-Z]+_FillType"); 849 escape = escape.replace(/PTR_VAL/g, "0x[0-9A-F]+"); 850 escape = escape.replace(/PT_VAL/g, "\\{\\{P_VAL\\}\\}"); 851 escape = escape.replace(/P_VAL/g, "(?:f?[xX] = )?(-?\\d+\\.?\\d*(?:e[+-]?\\d+)?)[Ff]?, *(?: f?[yY] = )?(-?\\d+\\.?\\d*(?:e[+-]?\\d+)?)[Ff]?"); 852 escape = escape.replace(/T_VAL/g, "(-?\\d+\\.?\\d*(?:e[+-]?\\d+)?)"); 853 escape = escape.replace(/W_VAL/g, "(-?\\d+\\.?\\d*(?:e[+-]?\\d+)?)[Ff]?"); 854 escape = escape.replace(/OPER/g, "[a-z]+"); 855 escape = escape.replace(/PATH/g, "pathB?"); 856 escape = escape.replace(/T_F/g, "([TF])"); 857 escape = escape.replace(/IDX/g, "(-?\\d+)"); 858 escape = escape.replace(/NUM/g, "(-?\\d+)"); 859 escape = escape.replace(/OPT/g, "(\\?|-?\\d+)"); 860 return new RegExp(escape, 'i'); 861} 862 863function match_regexp(str, lineNo, array, id, pattern) { 864 var regex = construct_regexp2(pattern); 865 if (filter_str_by(id, str, regex, array)) { 866 return true; 867 } 868 regex = construct_regexp2c(pattern); 869 return filter_str_by(id, str, regex, array); 870} 871 872function endsWith(str, suffix) { 873 return str.indexOf(suffix, str.length - suffix.length) !== -1; 874} 875 876function parse_all(test) { 877 var lines = test.match(/[^\r\n]+/g); 878 var records = []; // a rec can be the original paths, a set of intersections, a set of active spans, a sort, or a path add 879 var record = []; 880 var recType = REC_TYPE_UNKNOWN; 881 var lastLineNo; 882 var moveX, moveY; 883 for (var lineNo = 0; lineNo < lines.length; ++lineNo) { 884 var line = lines[lineNo]; 885 if (line.length == 0) { 886 continue; 887 } 888 var opStart = "SkOpSegment::"; 889 if (line.lastIndexOf(opStart, 0) === 0) { 890 line = line.substr(opStart.length); 891 } 892 var angleStart = "SkOpAngle::"; 893 if (line.lastIndexOf(angleStart, 0) === 0) { 894 line = line.substr(angleStart.length); 895 } 896 var coinStart = "SkOpCoincidence::"; 897 if (line.lastIndexOf(coinStart, 0) === 0) { 898 line = line.substr(coinStart.length); 899 } 900 var type = line.lastIndexOf("debugShowActiveSpans", 0) === 0 ? REC_TYPE_ACTIVE 901 : line.lastIndexOf("debugShowCoincidence", 0) === 0 ? REC_TYPE_COINCIDENCE 902 : line.lastIndexOf("((SkOpSegment*)", 0) === 0 ? REC_TYPE_PATH2 903 : line.lastIndexOf("debugShowTs", 0) === 0 ? REC_TYPE_COIN 904 : line.lastIndexOf("afterPart", 0) === 0 ? REC_TYPE_AFTERPART 905 : line.lastIndexOf("debugShow", 0) === 0 ? REC_TYPE_SECT 906 : line.lastIndexOf("activeOp", 0) === 0 ? REC_TYPE_ACTIVE_OP 907 : line.lastIndexOf("computed", 0) === 0 ? REC_TYPE_COMPUTED 908 : line.lastIndexOf("debugOne", 0) === 0 ? REC_TYPE_SORT 909 : line.lastIndexOf("aligned=", 0) === 0 ? REC_TYPE_ALIGNED 910 : line.lastIndexOf("dumpOne", 0) === 0 ? REC_TYPE_SORT 911 : line.lastIndexOf("findTop", 0) === 0 ? REC_TYPE_TOP 912 : line.lastIndexOf("pathB.", 0) === 0 ? REC_TYPE_ADD 913 : line.lastIndexOf("path.", 0) === 0 ? REC_TYPE_ADD 914 : line.lastIndexOf("after", 0) === 0 ? REC_TYPE_ANGLE 915 : line.lastIndexOf("mark", 0) === 0 ? REC_TYPE_MARK 916 : line.lastIndexOf(" {{", 0) === 0 ? REC_TYPE_COMPUTED 917 : line.lastIndexOf("seg=", 0) === 0 ? REC_TYPE_PATH 918 : line.lastIndexOf("op", 0) === 0 ? REC_TYPE_OP 919 : line.lastIndexOf("$", 0) === 0 ? REC_TYPE_PATH 920 : REC_TYPE_UNKNOWN; 921 if (recType != type || recType == REC_TYPE_ADD || recType == REC_TYPE_SECT 922 || recType == REC_TYPE_ACTIVE_OP || recType == REC_TYPE_ANGLE) { 923 if (recType != REC_TYPE_UNKNOWN) { 924 records.push(recType); 925 records.push(lastLineNo); 926 records.push(record); 927 } 928 record = []; 929 recType = type; 930 lastLineNo = lineNo; 931 } 932 var found = false; 933 switch (recType) { 934 case REC_TYPE_ACTIVE: 935 found = match_regexp(line, lineNo, record, ACTIVE_LINE_SPAN, "debugShowActiveSpans" + 936" id=IDX LINE_VAL t=T_VAL tEnd=T_VAL windSum=OPT windValue=IDX" 937 ) || match_regexp(line, lineNo, record, ACTIVE_QUAD_SPAN, "debugShowActiveSpans" + 938" id=IDX QUAD_VAL t=T_VAL tEnd=T_VAL windSum=OPT windValue=IDX" 939 ) || match_regexp(line, lineNo, record, ACTIVE_CONIC_SPAN, "debugShowActiveSpans" + 940" id=IDX CONIC_VAL t=T_VAL tEnd=T_VAL windSum=OPT windValue=IDX" 941 ) || match_regexp(line, lineNo, record, ACTIVE_CUBIC_SPAN, "debugShowActiveSpans" + 942" id=IDX CUBIC_VAL t=T_VAL tEnd=T_VAL windSum=OPT windValue=IDX" 943 ) || match_regexp(line, lineNo, record, ACTIVE_LINE_SPAN, "debugShowActiveSpans" + 944" id=IDX LINE_VAL t=T_VAL tEnd=T_VAL windSum=OPT oppSum=OPT windValue=IDX oppValue=NUM" 945 ) || match_regexp(line, lineNo, record, ACTIVE_QUAD_SPAN, "debugShowActiveSpans" + 946" id=IDX QUAD_VAL t=T_VAL tEnd=T_VAL windSum=OPT oppSum=OPT windValue=IDX oppValue=NUM" 947 ) || match_regexp(line, lineNo, record, ACTIVE_CONIC_SPAN, "debugShowActiveSpans" + 948" id=IDX CONIC_VAL t=T_VAL tEnd=T_VAL windSum=OPT oppSum=OPT windValue=IDX oppValue=NUM" 949 ) || match_regexp(line, lineNo, record, ACTIVE_CUBIC_SPAN, "debugShowActiveSpans" + 950" id=IDX CUBIC_VAL t=T_VAL tEnd=T_VAL windSum=OPT oppSum=OPT windValue=IDX oppValue=NUM" 951 ); 952 break; 953 case REC_TYPE_ACTIVE_OP: 954 found = match_regexp(line, lineNo, record, ACTIVE_OP, "activeOp" + 955" id=IDX t=T_VAL tEnd=T_VAL op=OPER miFrom=NUM miTo=NUM suFrom=NUM suTo=NUM result=IDX" 956 ); 957 break; 958 case REC_TYPE_ADD: 959 if (match_regexp(line, lineNo, record, ADD_MOVETO, "PATH.moveTo(P_VAL);")) { 960 moveX = record[1][0]; 961 moveY = record[1][1]; 962 found = true; 963 } else if (match_regexp(line, lineNo, record, ADD_LINETO, "PATH.lineTo(P_VAL);")) { 964 record[1].unshift(moveY); 965 record[1].unshift(moveX); 966 moveX = record[1][2]; 967 moveY = record[1][3]; 968 found = true; 969 } else if (match_regexp(line, lineNo, record, ADD_QUADTO, "PATH.quadTo(P_VAL, P_VAL);")) { 970 record[1].unshift(moveY); 971 record[1].unshift(moveX); 972 moveX = record[1][4]; 973 moveY = record[1][5]; 974 found = true; 975 } else if (match_regexp(line, lineNo, record, ADD_CONICTO, "PATH.conicTo(P_VAL, P_VAL, T_VAL);")) { 976 record[1].unshift(moveY); 977 record[1].unshift(moveX); 978 moveX = record[1][4]; 979 moveY = record[1][5]; 980 found = true; 981 } else if (match_regexp(line, lineNo, record, ADD_CUBICTO, "PATH.cubicTo(P_VAL, P_VAL, P_VAL);")) { 982 record[1].unshift(moveY); 983 record[1].unshift(moveX); 984 moveX = record[1][6]; 985 moveY = record[1][7]; 986 found = true; 987 } else if (match_regexp(line, lineNo, record, ADD_FILL, "PATH.setFillType(FILL_TYPE);")) { 988 found = true; 989 } else { 990 found = match_regexp(line, lineNo, record, ADD_CLOSE, "PATH.close();"); 991 } 992 break; 993 case REC_TYPE_AFTERPART: 994 found = match_regexp(line, lineNo, record, PATH_LINE, "afterPart LINE_VAL id=IDX") 995 || match_regexp(line, lineNo, record, PATH_QUAD, "afterPart QUAD_VAL id=IDX") 996 || match_regexp(line, lineNo, record, PATH_CONIC, "afterPart CONIC_VAL id=IDX") 997 || match_regexp(line, lineNo, record, PATH_CUBIC, "afterPart CUBIC_VAL id=IDX") 998 break; 999 case REC_TYPE_ALIGNED: 1000 found = match_regexp(line, lineNo, record, PATH_LINE, "aligned=IDX LINE_VAL" 1001 ) || match_regexp(line, lineNo, record, PATH_QUAD, "aligned=IDX QUAD_VAL" 1002 ) || match_regexp(line, lineNo, record, PATH_CONIC, "aligned=IDX CONIC_VAL" 1003 ) || match_regexp(line, lineNo, record, PATH_CUBIC, "aligned=IDX CUBIC_VAL" 1004 ); 1005 break; 1006 case REC_TYPE_ANGLE: 1007 found = match_regexp(line, lineNo, record, ANGLE_AFTER, "after " + 1008"[IDX/IDX] NUM/NUM tStart=T_VAL tEnd=T_VAL < [IDX/IDX] NUM/NUM tStart=T_VAL tEnd=T_VAL < [IDX/IDX] NUM/NUM tStart=T_VAL tEnd=T_VAL T_F IDX"); 1009 break; 1010 case REC_TYPE_COIN: 1011 found = true; 1012 break; 1013 case REC_TYPE_COINCIDENCE: 1014 found = match_regexp(line, lineNo, record, COIN_MAIN_SPAN, "debugShowCoincidence" + 1015" + id=IDX t=T_VAL tEnd=T_VAL" 1016 ) || match_regexp(line, lineNo, record, COIN_OPP_SPAN, "debugShowCoincidence" + 1017" - id=IDX t=T_VAL tEnd=T_VAL" 1018 ); 1019 break; 1020 case REC_TYPE_COMPUTED: 1021 found = line == "computed quadratics given" 1022 || match_regexp(line, lineNo, record, COMPUTED_SET_1, "computed quadratics set 1" 1023 ) || match_regexp(line, lineNo, record, COMPUTED_SET_2, "computed quadratics set 2" 1024 ) || match_regexp(line, lineNo, record, PATH_QUAD, " QUAD_VAL," 1025 ) || match_regexp(line, lineNo, record, PATH_CONIC, " CONIC_VAL," 1026 ) || match_regexp(line, lineNo, record, PATH_CUBIC, " CUBIC_VAL," 1027 ); 1028 break; 1029 case REC_TYPE_PATH: 1030 found = match_regexp(line, lineNo, record, PATH_LINE, "seg=IDX LINE_VAL" 1031 ) || match_regexp(line, lineNo, record, PATH_QUAD, "seg=IDX QUAD_VAL" 1032 ) || match_regexp(line, lineNo, record, PATH_CONIC, "seg=IDX CONIC_VAL" 1033 ) || match_regexp(line, lineNo, record, PATH_CUBIC, "seg=IDX CUBIC_VAL" 1034 ); 1035 break; 1036 case REC_TYPE_PATH2: 1037 found = match_regexp(line, lineNo, record, PATH_LINE, "((SkOpSegment*) PTR_VAL) [IDX] {LINE_VAL}" 1038 ) || match_regexp(line, lineNo, record, PATH_QUAD, "((SkOpSegment*) PTR_VAL) [IDX] {QUAD_VAL}" 1039 ) || match_regexp(line, lineNo, record, PATH_CONIC, "((SkOpSegment*) PTR_VAL) [IDX] {CONIC_VAL}" 1040 ) || match_regexp(line, lineNo, record, PATH_CUBIC, "((SkOpSegment*) PTR_VAL) [IDX] {CUBIC_VAL}" 1041 ); 1042 break; 1043 case REC_TYPE_SECT: 1044 found = match_regexp(line, lineNo, record, INTERSECT_LINE, "debugShowLineIntersection" + 1045" wtTs[0]=T_VAL LINE_VAL PT_VAL wnTs[0]=T_VAL LINE_VAL" 1046 ) || match_regexp(line, lineNo, record, INTERSECT_LINE_2, "debugShowLineIntersection" + 1047" wtTs[0]=T_VAL LINE_VAL PT_VAL wtTs[1]=T_VAL PT_VAL wnTs[0]=T_VAL LINE_VAL wnTs[1]=T_VAL" 1048 ) || match_regexp(line, lineNo, record, INTERSECT_LINE_NO, "debugShowLineIntersection" + 1049" no intersect LINE_VAL LINE_VAL" 1050 ) || match_regexp(line, lineNo, record, INTERSECT_QUAD_LINE, "debugShowQuadLineIntersection" + 1051" wtTs[0]=T_VAL QUAD_VAL PT_VAL wnTs[0]=T_VAL LINE_VAL" 1052 ) || match_regexp(line, lineNo, record, INTERSECT_QUAD_LINE_2, "debugShowQuadLineIntersection" + 1053" wtTs[0]=T_VAL QUAD_VAL PT_VAL wtTs[1]=T_VAL PT_VAL wnTs[0]=T_VAL LINE_VAL wnTs[1]=T_VAL" 1054 ) || match_regexp(line, lineNo, record, INTERSECT_QUAD_LINE_NO, "debugShowQuadLineIntersection" + 1055" no intersect QUAD_VAL LINE_VAL" 1056 ) || match_regexp(line, lineNo, record, INTERSECT_QUAD, "debugShowQuadIntersection" + 1057" wtTs[0]=T_VAL QUAD_VAL PT_VAL wnTs[0]=T_VAL QUAD_VAL" 1058 ) || match_regexp(line, lineNo, record, INTERSECT_QUAD_2, "debugShowQuadIntersection" + 1059" wtTs[0]=T_VAL QUAD_VAL PT_VAL wtTs[1]=T_VAL PT_VAL wnTs[0]=T_VAL QUAD_VAL wnTs[1]=T_VAL" 1060 ) || match_regexp(line, lineNo, record, INTERSECT_QUAD_NO, "debugShowQuadIntersection" + 1061" no intersect QUAD_VAL QUAD_VAL" 1062 1063 ) || match_regexp(line, lineNo, record, INTERSECT_CONIC_LINE, "debugShowConicLineIntersection" + 1064" wtTs[0]=T_VAL CONIC_VAL PT_VAL wnTs[0]=T_VAL LINE_VAL" 1065 ) || match_regexp(line, lineNo, record, INTERSECT_CONIC_LINE_2, "debugShowConicLineIntersection" + 1066" wtTs[0]=T_VAL CONIC_VAL PT_VAL wtTs[1]=T_VAL PT_VAL wnTs[0]=T_VAL LINE_VAL wnTs[1]=T_VAL" 1067 ) || match_regexp(line, lineNo, record, INTERSECT_CONIC_LINE_NO, "debugShowConicLineIntersection" + 1068" no intersect CONIC_VAL LINE_VAL" 1069 1070 ) || match_regexp(line, lineNo, record, INTERSECT_CONIC_QUAD, "debugShowConicQuadIntersection" + 1071" wtTs[0]=T_VAL CONIC_VAL PT_VAL wnTs[0]=T_VAL QUAD_VAL" 1072 ) || match_regexp(line, lineNo, record, INTERSECT_CONIC_QUAD_2, "debugShowConicQuadIntersection" + 1073" wtTs[0]=T_VAL CONIC_VAL PT_VAL wtTs[1]=T_VAL PT_VAL wnTs[0]=T_VAL QUAD_VAL wnTs[1]=T_VAL" 1074 ) || match_regexp(line, lineNo, record, INTERSECT_CONIC_QUAD_3, "debugShowConicQuadIntersection" + 1075" wtTs[0]=T_VAL CONIC_VAL PT_VAL wtTs[1]=T_VAL PT_VAL wtTs[2]=T_VAL PT_VAL wnTs[0]=T_VAL QUAD_VAL wnTs[1]=T_VAL wnTs[2]=T_VAL" 1076 ) || match_regexp(line, lineNo, record, INTERSECT_CONIC_QUAD_4, "debugShowConicQuadIntersection" + 1077" wtTs[0]=T_VAL CONIC_VAL PT_VAL wtTs[1]=T_VAL PT_VAL wtTs[2]=T_VAL PT_VAL wtTs[3]=T_VAL PT_VAL wnTs[0]=T_VAL QUAD_VAL wnTs[1]=T_VAL wnTs[2]=T_VAL wnTs[3]=T_VAL" 1078 ) || match_regexp(line, lineNo, record, INTERSECT_CONIC_QUAD_NO, "debugShowConicQuadIntersection" + 1079" no intersect CONIC_VAL QUAD_VAL" 1080 1081 ) || match_regexp(line, lineNo, record, INTERSECT_CONIC, "debugShowConicIntersection" + 1082" wtTs[0]=T_VAL CONIC_VAL PT_VAL wnTs[0]=T_VAL CONIC_VAL" 1083 ) || match_regexp(line, lineNo, record, INTERSECT_CONIC_2, "debugShowConicIntersection" + 1084" wtTs[0]=T_VAL CONIC_VAL PT_VAL wtTs[1]=T_VAL PT_VAL wnTs[0]=T_VAL CONIC_VAL wnTs[1]=T_VAL" 1085 ) || match_regexp(line, lineNo, record, INTERSECT_CONIC_NO, "debugShowConicIntersection" + 1086" no intersect CONIC_VAL CONIC_VAL" 1087 ) || match_regexp(line, lineNo, record, INTERSECT_CUBIC_LINE, "debugShowCubicLineIntersection" + 1088" wtTs[0]=T_VAL CUBIC_VAL PT_VAL wnTs[0]=T_VAL LINE_VAL" 1089 ) || match_regexp(line, lineNo, record, INTERSECT_CUBIC_LINE_2, "debugShowCubicLineIntersection" + 1090" wtTs[0]=T_VAL CUBIC_VAL PT_VAL wtTs[1]=T_VAL PT_VAL wnTs[0]=T_VAL LINE_VAL wnTs[1]=T_VAL" 1091 ) || match_regexp(line, lineNo, record, INTERSECT_CUBIC_LINE_3, "debugShowCubicLineIntersection" + 1092" wtTs[0]=T_VAL CUBIC_VAL PT_VAL wtTs[1]=T_VAL PT_VAL wtTs[2]=T_VAL PT_VAL wnTs[0]=T_VAL LINE_VAL wnTs[1]=T_VAL wnTs[2]=T_VAL" 1093 ) || match_regexp(line, lineNo, record, INTERSECT_CUBIC_LINE_NO, "debugShowCubicLineIntersection" + 1094" no intersect CUBIC_VAL LINE_VAL" 1095 ) || match_regexp(line, lineNo, record, INTERSECT_CUBIC_QUAD, "debugShowCubicQuadIntersection" + 1096" wtTs[0]=T_VAL CUBIC_VAL PT_VAL wnTs[0]=T_VAL QUAD_VAL" 1097 ) || match_regexp(line, lineNo, record, INTERSECT_CUBIC_QUAD_2, "debugShowCubicQuadIntersection" + 1098" wtTs[0]=T_VAL CUBIC_VAL PT_VAL wtTs[1]=T_VAL PT_VAL wnTs[0]=T_VAL QUAD_VAL wnTs[1]=T_VAL" 1099 ) || match_regexp(line, lineNo, record, INTERSECT_CUBIC_QUAD_3, "debugShowCubicQuadIntersection" + 1100" wtTs[0]=T_VAL CUBIC_VAL PT_VAL wtTs[1]=T_VAL PT_VAL wtTs[2]=T_VAL PT_VAL wnTs[0]=T_VAL QUAD_VAL wnTs[1]=T_VAL wnTs[2]=T_VAL" 1101 ) || match_regexp(line, lineNo, record, INTERSECT_CUBIC_QUAD_4, "debugShowCubicQuadIntersection" + 1102" wtTs[0]=T_VAL CUBIC_VAL PT_VAL wtTs[1]=T_VAL PT_VAL wtTs[2]=T_VAL wtTs[3]=T_VAL PT_VAL wnTs[0]=T_VAL QUAD_VAL wnTs[1]=T_VAL wnTs[2]=T_VAL wnTs[3]=T_VAL" 1103 ) || match_regexp(line, lineNo, record, INTERSECT_CUBIC_QUAD_NO, "debugShowCubicQuadIntersection" + 1104" no intersect CUBIC_VAL QUAD_VAL" 1105 ) || match_regexp(line, lineNo, record, INTERSECT_CUBIC, "debugShowCubicIntersection" + 1106" wtTs[0]=T_VAL CUBIC_VAL PT_VAL wnTs[0]=T_VAL CUBIC_VAL" 1107 ) || match_regexp(line, lineNo, record, INTERSECT_CUBIC_2, "debugShowCubicIntersection" + 1108" wtTs[0]=T_VAL CUBIC_VAL PT_VAL wtTs[1]=T_VAL PT_VAL wnTs[0]=T_VAL CUBIC_VAL wnTs[1]=T_VAL" 1109 ) || match_regexp(line, lineNo, record, INTERSECT_CUBIC_3, "debugShowCubicIntersection" + 1110" wtTs[0]=T_VAL CUBIC_VAL PT_VAL wtTs[1]=T_VAL PT_VAL wtTs[2]=T_VAL PT_VAL wnTs[0]=T_VAL CUBIC_VAL wnTs[1]=T_VAL wnTs[2]=T_VAL" 1111 ) || match_regexp(line, lineNo, record, INTERSECT_CUBIC_4, "debugShowCubicIntersection" + 1112" wtTs[0]=T_VAL CUBIC_VAL PT_VAL wtTs[1]=T_VAL PT_VAL wtTs[2]=T_VAL PT_VAL wtTs[3]=T_VAL PT_VAL wnTs[0]=T_VAL CUBIC_VAL wnTs[1]=T_VAL wnTs[2]=T_VAL wnTs[3]=T_VAL" 1113 ) || match_regexp(line, lineNo, record, INTERSECT_CUBIC_NO, "debugShowCubicIntersection" + 1114" no intersect CUBIC_VAL CUBIC_VAL" 1115 ) || match_regexp(line, lineNo, record, INTERSECT_SELF_CUBIC, "debugShowCubicIntersection" + 1116" wtTs[0]=T_VAL CUBIC_VAL PT_VAL wtTs[1]=T_VAL" 1117 ) || match_regexp(line, lineNo, record, INTERSECT_SELF_CUBIC_NO, "debugShowCubicIntersection" + 1118" no self intersect CUBIC_VAL" 1119 ); 1120 break; 1121 case REC_TYPE_SORT: 1122 var hasDone = / done/.test(line); 1123 var hasUnorderable = / unorderable/.test(line); 1124 var hasSmall = / small/.test(line); 1125 var hasTiny = / tiny/.test(line); 1126 var hasOperand = / operand/.test(line); 1127 var hasStop = / stop/.test(line); 1128 line.replace(/[ a-z]+$/, ""); 1129 found = match_regexp(line, lineNo, record, SORT_UNARY, "debugOne" + 1130" [IDX/IDX] next=IDX/IDX sect=IDX/IDX s=T_VAL [IDX] e=T_VAL [IDX] sgn=NUM windVal=IDX windSum=OPT" 1131 ) || match_regexp(line, lineNo, record, SORT_BINARY, "debugOne" + 1132" [IDX/IDX] next=IDX/IDX sect=IDX/IDX s=T_VAL [IDX] e=T_VAL [IDX] sgn=NUM windVal=IDX windSum=OPT oppVal=IDX oppSum=OPT" 1133 ) || match_regexp(line, lineNo, record, SORT_UNARY, "dumpOne" + 1134" [IDX/IDX] next=IDX/IDX sect=NUM/NUM s=T_VAL [IDX] e=T_VAL [IDX] sgn=NUM windVal=IDX windSum=OPT" 1135 ) || match_regexp(line, lineNo, record, SORT_BINARY, "dumpOne" + 1136" [IDX/IDX] next=IDX/IDX sect=NUM/NUM s=T_VAL [IDX] e=T_VAL [IDX] sgn=NUM windVal=IDX windSum=OPT oppVal=IDX oppSum=OPT" 1137 ); 1138 if (found) { 1139 record[1].push(hasDone); 1140 record[1].push(hasUnorderable); 1141 record[1].push(hasSmall); 1142 record[1].push(hasTiny); 1143 record[1].push(hasOperand); 1144 record[1].push(hasStop); 1145 } 1146 break; 1147 case REC_TYPE_TOP: 1148 found = match_regexp(line, lineNo, record, ACTIVE_OP, "findTop" + 1149" id=IDX s=T_VAL e=T_VAL cw=NUM swap=NUM inflections=NUM monotonic=NUM" 1150 ) || match_regexp(line, lineNo, record, ACTIVE_OP, "findTop" + 1151" id=IDX s=T_VAL e=T_VAL (-) cw=NUM swap=NUM inflections=NUM monotonic=NUM" 1152 ) || match_regexp(line, lineNo, record, ACTIVE_OP, "findTop" + 1153" id=IDX s=T_VAL e=T_VAL (+) cw=NUM swap=NUM inflections=NUM monotonic=NUM" 1154 ); 1155 break; 1156 case REC_TYPE_MARK: 1157 found = match_regexp(line, lineNo, record, MARK_LINE, "markWinding" + 1158" id=IDX LINE_VAL t=T_VAL [IDX] PT_VAL tEnd=T_VAL newWindSum=NUM newOppSum=OPT oppSum=OPT windSum=OPT windValue=IDX" 1159 ) || match_regexp(line, lineNo, record, MARK_QUAD, "markWinding" + 1160" id=IDX QUAD_VAL t=T_VAL [IDX] PT_VAL tEnd=T_VAL newWindSum=NUM newOppSum=OPT oppSum=OPT windSum=OPT windValue=IDX" 1161 ) || match_regexp(line, lineNo, record, MARK_CONIC, "markWinding" + 1162" id=IDX CONIC_VAL t=T_VAL [IDX] PT_VAL tEnd=T_VAL newWindSum=NUM newOppSum=OPT oppSum=OPT windSum=OPT windValue=IDX" 1163 ) || match_regexp(line, lineNo, record, MARK_CUBIC, "markWinding" + 1164" id=IDX CUBIC_VAL t=T_VAL [IDX] PT_VAL tEnd=T_VAL newWindSum=NUM newOppSum=OPT oppSum=OPT windSum=OPT windValue=IDX" 1165 ) || match_regexp(line, lineNo, record, MARK_DONE_LINE, "markDone" + 1166" id=IDX LINE_VAL t=T_VAL [IDX] PT_VAL tEnd=T_VAL newWindSum=OPT newOppSum=OPT oppSum=OPT windSum=OPT windValue=IDX oppValue=OPT" 1167 ) || match_regexp(line, lineNo, record, MARK_DONE_QUAD, "markDone" + 1168" id=IDX QUAD_VAL t=T_VAL [IDX] PT_VAL tEnd=T_VAL newWindSum=OPT newOppSum=OPT oppSum=OPT windSum=OPT windValue=IDX oppValue=OPT" 1169 ) || match_regexp(line, lineNo, record, MARK_DONE_CONIC, "markDone" + 1170" id=IDX CONIC_VAL t=T_VAL [IDX] PT_VAL tEnd=T_VAL newWindSum=OPT newOppSum=OPT oppSum=OPT windSum=OPT windValue=IDX oppValue=OPT" 1171 ) || match_regexp(line, lineNo, record, MARK_DONE_CUBIC, "markDone" + 1172" id=IDX CUBIC_VAL t=T_VAL [IDX] PT_VAL tEnd=T_VAL newWindSum=OPT newOppSum=OPT oppSum=OPT windSum=OPT windValue=IDX oppValue=OPT" 1173 ) || match_regexp(line, lineNo, record, MARK_SIMPLE_LINE, "markWinding" + 1174" id=IDX LINE_VAL t=T_VAL [IDX] PT_VAL tEnd=T_VAL newWindSum=NUM windSum=OPT windValue=IDX" 1175 ) || match_regexp(line, lineNo, record, MARK_SIMPLE_QUAD, "markWinding" + 1176" id=IDX QUAD_VAL t=T_VAL [IDX] PT_VAL tEnd=T_VAL newWindSum=NUM windSum=OPT windValue=IDX" 1177 ) || match_regexp(line, lineNo, record, MARK_SIMPLE_CONIC, "markWinding" + 1178" id=IDX CONIC_VAL t=T_VAL [IDX] PT_VAL tEnd=T_VAL newWindSum=NUM windSum=OPT windValue=IDX" 1179 ) || match_regexp(line, lineNo, record, MARK_SIMPLE_CUBIC, "markWinding" + 1180" id=IDX CUBIC_VAL t=T_VAL [IDX] PT_VAL tEnd=T_VAL newWindSum=NUM windSum=OPT windValue=IDX" 1181 ) || match_regexp(line, lineNo, record, MARK_ANGLE_LAST, "markAngle" + 1182" last segment=IDX span=IDX" 1183 ) || match_regexp(line, lineNo, record, MARK_ANGLE_LAST, "markAngle" + 1184" last seg=IDX span=IDX" 1185 ) || match_regexp(line, lineNo, record, MARK_ANGLE_LAST, "markAngle" + 1186" last segment=IDX span=IDX windSum=OPT" 1187 ) || match_regexp(line, lineNo, record, MARK_ANGLE_LAST, "markAngle" + 1188" last seg=IDX span=IDX windSum=OPT" 1189 ); 1190 break; 1191 case REC_TYPE_OP: 1192 if (line.lastIndexOf("oppSign oppSign=", 0) === 0 1193 || line.lastIndexOf("operator<", 0) === 0) { 1194 found = true; 1195 break; 1196 } 1197 found = match_regexp(line, lineNo, record, OP_DIFFERENCE, "op diff" 1198 ) || match_regexp(line, lineNo, record, OP_INTERSECT, "op intersect" 1199 ) || match_regexp(line, lineNo, record, OP_INTERSECT, "op sect" 1200 ) || match_regexp(line, lineNo, record, OP_UNION, "op union" 1201 ) || match_regexp(line, lineNo, record, OP_XOR, "op xor" 1202 ); 1203 break; 1204 case REC_TYPE_UNKNOWN: 1205 found = true; 1206 break; 1207 } 1208 if (!found) { 1209 console.log(line + " [" + lineNo + "] of type " + type + " not found"); 1210 } 1211 } 1212 if (recType != REC_TYPE_UNKNOWN) { 1213 records.push(recType); 1214 records.push(lastLineNo); 1215 records.push(record); 1216 } 1217 if (records.length >= 1) { 1218 tests[testIndex] = records; 1219 testLines[testIndex] = lines; 1220 } 1221} 1222 1223function init(test) { 1224 var canvas = document.getElementById('canvas'); 1225 if (!canvas.getContext) return; 1226 ctx = canvas.getContext('2d'); 1227 var resScale = retina_scale && window.devicePixelRatio ? window.devicePixelRatio : 1; 1228 var unscaledWidth = window.innerWidth - 20; 1229 var unscaledHeight = window.innerHeight - 20; 1230 screenWidth = unscaledWidth; 1231 screenHeight = unscaledHeight; 1232 canvas.width = unscaledWidth * resScale; 1233 canvas.height = unscaledHeight * resScale; 1234 canvas.style.width = unscaledWidth + 'px'; 1235 canvas.style.height = unscaledHeight + 'px'; 1236 if (resScale != 1) { 1237 ctx.scale(resScale, resScale); 1238 } 1239 xmin = Infinity; 1240 xmax = -Infinity; 1241 ymin = Infinity; 1242 ymax = -Infinity; 1243 hasPath = hasAlignedPath = hasComputedPath = false; 1244 firstActiveSpan = -1; 1245 for (var tIndex = 0; tIndex < test.length; tIndex += 3) { 1246 var recType = test[tIndex]; 1247 if (!typeof recType == 'number' || recType < REC_TYPE_UNKNOWN || recType > REC_TYPE_LAST) { 1248 console.log("unknown rec type: " + recType); 1249 throw "stop execution"; 1250 } 1251 var records = test[tIndex + 2]; 1252 for (var recordIndex = 0; recordIndex < records.length; recordIndex += 2) { 1253 var fragType = records[recordIndex]; 1254 if (!typeof fragType == 'number' || fragType < 1 || fragType > FRAG_TYPE_LAST) { 1255 console.log("unknown in range frag type: " + fragType); 1256 throw "stop execution"; 1257 } 1258 var frags = records[recordIndex + 1]; 1259 var first = 0; 1260 var last = -1; 1261 var first2 = 0; 1262 var last2 = 0; 1263 switch (recType) { 1264 case REC_TYPE_ALIGNED: 1265 hasAlignedPath = true; 1266 case REC_TYPE_COMPUTED: 1267 if (fragType == COMPUTED_SET_1 || fragType == COMPUTED_SET_2) { 1268 break; 1269 } 1270 if (REC_TYPE_COMPUTED == recType) { 1271 hasComputedPath = true; 1272 } 1273 case REC_TYPE_PATH: 1274 first = 1; 1275 switch (fragType) { 1276 case PATH_LINE: 1277 last = 5; 1278 break; 1279 case PATH_CONIC: 1280 case PATH_QUAD: 1281 last = 7; 1282 break; 1283 case PATH_CUBIC: 1284 last = 9; 1285 break; 1286 default: 1287 console.log("unknown " + (recType == REC_TYPE_PATH ? "REC_TYPE_PATH" 1288 : "REC_TYPE_COMPUTED") + " frag type:" + fragType); 1289 throw "stop execution"; 1290 } 1291 if (recType == REC_TYPE_PATH) { 1292 hasPath = true; 1293 } 1294 break; 1295 case REC_TYPE_PATH2: 1296 first = 1; 1297 switch (fragType) { 1298 case PATH_LINE: 1299 last = 5; 1300 break; 1301 case PATH_CONIC: 1302 case PATH_QUAD: 1303 last = 7; 1304 break; 1305 case PATH_CUBIC: 1306 last = 9; 1307 break; 1308 default: 1309 console.log("unknown " + (recType == REC_TYPE_PATH2 ? "REC_TYPE_PATH2" 1310 : "REC_TYPE_COMPUTED") + " frag type:" + fragType); 1311 throw "stop execution"; 1312 } 1313 if (recType == REC_TYPE_PATH2) { 1314 hasPath = true; 1315 } 1316 break; 1317 case REC_TYPE_ACTIVE: 1318 if (firstActiveSpan < 0) { 1319 firstActiveSpan = tIndex; 1320 } 1321 first = 1; 1322 switch (fragType) { 1323 case ACTIVE_LINE_SPAN: 1324 last = 5; 1325 break; 1326 case ACTIVE_CONIC_SPAN: 1327 case ACTIVE_QUAD_SPAN: 1328 last = 7; 1329 break; 1330 case ACTIVE_CUBIC_SPAN: 1331 last = 9; 1332 break; 1333 default: 1334 console.log("unknown REC_TYPE_ACTIVE frag type: " + fragType); 1335 throw "stop execution"; 1336 } 1337 break; 1338 case REC_TYPE_ADD: 1339 switch (fragType) { 1340 case ADD_MOVETO: 1341 break; 1342 case ADD_LINETO: 1343 last = 4; 1344 break; 1345 case ADD_CONICTO: 1346 case ADD_QUADTO: 1347 last = 6; 1348 break; 1349 case ADD_CUBICTO: 1350 last = 8; 1351 break; 1352 case ADD_CLOSE: 1353 case ADD_FILL: 1354 break; 1355 default: 1356 console.log("unknown REC_TYPE_ADD frag type: " + fragType); 1357 throw "stop execution"; 1358 } 1359 break; 1360 case REC_TYPE_AFTERPART: 1361 switch (fragType) { 1362 case PATH_LINE: 1363 last = 4; 1364 break; 1365 case PATH_CONIC: 1366 case PATH_QUAD: 1367 last = 6; 1368 break; 1369 case PATH_CUBIC: 1370 last = 8; 1371 break; 1372 default: 1373 console.log("unknown REC_TYPE_ACTIVEPART frag type: " + fragType); 1374 throw "stop execution"; 1375 } 1376 break; 1377 case REC_TYPE_SECT: 1378 switch (fragType) { 1379 case INTERSECT_LINE: 1380 first = 1; last = 5; first2 = 8; last2 = 12; 1381 break; 1382 case INTERSECT_LINE_2: 1383 first = 1; last = 5; first2 = 11; last2 = 15; 1384 break; 1385 case INTERSECT_LINE_NO: 1386 first = 0; last = 4; first2 = 4; last2 = 8; 1387 break; 1388 case INTERSECT_CONIC_LINE: 1389 first = 1; last = 7; first2 = 11; last2 = 15; 1390 break; 1391 case INTERSECT_QUAD_LINE: 1392 first = 1; last = 7; first2 = 10; last2 = 14; 1393 break; 1394 case INTERSECT_CONIC_LINE_2: 1395 first = 1; last = 7; first2 = 14; last2 = 18; 1396 break; 1397 case INTERSECT_QUAD_LINE_2: 1398 first = 1; last = 7; first2 = 13; last2 = 17; 1399 break; 1400 case INTERSECT_CONIC_LINE_NO: 1401 first = 0; last = 6; first2 = 7; last2 = 11; 1402 break; 1403 case INTERSECT_QUAD_LINE_NO: 1404 first = 0; last = 6; first2 = 6; last2 = 10; 1405 break; 1406 case INTERSECT_CONIC: 1407 first = 1; last = 7; first2 = 11; last2 = 17; 1408 break; 1409 case INTERSECT_QUAD: 1410 first = 1; last = 7; first2 = 10; last2 = 16; 1411 break; 1412 case INTERSECT_CONIC_2: 1413 first = 1; last = 7; first2 = 14; last2 = 20; 1414 break; 1415 case INTERSECT_QUAD_2: 1416 first = 1; last = 7; first2 = 13; last2 = 19; 1417 break; 1418 case INTERSECT_CONIC_NO: 1419 first = 0; last = 6; first2 = 7; last2 = 13; 1420 break; 1421 case INTERSECT_QUAD_NO: 1422 first = 0; last = 6; first2 = 6; last2 = 12; 1423 break; 1424 case INTERSECT_SELF_CUBIC: 1425 first = 1; last = 9; 1426 break; 1427 case INTERSECT_SELF_CUBIC_NO: 1428 first = 0; last = 8; 1429 break; 1430 case INTERSECT_CUBIC_LINE: 1431 first = 1; last = 9; first2 = 12; last2 = 16; 1432 break; 1433 case INTERSECT_CUBIC_LINE_2: 1434 first = 1; last = 9; first2 = 15; last2 = 19; 1435 break; 1436 case INTERSECT_CUBIC_LINE_3: 1437 first = 1; last = 9; first2 = 18; last2 = 22; 1438 break; 1439 case INTERSECT_CUBIC_LINE_NO: 1440 first = 0; last = 8; first2 = 8; last2 = 12; 1441 break; 1442 case INTERSECT_CONIC_QUAD: 1443 first = 1; last = 7; first2 = 11; last2 = 17; 1444 break; 1445 case INTERSECT_CONIC_QUAD_2: 1446 first = 1; last = 7; first2 = 14; last2 = 20; 1447 break; 1448 case INTERSECT_CONIC_QUAD_3: 1449 first = 1; last = 7; first2 = 17; last2 = 23; 1450 break; 1451 case INTERSECT_CONIC_QUAD_4: 1452 first = 1; last = 7; first2 = 20; last2 = 26; 1453 break; 1454 case INTERSECT_CONIC_QUAD_NO: 1455 first = 0; last = 6; first2 = 7; last2 = 13; 1456 break; 1457 case INTERSECT_CUBIC_QUAD: 1458 first = 1; last = 9; first2 = 12; last2 = 18; 1459 break; 1460 case INTERSECT_CUBIC_QUAD_2: 1461 first = 1; last = 9; first2 = 15; last2 = 21; 1462 break; 1463 case INTERSECT_CUBIC_QUAD_3: 1464 first = 1; last = 9; first2 = 18; last2 = 24; 1465 break; 1466 case INTERSECT_CUBIC_QUAD_4: 1467 first = 1; last = 9; first2 = 21; last2 = 27; 1468 break; 1469 case INTERSECT_CUBIC_QUAD_NO: 1470 first = 0; last = 8; first2 = 8; last2 = 14; 1471 break; 1472 case INTERSECT_CUBIC: 1473 first = 1; last = 9; first2 = 12; last2 = 20; 1474 break; 1475 case INTERSECT_CUBIC_2: 1476 first = 1; last = 9; first2 = 15; last2 = 23; 1477 break; 1478 case INTERSECT_CUBIC_3: 1479 first = 1; last = 9; first2 = 18; last2 = 26; 1480 break; 1481 case INTERSECT_CUBIC_4: 1482 first = 1; last = 9; first2 = 21; last2 = 29; 1483 break; 1484 case INTERSECT_CUBIC_NO: 1485 first = 0; last = 8; first2 = 8; last2 = 16; 1486 break; 1487 default: 1488 console.log("unknown REC_TYPE_SECT frag type: " + fragType); 1489 throw "stop execution"; 1490 } 1491 break; 1492 default: 1493 continue; 1494 } 1495 for (var idx = first; idx < last; idx += 2) { 1496 xmin = Math.min(xmin, frags[idx]); 1497 xmax = Math.max(xmax, frags[idx]); 1498 ymin = Math.min(ymin, frags[idx + 1]); 1499 ymax = Math.max(ymax, frags[idx + 1]); 1500 } 1501 for (var idx = first2; idx < last2; idx += 2) { 1502 xmin = Math.min(xmin, frags[idx]); 1503 xmax = Math.max(xmax, frags[idx]); 1504 ymin = Math.min(ymin, frags[idx + 1]); 1505 ymax = Math.max(ymax, frags[idx + 1]); 1506 } 1507 } 1508 } 1509 var angleBounds = [Infinity, Infinity, -Infinity, -Infinity]; 1510 for (var tIndex = 0; tIndex < test.length; tIndex += 3) { 1511 var recType = test[tIndex]; 1512 var records = test[tIndex + 2]; 1513 for (var recordIndex = 0; recordIndex < records.length; recordIndex += 2) { 1514 var fragType = records[recordIndex]; 1515 var frags = records[recordIndex + 1]; 1516 switch (recType) { 1517 case REC_TYPE_ACTIVE_OP: 1518 if (!draw_op) { 1519 break; 1520 } 1521 { 1522 var curve = curvePartialByID(test, frags[0], frags[1], frags[2]); 1523 curve_extremes(curve, angleBounds); 1524 } 1525 break; 1526 case REC_TYPE_ANGLE: 1527 if (!draw_angle) { 1528 break; 1529 } 1530 { 1531 var curve = curvePartialByID(test, frags[0], frags[4], frags[5]); 1532 curve_extremes(curve, angleBounds); 1533 curve = curvePartialByID(test, frags[6], frags[10], frags[11]); 1534 curve_extremes(curve, angleBounds); 1535 curve = curvePartialByID(test, frags[12], frags[16], frags[17]); 1536 } 1537 break; 1538 case REC_TYPE_COINCIDENCE: 1539 if (!draw_coincidence) { 1540 break; 1541 } 1542 { 1543 var curve = curvePartialByID(test, frags[0], frags[1], frags[2]); 1544 curve_extremes(curve, angleBounds); 1545 } 1546 break; 1547 case REC_TYPE_SORT: 1548 if (!draw_sort) { 1549 break; 1550 } 1551 if (fragType == SORT_UNARY || fragType == SORT_BINARY) { 1552 var curve = curvePartialByID(test, frags[0], frags[6], frags[8]); 1553 curve_extremes(curve, angleBounds); 1554 } 1555 break; 1556 case REC_TYPE_TOP: 1557 if (!draw_top) { 1558 break; 1559 } 1560 { 1561 var curve = curvePartialByID(test, frags[0], frags[1], frags[2]); 1562 curve_extremes(curve, angleBounds); 1563 } 1564 break; 1565 } 1566 } 1567 } 1568 xmin = Math.min(xmin, angleBounds[0]); 1569 ymin = Math.min(ymin, angleBounds[1]); 1570 xmax = Math.max(xmax, angleBounds[2]); 1571 ymax = Math.max(ymax, angleBounds[3]); 1572 setScale(xmin, xmax, ymin, ymax); 1573 if (hasPath == false && hasComputedPath == true && !draw_computed) { 1574 draw_computed = 7; // show quadratics, conics, and cubics 1575 } 1576 if (hasPath == true && hasComputedPath == false && draw_computed) { 1577 draw_computed = 0; 1578 } 1579} 1580 1581function curveByIDMatch(test, id, recMatch) { 1582 var tIndex = -3; 1583 while ((tIndex += 3) < test.length) { 1584 var recType = test[tIndex]; 1585 if (recType == REC_TYPE_OP) { 1586 continue; 1587 } 1588 if (recType != recMatch) { 1589 return []; 1590 } 1591 var records = test[tIndex + 2]; 1592 for (var recordIndex = 0; recordIndex < records.length; recordIndex += 2) { 1593 var fragType = records[recordIndex]; 1594 var frags = records[recordIndex + 1]; 1595 if (frags[0] == id) { 1596 switch (fragType) { 1597 case PATH_LINE: 1598 return [frags[1], frags[2], frags[3], frags[4]]; 1599 case PATH_QUAD: 1600 return [frags[1], frags[2], frags[3], frags[4], 1601 frags[5], frags[6]]; 1602 case PATH_CONIC: 1603 return [frags[1], frags[2], frags[3], frags[4], 1604 frags[5], frags[6], frags[7]]; 1605 case PATH_CUBIC: 1606 return [frags[1], frags[2], frags[3], frags[4], 1607 frags[5], frags[6], frags[7], frags[8]]; 1608 } 1609 } 1610 } 1611 } 1612 return []; 1613} 1614 1615function curveByID(test, id) { 1616 var result = draw_path >= 4 ? curveByIDMatch(test, id, REC_TYPE_ALIGNED) : []; 1617 if (!result.length) { 1618 result = curveByIDMatch(test, id, REC_TYPE_PATH); 1619 } 1620 return result; 1621} 1622 1623function curvePartialByIDMatch(test, id, t0, t1, recMatch) { 1624 var tIndex = -3; 1625 while ((tIndex += 3) < test.length) { 1626 var recType = test[tIndex]; 1627 if (recType == REC_TYPE_OP) { 1628 continue; 1629 } 1630 if (recType != recMatch) { 1631 return []; 1632 } 1633 var records = test[tIndex + 2]; 1634 for (var recordIndex = 0; recordIndex < records.length; recordIndex += 2) { 1635 var fragType = records[recordIndex]; 1636 var frags = records[recordIndex + 1]; 1637 if (frags[0] == id) { 1638 switch (fragType) { 1639 case PATH_LINE: 1640 return linePartial(frags[1], frags[2], frags[3], frags[4], t0, t1); 1641 case PATH_QUAD: 1642 return quadPartial(frags[1], frags[2], frags[3], frags[4], 1643 frags[5], frags[6], t0, t1); 1644 case PATH_CONIC: 1645 return conicPartial(frags[1], frags[2], frags[3], frags[4], 1646 frags[5], frags[6], frags[7], t0, t1); 1647 case PATH_CUBIC: 1648 return cubicPartial(frags[1], frags[2], frags[3], frags[4], 1649 frags[5], frags[6], frags[7], frags[8], t0, t1); 1650 } 1651 } 1652 } 1653 } 1654 return []; 1655} 1656 1657function curvePartialByID(test, id, t0, t1) { 1658 var result = draw_path >= 4 ? curvePartialByIDMatch(test, id, t0, t1, REC_TYPE_ALIGNED) : []; 1659 if (!result.length) { 1660 result = curvePartialByIDMatch(test, id, t0, t1, REC_TYPE_PATH); 1661 } 1662 return result; 1663} 1664 1665function idByCurveIDMatch(test, frag, type, recMatch) { 1666 var tIndex = 0; 1667 while (tIndex < test.length) { 1668 var recType = test[tIndex]; 1669 if (recType != recMatch) { 1670 ++tIndex; 1671 continue; 1672 } 1673 var records = test[tIndex + 2]; 1674 for (var recordIndex = 0; recordIndex < records.length; recordIndex += 2) { 1675 var fragType = records[recordIndex]; 1676 var frags = records[recordIndex + 1]; 1677 if (frag.length != frags.length - 1) { 1678 continue; 1679 } 1680 switch (fragType) { 1681 case PATH_LINE: 1682 if (frag[0] != frags[1] || frag[1] != frags[2] 1683 || frag[2] != frags[3] || frag[3] != frags[4]) { 1684 continue; 1685 } 1686 return frags[0]; 1687 case PATH_QUAD: 1688 if (frag[0] != frags[1] || frag[1] != frags[2] 1689 || frag[2] != frags[3] || frag[3] != frags[4] 1690 || frag[4] != frags[5] || frag[5] != frags[6]) { 1691 continue; 1692 } 1693 return frags[0]; 1694 case PATH_CONIC: 1695 if (frag[0] != frags[1] || frag[1] != frags[2] 1696 || frag[2] != frags[3] || frag[3] != frags[4] 1697 || frag[4] != frags[5] || frag[5] != frags[6] 1698 || frag[6] != frags[7]) { 1699 continue; 1700 } 1701 return frags[0]; 1702 case PATH_CUBIC: 1703 if (frag[0] != frags[1] || frag[1] != frags[2] 1704 || frag[2] != frags[3] || frag[3] != frags[4] 1705 || frag[4] != frags[5] || frag[5] != frags[6] 1706 || frag[6] != frags[7] || frag[7] != frags[8]) { 1707 continue; 1708 } 1709 return frags[0]; 1710 } 1711 } 1712 ++tIndex; 1713 } 1714 return -1; 1715} 1716 1717function idByCurve(test, frag, type) { 1718 var result = draw_path >= 4 ? idByCurveIDMatch(test, frag, type, REC_TYPE_ALIGNED) : []; 1719 if (!result.length) { 1720 result = idByCurveIDMatch(test, frag, type, REC_TYPE_PATH); 1721 } 1722 return result; 1723} 1724 1725function curve_extremes(curve, bounds) { 1726 var length = curve.length == 7 ? 6 : curve.length; 1727 for (var index = 0; index < length; index += 2) { 1728 var x = curve[index]; 1729 var y = curve[index + 1]; 1730 bounds[0] = Math.min(bounds[0], x); 1731 bounds[1] = Math.min(bounds[1], y); 1732 bounds[2] = Math.max(bounds[2], x); 1733 bounds[3] = Math.max(bounds[3], y); 1734 } 1735} 1736 1737function setScale(x0, x1, y0, y1) { 1738 var srcWidth = x1 - x0; 1739 var srcHeight = y1 - y0; 1740 var usableWidth = screenWidth; 1741 var xDigits = Math.ceil(Math.log(Math.abs(xmax)) / Math.log(10)); 1742 var yDigits = Math.ceil(Math.log(Math.abs(ymax)) / Math.log(10)); 1743 usableWidth -= (xDigits + yDigits) * 10; 1744 usableWidth -= decimal_places * 10; 1745 if (draw_legend) { 1746 usableWidth -= 40; 1747 } 1748 var hscale = usableWidth / srcWidth; 1749 var vscale = screenHeight / srcHeight; 1750 scale = Math.min(hscale, vscale); 1751 var invScale = 1 / scale; 1752 var sxmin = x0 - invScale * 5; 1753 var symin = y0 - invScale * 10; 1754 var sxmax = x1 + invScale * (6 * decimal_places + 10); 1755 var symax = y1 + invScale * 10; 1756 srcWidth = sxmax - sxmin; 1757 srcHeight = symax - symin; 1758 hscale = usableWidth / srcWidth; 1759 vscale = screenHeight / srcHeight; 1760 scale = Math.min(hscale, vscale); 1761 srcLeft = sxmin; 1762 srcTop = symin; 1763} 1764 1765function drawArc(curve, op, from, to) { 1766 var type = PATH_LINE + (curve.length / 2 - 2); 1767 var pt = pointAtT(curve, type, op ? 0.4 : 0.6); 1768 var dy = pt.y - curve[1]; 1769 var dx = pt.x - curve[0]; 1770 var dist = Math.sqrt(dy * dy + dx * dx); 1771 var _dist = dist * scale; 1772 var angle = Math.atan2(dy, dx); 1773 var _px = (curve[0] - srcLeft) * scale; 1774 var _py = (curve[1] - srcTop) * scale; 1775 var divisor = 4; 1776 var endDist; 1777 do { 1778 var ends = []; 1779 for (var index = -1; index <= 1; index += 2) { 1780 var px = Math.cos(index * Math.PI / divisor); 1781 var py = Math.sin(index * Math.PI / divisor); 1782 ends.push(px); 1783 ends.push(py); 1784 } 1785 var endDx = (ends[2] - ends[0]) * scale * dist; 1786 var endDy = (ends[3] - ends[1]) * scale * dist; 1787 endDist = Math.sqrt(endDx * endDx + endDy * endDy); 1788 if (endDist < 100) { 1789 break; 1790 } 1791 divisor *= 2; 1792 } while (true); 1793 if (endDist < 30) { 1794 return; 1795 } 1796 if (op) { 1797 divisor *= 2; 1798 } 1799 ctx.strokeStyle = op ? "rgba(210,0,45, 0.4)" : "rgba(90,90,90, 0.5)"; 1800 ctx.beginPath(); 1801 ctx.arc(_px, _py, _dist, angle - Math.PI / divisor, angle + Math.PI / divisor, false); 1802 ctx.stroke(); 1803 var saveAlign = ctx.textAlign; 1804 var saveStyle = ctx.fillStyle; 1805 var saveFont = ctx.font; 1806 ctx.textAlign = "center"; 1807 ctx.fillStyle = "black"; 1808 ctx.font = "normal 24px Arial"; 1809 divisor *= 0.8; 1810 for (var index = -1; index <= 1; index += 2) { 1811 var px = curve[0] + Math.cos(angle + index * Math.PI / divisor) * dist; 1812 var py = curve[1] + Math.sin(angle + index * Math.PI / divisor) * dist; 1813 var _px = (px - srcLeft) * scale; 1814 var _py = (py - srcTop) * scale; 1815 ctx.fillText(index < 0 ? to.toString() : from.toString(), _px, _py + 8); 1816 } 1817 ctx.textAlign = saveAlign; 1818 ctx.fillStyle = saveStyle; 1819 ctx.font = saveFont; 1820} 1821 1822function drawPoint(px, py, end) { 1823 var length = drawnPts.length == 7 ? 6 : drawnPts.length; 1824 for (var pts = 0; pts < length; pts += 2) { 1825 var x = drawnPts[pts]; 1826 var y = drawnPts[pts + 1]; 1827 if (px == x && py == y) { 1828 return; 1829 } 1830 } 1831 drawnPts.push(px); 1832 drawnPts.push(py); 1833 var label = px.toFixed(decimal_places) + ", " + py.toFixed(decimal_places); 1834 var _px = (px - srcLeft) * scale; 1835 var _py = (py - srcTop) * scale; 1836 ctx.beginPath(); 1837 ctx.arc(_px, _py, 3, 0, Math.PI*2, true); 1838 ctx.closePath(); 1839 if (end) { 1840 ctx.fill(); 1841 } else { 1842 ctx.stroke(); 1843 } 1844 if (debug_xy) { 1845 ctx.textAlign = "left"; 1846 ctx.fillText(label, _px + 5, _py); 1847 } 1848} 1849 1850function coordCount(curveType) { 1851 switch (curveType) { 1852 case PATH_LINE: 1853 return 4; 1854 case PATH_QUAD: 1855 return 6; 1856 case PATH_CONIC: 1857 return 6; 1858 case PATH_CUBIC: 1859 return 8; 1860 } 1861 return -1; 1862} 1863 1864function drawPoints(ptArray, curveType, drawControls) { 1865 var count = coordCount(curveType); 1866 for (var idx = 0; idx < count; idx += 2) { 1867 if (!drawControls && idx != 0 && idx != count - 2) { 1868 continue; 1869 } 1870 drawPoint(ptArray[idx], ptArray[idx + 1], idx == 0 || idx == count - 2); 1871 } 1872} 1873 1874function drawControlLines(curve, curveType, drawEnd) { 1875 if (curveType == PATH_LINE) { 1876 return; 1877 } 1878 ctx.strokeStyle = "rgba(0,0,0, 0.3)"; 1879 drawLine(curve[0], curve[1], curve[2], curve[3]); 1880 drawLine(curve[2], curve[3], curve[4], curve[5]); 1881 if (curveType == PATH_CUBIC) { 1882 drawLine(curve[4], curve[5], curve[6], curve[7]); 1883 if (drawEnd > 1) { 1884 drawLine(curve[6], curve[7], curve[0], curve[1]); 1885 if (drawEnd > 2) { 1886 drawLine(curve[0], curve[1], curve[4], curve[5]); 1887 drawLine(curve[6], curve[7], curve[2], curve[3]); 1888 } 1889 } 1890 } else if (drawEnd > 1) { 1891 drawLine(curve[4], curve[5], curve[0], curve[1]); 1892 } 1893} 1894 1895function pointAtT(curve, curveType, t) { 1896 var xy = {}; 1897 switch (curveType) { 1898 case PATH_LINE: 1899 var a = 1 - t; 1900 var b = t; 1901 xy.x = a * curve[0] + b * curve[2]; 1902 xy.y = a * curve[1] + b * curve[3]; 1903 break; 1904 case PATH_QUAD: 1905 var one_t = 1 - t; 1906 var a = one_t * one_t; 1907 var b = 2 * one_t * t; 1908 var c = t * t; 1909 xy.x = a * curve[0] + b * curve[2] + c * curve[4]; 1910 xy.y = a * curve[1] + b * curve[3] + c * curve[5]; 1911 break; 1912 case PATH_CONIC: 1913 var one_t = 1 - t; 1914 var a = one_t * one_t; 1915 var b = 2 * one_t * t; 1916 var c = t * t; 1917 xy.x = a * curve[0] + b * curve[2] * curve[6] + c * curve[4]; 1918 xy.y = a * curve[1] + b * curve[3] * curve[6] + c * curve[5]; 1919 var d = a + b * curve[6] + c; 1920 xy.x /= d; 1921 xy.y /= d; 1922 break; 1923 case PATH_CUBIC: 1924 var one_t = 1 - t; 1925 var one_t2 = one_t * one_t; 1926 var a = one_t2 * one_t; 1927 var b = 3 * one_t2 * t; 1928 var t2 = t * t; 1929 var c = 3 * one_t * t2; 1930 var d = t2 * t; 1931 xy.x = a * curve[0] + b * curve[2] + c * curve[4] + d * curve[6]; 1932 xy.y = a * curve[1] + b * curve[3] + c * curve[5] + d * curve[7]; 1933 break; 1934 } 1935 return xy; 1936} 1937 1938function drawPointAtT(curve, curveType) { 1939 var x, y; 1940 var xy = pointAtT(curve, curveType, curveT); 1941 drawPoint(xy.x, xy.y, true); 1942 if (!draw_intersectT) { 1943 return; 1944 } 1945 ctx.fillStyle = "red"; 1946 drawTAtPointUp(xy.x, xy.y, curveT); 1947} 1948 1949function drawTAtPointUp(px, py, t) { 1950 var label = t.toFixed(decimal_places); 1951 var _px = (px - srcLeft)* scale; 1952 var _py = (py - srcTop) * scale; 1953 ctx.fillText(label, _px + 5, _py - 10); 1954} 1955 1956function drawTAtPointDown(px, py, t) { 1957 var label = t.toFixed(decimal_places); 1958 var _px = (px - srcLeft)* scale; 1959 var _py = (py - srcTop) * scale; 1960 ctx.fillText(label, _px + 5, _py + 10); 1961} 1962 1963function alreadyDrawnLine(x1, y1, x2, y2) { 1964 if (collect_bounds) { 1965 if (focus_enabled) { 1966 focusXmin = Math.min(focusXmin, x1, x2); 1967 focusYmin = Math.min(focusYmin, y1, y2); 1968 focusXmax = Math.max(focusXmax, x1, x2); 1969 focusYmax = Math.max(focusYmax, y1, y2); 1970 } 1971 return true; 1972 } 1973 for (var pts = 0; pts < drawnLines.length; pts += 4) { 1974 if (x1 == drawnLines[pts] && y1 == drawnLines[pts + 1] 1975 && x2 == drawnLines[pts + 2] && y2 == drawnLines[pts + 3]) { 1976 return true; 1977 } 1978 } 1979 drawnLines.push(x1); 1980 drawnLines.push(y1); 1981 drawnLines.push(x2); 1982 drawnLines.push(y2); 1983 return false; 1984} 1985 1986function drawLine(x1, y1, x2, y2) { 1987 if (alreadyDrawnLine(x1, y1, x2, y2)) { 1988 return; 1989 } 1990 ctx.beginPath(); 1991 ctx.moveTo((x1 - srcLeft) * scale, 1992 (y1 - srcTop) * scale); 1993 ctx.lineTo((x2 - srcLeft) * scale, 1994 (y2 - srcTop) * scale); 1995 ctx.stroke(); 1996} 1997 1998function linePartial(x1, y1, x2, y2, t1, t2) { 1999 var dx = x1 - x2; 2000 var dy = y1 - y2; 2001 var array = [ 2002 x1 - t1 * dx, 2003 y1 - t1 * dy, 2004 x1 - t2 * dx, 2005 y1 - t2 * dy 2006 ]; 2007 return array; 2008} 2009 2010function drawLinePartial(x1, y1, x2, y2, t1, t2) { 2011 var a = linePartial(x1, y1, x2, y2, t1, t2); 2012 var ax = a[0]; 2013 var ay = a[1]; 2014 var bx = a[2]; 2015 var by = a[3]; 2016 if (alreadyDrawnLine(ax, ay, bx, by)) { 2017 return; 2018 } 2019 ctx.beginPath(); 2020 ctx.moveTo((ax - srcLeft) * scale, 2021 (ay - srcTop) * scale); 2022 ctx.lineTo((bx - srcLeft) * scale, 2023 (by - srcTop) * scale); 2024 ctx.stroke(); 2025} 2026 2027function alreadyDrawnQuad(x1, y1, x2, y2, x3, y3) { 2028 if (collect_bounds) { 2029 if (focus_enabled) { 2030 focusXmin = Math.min(focusXmin, x1, x2, x3); 2031 focusYmin = Math.min(focusYmin, y1, y2, y3); 2032 focusXmax = Math.max(focusXmax, x1, x2, x3); 2033 focusYmax = Math.max(focusYmax, y1, y2, y3); 2034 } 2035 return true; 2036 } 2037 for (var pts = 0; pts < drawnQuads.length; pts += 6) { 2038 if (x1 == drawnQuads[pts] && y1 == drawnQuads[pts + 1] 2039 && x2 == drawnQuads[pts + 2] && y2 == drawnQuads[pts + 3] 2040 && x3 == drawnQuads[pts + 4] && y3 == drawnQuads[pts + 5]) { 2041 return true; 2042 } 2043 } 2044 drawnQuads.push(x1); 2045 drawnQuads.push(y1); 2046 drawnQuads.push(x2); 2047 drawnQuads.push(y2); 2048 drawnQuads.push(x3); 2049 drawnQuads.push(y3); 2050 return false; 2051} 2052 2053function drawQuad(x1, y1, x2, y2, x3, y3) { 2054 if (alreadyDrawnQuad(x1, y1, x2, y2, x3, y3)) { 2055 return; 2056 } 2057 ctx.beginPath(); 2058 ctx.moveTo((x1 - srcLeft) * scale, 2059 (y1 - srcTop) * scale); 2060 ctx.quadraticCurveTo((x2 - srcLeft) * scale, 2061 (y2 - srcTop) * scale, 2062 (x3 - srcLeft) * scale, 2063 (y3 - srcTop) * scale); 2064 ctx.stroke(); 2065} 2066 2067function interp(A, B, t) { 2068 return A + (B - A) * t; 2069} 2070 2071function interp_quad_coords(x1, x2, x3, t) 2072{ 2073 var ab = interp(x1, x2, t); 2074 var bc = interp(x2, x3, t); 2075 var abc = interp(ab, bc, t); 2076 return abc; 2077} 2078 2079function quadPartial(x1, y1, x2, y2, x3, y3, t1, t2) { 2080 var ax = interp_quad_coords(x1, x2, x3, t1); 2081 var ay = interp_quad_coords(y1, y2, y3, t1); 2082 var dx = interp_quad_coords(x1, x2, x3, (t1 + t2) / 2); 2083 var dy = interp_quad_coords(y1, y2, y3, (t1 + t2) / 2); 2084 var cx = interp_quad_coords(x1, x2, x3, t2); 2085 var cy = interp_quad_coords(y1, y2, y3, t2); 2086 var bx = 2*dx - (ax + cx)/2; 2087 var by = 2*dy - (ay + cy)/2; 2088 var array = [ 2089 ax, ay, bx, by, cx, cy 2090 ]; 2091 return array; 2092} 2093 2094function drawQuadPartial(x1, y1, x2, y2, x3, y3, t1, t2) { 2095 var a = quadPartial(x1, y1, x2, y2, x3, y3, t1, t2); 2096 var ax = a[0]; 2097 var ay = a[1]; 2098 var bx = a[2]; 2099 var by = a[3]; 2100 var cx = a[4]; 2101 var cy = a[5]; 2102 if (alreadyDrawnQuad(ax, ay, bx, by, cx, cy)) { 2103 return; 2104 } 2105 ctx.beginPath(); 2106 ctx.moveTo((ax - srcLeft) * scale, 2107 (ay - srcTop) * scale); 2108 ctx.quadraticCurveTo((bx - srcLeft) * scale, 2109 (by - srcTop) * scale, 2110 (cx - srcLeft) * scale, 2111 (cy - srcTop) * scale); 2112 ctx.stroke(); 2113} 2114 2115function alreadyDrawnConic(x1, y1, x2, y2, x3, y3, w) { 2116 if (collect_bounds) { 2117 if (focus_enabled) { 2118 focusXmin = Math.min(focusXmin, x1, x2, x3); 2119 focusYmin = Math.min(focusYmin, y1, y2, y3); 2120 focusXmax = Math.max(focusXmax, x1, x2, x3); 2121 focusYmax = Math.max(focusYmax, y1, y2, y3); 2122 } 2123 return true; 2124 } 2125 for (var pts = 0; pts < drawnConics.length; pts += 8) { 2126 if (x1 == drawnConics[pts] && y1 == drawnCubics[pts + 1] 2127 && x2 == drawnCubics[pts + 2] && y2 == drawnCubics[pts + 3] 2128 && x3 == drawnCubics[pts + 4] && y3 == drawnCubics[pts + 5] 2129 && w == drawnCubics[pts + 6]) { 2130 return true; 2131 } 2132 } 2133 drawnConics.push(x1); 2134 drawnConics.push(y1); 2135 drawnConics.push(x2); 2136 drawnConics.push(y2); 2137 drawnConics.push(x3); 2138 drawnConics.push(y3); 2139 drawnCubics.push(w); 2140 return false; 2141} 2142 2143var kMaxConicToQuadPOW2 = 5; 2144 2145function computeQuadPOW2(curve, tol) { 2146 var a = curve[6] - 1; 2147 var k = a / (4 * (2 + a)); 2148 var x = k * (curve[0] - 2 * curve[2] + curve[4]); 2149 var y = k * (curve[1] - 2 * curve[3] + curve[5]); 2150 2151 var error = Math.sqrt(x * x + y * y); 2152 var pow2; 2153 for (pow2 = 0; pow2 < kMaxConicToQuadPOW2; ++pow2) { 2154 if (error <= tol) { 2155 break; 2156 } 2157 error *= 0.25; 2158 } 2159 return pow2; 2160} 2161 2162function subdivide_w_value(w) { 2163 return Math.sqrt(0.5 + w * 0.5); 2164} 2165 2166function chop(curve, part1, part2) { 2167 var w = curve[6]; 2168 var scale = 1 / (1 + w); 2169 part1[0] = curve[0]; 2170 part1[1] = curve[1]; 2171 part1[2] = (curve[0] + curve[2] * w) * scale; 2172 part1[3] = (curve[1] + curve[3] * w) * scale; 2173 part1[4] = part2[0] = (curve[0] + (curve[2] * w) * 2 + curve[4]) * scale * 0.5; 2174 part1[5] = part2[1] = (curve[1] + (curve[3] * w) * 2 + curve[5]) * scale * 0.5; 2175 part2[2] = (curve[2] * w + curve[4]) * scale; 2176 part2[3] = (curve[3] * w + curve[5]) * scale; 2177 part2[4] = curve[4]; 2178 part2[5] = curve[5]; 2179 part1[6] = part2[6] = subdivide_w_value(w); 2180} 2181 2182function subdivide(curve, level, pts) { 2183 if (0 == level) { 2184 pts.push(curve[2]); 2185 pts.push(curve[3]); 2186 pts.push(curve[4]); 2187 pts.push(curve[5]); 2188 } else { 2189 var part1 = [], part2 = []; 2190 chop(curve, part1, part2); 2191 --level; 2192 subdivide(part1, level, pts); 2193 subdivide(part2, level, pts); 2194 } 2195} 2196 2197function chopIntoQuadsPOW2(curve, pow2, pts) { 2198 subdivide(curve, pow2, pts); 2199 return 1 << pow2; 2200} 2201 2202function drawConicWithQuads(x1, y1, x2, y2, x3, y3, w) { 2203 if (alreadyDrawnConic(x1, y1, x2, y2, x3, y3, w)) { 2204 return; 2205 } 2206 ctx.beginPath(); 2207 ctx.moveTo((x1 - srcLeft) * scale, 2208 (y1 - srcTop) * scale); 2209 var tol = 1 / scale; 2210 var curve = [x1, y1, x2, y2, x3, y3, w]; 2211 var pow2 = computeQuadPOW2(curve, tol); 2212 var pts = []; 2213 chopIntoQuadsPOW2(curve, pow2, pts); 2214 for (var i = 0; i < pts.length; i += 4) { 2215 ctx.quadraticCurveTo( 2216 (pts[i + 0] - srcLeft) * scale, (pts[i + 1] - srcTop) * scale, 2217 (pts[i + 2] - srcLeft) * scale, (pts[i + 3] - srcTop) * scale); 2218 } 2219 ctx.stroke(); 2220} 2221 2222function conic_eval_numerator(x1, x2, x3, w, t) { 2223 var src2w = x2 * w; 2224 var C = x1; 2225 var A = x3 - 2 * src2w + C; 2226 var B = 2 * (src2w - C); 2227 return (A * t + B) * t + C; 2228} 2229 2230 2231function conic_eval_denominator(w, t) { 2232 var B = 2 * (w - 1); 2233 var C = 1; 2234 var A = -B; 2235 return (A * t + B) * t + C; 2236} 2237 2238function conicPartial(x1, y1, x2, y2, x3, y3, w, t1, t2) { 2239 var ax = conic_eval_numerator(x1, x2, x3, w, t1); 2240 var ay = conic_eval_numerator(y1, y2, y3, w, t1); 2241 var az = conic_eval_denominator(w, t1); 2242 var midT = (t1 + t2) / 2; 2243 var dx = conic_eval_numerator(x1, x2, x3, w, midT); 2244 var dy = conic_eval_numerator(y1, y2, y3, w, midT); 2245 var dz = conic_eval_denominator(w, midT); 2246 var cx = conic_eval_numerator(x1, x2, x3, w, t2); 2247 var cy = conic_eval_numerator(y1, y2, y3, w, t2); 2248 var cz = conic_eval_denominator(w, t2); 2249 var bx = 2 * dx - (ax + cx) / 2; 2250 var by = 2 * dy - (ay + cy) / 2; 2251 var bz = 2 * dz - (az + cz) / 2; 2252 var dt = t2 - t1; 2253 var dt_1 = 1 - dt; 2254 var array = [ 2255 ax / az, ay / az, bx / bz, by / bz, cx / cz, cy / cz, 0 2256 ]; 2257 var dMidAC = { x:(array[0] + array[4]) / 2, y:(array[1] + array[5]) / 2 }; 2258 var dMid = { x:dx / dz, y:dy / dz }; 2259 var dWNumer = { x:dMidAC.x - dMid.x, y:dMidAC.y - dMid.y }; 2260 var dWDenom = { x:dMid.x - array[2], y:dMid.y - array[3] }; 2261 var partW = Math.sqrt(dWNumer.x * dWNumer.x + dWNumer.y * dWNumer.y) 2262 / Math.sqrt(dWDenom.x * dWDenom.x + dWDenom.y * dWDenom.y); 2263 array[6] = partW; 2264 return array; 2265} 2266 2267function drawConicPartial(x1, y1, x2, y2, x3, y3, w, t1, t2) { 2268 var a = conicPartial(x1, y1, x2, y2, x3, y3, w, t1, t2); 2269 var ax = a[0]; 2270 var ay = a[1]; 2271 var bx = a[2]; 2272 var by = a[3]; 2273 var cx = a[4]; 2274 var cy = a[5]; 2275 var w_ = a[6]; 2276 drawConicWithQuads(ax, ay, bx, by, cx, cy, w_); 2277} 2278 2279function alreadyDrawnCubic(x1, y1, x2, y2, x3, y3, x4, y4) { 2280 if (collect_bounds) { 2281 if (focus_enabled) { 2282 focusXmin = Math.min(focusXmin, x1, x2, x3, x4); 2283 focusYmin = Math.min(focusYmin, y1, y2, y3, y4); 2284 focusXmax = Math.max(focusXmax, x1, x2, x3, x4); 2285 focusYmax = Math.max(focusYmax, y1, y2, y3, y4); 2286 } 2287 return true; 2288 } 2289 for (var pts = 0; pts < drawnCubics.length; pts += 8) { 2290 if (x1 == drawnCubics[pts] && y1 == drawnCubics[pts + 1] 2291 && x2 == drawnCubics[pts + 2] && y2 == drawnCubics[pts + 3] 2292 && x3 == drawnCubics[pts + 4] && y3 == drawnCubics[pts + 5] 2293 && x4 == drawnCubics[pts + 6] && y4 == drawnCubics[pts + 7]) { 2294 return true; 2295 } 2296 } 2297 drawnCubics.push(x1); 2298 drawnCubics.push(y1); 2299 drawnCubics.push(x2); 2300 drawnCubics.push(y2); 2301 drawnCubics.push(x3); 2302 drawnCubics.push(y3); 2303 drawnCubics.push(x4); 2304 drawnCubics.push(y4); 2305 return false; 2306} 2307 2308function drawCubic(x1, y1, x2, y2, x3, y3, x4, y4) { 2309 if (alreadyDrawnCubic(x1, y1, x2, y2, x3, y3, x4, y4)) { 2310 return; 2311 } 2312 ctx.beginPath(); 2313 ctx.moveTo((x1 - srcLeft) * scale, 2314 (y1 - srcTop) * scale); 2315 ctx.bezierCurveTo((x2 - srcLeft) * scale, 2316 (y2 - srcTop) * scale, 2317 (x3 - srcLeft) * scale, 2318 (y3 - srcTop) * scale, 2319 (x4 - srcLeft) * scale, 2320 (y4 - srcTop) * scale); 2321 ctx.stroke(); 2322} 2323 2324function interp_cubic_coords(x1, x2, x3, x4, t) 2325{ 2326 var ab = interp(x1, x2, t); 2327 var bc = interp(x2, x3, t); 2328 var cd = interp(x3, x4, t); 2329 var abc = interp(ab, bc, t); 2330 var bcd = interp(bc, cd, t); 2331 var abcd = interp(abc, bcd, t); 2332 return abcd; 2333} 2334 2335function cubicPartial(x1, y1, x2, y2, x3, y3, x4, y4, t1, t2) { 2336 var ax = interp_cubic_coords(x1, x2, x3, x4, t1); 2337 var ay = interp_cubic_coords(y1, y2, y3, y4, t1); 2338 var ex = interp_cubic_coords(x1, x2, x3, x4, (t1*2+t2)/3); 2339 var ey = interp_cubic_coords(y1, y2, y3, y4, (t1*2+t2)/3); 2340 var fx = interp_cubic_coords(x1, x2, x3, x4, (t1+t2*2)/3); 2341 var fy = interp_cubic_coords(y1, y2, y3, y4, (t1+t2*2)/3); 2342 var dx = interp_cubic_coords(x1, x2, x3, x4, t2); 2343 var dy = interp_cubic_coords(y1, y2, y3, y4, t2); 2344 var mx = ex * 27 - ax * 8 - dx; 2345 var my = ey * 27 - ay * 8 - dy; 2346 var nx = fx * 27 - ax - dx * 8; 2347 var ny = fy * 27 - ay - dy * 8; 2348 var bx = (mx * 2 - nx) / 18; 2349 var by = (my * 2 - ny) / 18; 2350 var cx = (nx * 2 - mx) / 18; 2351 var cy = (ny * 2 - my) / 18; 2352 var array = [ 2353 ax, ay, bx, by, cx, cy, dx, dy 2354 ]; 2355 return array; 2356} 2357 2358function drawCubicPartial(x1, y1, x2, y2, x3, y3, x4, y4, t1, t2) { 2359 var a = cubicPartial(x1, y1, x2, y2, x3, y3, x4, y4, t1, t2); 2360 var ax = a[0]; 2361 var ay = a[1]; 2362 var bx = a[2]; 2363 var by = a[3]; 2364 var cx = a[4]; 2365 var cy = a[5]; 2366 var dx = a[6]; 2367 var dy = a[7]; 2368 if (alreadyDrawnCubic(ax, ay, bx, by, cx, cy, dx, dy)) { 2369 return; 2370 } 2371 ctx.beginPath(); 2372 ctx.moveTo((ax - srcLeft) * scale, 2373 (ay - srcTop) * scale); 2374 ctx.bezierCurveTo((bx - srcLeft) * scale, 2375 (by - srcTop) * scale, 2376 (cx - srcLeft) * scale, 2377 (cy - srcTop) * scale, 2378 (dx - srcLeft) * scale, 2379 (dy - srcTop) * scale); 2380 ctx.stroke(); 2381} 2382 2383function drawCurve(c) { 2384 switch (c.length) { 2385 case 4: 2386 drawLine(c[0], c[1], c[2], c[3]); 2387 break; 2388 case 6: 2389 drawQuad(c[0], c[1], c[2], c[3], c[4], c[5]); 2390 break; 2391 case 7: 2392 drawConicWithQuads(c[0], c[1], c[2], c[3], c[4], c[5], c[6]); 2393 break; 2394 case 8: 2395 drawCubic(c[0], c[1], c[2], c[3], c[4], c[5], c[6], c[7]); 2396 break; 2397 } 2398} 2399 2400function boundsWidth(pts) { 2401 var min = pts[0]; 2402 var max = pts[0]; 2403 var length = pts.length == 7 ? 6 : pts.length; 2404 for (var idx = 2; idx < length; idx += 2) { 2405 min = Math.min(min, pts[idx]); 2406 max = Math.max(max, pts[idx]); 2407 } 2408 return max - min; 2409} 2410 2411function boundsHeight(pts) { 2412 var min = pts[1]; 2413 var max = pts[1]; 2414 var length = pts.length == 7 ? 6 : pts.length; 2415 for (var idx = 3; idx < length; idx += 2) { 2416 min = Math.min(min, pts[idx]); 2417 max = Math.max(max, pts[idx]); 2418 } 2419 return max - min; 2420} 2421 2422function tangent(pts) { 2423 var dx = pts[2] - pts[0]; 2424 var dy = pts[3] - pts[1]; 2425 if (dx == 0 && dy == 0 && pts.length > 4) { 2426 dx = pts[4] - pts[0]; 2427 dy = pts[5] - pts[1]; 2428 if (dx == 0 && dy == 0 && pts.length == 8) { 2429 dx = pts[6] - pts[0]; 2430 dy = pts[7] - pts[1]; 2431 } 2432 } 2433 return Math.atan2(-dy, dx); 2434} 2435 2436function hodograph(cubic) { 2437 var hodo = []; 2438 hodo[0] = 3 * (cubic[2] - cubic[0]); 2439 hodo[1] = 3 * (cubic[3] - cubic[1]); 2440 hodo[2] = 3 * (cubic[4] - cubic[2]); 2441 hodo[3] = 3 * (cubic[5] - cubic[3]); 2442 hodo[4] = 3 * (cubic[6] - cubic[4]); 2443 hodo[5] = 3 * (cubic[7] - cubic[5]); 2444 return hodo; 2445} 2446 2447function hodograph2(cubic) { 2448 var quad = hodograph(cubic); 2449 var hodo = []; 2450 hodo[0] = 2 * (quad[2] - quad[0]); 2451 hodo[1] = 2 * (quad[3] - quad[1]); 2452 hodo[2] = 2 * (quad[4] - quad[2]); 2453 hodo[3] = 2 * (quad[5] - quad[3]); 2454 return hodo; 2455} 2456 2457function quadraticRootsReal(A, B, C, s) { 2458 if (A == 0) { 2459 if (B == 0) { 2460 s[0] = 0; 2461 return C == 0; 2462 } 2463 s[0] = -C / B; 2464 return 1; 2465 } 2466 /* normal form: x^2 + px + q = 0 */ 2467 var p = B / (2 * A); 2468 var q = C / A; 2469 var p2 = p * p; 2470 if (p2 < q) { 2471 return 0; 2472 } 2473 var sqrt_D = 0; 2474 if (p2 > q) { 2475 sqrt_D = sqrt(p2 - q); 2476 } 2477 s[0] = sqrt_D - p; 2478 s[1] = -sqrt_D - p; 2479 return 1 + s[0] != s[1]; 2480} 2481 2482function add_valid_ts(s, realRoots, t) { 2483 var foundRoots = 0; 2484 for (var index = 0; index < realRoots; ++index) { 2485 var tValue = s[index]; 2486 if (tValue >= 0 && tValue <= 1) { 2487 for (var idx2 = 0; idx2 < foundRoots; ++idx2) { 2488 if (t[idx2] != tValue) { 2489 t[foundRoots++] = tValue; 2490 } 2491 } 2492 } 2493 } 2494 return foundRoots; 2495} 2496 2497function quadraticRootsValidT(a, b, c, t) { 2498 var s = []; 2499 var realRoots = quadraticRootsReal(A, B, C, s); 2500 var foundRoots = add_valid_ts(s, realRoots, t); 2501 return foundRoots != 0; 2502} 2503 2504function find_cubic_inflections(cubic, tValues) { 2505 var Ax = src[2] - src[0]; 2506 var Ay = src[3] - src[1]; 2507 var Bx = src[4] - 2 * src[2] + src[0]; 2508 var By = src[5] - 2 * src[3] + src[1]; 2509 var Cx = src[6] + 3 * (src[2] - src[4]) - src[0]; 2510 var Cy = src[7] + 3 * (src[3] - src[5]) - src[1]; 2511 return quadraticRootsValidT(Bx * Cy - By * Cx, (Ax * Cy - Ay * Cx), 2512 Ax * By - Ay * Bx, tValues); 2513} 2514 2515function dxy_at_t(curve, type, t) { 2516 var dxy = {}; 2517 if (type == PATH_LINE) { 2518 dxy.x = curve[2] - curve[0]; 2519 dxy.y = curve[3] - curve[1]; 2520 } else if (type == PATH_QUAD) { 2521 var a = t - 1; 2522 var b = 1 - 2 * t; 2523 var c = t; 2524 dxy.x = a * curve[0] + b * curve[2] + c * curve[4]; 2525 dxy.y = a * curve[1] + b * curve[3] + c * curve[5]; 2526 } else if (type == PATH_CONIC) { 2527 var p20x = curve[4] - curve[0]; 2528 var p20y = curve[5] - curve[1]; 2529 var p10xw = (curve[2] - curve[0]) * curve[6]; 2530 var p10yw = (curve[3] - curve[1]) * curve[6]; 2531 var coeff0x = curve[6] * p20x - p20x; 2532 var coeff0y = curve[6] * p20y - p20y; 2533 var coeff1x = p20x - 2 * p10xw; 2534 var coeff1y = p20y - 2 * p10yw; 2535 dxy.x = t * (t * coeff0x + coeff1x) + p10xw; 2536 dxy.y = t * (t * coeff0y + coeff1y) + p10yw; 2537 } else if (type == PATH_CUBIC) { 2538 var one_t = 1 - t; 2539 var a = curve[0]; 2540 var b = curve[2]; 2541 var c = curve[4]; 2542 var d = curve[6]; 2543 dxy.x = 3 * ((b - a) * one_t * one_t + 2 * (c - b) * t * one_t + (d - c) * t * t); 2544 a = curve[1]; 2545 b = curve[3]; 2546 c = curve[5]; 2547 d = curve[7]; 2548 dxy.y = 3 * ((b - a) * one_t * one_t + 2 * (c - b) * t * one_t + (d - c) * t * t); 2549 } 2550 return dxy; 2551} 2552 2553function dpt_at_t(curve, t) { 2554 var type = PATH_LINE + (curve.length / 2 - 2); 2555 return dxy_at_t(curve, type, t); 2556} 2557 2558function drawLabel(num, px, py) { 2559 ctx.beginPath(); 2560 ctx.arc(px, py, 8, 0, Math.PI*2, true); 2561 ctx.closePath(); 2562 ctx.strokeStyle = "rgba(0,0,0, 0.4)"; 2563 ctx.lineWidth = num == 0 || num == 3 ? 2 : 1; 2564 ctx.stroke(); 2565 ctx.fillStyle = "black"; 2566 ctx.font = "normal 10px Arial"; 2567 // ctx.rotate(0.001); 2568 ctx.fillText(num, px - 2, py + 3); 2569 // ctx.rotate(-0.001); 2570} 2571 2572function drawLabelX(ymin, num, loc) { 2573 var px = (loc - srcLeft) * scale; 2574 var py = (ymin - srcTop) * scale - 20; 2575 drawLabel(num, px, py); 2576} 2577 2578function drawLabelY(xmin, num, loc) { 2579 var px = (xmin - srcLeft) * scale - 20; 2580 var py = (loc - srcTop) * scale; 2581 drawLabel(num, px, py); 2582} 2583 2584function drawHodoOrigin(hx, hy, hMinX, hMinY, hMaxX, hMaxY) { 2585 ctx.beginPath(); 2586 ctx.moveTo(hx, hy - 100); 2587 ctx.lineTo(hx, hy); 2588 ctx.strokeStyle = hMinY < 0 ? "green" : "blue"; 2589 ctx.stroke(); 2590 ctx.beginPath(); 2591 ctx.moveTo(hx, hy); 2592 ctx.lineTo(hx, hy + 100); 2593 ctx.strokeStyle = hMaxY > 0 ? "green" : "blue"; 2594 ctx.stroke(); 2595 ctx.beginPath(); 2596 ctx.moveTo(hx - 100, hy); 2597 ctx.lineTo(hx, hy); 2598 ctx.strokeStyle = hMinX < 0 ? "green" : "blue"; 2599 ctx.stroke(); 2600 ctx.beginPath(); 2601 ctx.moveTo(hx, hy); 2602 ctx.lineTo(hx + 100, hy); 2603 ctx.strokeStyle = hMaxX > 0 ? "green" : "blue"; 2604 ctx.stroke(); 2605} 2606 2607function scalexy(x, y, mag) { 2608 var length = Math.sqrt(x * x + y * y); 2609 return mag / length; 2610} 2611 2612function drawArrow(x, y, dx, dy, s) { 2613 var dscale = scalexy(dx, dy, 1 / scale * 100 * s); 2614 dx *= dscale; 2615 dy *= dscale; 2616 ctx.beginPath(); 2617 ctx.moveTo((x - srcLeft) * scale, (y - srcTop) * scale); 2618 x += dx; 2619 y += dy; 2620 ctx.lineTo((x - srcLeft) * scale, (y - srcTop) * scale); 2621 dx /= 10; 2622 dy /= 10; 2623 ctx.lineTo((x - dy - srcLeft) * scale, (y + dx - srcTop) * scale); 2624 ctx.lineTo((x + dx * 2 - srcLeft) * scale, (y + dy * 2 - srcTop) * scale); 2625 ctx.lineTo((x + dy - srcLeft) * scale, (y - dx - srcTop) * scale); 2626 ctx.lineTo((x - srcLeft) * scale, (y - srcTop) * scale); 2627 ctx.strokeStyle = "rgba(0,75,0, 0.4)"; 2628 ctx.stroke(); 2629} 2630 2631function x_at_t(curve, t) { 2632 var one_t = 1 - t; 2633 if (curve.length == 4) { 2634 return one_t * curve[0] + t * curve[2]; 2635 } 2636 var one_t2 = one_t * one_t; 2637 var t2 = t * t; 2638 if (curve.length == 6) { 2639 return one_t2 * curve[0] + 2 * one_t * t * curve[2] + t2 * curve[4]; 2640 } 2641 if (curve.length == 7) { 2642 return (one_t2 * curve[0] + 2 * one_t * t * curve[2] * curve[6] + t2 * curve[4]) 2643 / (one_t2 +2 * one_t * t * curve[6] + t2); 2644 } 2645 var a = one_t2 * one_t; 2646 var b = 3 * one_t2 * t; 2647 var c = 3 * one_t * t2; 2648 var d = t2 * t; 2649 return a * curve[0] + b * curve[2] + c * curve[4] + d * curve[6]; 2650} 2651 2652function y_at_t(curve, t) { 2653 var one_t = 1 - t; 2654 if (curve.length == 4) { 2655 return one_t * curve[1] + t * curve[3]; 2656 } 2657 var one_t2 = one_t * one_t; 2658 var t2 = t * t; 2659 if (curve.length == 6) { 2660 return one_t2 * curve[1] + 2 * one_t * t * curve[3] + t2 * curve[5]; 2661 } 2662 if (curve.length == 7) { 2663 return (one_t2 * curve[1] + 2 * one_t * t * curve[3] * curve[6] + t2 * curve[5]) 2664 / (one_t2 +2 * one_t * t * curve[6] + t2); 2665 } 2666 var a = one_t2 * one_t; 2667 var b = 3 * one_t2 * t; 2668 var c = 3 * one_t * t2; 2669 var d = t2 * t; 2670 return a * curve[1] + b * curve[3] + c * curve[5] + d * curve[7]; 2671} 2672 2673function pt_at_t(curve, t) { 2674 var pt = {}; 2675 pt.x = x_at_t(curve, t); 2676 pt.y = y_at_t(curve, t); 2677 return pt; 2678} 2679 2680function drawOrder(curve, t, label) { 2681 var px = x_at_t(curve, t); 2682 var py = y_at_t(curve, t); 2683 var _px = (px - srcLeft) * scale; 2684 var _py = (py - srcTop) * scale; 2685 ctx.beginPath(); 2686 ctx.arc(_px, _py, 15, 0, Math.PI * 2, true); 2687 ctx.closePath(); 2688 ctx.fillStyle = "white"; 2689 ctx.fill(); 2690 if (label == 'L') { 2691 ctx.strokeStyle = "rgba(255,0,0, 1)"; 2692 ctx.fillStyle = "rgba(255,0,0, 1)"; 2693 } else { 2694 ctx.strokeStyle = "rgba(0,0,255, 1)"; 2695 ctx.fillStyle = "rgba(0,0,255, 1)"; 2696 } 2697 ctx.stroke(); 2698 ctx.font = "normal 16px Arial"; 2699 ctx.textAlign = "center"; 2700 ctx.fillText(label, _px, _py + 5); 2701 ctx.font = "normal 10px Arial"; 2702} 2703 2704function drawVisibleOrder(curve, label) { 2705 var s = pt_at_t(curve, 0); 2706 var e = pt_at_t(curve, 1); 2707 var sOn = ptOnScreen(s); 2708 var eOn = ptOnScreen(e); 2709 var defaultT = 0.85; 2710 if (sOn && eOn) 2711 return drawOrder(curve, defaultT, label); 2712 if (sOn || eOn) { 2713 if (eOn) { 2714 defaultT = 1 - defaultT; 2715 } 2716 var step = sOn ? -defaultT / 2 : (1 - defaultT) / 2; 2717 var t = defaultT; 2718 var tries = 16; 2719 do { 2720 var mid = pt_at_t(curve, t); 2721 if (ptOnScreen(mid)) 2722 return drawOrder(curve, t, label); 2723 t += step; 2724 step /= 2; 2725 } while (--tries > 0); 2726 drawOrder(curve, defaultT, label); 2727 } 2728 // scattershot until we find a visible point 2729 var denom = 2; // visit odd number num / denom to hit unique pts 2730 var tries = 6; // tries 1/2, 1/4, 3/4, 1/8, 3/8, 5/8, 7/8, 1/16 ... 2731 do { 2732 for (var numer = 1; numer < denom; numer += 2) { 2733 var t = numer / denom + 0.1; 2734 if (t >= 1) { 2735 break; 2736 } 2737 var mid = pt_at_t(curve, t); 2738 if (ptOnScreen(mid)) 2739 return drawOrder(curve, t, label); 2740 } 2741 denom *= 2; 2742 } while (--tries > 0); 2743 drawOrder(curve, defaultT, label); 2744} 2745 2746function set_length(pt, newLen) { 2747 var len = Math.sqrt(pt.x * pt.x + pt.y * pt.y); 2748 var scale = newLen / len; 2749 var newPt = { x: pt.x * scale, y: pt.y * scale }; 2750 return newPt; 2751} 2752 2753function drawDirection(curve, t) { 2754 var d = dpt_at_t(curve, t); 2755 d = set_length(d, 16); 2756 var pt = localToGlobal(pt_at_t(curve, t)); 2757 ctx.beginPath(); 2758 ctx.moveTo(pt.x - d.y, pt.y + d.x); 2759 ctx.lineTo(pt.x + d.x, pt.y + d.y); 2760 ctx.lineTo(pt.x + d.y, pt.y - d.x); 2761 ctx.strokeStyle = "rgba(0,75,0, 0.4)"; 2762 ctx.stroke(); 2763} 2764 2765function drawVisibleDirection(curve) { 2766 var s = pt_at_t(curve, 0); 2767 var e = pt_at_t(curve, 1); 2768 var sOn = ptOnScreen(s); 2769 var eOn = ptOnScreen(e); 2770 var defaultT = 0.65; 2771 if (sOn && eOn) { 2772 return drawDirection(curve, defaultT); 2773 } 2774 if (sOn || eOn) { 2775 if (eOn) { 2776 defaultT = 1 - defaultT; 2777 } 2778 var step = sOn ? -defaultT / 2 : (1 - defaultT) / 2; 2779 var t = defaultT; 2780 var tries = 16; 2781 do { 2782 var mid = pt_at_t(curve, t); 2783 if (ptOnScreen(mid)) 2784 return drawDirection(curve, t); 2785 t += step; 2786 step /= 2; 2787 } while (--tries > 0); 2788 drawDirection(curve, defaultT); 2789 } 2790 // scattershot until we find a visible point 2791 var denom = 2; // visit odd number num / denom to hit unique pts 2792 var tries = 6; // tries 1/2, 1/4, 3/4, 1/8, 3/8, 5/8, 7/8, 1/16 ... 2793 do { 2794 for (var numer = 1; numer < denom; numer += 2) { 2795 var t = numer / denom + 0.1; 2796 if (t >= 1) { 2797 break; 2798 } 2799 var mid = pt_at_t(curve, t); 2800 if (ptOnScreen(mid)) 2801 return drawDirection(curve, t); 2802 } 2803 denom *= 2; 2804 } while (--tries > 0); 2805 drawDirection(curve, defaultT); 2806} 2807 2808function drawID(curve, t, id) { 2809 var px = x_at_t(curve, t); 2810 var py = y_at_t(curve, t); 2811 var _px = (px - srcLeft) * scale; 2812 var _py = (py - srcTop) * scale; 2813 draw_id_at(id, _px, _py); 2814} 2815 2816function localToGlobal(local) { 2817 var global = {}; 2818 global.x = (local.x - srcLeft) * scale; 2819 global.y = (local.y - srcTop) * scale; 2820 return global; 2821} 2822 2823function ptOnScreen(local) { 2824 var pt = localToGlobal(local); 2825 return 10 <= pt.x && pt.x <= screenWidth - 10 2826 && 10 <= pt.y && pt.y <= screenHeight - 10; 2827} 2828 2829function drawVisibleID(curve, defaultT, id) { 2830 // determine if either or both ends are visible 2831 var s = pt_at_t(curve, 0); 2832 var e = pt_at_t(curve, 1); 2833 var sOn = ptOnScreen(s); 2834 var eOn = ptOnScreen(e); 2835 if (sOn && eOn) 2836 return drawID(curve, defaultT, id); 2837 if (sOn || eOn) { 2838 var step = sOn ? -defaultT / 2 : (1 - defaultT) / 2; 2839 var t = defaultT; 2840 var tries = 16; 2841 do { 2842 var mid = pt_at_t(curve, t); 2843 if (ptOnScreen(mid)) 2844 return drawID(curve, t, id); 2845 t += step; 2846 step /= 2; 2847 } while (--tries > 0); 2848 drawID(curve, defaultT, id); 2849 } 2850 // scattershot until we find a visible point 2851 var denom = 2; // visit odd number num / denom to hit unique pts 2852 var tries = 6; // tries 1/2, 1/4, 3/4, 1/8, 3/8, 5/8, 7/8, 1/16 ... 2853 do { 2854 for (var numer = 1; numer < denom; numer += 2) { 2855 var t = numer / denom; 2856 var mid = pt_at_t(curve, t); 2857 if (ptOnScreen(mid)) 2858 return drawID(curve, t, id); 2859 } 2860 denom *= 2; 2861 } while (--tries > 0); 2862 drawID(curve, defaultT, id); 2863} 2864 2865function draw_id_at(id, _px, _py) { 2866 ctx.beginPath(); 2867 ctx.arc(_px, _py, 15, 0, Math.PI * 2, true); 2868 ctx.closePath(); 2869 ctx.fillStyle = "white"; 2870 ctx.fill(); 2871 ctx.strokeStyle = "rgba(127,127,0, 1)"; 2872 ctx.fillStyle = "rgba(127,127,0, 1)"; 2873 ctx.stroke(); 2874 ctx.font = "normal 16px Arial"; 2875 ctx.textAlign = "center"; 2876 ctx.fillText(id, _px, _py + 5); 2877 ctx.font = "normal 10px Arial"; 2878} 2879 2880function drawLinePartialID(id, x1, y1, x2, y2, t1, t2) { 2881 var curve = [x1, y1, x2, y2]; 2882 drawCurvePartialID(id, curve, t1, t2); 2883} 2884 2885function drawLineID(id, x1, y1, x2, y2) { 2886 drawLinePartialID(id, x1, y1, x2, y2, 0, 1); 2887} 2888 2889function drawQuadPartialID(id, x1, y1, x2, y2, x3, y3, t1, t2) { 2890 var curve = [x1, y1, x2, y2, x3, y3]; 2891 drawCurvePartialID(id, curve, t1, t2); 2892} 2893 2894function drawQuadID(id, x1, y1, x2, y2, x3, y3) { 2895 drawQuadPartialID(id, x1, y1, x2, y2, x3, y3, 0, 1); 2896} 2897 2898function drawConicPartialID(id, x1, y1, x2, y2, x3, y3, w, t1, t2) { 2899 var curve = [x1, y1, x2, y2, x3, y3, w]; 2900 drawCurvePartialID(id, curve, t1, t2); 2901} 2902 2903function drawConicID(id, x1, y1, x2, y2, x3, y3, w) { 2904 drawConicPartialID(id, x1, y1, x2, y2, x3, y3, w, 0, 1); 2905} 2906 2907function drawCubicPartialID(id, x1, y1, x2, y2, x3, y3, x4, y4, t1, t2) { 2908 var curve = [x1, y1, x2, y2, x3, y3, x4, y4]; 2909 drawCurvePartialID(id, curve, t1, t2); 2910} 2911 2912function drawCubicID(id, x1, y1, x2, y2, x3, y3, x4, y4) { 2913 drawCubicPartialID(id, x1, y1, x2, y2, x3, y3, x4, y4, 0, 1); 2914} 2915 2916function drawCurvePartialID(id, curve, t1, t2) { 2917 drawVisibleID(curve, (t1 + t2) / 2, id); 2918} 2919 2920function drawCurveSpecials(test, curve, type) { 2921 if (pt_labels) { 2922 drawPoints(curve, type, pt_labels == 2); 2923 } 2924 if (control_lines != 0) { 2925 drawControlLines(curve, type, control_lines); 2926 } 2927 if (curve_t) { 2928 drawPointAtT(curve, type); 2929 } 2930 if (draw_midpoint) { 2931 var mid = pointAtT(curve, type, 0.5); 2932 drawPoint(mid.x, mid.y, true); 2933 } 2934 if (draw_id) { 2935 var id = idByCurve(test, curve, type); 2936 if (id >= 0) { 2937 drawVisibleID(curve, 0.5, id); 2938 } 2939 } 2940 if (draw_direction) { 2941 drawVisibleDirection(curve); 2942 } 2943 if (type == PATH_LINE) { 2944 return; 2945 } 2946 if (draw_deriviatives > 0) { 2947 var d = dxy_at_t(curve, type, 0); 2948 drawArrow(curve[0], curve[1], d.x, d.y, 1); 2949 if (draw_deriviatives == 2) { 2950 d = dxy_at_t(curve, type, 1); 2951 if (type == PATH_CUBIC) { 2952 drawArrow(curve[6], curve[7], d.x, d.y, 1); 2953 } else { 2954 drawArrow(curve[4], curve[5], d.x, d.y, 1); 2955 } 2956 } 2957 if (draw_midpoint) { 2958 var mid = pointAtT(curve, type, 0.5); 2959 d = dxy_at_t(curve, type, 0.5); 2960 drawArrow(mid.x, mid.y, d.x, d.y, 1); 2961 } 2962 } 2963 if (type != PATH_CUBIC) { 2964 return; 2965 } 2966 if (draw_sequence) { 2967 var ymin = Math.min(curve[1], curve[3], curve[5], curve[7]); 2968 for (var i = 0; i < 8; i+= 2) { 2969 drawLabelX(ymin, i >> 1, curve[i]); 2970 } 2971 var xmin = Math.min(curve[0], curve[2], curve[4], curve[6]); 2972 for (var i = 1; i < 8; i+= 2) { 2973 drawLabelY(xmin, i >> 1, curve[i]); 2974 } 2975 } 2976} 2977 2978function logCurves(test) { 2979 for (curves in test) { 2980 var curve = test[curves]; 2981 dumpCurve(curve); 2982 } 2983} 2984 2985function curveToString(curve) { 2986 var str = "{{"; 2987 var length = curve.length == 7 ? 6 : curve.length; 2988 if (curve.length == 7) { 2989 str += "{"; 2990 } 2991 for (i = 0; i < length; i += 2) { 2992 str += curve[i].toFixed(decimal_places) + "," + curve[i + 1].toFixed(decimal_places); 2993 if (i < curve.length - 2) { 2994 str += "}, {"; 2995 } 2996 } 2997 str += "}"; 2998 if (curve.length == 7) { 2999 str += "}, " + curve[6].toFixed(decimal_places); 3000 } 3001 str += "}"; 3002 return str; 3003} 3004 3005function dumpCurve(curve) { 3006 console.log(curveToString(curve)); 3007} 3008 3009function draw(test, lines, title) { 3010 ctx.fillStyle = "rgba(0,0,0, 0.1)"; 3011 ctx.font = "normal 50px Arial"; 3012 ctx.textAlign = "left"; 3013 ctx.fillText(title, 50, 50); 3014 ctx.font = "normal 10px Arial"; 3015 ctx.lineWidth = "1.001"; "0.999"; 3016 var secondPath = test.length; 3017 var closeCount = 0; 3018 logStart = -1; 3019 logRange = 0; 3020 // find last active rec type at this step 3021 var curType = test[0]; 3022 var curStep = 0; 3023 var hasOp = false; 3024 var lastActive = 0; 3025 var lastAdd = 0; 3026 var lastCoin = 0; 3027 var lastSect = 0; 3028 var lastSort = 0; 3029 var lastMark = 0; 3030 var lastTop = 0; 3031 activeCount = 0; 3032 addCount = 0; 3033 angleCount = 0; 3034 opCount = 0; 3035 sectCount = 0; 3036 sortCount = 0; 3037 topCount = 0; 3038 markCount = 0; 3039 activeMax = 0; 3040 addMax = 0; 3041 angleMax = 0; 3042 coinMax = 0; 3043 opMax = 0; 3044 sectMax = 0; 3045 sectMax2 = 0; 3046 sortMax = 0; 3047 topMax = 0; 3048 markMax = 0; 3049 lastIndex = test.length - 3; 3050 for (var tIndex = 0; tIndex < test.length; tIndex += 3) { 3051 var recType = test[tIndex]; 3052 if (!typeof recType == 'number' || recType < REC_TYPE_UNKNOWN || recType > REC_TYPE_LAST) { 3053 console.log("unknown rec type: " + recType); 3054 throw "stop execution"; 3055 } 3056 // if (curType == recType && curType != REC_TYPE_ADD) { 3057 // continue; 3058 // } 3059 var inStepRange = step_limit == 0 || curStep < step_limit; 3060 curType = recType; 3061 if (recType == REC_TYPE_OP) { 3062 hasOp = true; 3063 continue; 3064 } 3065 if (recType == REC_TYPE_UNKNOWN) { 3066 // these types do not advance step 3067 continue; 3068 } 3069 var bumpStep = false; 3070 var records = test[tIndex + 2]; 3071 var fragType = records[0]; 3072 if (recType == REC_TYPE_ADD) { 3073 if (records.length != 2) { 3074 console.log("expect only two elements: " + records.length); 3075 throw "stop execution"; 3076 } 3077 if (fragType == ADD_MOVETO || fragType == ADD_CLOSE) { 3078 continue; 3079 } 3080 ++addMax; 3081 if (!draw_add || !inStepRange) { 3082 continue; 3083 } 3084 lastAdd = tIndex; 3085 ++addCount; 3086 bumpStep = true; 3087 } 3088 if (recType == REC_TYPE_PATH && hasOp) { 3089 secondPath = tIndex; 3090 } 3091 if (recType == REC_TYPE_PATH2 && hasOp) { 3092 secondPath = tIndex; 3093 } 3094 if (recType == REC_TYPE_ACTIVE) { 3095 ++activeMax; 3096 if (!draw_active || !inStepRange) { 3097 continue; 3098 } 3099 lastActive = tIndex; 3100 ++activeCount; 3101 bumpStep = true; 3102 } 3103 if (recType == REC_TYPE_ACTIVE_OP) { 3104 ++opMax; 3105 if (!draw_op || !inStepRange) { 3106 continue; 3107 } 3108 lastOp = tIndex; 3109 ++opCount; 3110 bumpStep = true; 3111 } 3112 if (recType == REC_TYPE_AFTERPART) { 3113 if (draw_angle != 3 || !inStepRange) { 3114 continue; 3115 } 3116 lastAngle = tIndex; 3117 ++angleCount; 3118 bumpStep = true; 3119 } 3120 if (recType == REC_TYPE_ANGLE) { 3121 ++angleMax; 3122 if (draw_angle == 0 || draw_angle == 3 || !inStepRange) { 3123 continue; 3124 } 3125 lastAngle = tIndex; 3126 ++angleCount; 3127 bumpStep = true; 3128 } 3129 if (recType == REC_TYPE_COINCIDENCE) { 3130 ++coinMax; 3131 if (!draw_coincidence || !inStepRange) { 3132 continue; 3133 } 3134 lastCoin = tIndex; 3135 ++coinCount; 3136 bumpStep = true; 3137 } 3138 if (recType == REC_TYPE_SECT) { 3139 if (records.length != 2) { 3140 console.log("expect only two elements: " + records.length); 3141 throw "stop execution"; 3142 } 3143 ++sectMax; 3144 var sectBump = 1; 3145 switch (fragType) { 3146 case INTERSECT_LINE: 3147 case INTERSECT_QUAD_LINE: 3148 case INTERSECT_QUAD: 3149 case INTERSECT_CONIC_LINE: 3150 case INTERSECT_CONIC_QUAD: 3151 case INTERSECT_CONIC: 3152 case INTERSECT_SELF_CUBIC: 3153 case INTERSECT_CUBIC_LINE: 3154 case INTERSECT_CUBIC_QUAD: 3155 case INTERSECT_CUBIC: 3156 sectBump = 1; 3157 break; 3158 case INTERSECT_LINE_2: 3159 case INTERSECT_QUAD_LINE_2: 3160 case INTERSECT_QUAD_2: 3161 case INTERSECT_CONIC_LINE_2: 3162 case INTERSECT_CONIC_QUAD_2: 3163 case INTERSECT_CONIC_2: 3164 case INTERSECT_CUBIC_LINE_2: 3165 case INTERSECT_CUBIC_QUAD_2: 3166 case INTERSECT_CUBIC_2: 3167 sectBump = 2; 3168 break; 3169 case INTERSECT_LINE_NO: 3170 case INTERSECT_QUAD_LINE_NO: 3171 case INTERSECT_QUAD_NO: 3172 case INTERSECT_CONIC_LINE_NO: 3173 case INTERSECT_CONIC_QUAD_NO: 3174 case INTERSECT_CONIC_NO: 3175 case INTERSECT_SELF_CUBIC_NO: 3176 case INTERSECT_CUBIC_LINE_NO: 3177 case INTERSECT_CUBIC_QUAD_NO: 3178 case INTERSECT_CUBIC_NO: 3179 sectBump = 0; 3180 break; 3181 case INTERSECT_CONIC_QUAD_3: 3182 case INTERSECT_CUBIC_LINE_3: 3183 case INTERSECT_CUBIC_QUAD_3: 3184 case INTERSECT_CUBIC_3: 3185 sectBump = 3; 3186 break; 3187 case INTERSECT_CONIC_QUAD_4: 3188 case INTERSECT_CUBIC_QUAD_4: 3189 case INTERSECT_CUBIC_4: 3190 sectBump = 4; 3191 break; 3192 default: 3193 console.log("missing case " + records.length); 3194 throw "stop execution"; 3195 } 3196 sectMax2 += sectBump; 3197 if (draw_intersection <= 1 || !inStepRange) { 3198 continue; 3199 } 3200 lastSect = tIndex; 3201 sectCount += sectBump; 3202 bumpStep = true; 3203 } 3204 if (recType == REC_TYPE_SORT) { 3205 ++sortMax; 3206 if (!draw_sort || !inStepRange) { 3207 continue; 3208 } 3209 lastSort = tIndex; 3210 ++sortCount; 3211 bumpStep = true; 3212 } 3213 if (recType == REC_TYPE_TOP) { 3214 ++topMax; 3215 if (!draw_top || !inStepRange) { 3216 continue; 3217 } 3218 lastTop = tIndex; 3219 ++topCount; 3220 bumpStep = true; 3221 } 3222 if (recType == REC_TYPE_MARK) { 3223 ++markMax; 3224 if (!draw_mark || !inStepRange) { 3225 continue; 3226 } 3227 lastMark = tIndex; 3228 ++markCount; 3229 bumpStep = true; 3230 } 3231 if (bumpStep) { 3232 lastIndex = tIndex; 3233 logStart = test[tIndex + 1]; 3234 logRange = records.length / 2; 3235 ++curStep; 3236 } 3237 } 3238 stepMax = (draw_add ? addMax : 0) 3239 + (draw_active ? activeMax : 0) 3240 + (draw_angle ? angleMax : 0) 3241 + (draw_coincidence ? coinMax : 0) 3242 + (draw_op ? opMax : 0) 3243 + (draw_sort ? sortMax : 0) 3244 + (draw_top ? topMax : 0) 3245 + (draw_mark ? markMax : 0) 3246 + (draw_intersection == 2 ? sectMax : draw_intersection == 3 ? sectMax2 : 0); 3247 if (stepMax == 0) { 3248 stepMax = addMax + activeMax + angleMax + coinMax + opMax + sortMax + topMax + markMax; 3249 } 3250 drawnPts = []; 3251 drawnLines = []; 3252 drawnQuads = []; 3253 drawnConics = []; 3254 drawnCubics = []; 3255 focusXmin = focusYmin = Infinity; 3256 focusXmax = focusYmax = -Infinity; 3257 var pathIndex = 0; 3258 var opLetter = 'S'; 3259 for (var tIndex = lastIndex; tIndex >= 0; tIndex -= 3) { 3260 var recType = test[tIndex]; 3261 var records = test[tIndex + 2]; 3262 for (var recordIndex = 0; recordIndex < records.length; recordIndex += 2) { 3263 var fragType = records[recordIndex]; 3264 if (!typeof fragType == 'number' || fragType < 1 || fragType > FRAG_TYPE_LAST) { 3265 console.log("unknown in range frag type: " + fragType); 3266 throw "stop execution"; 3267 } 3268 var frags = records[recordIndex + 1]; 3269 focus_enabled = false; 3270 switch (recType) { 3271 case REC_TYPE_COMPUTED: 3272 if (draw_computed == 0) { 3273 continue; 3274 } 3275 ctx.lineWidth = 1; 3276 ctx.strokeStyle = pathIndex == 0 ? "black" : "red"; 3277 ctx.fillStyle = "blue"; 3278 var drawThis = false; 3279 switch (fragType) { 3280 case PATH_QUAD: 3281 if ((draw_computed & 0x9) == 1 || ((draw_computed & 8) != 0 3282 && (draw_computed & 7) == pathIndex)) { 3283 drawQuad(frags[0], frags[1], frags[2], frags[3], 3284 frags[4], frags[5]); 3285 drawThis = true; 3286 } 3287 break; 3288 case PATH_CONIC: 3289 if ((draw_computed & 0xA) == 2 || ((draw_computed & 8) != 0 3290 && (draw_computed & 7) == pathIndex)) { 3291 drawConicWithQuads(frags[0], frags[1], frags[2], frags[3], 3292 frags[4], frags[5], frags[6]); 3293 drawThis = true; 3294 } 3295 break; 3296 case PATH_CUBIC: 3297 if ((draw_computed & 0xC) == 4 || ((draw_computed & 8) != 0 3298 && (draw_computed & 7) == pathIndex)) { 3299 drawCubic(frags[0], frags[1], frags[2], frags[3], 3300 frags[4], frags[5], frags[6], frags[7]); 3301 drawThis = true; 3302 } 3303 ++pathIndex; 3304 break; 3305 case COMPUTED_SET_1: 3306 pathIndex = 0; 3307 break; 3308 case COMPUTED_SET_2: 3309 pathIndex = 1; 3310 break; 3311 default: 3312 console.log("unknown REC_TYPE_COMPUTED frag type: " + fragType); 3313 throw "stop execution"; 3314 } 3315 if (!drawThis || collect_bounds) { 3316 break; 3317 } 3318 drawCurveSpecials(test, frags, fragType); 3319 break; 3320 case REC_TYPE_ALIGNED: 3321 if (draw_path < 4) { 3322 continue; 3323 } 3324 case REC_TYPE_PATH: 3325 case REC_TYPE_PATH2: 3326 if (REC_TYPE_ALIGNED != recType && draw_path >= 4) { 3327 continue; 3328 } 3329 if (!draw_path) { 3330 continue; 3331 } 3332 var firstPath = tIndex < secondPath; 3333 if ((draw_path & (firstPath ? 1 : 2)) == 0) { 3334 continue; 3335 } 3336 ctx.lineWidth = 1; 3337 ctx.strokeStyle = firstPath ? "black" : "red"; 3338 ctx.fillStyle = "blue"; 3339 var frags2 = []; 3340 switch (fragType) { 3341 case PATH_LINE: 3342 for (var i = 0; i < 4; ++ i) { frags2[i] = frags[i + 1]; } 3343 drawLine(frags2[0], frags2[1], frags2[2], frags2[3]); 3344 break; 3345 case PATH_QUAD: 3346 for (var i = 0; i < 6; ++ i) { frags2[i] = frags[i + 1]; } 3347 drawQuad(frags2[0], frags2[1], frags2[2], frags2[3], 3348 frags2[4], frags2[5]); 3349 break; 3350 case PATH_CONIC: 3351 for (var i = 0; i < 7; ++ i) { frags2[i] = frags[i + 1]; } 3352 drawConicWithQuads(frags2[0], frags2[1], frags2[2], frags2[3], 3353 frags2[4], frags2[5], frags2[6]); 3354 break; 3355 case PATH_CUBIC: 3356 for (var i = 0; i < 8; ++ i) { frags2[i] = frags[i + 1]; } 3357 drawCubic(frags2[0], frags2[1], frags2[2], frags2[3], 3358 frags2[4], frags2[5], frags2[6], frags2[7]); 3359 break; 3360 default: 3361 console.log("unknown " + recType + " frag type: " + fragType); 3362 throw "stop execution"; 3363 } 3364 if (collect_bounds) { 3365 break; 3366 } 3367 drawCurveSpecials(test, frags2, fragType); 3368 break; 3369 case REC_TYPE_OP: 3370 switch (fragType) { 3371 case OP_INTERSECT: opLetter = 'I'; break; 3372 case OP_DIFFERENCE: opLetter = 'D'; break; 3373 case OP_UNION: opLetter = 'U'; break; 3374 case OP_XOR: opLetter = 'X'; break; 3375 default: 3376 console.log("unknown REC_TYPE_OP frag type: " + fragType); 3377 throw "stop execution"; 3378 } 3379 break; 3380 case REC_TYPE_ACTIVE: 3381 if (!draw_active || (step_limit > 0 && tIndex < lastActive)) { 3382 continue; 3383 } 3384 var x1 = frags[SPAN_X1]; 3385 var y1 = frags[SPAN_Y1]; 3386 var x2 = frags[SPAN_X2]; 3387 var y2 = frags[SPAN_Y2]; 3388 var x3, y3, x3, y4, w; 3389 ctx.lineWidth = 3; 3390 ctx.strokeStyle = "rgba(0,0,255, 0.3)"; 3391 focus_enabled = true; 3392 switch (fragType) { 3393 case ACTIVE_LINE_SPAN: 3394 drawLine(x1, y1, x2, y2); 3395 if (draw_id) { 3396 drawLineID(frags[0], x1, y1, x2, y2); 3397 } 3398 if (pt_labels) { 3399 var curve = [x1, y1, x2, y2]; 3400 ctx.fillStyle = "blue"; 3401 drawPoints(curve, PATH_LINE, pt_labels == 2); 3402 } 3403 break; 3404 case ACTIVE_QUAD_SPAN: 3405 x3 = frags[SPAN_X3]; 3406 y3 = frags[SPAN_Y3]; 3407 drawQuad(x1, y1, x2, y2, x3, y3); 3408 if (draw_id) { 3409 drawQuadID(frags[0], x1, y1, x2, y2, x3, y3); 3410 } 3411 if (pt_labels) { 3412 var curve = [x1, y1, x2, y2, x3, y3]; 3413 ctx.fillStyle = "blue"; 3414 drawPoints(curve, PATH_QUAD, pt_labels == 2); 3415 } 3416 break; 3417 case ACTIVE_CONIC_SPAN: 3418 x3 = frags[SPAN_X3]; 3419 y3 = frags[SPAN_Y3]; 3420 w = frags[SPAN_K_W]; 3421 drawConicWithQuads(x1, y1, x2, y2, x3, y3, w); 3422 if (draw_id) { 3423 drawConicID(frags[0], x1, y1, x2, y2, x3, y3, w); 3424 } 3425 if (pt_labels) { 3426 var curve = [x1, y1, x2, y2, x3, y3, w]; 3427 ctx.fillStyle = "blue"; 3428 drawPoints(curve, PATH_CONIC, pt_labels == 2); 3429 } 3430 break; 3431 case ACTIVE_CUBIC_SPAN: 3432 x3 = frags[SPAN_X3]; 3433 y3 = frags[SPAN_Y3]; 3434 x4 = frags[SPAN_X4]; 3435 y4 = frags[SPAN_Y4]; 3436 drawCubic(x1, y1, x2, y2, x3, y3, x4, y4); 3437 if (draw_id) { 3438 drawCubicID(frags[0], x1, y1, x2, y2, x3, y3, x4, y4); 3439 } 3440 if (pt_labels) { 3441 var curve = [x1, y1, x2, y2, x3, y3, x4, y4]; 3442 ctx.fillStyle = "blue"; 3443 drawPoints(curve, PATH_CUBIC, pt_labels == 2); 3444 } 3445 break; 3446 default: 3447 console.log("unknown REC_TYPE_ACTIVE frag type: " + fragType); 3448 throw "stop execution"; 3449 } 3450 break; 3451 case REC_TYPE_ACTIVE_OP: 3452 if (!draw_op || (step_limit > 0 && tIndex < lastOp)) { 3453 continue; 3454 } 3455 focus_enabled = true; 3456 ctx.lineWidth = 3; 3457 var activeSpan = frags[7] == "1"; 3458 ctx.strokeStyle = activeSpan ? "rgba(45,160,0, 0.3)" : "rgba(255,45,0, 0.5)"; 3459 var curve = curvePartialByID(test, frags[0], frags[1], frags[2]); 3460 drawCurve(curve); 3461 if (draw_op > 1) { 3462 drawArc(curve, false, frags[3], frags[4]); 3463 drawArc(curve, true, frags[5], frags[6]); 3464 } 3465 break; 3466 case REC_TYPE_ADD: 3467 if (!draw_add) { 3468 continue; 3469 } 3470 ctx.lineWidth = 3; 3471 ctx.strokeStyle = closeCount == 0 ? "rgba(0,0,255, 0.3)" 3472 : closeCount == 1 ? "rgba(0,127,0, 0.3)" 3473 : closeCount == 2 ? "rgba(0,127,127, 0.3)" 3474 : closeCount == 3 ? "rgba(127,127,0, 0.3)" 3475 : "rgba(127,0,127, 0.3)"; 3476 focus_enabled = true; 3477 switch (fragType) { 3478 case ADD_MOVETO: 3479 break; 3480 case ADD_LINETO: 3481 if (step_limit == 0 || tIndex >= lastAdd) { 3482 drawLine(frags[0], frags[1], frags[2], frags[3]); 3483 } 3484 break; 3485 case ADD_QUADTO: 3486 if (step_limit == 0 || tIndex >= lastAdd) { 3487 drawQuad(frags[0], frags[1], frags[2], frags[3], frags[4], frags[5]); 3488 } 3489 break; 3490 case ADD_CONICTO: 3491 if (step_limit == 0 || tIndex >= lastAdd) { 3492 drawConicWithQuads(frags[0], frags[1], frags[2], frags[3], 3493 frags[4], frags[5], frags[6]); 3494 } 3495 break; 3496 case ADD_CUBICTO: 3497 if (step_limit == 0 || tIndex >= lastAdd) { 3498 drawCubic(frags[0], frags[1], frags[2], frags[3], 3499 frags[4], frags[5], frags[6], frags[7]); 3500 } 3501 break; 3502 case ADD_CLOSE: 3503 ++closeCount; 3504 break; 3505 case ADD_FILL: 3506 break; 3507 default: 3508 console.log("unknown REC_TYPE_ADD frag type: " + fragType); 3509 throw "stop execution"; 3510 } 3511 break; 3512 case REC_TYPE_ANGLE: 3513 angleBetween = frags[18] == "T"; 3514 afterIndex = 0; 3515 if (draw_angle == 0 || draw_angle == 3 || (step_limit > 0 && tIndex < lastAngle)) { 3516 continue; 3517 } 3518 focus_enabled = true; 3519 ctx.lineWidth = 3; 3520 ctx.strokeStyle = "rgba(127,45,127, 0.3)"; 3521 var leftCurve = curvePartialByID(test, frags[0], frags[4], frags[5]); 3522 var midCurve = curvePartialByID(test, frags[6], frags[10], frags[11]); 3523 var rightCurve = curvePartialByID(test, frags[12], frags[16], frags[17]); 3524 drawCurve(leftCurve); 3525 drawCurve(rightCurve); 3526 ctx.strokeStyle = angleBetween ? "rgba(0,160,45, 0.3)" : "rgba(255,0,45, 0.5)"; 3527 drawCurve(midCurve); 3528 if (draw_angle > 1) { 3529 drawVisibleOrder(leftCurve, 'L'); 3530 drawVisibleOrder(rightCurve, 'R'); 3531 } 3532 if (draw_id) { 3533 drawVisibleID(leftCurve, 0.5, frags[0]); 3534 drawVisibleID(midCurve, 0.5, frags[6]); 3535 drawVisibleID(rightCurve, 0.5, frags[12]); 3536 } 3537 break; 3538 case REC_TYPE_AFTERPART: 3539 if (draw_angle != 3 || (step_limit > 0 && tIndex < lastAngle)) { 3540 continue; 3541 } 3542 ctx.strokeStyle = afterIndex == 0 ? "rgba(255,0,0, 1.0)" 3543 : (afterIndex == 1) == angleBetween ? "rgba(0,128,0, 1.0)" 3544 : "rgba(0,0,255, 1.0)"; 3545 var curve; 3546 var id; 3547 switch (fragType) { 3548 case PATH_LINE: 3549 curve = [ frags[0], frags[1], frags[2], frags[3] ]; 3550 id = frags[4]; 3551 break; 3552 case PATH_QUAD: 3553 curve = [ frags[0], frags[1], frags[2], frags[3], 3554 frags[4], frags[5] ]; 3555 id = frags[6]; 3556 break; 3557 case PATH_CONIC: 3558 curve = [ frags[0], frags[1], frags[2], frags[3], 3559 frags[4], frags[5], frags[6] ]; 3560 id = frags[7]; 3561 break; 3562 case PATH_CUBIC: 3563 curve = [ frags[0], frags[1], frags[2], frags[3], 3564 frags[4], frags[5], frags[6], frags[7] ]; 3565 id = frags[8]; 3566 break; 3567 default: 3568 console.log("unknown REC_TYPE_AFTERPART frag type: " + fragType); 3569 throw "stop execution"; 3570 } 3571 drawCurve(curve); 3572 if (draw_id) { 3573 drawVisibleID(curve, 0.5, id); 3574 } 3575 ++afterIndex; 3576 break; 3577 case REC_TYPE_COINCIDENCE: 3578 if (!draw_coincidence || (step_limit > 0 && tIndex < lastCoin)) { 3579 continue; 3580 } 3581 focus_enabled = true; 3582 ctx.lineWidth = 3; 3583 ctx.strokeStyle = "rgba(127,45,63, 0.3)"; 3584 var curve = curvePartialByID(test, frags[0], frags[1], frags[2]); 3585 drawCurve(curve); 3586 break; 3587 case REC_TYPE_SECT: 3588 if (!draw_intersection) { 3589 continue; 3590 } 3591 if (draw_intersection != 1 && (step_limit > 0 && tIndex < lastSect)) { 3592 continue; 3593 } 3594 // draw_intersection == 1 : show all 3595 // draw_intersection == 2 : step == 0 ? show all : show intersection line #step 3596 // draw_intersection == 3 : step == 0 ? show all : show intersection #step 3597 ctx.lineWidth = 1; 3598 ctx.strokeStyle = "rgba(0,0,255, 0.3)"; 3599 ctx.fillStyle = "blue"; 3600 focus_enabled = true; 3601 var f = []; 3602 var c1s; 3603 var c1l; 3604 var c2s; 3605 var c2l; 3606 switch (fragType) { 3607 case INTERSECT_LINE: 3608 f.push(5, 6, 0, 7); 3609 c1s = 1; c1l = 4; c2s = 8; c2l = 4; 3610 break; 3611 case INTERSECT_LINE_2: 3612 f.push(5, 6, 0, 10); 3613 f.push(8, 9, 7, 15); 3614 c1s = 1; c1l = 4; c2s = 11; c2l = 4; 3615 break; 3616 case INTERSECT_LINE_NO: 3617 c1s = 0; c1l = 4; c2s = 4; c2l = 4; 3618 break; 3619 case INTERSECT_QUAD_LINE: 3620 f.push(7, 8, 0, 9); 3621 c1s = 1; c1l = 6; c2s = 10; c2l = 4; 3622 break; 3623 case INTERSECT_QUAD_LINE_2: 3624 f.push(7, 8, 0, 12); 3625 f.push(10, 11, 9, 17); 3626 c1s = 1; c1l = 6; c2s = 13; c2l = 4; 3627 break; 3628 case INTERSECT_QUAD_LINE_NO: 3629 c1s = 0; c1l = 6; c2s = 6; c2l = 4; 3630 break; 3631 case INTERSECT_QUAD: 3632 f.push(7, 8, 0, 9); 3633 c1s = 1; c1l = 6; c2s = 10; c2l = 6; 3634 break; 3635 case INTERSECT_QUAD_2: 3636 f.push(7, 8, 0, 12); 3637 f.push(10, 11, 9, 19); 3638 c1s = 1; c1l = 6; c2s = 13; c2l = 6; 3639 break; 3640 case INTERSECT_QUAD_NO: 3641 c1s = 0; c1l = 6; c2s = 6; c2l = 6; 3642 break; 3643 case INTERSECT_CONIC_LINE: 3644 f.push(8, 9, 0, 10); 3645 c1s = 1; c1l = 7; c2s = 11; c2l = 4; 3646 break; 3647 case INTERSECT_CONIC_LINE_2: 3648 f.push(8, 9, 0, 12); 3649 f.push(11, 12, 10, 18); 3650 c1s = 1; c1l = 7; c2s = 14; c2l = 4; 3651 break; 3652 case INTERSECT_CONIC_LINE_NO: 3653 c1s = 0; c1l = 7; c2s = 7; c2l = 4; 3654 break; 3655 case INTERSECT_CONIC_QUAD: 3656 f.push(8, 9, 0, 10); 3657 c1s = 1; c1l = 7; c2s = 11; c2l = 6; 3658 break; 3659 case INTERSECT_CONIC_QUAD_2: 3660 f.push(8, 9, 0, 12); 3661 f.push(11, 12, 10, 18); 3662 c1s = 1; c1l = 7; c2s = 14; c2l = 6; 3663 break; 3664 case INTERSECT_CONIC_QUAD_3: 3665 f.push(8, 9, 0, 15); 3666 f.push(11, 12, 10, 21); 3667 f.push(14, 15, 13, 22); 3668 c1s = 1; c1l = 7; c2s = 17; c2l = 6; 3669 break; 3670 case INTERSECT_CONIC_QUAD_4: 3671 f.push(8, 9, 0, 18); 3672 f.push(11, 12, 10, 24); 3673 f.push(14, 15, 13, 25); 3674 f.push(17, 18, 16, 26); 3675 c1s = 1; c1l = 7; c2s = 20; c2l = 6; 3676 break; 3677 case INTERSECT_CONIC_QUAD_NO: 3678 c1s = 0; c1l = 7; c2s = 7; c2l = 6; 3679 break; 3680 case INTERSECT_CONIC: 3681 f.push(8, 9, 0, 10); 3682 c1s = 1; c1l = 7; c2s = 11; c2l = 7; 3683 break; 3684 case INTERSECT_CONIC_2: 3685 f.push(8, 9, 0, 13); 3686 f.push(11, 12, 10, 21); 3687 c1s = 1; c1l = 7; c2s = 14; c2l = 7; 3688 break; 3689 case INTERSECT_CONIC_NO: 3690 c1s = 0; c1l = 7; c2s = 7; c2l = 7; 3691 break; 3692 case INTERSECT_SELF_CUBIC: 3693 f.push(9, 10, 0, 11); 3694 c1s = 1; c1l = 8; c2s = 0; c2l = 0; 3695 break; 3696 case INTERSECT_SELF_CUBIC_NO: 3697 c1s = 0; c1l = 8; c2s = 0; c2l = 0; 3698 break; 3699 case INTERSECT_CUBIC_LINE: 3700 f.push(9, 10, 0, 11); 3701 c1s = 1; c1l = 8; c2s = 12; c2l = 4; 3702 break; 3703 case INTERSECT_CUBIC_LINE_2: 3704 f.push(9, 10, 0, 14); 3705 f.push(12, 13, 11, 19); 3706 c1s = 1; c1l = 8; c2s = 15; c2l = 4; 3707 break; 3708 case INTERSECT_CUBIC_LINE_3: 3709 f.push(9, 10, 0, 17); 3710 f.push(12, 13, 11, 22); 3711 f.push(15, 16, 14, 23); 3712 c1s = 1; c1l = 8; c2s = 18; c2l = 4; 3713 break; 3714 case INTERSECT_CUBIC_QUAD_NO: 3715 c1s = 0; c1l = 8; c2s = 8; c2l = 6; 3716 break; 3717 case INTERSECT_CUBIC_QUAD: 3718 f.push(9, 10, 0, 11); 3719 c1s = 1; c1l = 8; c2s = 12; c2l = 6; 3720 break; 3721 case INTERSECT_CUBIC_QUAD_2: 3722 f.push(9, 10, 0, 14); 3723 f.push(12, 13, 11, 21); 3724 c1s = 1; c1l = 8; c2s = 15; c2l = 6; 3725 break; 3726 case INTERSECT_CUBIC_QUAD_3: 3727 f.push(9, 10, 0, 17); 3728 f.push(12, 13, 11, 24); 3729 f.push(15, 16, 14, 25); 3730 c1s = 1; c1l = 8; c2s = 18; c2l = 6; 3731 break; 3732 case INTERSECT_CUBIC_QUAD_4: 3733 f.push(9, 10, 0, 20); 3734 f.push(12, 13, 11, 27); 3735 f.push(15, 16, 14, 28); 3736 f.push(18, 19, 17, 29); 3737 c1s = 1; c1l = 8; c2s = 21; c2l = 6; 3738 break; 3739 case INTERSECT_CUBIC_LINE_NO: 3740 c1s = 0; c1l = 8; c2s = 8; c2l = 4; 3741 break; 3742 case INTERSECT_CUBIC: 3743 f.push(9, 10, 0, 11); 3744 c1s = 1; c1l = 8; c2s = 12; c2l = 8; 3745 break; 3746 case INTERSECT_CUBIC_2: 3747 f.push(9, 10, 0, 14); 3748 f.push(12, 13, 11, 23); 3749 c1s = 1; c1l = 8; c2s = 15; c2l = 8; 3750 break; 3751 case INTERSECT_CUBIC_3: 3752 f.push(9, 10, 0, 17); 3753 f.push(12, 13, 11, 26); 3754 f.push(15, 16, 14, 27); 3755 c1s = 1; c1l = 8; c2s = 18; c2l = 8; 3756 break; 3757 case INTERSECT_CUBIC_4: 3758 f.push(9, 10, 0, 20); 3759 f.push(12, 13, 11, 29); 3760 f.push(15, 16, 14, 30); 3761 f.push(18, 19, 17, 31); 3762 c1s = 1; c1l = 8; c2s = 21; c2l = 8; 3763 break; 3764 case INTERSECT_CUBIC_NO: 3765 c1s = 0; c1l = 8; c2s = 8; c2l = 8; 3766 break; 3767 default: 3768 console.log("unknown REC_TYPE_SECT frag type: " + fragType); 3769 throw "stop execution"; 3770 } 3771 if (draw_intersection != 1) { 3772 var id = -1; 3773 var curve; 3774 switch (c1l) { 3775 case 4: 3776 drawLine(frags[c1s], frags[c1s + 1], frags[c1s + 2], frags[c1s + 3]); 3777 if (draw_id) { 3778 curve = [frags[c1s], frags[c1s + 1], frags[c1s + 2], frags[c1s + 3]]; 3779 id = idByCurve(test, curve, PATH_LINE); 3780 } 3781 break; 3782 case 6: 3783 drawQuad(frags[c1s], frags[c1s + 1], frags[c1s + 2], frags[c1s + 3], 3784 frags[c1s + 4], frags[c1s + 5]); 3785 if (draw_id) { 3786 curve = [frags[c1s], frags[c1s + 1], frags[c1s + 2], frags[c1s + 3], 3787 frags[c1s + 4], frags[c1s + 5]]; 3788 id = idByCurve(test, curve, PATH_QUAD); 3789 } 3790 break; 3791 case 7: 3792 drawConicWithQuads(frags[c1s], frags[c1s + 1], frags[c1s + 2], frags[c1s + 3], 3793 frags[c1s + 4], frags[c1s + 5], frags[c1s + 6]); 3794 if (draw_id) { 3795 curve = [frags[c1s], frags[c1s + 1], frags[c1s + 2], frags[c1s + 3], 3796 frags[c1s + 4], frags[c1s + 5], frags[c1s + 6]]; 3797 id = idByCurve(test, curve, PATH_CONIC); 3798 } 3799 break; 3800 case 8: 3801 drawCubic(frags[c1s], frags[c1s + 1], frags[c1s + 2], frags[c1s + 3], 3802 frags[c1s + 4], frags[c1s + 5], frags[c1s + 6], frags[c1s + 7]); 3803 if (draw_id) { 3804 curve = [frags[c1s], frags[c1s + 1], frags[c1s + 2], frags[c1s + 3], 3805 frags[c1s + 4], frags[c1s + 5], frags[c1s + 6], frags[c1s + 7]]; 3806 id = idByCurve(test, curve, PATH_CUBIC); 3807 } 3808 break; 3809 } 3810 if (id >= 0) { 3811 drawVisibleID(curve, 0.5, id); 3812 } 3813 id = -1; 3814 switch (c2l) { 3815 case 0: 3816 break; 3817 case 4: 3818 drawLine(frags[c2s], frags[c2s + 1], frags[c2s + 2], frags[c2s + 3]); 3819 if (draw_id) { 3820 curve = [frags[c2s], frags[c2s + 1], frags[c2s + 2], frags[c2s + 3]]; 3821 id = idByCurve(test, curve, PATH_LINE); 3822 } 3823 break; 3824 case 6: 3825 drawQuad(frags[c2s], frags[c2s + 1], frags[c2s + 2], frags[c2s + 3], 3826 frags[c2s + 4], frags[c2s + 5]); 3827 if (draw_id) { 3828 curve = [frags[c2s], frags[c2s + 1], frags[c2s + 2], frags[c2s + 3], 3829 frags[c2s + 4], frags[c2s + 5]]; 3830 id = idByCurve(test, curve, PATH_QUAD); 3831 } 3832 break; 3833 case 7: 3834 drawConicWithQuads(frags[c2s], frags[c2s + 1], frags[c2s + 2], frags[c2s + 3], 3835 frags[c2s + 4], frags[c2s + 5], frags[c2s + 6]); 3836 if (draw_id) { 3837 curve = [frags[c2s], frags[c2s + 1], frags[c2s + 2], frags[c2s + 3], 3838 frags[c2s + 4], frags[c2s + 5], frags[c2s + 6]]; 3839 id = idByCurve(test, curve, PATH_CONIC); 3840 } 3841 break; 3842 case 8: 3843 drawCubic(frags[c2s], frags[c2s + 1], frags[c2s + 2], frags[c2s + 3], 3844 frags[c2s + 4], frags[c2s + 5], frags[c2s + 6], frags[c2s + 7]); 3845 if (draw_id) { 3846 curve = [frags[c2s], frags[c2s + 1], frags[c2s + 2], frags[c2s + 3], 3847 frags[c2s + 4], frags[c2s + 5], frags[c2s + 6], frags[c2s + 7]]; 3848 id = idByCurve(test, curve, PATH_CUBIC); 3849 } 3850 break; 3851 } 3852 if (id >= 0) { 3853 drawVisibleID(curve, 0.5, id); 3854 } 3855 } 3856 if (collect_bounds) { 3857 break; 3858 } 3859 if (draw_intersection != 3 || step_limit == 0 || tIndex >= lastSect) { 3860 for (var idx = 0; idx < f.length; idx += 4) { 3861 drawPoint(frags[f[idx]], frags[f[idx + 1]], true); 3862 } 3863 } 3864 if (!draw_intersectT) { 3865 break; 3866 } 3867 ctx.fillStyle = "red"; 3868 if (draw_intersection != 3 || step_limit == 0 || tIndex >= lastSect) { 3869 for (var idx = 0; idx < f.length; idx += 4) { 3870 drawTAtPointUp(frags[f[idx]], frags[f[idx + 1]], frags[f[idx + 2]]); 3871 drawTAtPointDown(frags[f[idx]], frags[f[idx + 1]], frags[f[idx + 3]]); 3872 } 3873 } 3874 break; 3875 case REC_TYPE_SORT: 3876 if (!draw_sort || (step_limit > 0 && tIndex < lastSort)) { 3877 continue; 3878 } 3879 ctx.lineWidth = 3; 3880 ctx.strokeStyle = "rgba(127,127,0, 0.5)"; 3881 focus_enabled = true; 3882 switch (fragType) { 3883 case SORT_UNARY: 3884 case SORT_BINARY: 3885 var curve = curvePartialByID(test, frags[0], frags[6], frags[8]); 3886 drawCurve(curve); 3887 break; 3888 default: 3889 console.log("unknown REC_TYPE_SORT frag type: " + fragType); 3890 throw "stop execution"; 3891 } 3892 break; 3893 case REC_TYPE_TOP: 3894 if (!draw_top || (step_limit > 0 && tIndex < lastTop)) { 3895 continue; 3896 } 3897 ctx.lineWidth = 3; 3898 ctx.strokeStyle = "rgba(127,127,0, 0.5)"; 3899 focus_enabled = true; 3900 { 3901 var curve = curvePartialByID(test, frags[0], frags[1], frags[2]); 3902 drawCurve(curve); 3903 var type = PATH_LINE + (curve.length / 2 - 2); 3904 var mid = pointAtT(curve, type, 0.5); 3905 var d = dxy_at_t(curve, type, 0.5); 3906 drawArrow(mid.x, mid.y, d.x, d.y, 0.3); 3907 } 3908 break; 3909 case REC_TYPE_MARK: 3910 if (!draw_mark || (step_limit > 0 && tIndex < lastMark)) { 3911 continue; 3912 } 3913 ctx.lineWidth = 3; 3914 ctx.strokeStyle = fragType >= MARK_DONE_LINE ? 3915 "rgba(127,0,127, 0.5)" : "rgba(127,127,0, 0.5)"; 3916 focus_enabled = true; 3917 switch (fragType) { 3918 case MARK_LINE: 3919 case MARK_DONE_LINE: 3920 case MARK_UNSORTABLE_LINE: 3921 case MARK_SIMPLE_LINE: 3922 case MARK_SIMPLE_DONE_LINE: 3923 case MARK_DONE_UNARY_LINE: 3924 drawLinePartial(frags[1], frags[2], frags[3], frags[4], 3925 frags[5], frags[9]); 3926 if (draw_id) { 3927 drawLinePartialID(frags[0], frags[1], frags[2], frags[3], frags[4], 3928 frags[5], frags[9]); 3929 } 3930 break; 3931 case MARK_QUAD: 3932 case MARK_DONE_QUAD: 3933 case MARK_UNSORTABLE_QUAD: 3934 case MARK_SIMPLE_QUAD: 3935 case MARK_SIMPLE_DONE_QUAD: 3936 case MARK_DONE_UNARY_QUAD: 3937 drawQuadPartial(frags[1], frags[2], frags[3], frags[4], 3938 frags[5], frags[6], frags[7], frags[11]); 3939 if (draw_id) { 3940 drawQuadPartialID(frags[0], frags[1], frags[2], frags[3], frags[4], 3941 frags[5], frags[6], frags[7], frags[11]); 3942 } 3943 break; 3944 case MARK_CUBIC: 3945 case MARK_DONE_CUBIC: 3946 case MARK_UNSORTABLE_CUBIC: 3947 case MARK_SIMPLE_CUBIC: 3948 case MARK_SIMPLE_DONE_CUBIC: 3949 case MARK_DONE_UNARY_CUBIC: 3950 drawCubicPartial(frags[1], frags[2], frags[3], frags[4], 3951 frags[5], frags[6], frags[7], frags[8], frags[9], frags[13]); 3952 if (draw_id) { 3953 drawCubicPartialID(frags[0], frags[1], frags[2], frags[3], frags[4], 3954 frags[5], frags[6], frags[7], frags[8], frags[9], frags[13]); 3955 } 3956 break; 3957 case MARK_ANGLE_LAST: 3958 // FIXME: ignored for now 3959 break; 3960 default: 3961 console.log("unknown REC_TYPE_MARK frag type: " + fragType); 3962 throw "stop execution"; 3963 } 3964 break; 3965 default: 3966 continue; 3967 } 3968 } 3969 switch (recType) { 3970 case REC_TYPE_SORT: 3971 if (!draw_sort || (step_limit > 0 && tIndex < lastSort)) { 3972 break; 3973 } 3974 var angles = []; // use tangent lines to describe arcs 3975 var windFrom = []; 3976 var windTo = []; 3977 var opp = []; 3978 var minXY = Number.MAX_VALUE; 3979 var partial; 3980 focus_enabled = true; 3981 var someUnsortable = false; 3982 for (var recordIndex = 0; recordIndex < records.length; recordIndex += 2) { 3983 var fragType = records[recordIndex]; 3984 var frags = records[recordIndex + 1]; 3985 var unsortable = (fragType == SORT_UNARY && frags[14]) || 3986 (fragType == SORT_BINARY && frags[16]); 3987 someUnsortable |= unsortable; 3988 switch (fragType) { 3989 case SORT_UNARY: 3990 case SORT_BINARY: 3991 partial = curvePartialByID(test, frags[0], frags[6], frags[8]); 3992 break; 3993 default: 3994 console.log("unknown REC_TYPE_SORT frag type: " + fragType); 3995 throw "stop execution"; 3996 } 3997 var dx = boundsWidth(partial); 3998 var dy = boundsHeight(partial); 3999 minXY = Math.min(minXY, dx * dx + dy * dy); 4000 if (collect_bounds) { 4001 continue; 4002 } 4003 angles.push(tangent(partial)); 4004 var from = frags[12]; 4005 var to = frags[12]; 4006 var sgn = frags[10]; 4007 if (sgn < 0) { 4008 from -= frags[11]; 4009 } else if (sgn > 0) { 4010 to -= frags[11]; 4011 } 4012 windFrom.push(from + (unsortable ? "!" : "")); 4013 windTo.push(to + (unsortable ? "!" : "")); 4014 opp.push(fragType == SORT_BINARY); 4015 if (draw_sort == 1) { 4016 drawVisibleOrder(partial, frags[12]); 4017 } else { 4018 drawVisibleOrder(partial, (recordIndex / 2) + 1); 4019 } 4020 } 4021 var radius = Math.sqrt(minXY) / 2 * scale; 4022 radius = Math.min(50, radius); 4023 var scaledRadius = radius / scale; 4024 var centerX = partial[0]; 4025 var centerY = partial[1]; 4026 if (collect_bounds) { 4027 if (focus_enabled) { 4028 focusXmin = Math.min(focusXmin, centerX - scaledRadius); 4029 focusYmin = Math.min(focusYmin, centerY - scaledRadius); 4030 focusXmax = Math.max(focusXmax, centerX + scaledRadius); 4031 focusYmax = Math.max(focusYmax, centerY + scaledRadius); 4032 } 4033 break; 4034 } 4035 break; 4036 default: 4037 break; 4038 } 4039 } 4040 if (collect_bounds) { 4041 return; 4042 } 4043 if (draw_log && logStart >= 0) { 4044 ctx.font = "normal 10px Arial"; 4045 ctx.textAlign = "left"; 4046 ctx.beginPath(); 4047 var top = screenHeight - 20 - (logRange + 2) * 10; 4048 ctx.rect(50, top, screenWidth - 100, (logRange + 2) * 10); 4049 ctx.fillStyle = "white"; 4050 ctx.fill(); 4051 ctx.fillStyle = "rgba(0,0,0, 0.5)"; 4052 if (logStart > 0) { 4053 ctx.fillText(lines[logStart - 1], 50, top + 8); 4054 } 4055 ctx.fillStyle = "black"; 4056 for (var idx = 0; idx < logRange; ++idx) { 4057 ctx.fillText(lines[logStart + idx], 50, top + 18 + 10 * idx); 4058 } 4059 ctx.fillStyle = "rgba(0,0,0, 0.5)"; 4060 if (logStart + logRange < lines.length) { 4061 ctx.fillText(lines[logStart + logRange], 50, top + 18 + 10 * logRange); 4062 } 4063 } 4064 if (draw_legend) { 4065 var pos = 0; 4066 var drawSomething = draw_add | draw_active | draw_angle | draw_coincidence | draw_sort | draw_mark; 4067 // drawBox(pos++, "yellow", "black", opLetter, true, ''); 4068 drawBox(pos++, "rgba(0,0,255, 0.3)", "black", draw_intersection > 1 ? sectCount : sectMax2, draw_intersection, intersectionKey); 4069 drawBox(pos++, "rgba(0,0,255, 0.3)", "black", draw_add ? addCount : addMax, draw_add, addKey); 4070 drawBox(pos++, "rgba(0,0,255, 0.3)", "black", draw_active ? activeCount : activeMax, draw_active, activeKey); 4071 drawBox(pos++, "rgba(127,127,0, 0.3)", "black", draw_angle ? angleCount : angleMax, draw_angle, angleKey); 4072 drawBox(pos++, "rgba(127,127,0, 0.3)", "black", draw_coincidence ? coinCount : coinMax, draw_coincidence, coincidenceKey); 4073 drawBox(pos++, "rgba(127,127,0, 0.3)", "black", draw_op ? opCount : opMax, draw_op, opKey); 4074 drawBox(pos++, "rgba(127,127,0, 0.3)", "black", draw_sort ? sortCount : sortMax, draw_sort, sortKey); 4075 drawBox(pos++, "rgba(127,127,0, 0.3)", "black", draw_top ? topCount : topMax, draw_top, topKey); 4076 drawBox(pos++, "rgba(127,0,127, 0.3)", "black", draw_mark ? markCount : markMax, draw_mark, markKey); 4077 drawBox(pos++, "black", "white", 4078 (new Array('P', 'P1', 'P2', 'P', 'p', 'p1', 'p2'))[draw_path], draw_path != 0, pathKey); 4079 drawBox(pos++, "rgba(0,63,0, 0.7)", "white", 4080 (new Array('Q', 'Q', 'C', 'QC', 'Qc', 'Cq'))[draw_computed], 4081 draw_computed != 0, computedKey); 4082 drawBox(pos++, "green", "black", step_limit, drawSomething, ''); 4083 drawBox(pos++, "green", "black", stepMax, drawSomething, ''); 4084 drawBox(pos++, "rgba(255,0,0, 0.6)", "black", lastIndex, drawSomething & draw_log, ''); 4085 drawBox(pos++, "rgba(255,0,0, 0.6)", "black", test.length - 1, drawSomething & draw_log, ''); 4086 if (curve_t) { 4087 drawCurveTControl(); 4088 } 4089 ctx.font = "normal 20px Arial"; 4090 ctx.fillStyle = "rgba(0,0,0, 0.3)"; 4091 ctx.textAlign = "right"; 4092 ctx.fillText(scale.toFixed(decimal_places) + 'x' , screenWidth - 10, screenHeight - 5); 4093 } 4094 if (draw_hints) { 4095 ctx.font = "normal 10px Arial"; 4096 ctx.fillStyle = "rgba(0,0,0, 0.5)"; 4097 ctx.textAlign = "right"; 4098 var y = 4; 4099 ctx.fillText("control lines : " + controlLinesKey, ctx.screenWidthwidth - 10, pos * 50 + y++ * 10); 4100 ctx.fillText("curve t : " + curveTKey, screenWidth - 10, pos * 50 + y++ * 10); 4101 ctx.fillText("deriviatives : " + deriviativesKey, screenWidth - 10, pos * 50 + y++ * 10); 4102 ctx.fillText("intersect t : " + intersectTKey, screenWidth - 10, pos * 50 + y++ * 10); 4103 ctx.fillText("log : " + logKey, screenWidth - 10, pos * 50 + y++ * 10); 4104 ctx.fillText("log curve : " + logCurvesKey, screenWidth - 10, pos * 50 + y++ * 10); 4105 ctx.fillText("mid point : " + midpointKey, screenWidth - 10, pos * 50 + y++ * 10); 4106 ctx.fillText("points : " + ptsKey, screenWidth - 10, pos * 50 + y++ * 10); 4107 ctx.fillText("sequence : " + sequenceKey, screenWidth - 10, pos * 50 + y++ * 10); 4108 ctx.fillText("xy : " + xyKey, screenWidth - 10, pos * 50 + y++ * 10); 4109 } 4110} 4111 4112function drawBox(y, backC, foreC, str, enable, label) { 4113 ctx.beginPath(); 4114 ctx.fillStyle = backC; 4115 ctx.rect(screenWidth - 40, y * 50 + 10, 40, 30); 4116 ctx.fill(); 4117 ctx.font = "normal 16px Arial"; 4118 ctx.fillStyle = foreC; 4119 ctx.textAlign = "center"; 4120 ctx.fillText(str, screenWidth - 20, y * 50 + 32); 4121 if (!enable) { 4122 ctx.fillStyle = "rgba(255,255,255, 0.5)"; 4123 ctx.fill(); 4124 } 4125 if (label != '') { 4126 ctx.font = "normal 9px Arial"; 4127 ctx.fillStyle = "black"; 4128 ctx.fillText(label, screenWidth - 47, y * 50 + 40); 4129 } 4130} 4131 4132function drawCurveTControl() { 4133 ctx.lineWidth = 2; 4134 ctx.strokeStyle = "rgba(0,0,0, 0.3)"; 4135 ctx.beginPath(); 4136 ctx.rect(screenWidth - 80, 40, 28, screenHeight - 80); 4137 ctx.stroke(); 4138 var ty = 40 + curveT * (screenHeight - 80); 4139 ctx.beginPath(); 4140 ctx.moveTo(screenWidth - 80, ty); 4141 ctx.lineTo(screenWidth - 85, ty - 5); 4142 ctx.lineTo(screenWidth - 85, ty + 5); 4143 ctx.lineTo(screenWidth - 80, ty); 4144 ctx.fillStyle = "rgba(0,0,0, 0.6)"; 4145 ctx.fill(); 4146 var num = curveT.toFixed(decimal_places); 4147 ctx.font = "normal 10px Arial"; 4148 ctx.textAlign = "left"; 4149 ctx.fillText(num, screenWidth - 78, ty); 4150} 4151 4152function ptInTControl() { 4153 var e = window.event; 4154 var tgt = e.target || e.srcElement; 4155 var left = tgt.offsetLeft; 4156 var top = tgt.offsetTop; 4157 var x = (e.clientX - left); 4158 var y = (e.clientY - top); 4159 if (x < screenWidth - 80 || x > screenWidth - 50) { 4160 return false; 4161 } 4162 if (y < 40 || y > screenHeight - 80) { 4163 return false; 4164 } 4165 curveT = (y - 40) / (screenHeight - 120); 4166 if (curveT < 0 || curveT > 1) { 4167 throw "stop execution"; 4168 } 4169 return true; 4170} 4171 4172function drawTop() { 4173 if (tests[testIndex] == null) { 4174 var str = testDivs[testIndex].textContent; 4175 parse_all(str); 4176 var title = testDivs[testIndex].id.toString(); 4177 testTitles[testIndex] = title; 4178 } 4179 init(tests[testIndex]); 4180 redraw(); 4181} 4182 4183function redraw() { 4184 if (focus_on_selection) { 4185 collect_bounds = true; 4186 draw(tests[testIndex], testLines[testIndex], testTitles[testIndex]); 4187 collect_bounds = false; 4188 if (focusXmin < focusXmax && focusYmin < focusYmax) { 4189 setScale(focusXmin, focusXmax, focusYmin, focusYmax); 4190 } 4191 } 4192 ctx.beginPath(); 4193 ctx.fillStyle = "white"; 4194 ctx.rect(0, 0, screenWidth, screenHeight); 4195 ctx.fill(); 4196 draw(tests[testIndex], testLines[testIndex], testTitles[testIndex]); 4197} 4198 4199function dumpCurvePartial(test, id, t0, t1) { 4200 var curve = curveByID(test, id); 4201 var name = ["line", "quad", "cubic"][curve.length / 2 - 2]; 4202 console.log("id=" + id + " " + name + "=" + curveToString(curve) 4203 + " t0=" + t0 + " t1=" + t1 4204 + " partial=" + curveToString(curvePartialByID(test, id, t0, t1))); 4205} 4206 4207function dumpAngleTest(test, id, t0, t1) { 4208 var curve = curveByID(test, id); 4209 console.log(" { {" + curveToString(curve) + "}, " 4210 + curve.length / 2 + ", " + t0 + ", " + t1 + ", {} }, //"); 4211} 4212 4213function dumpLogToConsole() { 4214 if (logStart < 0) { 4215 return; 4216 } 4217 var test = tests[testIndex]; 4218 var recType = REC_TYPE_UNKNOWN; 4219 var records; 4220 for (var index = 0; index < test.length; index += 3) { 4221 var lastLineNo = test[index + 1]; 4222 if (lastLineNo >= logStart && lastLineNo < logStart + logRange) { 4223 recType = test[index]; 4224 records = test[index + 2]; 4225 break; 4226 } 4227 } 4228 if (recType == REC_TYPE_UNKNOWN) { 4229 return; 4230 } 4231 var lines = testLines[testIndex]; 4232 for (var idx = 0; idx < logRange; ++idx) { 4233 var line = lines[logStart + idx]; 4234 console.log(line); 4235 for (var recordIndex = 0; recordIndex < records.length; recordIndex += 2) { 4236 var fragType = records[recordIndex]; 4237 var frags = records[recordIndex + 1]; 4238 if (recType == REC_TYPE_ANGLE && fragType == ANGLE_AFTER) { 4239 dumpCurvePartial(test, frags[0], frags[4], frags[5]); 4240 dumpCurvePartial(test, frags[6], frags[10], frags[11]); 4241 dumpCurvePartial(test, frags[12], frags[16], frags[17]); 4242 console.log("\nstatic IntersectData intersectDataSet[] = { //"); 4243 dumpAngleTest(test, frags[0], frags[4], frags[5]); 4244 dumpAngleTest(test, frags[6], frags[10], frags[11]); 4245 dumpAngleTest(test, frags[12], frags[16], frags[17]); 4246 console.log("}; //"); 4247 } 4248 } 4249 } 4250} 4251 4252var activeKey = 'a'; 4253var pathKey = 'b'; 4254var pathBackKey = 'B'; 4255var centerKey = 'c'; 4256var coincidenceKey = 'C'; 4257var addKey = 'd'; 4258var deriviativesKey = 'f'; 4259var angleKey = 'g'; 4260var angleBackKey = 'G'; 4261var intersectionKey = 'i'; 4262var intersectionBackKey = 'I'; 4263var sequenceKey = 'j'; 4264var midpointKey = 'k'; 4265var logKey = 'l'; 4266var logToConsoleKey = 'L'; 4267var markKey = 'm'; 4268var sortKey = 'o'; 4269var opKey = 'p'; 4270var opBackKey = 'P'; 4271var computedKey = 'q'; 4272var computedBackKey = 'Q'; 4273var directionKey = 'r'; 4274var stepKey = 's'; 4275var stepBackKey = 'S'; 4276var intersectTKey = 't'; 4277var topKey = 'T'; 4278var curveTKey = 'u'; 4279var controlLinesBackKey = 'V'; 4280var controlLinesKey = 'v'; 4281var ptsKey = 'x'; 4282var xyKey = 'y'; 4283var logCurvesKey = 'z'; 4284var focusKey = '`'; 4285var idKey = '.'; 4286var retinaKey = '\\'; 4287 4288function doKeyPress(evt) { 4289 var char = String.fromCharCode(evt.charCode); 4290 var focusWasOn = false; 4291 switch (char) { 4292 case '0': 4293 case '1': 4294 case '2': 4295 case '3': 4296 case '4': 4297 case '5': 4298 case '6': 4299 case '7': 4300 case '8': 4301 case '9': 4302 decimal_places = char - '0'; 4303 redraw(); 4304 break; 4305 case activeKey: 4306 draw_active ^= true; 4307 redraw(); 4308 break; 4309 case addKey: 4310 draw_add ^= true; 4311 redraw(); 4312 break; 4313 case angleKey: 4314 draw_angle = (draw_angle + 1) % 4; 4315 redraw(); 4316 break; 4317 case angleBackKey: 4318 draw_angle = (draw_angle + 2) % 3; 4319 redraw(); 4320 break; 4321 case centerKey: 4322 setScale(xmin, xmax, ymin, ymax); 4323 redraw(); 4324 break; 4325 case coincidenceKey: 4326 draw_coincidence ^= true; 4327 redraw(); 4328 break; 4329 case controlLinesBackKey: 4330 control_lines = (control_lines + 3) % 4; 4331 redraw(); 4332 break; 4333 case controlLinesKey: 4334 control_lines = (control_lines + 1) % 4; 4335 redraw(); 4336 break; 4337 case computedBackKey: 4338 draw_computed = (draw_computed + 5) % 6; 4339 redraw(); 4340 break; 4341 case computedKey: 4342 draw_computed = (draw_computed + 1) % 6; 4343 redraw(); 4344 break; 4345 case curveTKey: 4346 curve_t ^= true; 4347 if (curve_t) { 4348 draw_legend = true; 4349 } 4350 redraw(); 4351 break; 4352 case deriviativesKey: 4353 draw_deriviatives = (draw_deriviatives + 1) % 3; 4354 redraw(); 4355 break; 4356 case directionKey: 4357 draw_direction ^= true; 4358 redraw(); 4359 break; 4360 case focusKey: 4361 focus_on_selection ^= true; 4362 setScale(xmin, xmax, ymin, ymax); 4363 redraw(); 4364 break; 4365 case idKey: 4366 draw_id ^= true; 4367 redraw(); 4368 break; 4369 case intersectionBackKey: 4370 draw_intersection = (draw_intersection + 3) % 4; 4371 redraw(); 4372 break; 4373 case intersectionKey: 4374 draw_intersection = (draw_intersection + 1) % 4; 4375 redraw(); 4376 break; 4377 case intersectTKey: 4378 draw_intersectT ^= true; 4379 redraw(); 4380 break; 4381 case logCurvesKey: 4382 logCurves(tests[testIndex]); 4383 break; 4384 case logKey: 4385 draw_log ^= true; 4386 redraw(); 4387 break; 4388 case logToConsoleKey: 4389 if (draw_log) { 4390 dumpLogToConsole(); 4391 } 4392 break; 4393 case markKey: 4394 draw_mark ^= true; 4395 redraw(); 4396 break; 4397 case midpointKey: 4398 draw_midpoint ^= true; 4399 redraw(); 4400 break; 4401 case opKey: 4402 draw_op = (draw_op + 1) % 3; 4403 redraw(); 4404 break; 4405 case opBackKey: 4406 draw_op = (draw_op + 2) % 3; 4407 redraw(); 4408 break; 4409 case pathKey: 4410 draw_path = (draw_path + 1) % (4 + (hasAlignedPath ? 3 : 0)); 4411 redraw(); 4412 break; 4413 case pathBackKey: 4414 draw_path = (draw_path + 3 + (hasAlignedPath ? 3 : 0)) % (4 + (hasAlignedPath ? 3 : 0)); 4415 redraw(); 4416 break; 4417 case ptsKey: 4418 pt_labels = (pt_labels + 1) % 3; 4419 redraw(); 4420 break; 4421 case retinaKey: 4422 retina_scale ^= true; 4423 drawTop(); 4424 break; 4425 case sequenceKey: 4426 draw_sequence ^= true; 4427 redraw(); 4428 break; 4429 case sortKey: 4430 draw_sort = (draw_sort + 1) % 3; 4431 drawTop(); 4432 break; 4433 case stepKey: 4434 step_limit++; 4435 if (step_limit > stepMax) { 4436 step_limit = stepMax; 4437 } 4438 redraw(); 4439 break; 4440 case stepBackKey: 4441 step_limit--; 4442 if (step_limit < 0) { 4443 step_limit = 0; 4444 } 4445 redraw(); 4446 break; 4447 case topKey: 4448 draw_top ^= true; 4449 redraw(); 4450 break; 4451 case xyKey: 4452 debug_xy = (debug_xy + 1) % 3; 4453 redraw(); 4454 break; 4455 case '-': 4456 focusWasOn = focus_on_selection; 4457 if (focusWasOn) { 4458 focus_on_selection = false; 4459 scale /= 1.2; 4460 } else { 4461 scale /= 2; 4462 calcLeftTop(); 4463 } 4464 redraw(); 4465 focus_on_selection = focusWasOn; 4466 break; 4467 case '=': 4468 case '+': 4469 focusWasOn = focus_on_selection; 4470 if (focusWasOn) { 4471 focus_on_selection = false; 4472 scale *= 1.2; 4473 } else { 4474 scale *= 2; 4475 calcLeftTop(); 4476 } 4477 redraw(); 4478 focus_on_selection = focusWasOn; 4479 break; 4480 case '?': 4481 draw_hints ^= true; 4482 if (draw_hints && !draw_legend) { 4483 draw_legend = true; 4484 } 4485 redraw(); 4486 break; 4487 case '/': 4488 draw_legend ^= true; 4489 redraw(); 4490 break; 4491 } 4492} 4493 4494function doKeyDown(evt) { 4495 var char = evt.keyCode; 4496 var preventDefault = false; 4497 switch (char) { 4498 case 37: // left arrow 4499 if (evt.shiftKey) { 4500 testIndex -= 9; 4501 } 4502 if (--testIndex < 0) 4503 testIndex = tests.length - 1; 4504 drawTop(); 4505 preventDefault = true; 4506 break; 4507 case 39: // right arrow 4508 if (evt.shiftKey) { 4509 testIndex += 9; 4510 } 4511 if (++testIndex >= tests.length) 4512 testIndex = 0; 4513 drawTop(); 4514 preventDefault = true; 4515 break; 4516 } 4517 if (preventDefault) { 4518 evt.preventDefault(); 4519 return false; 4520 } 4521 return true; 4522} 4523 4524(function() { 4525 var hidden = "hidden"; 4526 4527 // Standards: 4528 if (hidden in document) 4529 document.addEventListener("visibilitychange", onchange); 4530 else if ((hidden = "mozHidden") in document) 4531 document.addEventListener("mozvisibilitychange", onchange); 4532 else if ((hidden = "webkitHidden") in document) 4533 document.addEventListener("webkitvisibilitychange", onchange); 4534 else if ((hidden = "msHidden") in document) 4535 document.addEventListener("msvisibilitychange", onchange); 4536 // IE 9 and lower: 4537 else if ('onfocusin' in document) 4538 document.onfocusin = document.onfocusout = onchange; 4539 // All others: 4540 else 4541 window.onpageshow = window.onpagehide 4542 = window.onfocus = window.onblur = onchange; 4543 4544 function onchange (evt) { 4545 var v = 'visible', h = 'hidden', 4546 evtMap = { 4547 focus:v, focusin:v, pageshow:v, blur:h, focusout:h, pagehide:h 4548 }; 4549 4550 evt = evt || window.event; 4551 if (evt.type in evtMap) 4552 document.body.className = evtMap[evt.type]; 4553 else 4554 document.body.className = this[hidden] ? "hidden" : "visible"; 4555 } 4556})(); 4557 4558function calcXY() { 4559 var e = window.event; 4560 var tgt = e.target || e.srcElement; 4561 var left = tgt.offsetLeft; 4562 var top = tgt.offsetTop; 4563 mouseX = (e.clientX - left) / scale + srcLeft; 4564 mouseY = (e.clientY - top) / scale + srcTop; 4565} 4566 4567function calcLeftTop() { 4568 srcLeft = mouseX - screenWidth / 2 / scale; 4569 srcTop = mouseY - screenHeight / 2 / scale; 4570} 4571 4572var disableClick = false; 4573 4574function handleMouseClick() { 4575 if (disableClick) { 4576 return; 4577 } 4578 if (!curve_t || !ptInTControl()) { 4579 calcXY(); 4580 calcLeftTop(); 4581 } 4582 redraw(); 4583// if (!curve_t || !ptInTControl()) { 4584// mouseX = screenWidth / 2 / scale + srcLeft; 4585// mouseY = screenHeight / 2 / scale + srcTop; 4586// } 4587} 4588 4589function handleMouseOver() { 4590 calcXY(); 4591 if (debug_xy != 2) { 4592 return; 4593 } 4594 var num = mouseX.toFixed(decimal_places) + ", " + mouseY.toFixed(decimal_places); 4595 ctx.beginPath(); 4596 ctx.rect(300,100,num.length * 6,10); 4597 ctx.fillStyle="white"; 4598 ctx.fill(); 4599 ctx.font = "normal 10px Arial"; 4600 ctx.fillStyle="black"; 4601 ctx.textAlign = "left"; 4602 ctx.fillText(num, 300, 108); 4603} 4604 4605function start() { 4606 for (var i = 0; i < testDivs.length; ++i) { 4607 tests[i] = null; 4608 } 4609 testIndex = 0; 4610 drawTop(); 4611 window.addEventListener('keypress', doKeyPress, true); 4612 window.addEventListener('keydown', doKeyDown, true); 4613 window.onresize = function() { 4614 drawTop(); 4615 } 4616 /* 4617 window.onpagehide = function() { 4618 disableClick = true; 4619 } 4620 */ 4621 window.onpageshow = function () { 4622 disableClick = false; 4623 } 4624} 4625 4626</script> 4627</head> 4628 4629<body onLoad="start();"> 4630<canvas id="canvas" width="750" height="500" 4631 onmousemove="handleMouseOver()" 4632 onclick="handleMouseClick()" 4633 ></canvas > 4634</body> 4635</html> 4636