blob: 4c8d52f3019cdc8b264ddfffa879e10369ada2d5 [file] [log] [blame]
caryclarkdac1d172014-06-17 05:15:38 -07001<html>
2<head>
Cary Clark59d5a0e2017-01-23 14:38:52 +00003<div height="0" hidden="true">
Ben Wagner29380bd2017-10-09 14:43:00 -04004
Cary Clark3a4a3212018-06-06 15:22:08 -04005<div id="halbug">
6seg=1 {{{278.653992f, 155.747406f}, {580.15918f, 155.747406f}}}
7seg=2 {{{580.15918f, 155.747406f}, {580.15918f, 593.602051f}}}
8seg=3 {{{580.15918f, 593.602051f}, {278.653992f, 593.602051f}}}
9seg=4 {{{278.653992f, 593.602051f}, {278.653992f, 155.747406f}}}
10op sect
11seg=5 {{{278.657715f, 155.747314f}, {580.238281f, 155.747314f}}}
12seg=6 {{{580.238281f, 155.747314f}, {580.238281f, 594.114014f}}}
13seg=7 {{{580.238281f, 594.114014f}, {278.657715f, 594.114014f}}}
14seg=8 {{{278.657715f, 594.114014f}, {278.657715f, 155.747314f}}}
15debugShowLineIntersection wtTs[0]=0 {{{580.238281,155.747314}, {580.238281,594.114014}}} {{580.238281,155.747314}} wnTs[0]=1 {{{278.657715,155.747314}, {580.238281,155.747314}}}
16debugShowLineIntersection wtTs[0]=1 {{{278.657715,594.114014}, {278.657715,155.747314}}} {{278.657715,155.747314}} wnTs[0]=0 {{{278.657715,155.747314}, {580.238281,155.747314}}}
17debugShowLineIntersection wtTs[0]=0 {{{580.238281,594.114014}, {278.657715,594.114014}}} {{580.238281,594.114014}} wnTs[0]=1 {{{580.238281,155.747314}, {580.238281,594.114014}}}
18debugShowLineIntersection wtTs[0]=0 {{{278.657715,594.114014}, {278.657715,155.747314}}} {{278.657715,594.114014}} wnTs[0]=1 {{{580.238281,594.114014}, {278.657715,594.114014}}}
19debugShowLineIntersection no intersect {{{278.653992,155.747406}, {580.15918,155.747406}}} {{{278.657715,155.747314}, {580.238281,155.747314}}}
20debugShowLineIntersection no intersect {{{580.15918,155.747406}, {580.15918,593.602051}}} {{{278.657715,155.747314}, {580.238281,155.747314}}}
21debugShowLineIntersection wtTs[0]=1.23485256e-05 {{{278.653992,155.747406}, {580.15918,155.747406}}} {{278.657715,155.747406}} wnTs[0]=1 {{{278.657715,594.114014}, {278.657715,155.747314}}}
22SkOpSegment::addT insert t=1.23485256e-05 segID=1 spanID=17
23debugShowLineIntersection wtTs[0]=0.999987651 {{{580.15918,593.602051}, {278.653992,593.602051}}} {{278.657715,593.602051}} wnTs[0]=0.00116789 {{{278.657715,594.114014}, {278.657715,155.747314}}}
24SkOpSegment::addT insert t=0.00116788728 segID=8 spanID=18
25SkOpSegment::addT insert t=0.999987651 segID=3 spanID=19
26debugShowLineIntersection wtTs[0]=0 {{{580.15918,155.747406}, {580.15918,593.602051}}} {{580.15918,155.747406}} wnTs[0]=1 {{{278.653992,155.747406}, {580.15918,155.747406}}}
27debugShowLineIntersection wtTs[0]=1 {{{278.653992,593.602051}, {278.653992,155.747406}}} {{278.653992,155.747406}} wnTs[0]=0 {{{278.653992,155.747406}, {580.15918,155.747406}}}
28debugShowLineIntersection wtTs[0]=0 {{{580.15918,593.602051}, {278.653992,593.602051}}} {{580.15918,593.602051}} wnTs[0]=1 {{{580.15918,155.747406}, {580.15918,593.602051}}}
29debugShowLineIntersection wtTs[0]=0 {{{278.653992,593.602051}, {278.653992,155.747406}}} {{278.653992,593.602051}} wnTs[0]=1 {{{580.15918,593.602051}, {278.653992,593.602051}}}
30-------------------------------------- addExpanded
31SkOpSegment::debugShowActiveSpans id=5 (278.657715,155.747314 580.238281,155.747314) t=0 tEnd=1 windSum=? windValue=1
32SkOpSegment::debugShowActiveSpans id=6 (580.238281,155.747314 580.238281,594.114014) t=0 tEnd=1 windSum=? windValue=1
33SkOpSegment::debugShowActiveSpans id=7 (580.238281,594.114014 278.657715,594.114014) t=0 tEnd=1 windSum=? windValue=1
34SkOpSegment::debugShowActiveSpans id=8 (278.657715,594.114014 278.657715,593.602051) t=0 tEnd=0.00116788728 windSum=? windValue=1
35SkOpSegment::debugShowActiveSpans id=8 (278.657715,593.602051 278.657715,155.747314) t=0.00116788728 tEnd=1 windSum=? windValue=1
36SkOpSegment::debugShowActiveSpans id=1 (278.653992,155.747406 278.657715,155.747406) t=0 tEnd=1.23485256e-05 windSum=? windValue=1
37SkOpSegment::debugShowActiveSpans id=1 (278.657715,155.747406 580.15918,155.747406) t=1.23485256e-05 tEnd=1 windSum=? windValue=1
38SkOpSegment::debugShowActiveSpans id=2 (580.15918,155.747406 580.15918,593.602051) t=0 tEnd=1 windSum=? windValue=1
39SkOpSegment::debugShowActiveSpans id=3 (580.15918,593.602051 278.657715,593.602051) t=0 tEnd=0.999987651 windSum=? windValue=1
40SkOpSegment::debugShowActiveSpans id=3 (278.657715,593.602051 278.653992,593.602051) t=0.999987651 tEnd=1 windSum=? windValue=1
41SkOpSegment::debugShowActiveSpans id=4 (278.653992,593.602051 278.653992,155.747406) t=0 tEnd=1 windSum=? windValue=1
42-------------------------------------- move_multiples
43-------------------------------------- move_nearby
44-------------------------------------- correctEnds
45-------------------------------------- addEndMovedSpans
46-------------------------------------- expand
47-------------------------------------- addExpanded
48-------------------------------------- mark
49-------------------------------------- missing_coincidence
50-------------------------------------- expand
51-------------------------------------- expand
52-------------------------------------- apply
53-------------------------------------- findOverlaps
54-------------------------------------- calc_angles
55SkOpSegment::sortAngles [5] tStart=0 [9]
56SkOpAngle::after [5/1] 31/31 tStart=0 tEnd=1 < [1/5] 15/15 tStart=1.23485256e-05 tEnd=0 < [8/4] 23/23 tStart=1 tEnd=0.00116788728 T 4
57SkOpAngle::afterPart {{{278.657715,155.747406}, {580.238281,155.747406}}} id=5
58SkOpAngle::afterPart {{{278.657715,155.747406}, {278.653992,155.747406}}} id=1
59SkOpAngle::afterPart {{{278.657715,155.747406}, {278.657715,593.602142}}} id=8
60SkOpAngle::after [5/1] 31/31 tStart=0 tEnd=1 < [1/6] 31/31 tStart=1.23485256e-05 tEnd=1 < [1/5] 15/15 tStart=1.23485256e-05 tEnd=0 T 12
61SkOpAngle::afterPart {{{278.657715,155.747406}, {580.238281,155.747406}}} id=5
62SkOpAngle::afterPart {{{278.657715,155.747406}, {580.15918,155.747406}}} id=1
63SkOpAngle::afterPart {{{278.657715,155.747406}, {278.653992,155.747406}}} id=1
64SkOpSegment::sortAngles [8] tStart=0.00116788728 [18]
65SkOpAngle::after [8/2] 23/23 tStart=0.00116788728 tEnd=0 < [3/7] 31/31 tStart=0.999987651 tEnd=0 < [8/3] 7/7 tStart=0.00116788728 tEnd=1 T 4
66SkOpAngle::afterPart {{{278.657715,593.602051}, {278.657715,594.114014}}} id=8
67SkOpAngle::afterPart {{{278.657715,593.602051}, {580.15918,593.602051}}} id=3
68SkOpAngle::afterPart {{{278.657715,593.602051}, {278.657715,155.747314}}} id=8
69SkOpAngle::after [8/2] 23/23 tStart=0.00116788728 tEnd=0 < [3/8] 15/15 tStart=0.999987651 tEnd=1 < [3/7] 31/31 tStart=0.999987651 tEnd=0 F 4
70SkOpAngle::afterPart {{{278.657715,593.602051}, {278.657715,594.114014}}} id=8
71SkOpAngle::afterPart {{{278.657715,593.602051}, {278.653992,593.602051}}} id=3
72SkOpAngle::afterPart {{{278.657715,593.602051}, {580.15918,593.602051}}} id=3
73SkOpAngle::after [3/7] 31/31 tStart=0.999987651 tEnd=0 < [3/8] 15/15 tStart=0.999987651 tEnd=1 < [8/3] 7/7 tStart=0.00116788728 tEnd=1 F 4
74SkOpAngle::afterPart {{{278.657715,593.602051}, {580.15918,593.602051}}} id=3
75SkOpAngle::afterPart {{{278.657715,593.602051}, {278.653992,593.602051}}} id=3
76SkOpAngle::afterPart {{{278.657715,593.602051}, {278.657715,155.747314}}} id=8
77SkOpAngle::after [8/3] 7/7 tStart=0.00116788728 tEnd=1 < [3/8] 15/15 tStart=0.999987651 tEnd=1 < [8/2] 23/23 tStart=0.00116788728 tEnd=0 T 4
78SkOpAngle::afterPart {{{278.657715,593.602051}, {278.657715,155.747314}}} id=8
79SkOpAngle::afterPart {{{278.657715,593.602051}, {278.653992,593.602051}}} id=3
80SkOpAngle::afterPart {{{278.657715,593.602051}, {278.657715,594.114014}}} id=8
81SkOpSegment::sortAngles [8] tStart=1 [16]
82SkOpSegment::sortAngles [1] tStart=1.23485256e-05 [17]
83SkOpSegment::sortAngles [3] tStart=0.999987651 [19]
84SkOpSpan::sortableTop dir=kTop seg=5 t=0.5 pt=(429.447998,155.747314)
85SkOpSpan::sortableTop [0] valid=1 operand=1 span=9 ccw=1 seg=5 {{{278.657715f, 155.747314f}, {580.238281f, 155.747314f}}} t=0.5 pt=(429.447998,155.747314) slope=(301.580566,0)
86SkOpSegment::markWinding id=5 (278.657715,155.747314 580.238281,155.747314) t=0 [9] (278.657715,155.747314) tEnd=1 newWindSum=-1 newOppSum=0 oppSum=0 windSum=-1 windValue=1 oppValue=0
87SkOpSegment::markWinding id=6 (580.238281,155.747314 580.238281,594.114014) t=0 [11] (580.238281,155.747314) tEnd=1 newWindSum=-1 newOppSum=0 oppSum=? windSum=? windValue=1 oppValue=0
88SkOpSegment::markWinding id=7 (580.238281,594.114014 278.657715,594.114014) t=0 [13] (580.238281,594.114014) tEnd=1 newWindSum=-1 newOppSum=0 oppSum=? windSum=? windValue=1 oppValue=0
89SkOpSegment::markWinding id=8 (278.657715,594.114014 278.657715,155.747314) t=0 [15] (278.657715,594.114014) tEnd=0.00116788728 newWindSum=-1 newOppSum=0 oppSum=? windSum=? windValue=1 oppValue=0
90SkOpSegment::markWinding id=5 (278.657715,155.747314 580.238281,155.747314) t=0 [9] (278.657715,155.747314) tEnd=1 newWindSum=-1 newOppSum=0 oppSum=0 windSum=-1 windValue=1 oppValue=0
91SkOpSegment::activeOp id=5 t=1 tEnd=0 op=sect miFrom=0 miTo=0 suFrom=0 suTo=1 result=0
92SkOpSegment::markDone id=5 (278.657715,155.747314 580.238281,155.747314) t=0 [9] (278.657715,155.747314) tEnd=1 newWindSum=-1 newOppSum=0 oppSum=0 windSum=-1 windValue=1 oppValue=0
93bridgeOp chase.append id=5 windSum=-1
94SkOpSpan::sortableTop dir=kTop seg=1 t=0.500006174 pt=(429.408447,155.747406)
95SkOpSpan::sortableTop [0] valid=0 operand=1 span=9 ccw=0 seg=5 {{{278.657715f, 155.747314f}, {580.238281f, 155.747314f}}} t=0.499868855 pt=(429.408447,155.747314) slope=(0,0)
96SkOpSpan::sortableTop [1] valid=1 operand=0 span=17 ccw=1 seg=1 {{{278.653992f, 155.747406f}, {580.15918f, 155.747406f}}} t=0.500006174 pt=(429.408447,155.747406) slope=(301.505188,0)
97SkOpSpan::sortableTop dir=kRight seg=1 t=0.500006174 pt=(429.408447,155.747406)
98SkOpSpan::sortableTop [0] valid=1 operand=1 span=11 ccw=1 seg=6 {{{580.238281f, 155.747314f}, {580.238281f, 594.114014f}}} t=2.08849656e-07 pt=(580.238281,155.747406) slope=(0,438.366699)
99SkOpSpan::sortableTop [1] valid=0 operand=0 span=3 ccw=0 seg=2 {{{580.15918f, 155.747406f}, {580.15918f, 593.602051f}}} t=0 pt=(580.15918,155.747406) slope=(0,0)
100SkOpSpan::sortableTop [2] valid=1 operand=0 span=17 ccw=0 seg=1 {{{278.653992f, 155.747406f}, {580.15918f, 155.747406f}}} t=0.500006174 pt=(429.408447,155.747406) slope=(301.505188,0)
101SkOpSpan::sortableTop dir=kTop seg=1 t=0.250009261 pt=(354.033081,155.747406)
102SkOpSpan::sortableTop [0] valid=0 operand=1 span=9 ccw=0 seg=5 {{{278.657715f, 155.747314f}, {580.238281f, 155.747314f}}} t=0.249934428 pt=(354.033081,155.747314) slope=(0,0)
103SkOpSpan::sortableTop [1] valid=1 operand=0 span=17 ccw=1 seg=1 {{{278.653992f, 155.747406f}, {580.15918f, 155.747406f}}} t=0.250009261 pt=(354.033081,155.747406) slope=(301.505188,0)
104SkOpSpan::sortableTop dir=kRight seg=1 t=0.250009261 pt=(354.033081,155.747406)
105SkOpSpan::sortableTop [0] valid=1 operand=1 span=11 ccw=1 seg=6 {{{580.238281f, 155.747314f}, {580.238281f, 594.114014f}}} t=2.08849656e-07 pt=(580.238281,155.747406) slope=(0,438.366699)
106SkOpSpan::sortableTop [1] valid=0 operand=0 span=3 ccw=0 seg=2 {{{580.15918f, 155.747406f}, {580.15918f, 593.602051f}}} t=0 pt=(580.15918,155.747406) slope=(0,0)
107SkOpSpan::sortableTop [2] valid=1 operand=0 span=17 ccw=0 seg=1 {{{278.653992f, 155.747406f}, {580.15918f, 155.747406f}}} t=0.250009261 pt=(354.033081,155.747406) slope=(301.505188,0)
108SkOpSpan::sortableTop dir=kTop seg=1 t=0.375007718 pt=(391.720764,155.747406)
109SkOpSpan::sortableTop [0] valid=0 operand=1 span=9 ccw=0 seg=5 {{{278.657715f, 155.747314f}, {580.238281f, 155.747314f}}} t=0.374901641 pt=(391.720764,155.747314) slope=(0,0)
110SkOpSpan::sortableTop [1] valid=1 operand=0 span=17 ccw=1 seg=1 {{{278.653992f, 155.747406f}, {580.15918f, 155.747406f}}} t=0.375007718 pt=(391.720764,155.747406) slope=(301.505188,0)
111SkOpSpan::sortableTop dir=kRight seg=1 t=0.375007718 pt=(391.720764,155.747406)
112SkOpSpan::sortableTop [0] valid=1 operand=1 span=11 ccw=1 seg=6 {{{580.238281f, 155.747314f}, {580.238281f, 594.114014f}}} t=2.08849656e-07 pt=(580.238281,155.747406) slope=(0,438.366699)
113SkOpSpan::sortableTop [1] valid=0 operand=0 span=3 ccw=0 seg=2 {{{580.15918f, 155.747406f}, {580.15918f, 593.602051f}}} t=0 pt=(580.15918,155.747406) slope=(0,0)
114SkOpSpan::sortableTop [2] valid=1 operand=0 span=17 ccw=0 seg=1 {{{278.653992f, 155.747406f}, {580.15918f, 155.747406f}}} t=0.375007718 pt=(391.720764,155.747406) slope=(301.505188,0)
115SkOpSpan::sortableTop dir=kTop seg=1 t=0.625004631 pt=(467.09613,155.747406)
116SkOpSpan::sortableTop [0] valid=0 operand=1 span=9 ccw=0 seg=5 {{{278.657715f, 155.747314f}, {580.238281f, 155.747314f}}} t=0.624836069 pt=(467.09613,155.747314) slope=(0,0)
117SkOpSpan::sortableTop [1] valid=1 operand=0 span=17 ccw=1 seg=1 {{{278.653992f, 155.747406f}, {580.15918f, 155.747406f}}} t=0.625004631 pt=(467.09613,155.747406) slope=(301.505188,0)
118SkOpSpan::sortableTop dir=kRight seg=1 t=0.625004631 pt=(467.09613,155.747406)
119SkOpSpan::sortableTop [0] valid=1 operand=1 span=11 ccw=1 seg=6 {{{580.238281f, 155.747314f}, {580.238281f, 594.114014f}}} t=2.08849656e-07 pt=(580.238281,155.747406) slope=(0,438.366699)
120SkOpSpan::sortableTop [1] valid=0 operand=0 span=3 ccw=0 seg=2 {{{580.15918f, 155.747406f}, {580.15918f, 593.602051f}}} t=0 pt=(580.15918,155.747406) slope=(0,0)
121SkOpSpan::sortableTop [2] valid=1 operand=0 span=17 ccw=0 seg=1 {{{278.653992f, 155.747406f}, {580.15918f, 155.747406f}}} t=0.625004631 pt=(467.09613,155.747406) slope=(301.505188,0)
122SkOpSpan::sortableTop dir=kTop seg=1 t=0.437506946 pt=(410.564606,155.747406)
123SkOpSpan::sortableTop [0] valid=0 operand=1 span=9 ccw=0 seg=5 {{{278.657715f, 155.747314f}, {580.238281f, 155.747314f}}} t=0.437385248 pt=(410.564606,155.747314) slope=(0,0)
124SkOpSpan::sortableTop [1] valid=1 operand=0 span=17 ccw=1 seg=1 {{{278.653992f, 155.747406f}, {580.15918f, 155.747406f}}} t=0.437506946 pt=(410.564606,155.747406) slope=(301.505188,0)
125SkOpSpan::sortableTop dir=kRight seg=1 t=0.437506946 pt=(410.564606,155.747406)
126SkOpSpan::sortableTop [0] valid=1 operand=1 span=11 ccw=1 seg=6 {{{580.238281f, 155.747314f}, {580.238281f, 594.114014f}}} t=2.08849656e-07 pt=(580.238281,155.747406) slope=(0,438.366699)
127SkOpSpan::sortableTop [1] valid=0 operand=0 span=3 ccw=0 seg=2 {{{580.15918f, 155.747406f}, {580.15918f, 593.602051f}}} t=0 pt=(580.15918,155.747406) slope=(0,0)
128SkOpSpan::sortableTop [2] valid=1 operand=0 span=17 ccw=0 seg=1 {{{278.653992f, 155.747406f}, {580.15918f, 155.747406f}}} t=0.437506946 pt=(410.564606,155.747406) slope=(301.505188,0)
129SkOpSpan::sortableTop dir=kTop seg=1 t=6.1742628e-06 pt=(278.655853,155.747406)
130SkOpSpan::sortableTop [0] valid=1 operand=0 span=1 ccw=1 seg=1 {{{278.653992f, 155.747406f}, {580.15918f, 155.747406f}}} t=6.1742628e-06 pt=(278.655853,155.747406) slope=(301.505188,0)
131SkOpSegment::markWinding id=1 (278.653992,155.747406 580.15918,155.747406) t=0 [1] (278.653992,155.747406) tEnd=1.23485256e-05 newWindSum=-1 newOppSum=0 oppSum=0 windSum=-1 windValue=1 oppValue=0
132SkOpSegment::markWinding id=1 (278.653992,155.747406 580.15918,155.747406) t=0 [1] (278.653992,155.747406) tEnd=1.23485256e-05 newWindSum=-1 newOppSum=0 oppSum=0 windSum=-1 windValue=1 oppValue=0
133SkOpSegment::markWinding id=4 (278.653992,593.602051 278.653992,155.747406) t=0 [7] (278.653992,593.602051) tEnd=1 newWindSum=-1 newOppSum=0 oppSum=? windSum=? windValue=1 oppValue=0
134SkOpSegment::markWinding id=3 (580.15918,593.602051 278.653992,593.602051) t=0.999987651 [19] (278.657715,593.602051) tEnd=1 newWindSum=-1 newOppSum=0 oppSum=? windSum=? windValue=1 oppValue=0
135SkOpSpan::sortableTop dir=kLeft seg=8 t=0.500583944 pt=(278.657715,374.674683)
136SkOpSpan::sortableTop [0] valid=1 operand=0 span=7 ccw=1 seg=4 {{{278.653992f, 593.602051f}, {278.653992f, 155.747406f}}} t=0.500000105 pt=(278.653992,374.674683) slope=(0,-437.854645)
137SkOpSpan::sortableTop [1] valid=1 operand=1 span=18 ccw=1 seg=8 {{{278.657715f, 594.114014f}, {278.657715f, 155.747314f}}} t=0.500583944 pt=(278.657715,374.674683) slope=(0,-438.366699)
138SkOpSegment::markWinding id=8 (278.657715,594.114014 278.657715,155.747314) t=0.00116788728 [18] (278.657715,593.602051) tEnd=1 newWindSum=-1 newOppSum=-1 oppSum=-1 windSum=-1 windValue=1 oppValue=0
139SkOpSegment::markWinding id=8 (278.657715,594.114014 278.657715,155.747314) t=0.00116788728 [18] (278.657715,593.602051) tEnd=1 newWindSum=-1 newOppSum=-1 oppSum=-1 windSum=-1 windValue=1 oppValue=0
140SkOpSegment::debugShowActiveSpans id=6 (580.238281,155.747314 580.238281,594.114014) t=0 tEnd=1 windSum=-1 oppSum=0 windValue=1 oppValue=0
141SkOpSegment::debugShowActiveSpans id=7 (580.238281,594.114014 278.657715,594.114014) t=0 tEnd=1 windSum=-1 oppSum=0 windValue=1 oppValue=0
142SkOpSegment::debugShowActiveSpans id=8 (278.657715,594.114014 278.657715,593.602051) t=0 tEnd=0.00116788728 windSum=-1 oppSum=0 windValue=1 oppValue=0
143SkOpSegment::debugShowActiveSpans id=8 (278.657715,593.602051 278.657715,155.747314) t=0.00116788728 tEnd=1 windSum=-1 oppSum=-1 windValue=1 oppValue=0
144SkOpSegment::debugShowActiveSpans id=1 (278.653992,155.747406 278.657715,155.747406) t=0 tEnd=1.23485256e-05 windSum=-1 oppSum=0 windValue=1 oppValue=0
145SkOpSegment::debugShowActiveSpans id=1 (278.657715,155.747406 580.15918,155.747406) t=1.23485256e-05 tEnd=1 windSum=? windValue=1
146SkOpSegment::debugShowActiveSpans id=2 (580.15918,155.747406 580.15918,593.602051) t=0 tEnd=1 windSum=? windValue=1
147SkOpSegment::debugShowActiveSpans id=3 (580.15918,593.602051 278.657715,593.602051) t=0 tEnd=0.999987651 windSum=? windValue=1
148SkOpSegment::debugShowActiveSpans id=3 (278.657715,593.602051 278.653992,593.602051) t=0.999987651 tEnd=1 windSum=-1 oppSum=0 windValue=1 oppValue=0
149SkOpSegment::debugShowActiveSpans id=4 (278.653992,593.602051 278.653992,155.747406) t=0 tEnd=1 windSum=-1 oppSum=0 windValue=1 oppValue=0
150SkOpSegment::activeOp id=1 t=1.23485256e-05 tEnd=0 op=sect miFrom=0 miTo=1 suFrom=0 suTo=0 result=0
151SkOpSegment::markDone id=1 (278.653992,155.747406 580.15918,155.747406) t=0 [1] (278.653992,155.747406) tEnd=1.23485256e-05 newWindSum=-1 newOppSum=0 oppSum=0 windSum=-1 windValue=1 oppValue=0
152SkOpSegment::markDone id=4 (278.653992,593.602051 278.653992,155.747406) t=0 [7] (278.653992,593.602051) tEnd=1 newWindSum=-1 newOppSum=0 oppSum=0 windSum=-1 windValue=1 oppValue=0
153SkOpSegment::markDone id=3 (580.15918,593.602051 278.653992,593.602051) t=0.999987651 [19] (278.657715,593.602051) tEnd=1 newWindSum=-1 newOppSum=0 oppSum=0 windSum=-1 windValue=1 oppValue=0
154bridgeOp chase.append id=3 windSum=-1
155SkOpSegment::debugShowActiveSpans id=6 (580.238281,155.747314 580.238281,594.114014) t=0 tEnd=1 windSum=-1 oppSum=0 windValue=1 oppValue=0
156SkOpSegment::debugShowActiveSpans id=7 (580.238281,594.114014 278.657715,594.114014) t=0 tEnd=1 windSum=-1 oppSum=0 windValue=1 oppValue=0
157SkOpSegment::debugShowActiveSpans id=8 (278.657715,594.114014 278.657715,593.602051) t=0 tEnd=0.00116788728 windSum=-1 oppSum=0 windValue=1 oppValue=0
158SkOpSegment::debugShowActiveSpans id=8 (278.657715,593.602051 278.657715,155.747314) t=0.00116788728 tEnd=1 windSum=-1 oppSum=-1 windValue=1 oppValue=0
159SkOpSegment::debugShowActiveSpans id=1 (278.657715,155.747406 580.15918,155.747406) t=1.23485256e-05 tEnd=1 windSum=? windValue=1
160SkOpSegment::debugShowActiveSpans id=2 (580.15918,155.747406 580.15918,593.602051) t=0 tEnd=1 windSum=? windValue=1
161SkOpSegment::debugShowActiveSpans id=3 (580.15918,593.602051 278.657715,593.602051) t=0 tEnd=0.999987651 windSum=? windValue=1
162SkOpSegment::activeOp id=8 t=0.00116788728 tEnd=1 op=sect miFrom=1 miTo=1 suFrom=1 suTo=0 result=1
163SkOpSegment::findNextOp
164SkOpAngle::dumpOne [8/4] next=5/1 sect=23/23 s=1 [16] e=0.00116788728 [18] sgn=1 windVal=1 windSum=-1 oppVal=0 oppSum=-1 operand
165SkOpAngle::dumpOne [5/1] next=1/6 sect=31/31 s=0 [9] e=1 [10] sgn=-1 windVal=1 windSum=-1 oppVal=0 oppSum=0 done unorderable operand
166SkOpAngle::dumpOne [1/6] next=1/5 sect=31/31 s=1.23485256e-05 [17] e=1 [2] sgn=-1 windVal=1 windSum=? unorderable
167SkOpAngle::dumpOne [1/5] next=8/4 sect=15/15 s=1.23485256e-05 [17] e=0 [1] sgn=1 windVal=1 windSum=-1 oppVal=0 oppSum=0 done
168SkOpSegment::activeOp id=5 t=0 tEnd=1 op=sect miFrom=1 miTo=1 suFrom=1 suTo=0 result=1
169SkOpSegment::activeOp id=1 t=1.23485256e-05 tEnd=1 op=sect miFrom=1 miTo=0 suFrom=0 suTo=0 result=0
170SkOpSegment::markDone id=1 (278.653992,155.747406 580.15918,155.747406) t=1.23485256e-05 [17] (278.657715,155.747406) tEnd=1 newWindSum=? newOppSum=? oppSum=? windSum=? windValue=1 oppValue=0
171SkOpSegment::markDone id=2 (580.15918,155.747406 580.15918,593.602051) t=0 [3] (580.15918,155.747406) tEnd=1 newWindSum=? newOppSum=? oppSum=? windSum=? windValue=1 oppValue=0
172SkOpSegment::markDone id=3 (580.15918,593.602051 278.653992,593.602051) t=0 [5] (580.15918,593.602051) tEnd=0.999987651 newWindSum=? newOppSum=? oppSum=? windSum=? windValue=1 oppValue=0
173SkOpSegment::activeOp id=1 t=1.23485256e-05 tEnd=0 op=sect miFrom=0 miTo=1 suFrom=0 suTo=0 result=0
174SkOpSegment::markDone id=8 (278.657715,594.114014 278.657715,155.747314) t=0.00116788728 [18] (278.657715,593.602051) tEnd=1 newWindSum=-1 newOppSum=-1 oppSum=-1 windSum=-1 windValue=1 oppValue=0
175SkOpSegment::findNextOp from:[8] to:[5] start=1653597136 end=1653597280
176bridgeOp current id=8 from=(278.657715,593.602051) to=(278.657715,155.747314)
177path.moveTo(278.657715,593.602051);
178path.lineTo(278.657715,155.747314);
179SkOpSegment::debugShowActiveSpans id=6 (580.238281,155.747314 580.238281,594.114014) t=0 tEnd=1 windSum=-1 oppSum=0 windValue=1 oppValue=0
180SkOpSegment::debugShowActiveSpans id=7 (580.238281,594.114014 278.657715,594.114014) t=0 tEnd=1 windSum=-1 oppSum=0 windValue=1 oppValue=0
181SkOpSegment::debugShowActiveSpans id=8 (278.657715,594.114014 278.657715,593.602051) t=0 tEnd=0.00116788728 windSum=-1 oppSum=0 windValue=1 oppValue=0
182SkOpSegment::activeOp id=8 t=0.00116788728 tEnd=0 op=sect miFrom=0 miTo=0 suFrom=0 suTo=1 result=0
183SkOpSegment::markDone id=8 (278.657715,594.114014 278.657715,155.747314) t=0 [15] (278.657715,594.114014) tEnd=0.00116788728 newWindSum=-1 newOppSum=0 oppSum=0 windSum=-1 windValue=1 oppValue=0
184SkOpSegment::markDone id=7 (580.238281,594.114014 278.657715,594.114014) t=0 [13] (580.238281,594.114014) tEnd=1 newWindSum=-1 newOppSum=0 oppSum=0 windSum=-1 windValue=1 oppValue=0
185SkOpSegment::markDone id=6 (580.238281,155.747314 580.238281,594.114014) t=0 [11] (580.238281,155.747314) tEnd=1 newWindSum=-1 newOppSum=0 oppSum=0 windSum=-1 windValue=1 oppValue=0
Ben Wagner29380bd2017-10-09 14:43:00 -0400186</div>
187
Cary Clark1d314432018-07-10 10:57:54 -0400188<div id="filinmangust14">
189seg=1 {{{559.002686f, 551}, {559.002686f, 570}}}
190seg=2 {{{559.002686f, 570}, {558.997681f, 570}}}
191seg=3 {{{558.997681f, 570}, {558.997681f, 551}}}
192seg=4 {{{558.997681f, 551}, {559.002686f, 551}}}
193op union
194<empty>
195seg=5 {{{364, 759.997498f}, {3403.40015f, 759.997498f}}}
196seg=6 {{{3403.40015f, 759.997498f}, {3403.40015f, 760.002502f}}}
197seg=7 {{{3403.40015f, 760.002502f}, {364, 760.002502f}}}
198seg=8 {{{364, 760.002502f}, {364, 759.997498f}}}
199seg=9 {{{3403.39771f, 6099}, {3403.39771f, 760}}}
200seg=10 {{{3403.39771f, 760}, {3403.40259f, 760}}}
201seg=11 {{{3403.40259f, 760}, {3403.39771f, 6099}}}
202seg=12 {{{1274, 379.997498f}, {3403.40015f, 379.997498f}}}
203seg=13 {{{3403.40015f, 379.997498f}, {3403.40015f, 380.002502f}}}
204seg=14 {{{3403.40015f, 380.002502f}, {1274, 380.002502f}}}
205seg=15 {{{1274, 380.002502f}, {1274, 379.997498f}}}
206seg=16 {{{3403.39771f, 760}, {3403.39771f, 380}}}
207seg=17 {{{3403.39771f, 380}, {3403.40259f, 380}}}
208seg=18 {{{3403.40259f, 380}, {3403.40259f, 760}}}
209seg=19 {{{3403.40259f, 760}, {3403.39771f, 760}}}
210debugShowLineIntersection wtTs[0]=0 {{{3403.40015,379.997498}, {3403.40015,380.002502}}} {{3403.40015,379.997498}} wnTs[0]=1 {{{1274,379.997498}, {3403.40015,379.997498}}}
211debugShowLineIntersection wtTs[0]=1 {{{1274,380.002502}, {1274,379.997498}}} {{1274,379.997498}} wnTs[0]=0 {{{1274,379.997498}, {3403.40015,379.997498}}}
212debugShowLineIntersection wtTs[0]=0 {{{3403.40015,380.002502}, {1274,380.002502}}} {{3403.40015,380.002502}} wnTs[0]=1 {{{3403.40015,379.997498}, {3403.40015,380.002502}}}
213debugShowLineIntersection wtTs[0]=0 {{{1274,380.002502}, {1274,379.997498}}} {{1274,380.002502}} wnTs[0]=1 {{{3403.40015,380.002502}, {1274,380.002502}}}
214debugShowLineIntersection no intersect {{{3403.39771,760}, {3403.39771,380}}} {{{3403.40015,379.997498}, {3403.40015,380.002502}}}
215debugShowLineIntersection wtTs[0]=0.5 {{{3403.39771,380}, {3403.40259,380}}} {{3403.40015,380}} wnTs[0]=0.5 {{{3403.40015,379.997498}, {3403.40015,380.002502}}}
216debugShowLineIntersection no intersect {{{3403.40259,380}, {3403.40259,760}}} {{{3403.40015,379.997498}, {3403.40015,380.002502}}}
217debugShowLineIntersection wtTs[0]=0.999993415 {{{3403.39771,760}, {3403.39771,380}}} {{3403.39771,380.002502}} wnTs[0]=1.14652e-06 {{{3403.40015,380.002502}, {1274,380.002502}}}
218debugShowLineIntersection no intersect {{{3403.40259,380}, {3403.40259,760}}} {{{3403.40015,380.002502}, {1274,380.002502}}}
219debugShowLineIntersection wtTs[0]=0 {{{3403.39771,380}, {3403.40259,380}}} {{3403.39771,380}} wnTs[0]=1 {{{3403.39771,760}, {3403.39771,380}}}
220SkOpSegment::markDone id=13 (3403.40015,379.997498 3403.40015,380.002502) t=0 [25] (3403.40015,379.997498) tEnd=1 newWindSum=? newOppSum=? oppSum=? windSum=? windValue=1 oppValue=0
221debugShowLineIntersection wtTs[0]=1 {{{3403.40259,760}, {3403.39771,760}}} {{3403.39771,760}} wnTs[0]=0 {{{3403.39771,760}, {3403.39771,380}}}
222debugShowLineIntersection wtTs[0]=0 {{{3403.40259,380}, {3403.40259,760}}} {{3403.40259,380}} wnTs[0]=1 {{{3403.39771,380}, {3403.40259,380}}}
223debugShowLineIntersection wtTs[0]=0 {{{3403.40259,760}, {3403.39771,760}}} {{3403.40259,760}} wnTs[0]=1 {{{3403.40259,380}, {3403.40259,760}}}
224debugShowLineIntersection wtTs[0]=0.999999197 {{{364,759.997498}, {3403.40015,759.997498}}} {{3403.39771,759.997498}} wnTs[0]=6.58537e-06 {{{3403.39771,760}, {3403.39771,380}}}
225debugShowLineIntersection no intersect {{{3403.40015,759.997498}, {3403.40015,760.002502}}} {{{3403.39771,760}, {3403.39771,380}}}
226debugShowLineIntersection no intersect {{{364,759.997498}, {3403.40015,759.997498}}} {{{3403.40259,380}, {3403.40259,760}}}
227debugShowLineIntersection no intersect {{{3403.40015,759.997498}, {3403.40015,760.002502}}} {{{3403.40259,380}, {3403.40259,760}}}
228debugShowLineIntersection wtTs[0]=0.5 {{{3403.40015,759.997498}, {3403.40015,760.002502}}} {{3403.40015,760}} wnTs[0]=0.5 {{{3403.40259,760}, {3403.39771,760}}}
229debugShowLineIntersection wtTs[0]=1 {{{3403.39771,6099}, {3403.39771,760}}} {{3403.39771,760}} wnTs[0]=0 {{{3403.39771,760}, {3403.39771,380}}}
230debugShowLineIntersection wtTs[0]=0 {{{3403.39771,760}, {3403.40259,760}}} {{3403.39771,760}} wnTs[0]=0 {{{3403.39771,760}, {3403.39771,380}}}
231debugShowLineIntersection wtTs[0]=8.36411997e-13 {{{3403.40259,760}, {3403.39771,6099}}} {{3403.39771,760}} wnTs[0]=0 {{{3403.39771,760}, {3403.39771,380}}}
232debugShowLineIntersection wtTs[0]=1 {{{3403.39771,760}, {3403.40259,760}}} {{3403.40259,760}} wnTs[0]=1 {{{3403.40259,380}, {3403.40259,760}}}
233debugShowLineIntersection wtTs[0]=0 {{{3403.40259,760}, {3403.39771,6099}}} {{3403.40259,760}} wnTs[0]=1 {{{3403.40259,380}, {3403.40259,760}}}
234SkOpSegment::markDone id=10 (3403.39771,760 3403.40259,760) t=0 [19] (3403.39771,760) tEnd=1 newWindSum=? newOppSum=? oppSum=? windSum=? windValue=1 oppValue=0
235SkOpSegment::markDone id=19 (3403.40259,760 3403.39771,760) t=0 [37] (3403.40259,760) tEnd=1 newWindSum=? newOppSum=? oppSum=? windSum=? windValue=1 oppValue=0
236debugShowLineIntersection wtTs[0]=1 {{{3403.39771,6099}, {3403.39771,760}}} {{3403.39771,760}} wnTs[0]=1 {{{3403.40259,760}, {3403.39771,760}}}
237debugShowLineIntersection wtTs[0]=0 {{{3403.39771,760}, {3403.40259,760}}} {{3403.39771,760}} wtTs[1]=1 {{3403.40259,760}} wnTs[0]=1 {{{3403.40259,760}, {3403.39771,760}}} wnTs[1]=0
238debugShowLineIntersection wtTs[0]=0 {{{3403.40259,760}, {3403.39771,6099}}} {{3403.40259,760}} wnTs[0]=0 {{{3403.40259,760}, {3403.39771,760}}}
239debugShowLineIntersection wtTs[0]=0 {{{559.002686,570}, {558.997681,570}}} {{559.002686,570}} wnTs[0]=1 {{{559.002686,551}, {559.002686,570}}}
240debugShowLineIntersection wtTs[0]=1 {{{558.997681,551}, {559.002686,551}}} {{559.002686,551}} wnTs[0]=0 {{{559.002686,551}, {559.002686,570}}}
241debugShowLineIntersection wtTs[0]=0 {{{558.997681,570}, {558.997681,551}}} {{558.997681,570}} wnTs[0]=1 {{{559.002686,570}, {558.997681,570}}}
242debugShowLineIntersection wtTs[0]=0 {{{558.997681,551}, {559.002686,551}}} {{558.997681,551}} wnTs[0]=1 {{{558.997681,570}, {558.997681,551}}}
243debugShowLineIntersection wtTs[0]=0 {{{3403.40015,759.997498}, {3403.40015,760.002502}}} {{3403.40015,759.997498}} wnTs[0]=1 {{{364,759.997498}, {3403.40015,759.997498}}}
244debugShowLineIntersection wtTs[0]=1 {{{364,760.002502}, {364,759.997498}}} {{364,759.997498}} wnTs[0]=0 {{{364,759.997498}, {3403.40015,759.997498}}}
245debugShowLineIntersection wtTs[0]=0 {{{3403.40015,760.002502}, {364,760.002502}}} {{3403.40015,760.002502}} wnTs[0]=1 {{{3403.40015,759.997498}, {3403.40015,760.002502}}}
246debugShowLineIntersection wtTs[0]=0 {{{364,760.002502}, {364,759.997498}}} {{364,760.002502}} wnTs[0]=1 {{{3403.40015,760.002502}, {364,760.002502}}}
247debugShowLineIntersection no intersect {{{3403.39771,6099}, {3403.39771,760}}} {{{3403.40015,759.997498}, {3403.40015,760.002502}}}
248debugShowLineIntersection wtTs[0]=0.5 {{{3403.39771,760}, {3403.40259,760}}} {{3403.40015,760}} wnTs[0]=0.5 {{{3403.40015,759.997498}, {3403.40015,760.002502}}}
249debugShowLineIntersection wtTs[0]=4.68710178e-07 {{{3403.40259,760}, {3403.39771,6099}}} {{3403.40015,760.002502}} wnTs[0]=1 {{{3403.40015,759.997498}, {3403.40015,760.002502}}}
250SkOpSegment::markDone id=6 (3403.40015,759.997498 3403.40015,760.002502) t=0 [11] (3403.40015,759.997498) tEnd=1 newWindSum=? newOppSum=? oppSum=? windSum=? windValue=1 oppValue=0
251debugShowLineIntersection wtTs[0]=0.999999531 {{{3403.39771,6099}, {3403.39771,760}}} {{3403.39771,760.002502}} wnTs[0]=8.03253e-07 {{{3403.40015,760.002502}, {364,760.002502}}}
252debugShowLineIntersection wtTs[0]=4.68710178e-07 {{{3403.40259,760}, {3403.39771,6099}}} {{3403.40015,760.002502}} wnTs[0]=0 {{{3403.40015,760.002502}, {364,760.002502}}}
253debugShowLineIntersection wtTs[0]=0 {{{3403.39771,760}, {3403.40259,760}}} {{3403.39771,760}} wnTs[0]=1 {{{3403.39771,6099}, {3403.39771,760}}}
254debugShowLineIntersection wtTs[0]=8.36411997e-13 {{{3403.40259,760}, {3403.39771,6099}}} {{3403.39771,760}} wtTs[1]=1 {{3403.39771,6099}} wnTs[0]=1 {{{3403.39771,6099}, {3403.39771,760}}} wnTs[1]=0
255debugShowLineIntersection wtTs[0]=0 {{{3403.40259,760}, {3403.39771,6099}}} {{3403.40259,760}} wnTs[0]=1 {{{3403.39771,760}, {3403.40259,760}}}
256------------------x--x------x--------- addExpanded
25700: segment=13 MoveNearbyClearAll2
25801: segment=17 MoveNearbyClearAll2
25902: segment=19 MoveNearbyClearAll2
26003: segment=6 MoveNearbyClearAll2
26104: segment=10 MoveNearbyClearAll2
26205: seg/base=9/17 seg/base=11/21 MarkCoinStart
26306: seg/base=9/18 seg/base=11/22 MarkCoinEnd
264SkOpSegment::debugShowActiveSpans id=12 (1274,379.997498 3403.40015,379.997498) t=0 tEnd=1 windSum=? windValue=1
265SkOpSegment::debugShowActiveSpans id=14 (3403.40015,380.002502 1274,380.002502) t=0 tEnd=1 windSum=? windValue=1
266SkOpSegment::debugShowActiveSpans id=15 (1274,380.002502 1274,379.997498) t=0 tEnd=1 windSum=? windValue=1
267SkOpSegment::debugShowActiveSpans id=16 (3403.39771,760 3403.39771,380) t=0 tEnd=1 windSum=? windValue=1
268SkOpSegment::debugShowActiveSpans id=17 (3403.39771,380 3403.40259,380) t=0 tEnd=1 windSum=? windValue=1
269SkOpSegment::debugShowActiveSpans id=18 (3403.40259,380 3403.40259,760) t=0 tEnd=1 windSum=? windValue=1
270SkOpSegment::debugShowActiveSpans id=1 (559.002686,551 559.002686,570) t=0 tEnd=1 windSum=? windValue=1
271SkOpSegment::debugShowActiveSpans id=2 (559.002686,570 558.997681,570) t=0 tEnd=1 windSum=? windValue=1
272SkOpSegment::debugShowActiveSpans id=3 (558.997681,570 558.997681,551) t=0 tEnd=1 windSum=? windValue=1
273SkOpSegment::debugShowActiveSpans id=4 (558.997681,551 559.002686,551) t=0 tEnd=1 windSum=? windValue=1
274SkOpSegment::debugShowActiveSpans id=5 (364,759.997498 3403.40015,759.997498) t=0 tEnd=1 windSum=? windValue=1
275SkOpSegment::debugShowActiveSpans id=7 (3403.40015,760.002502 364,760.002502) t=0 tEnd=1 windSum=? windValue=1
276SkOpSegment::debugShowActiveSpans id=8 (364,760.002502 364,759.997498) t=0 tEnd=1 windSum=? windValue=1
277SkOpSegment::debugShowActiveSpans id=9 (3403.39771,6099 3403.39771,760) t=0 tEnd=1 windSum=? windValue=1
278SkOpSegment::debugShowActiveSpans id=11 (3403.40259,760 3403.39771,6099) t=0 tEnd=1 windSum=? windValue=1
279------------------x--x------x--------- move_multiples
28000: segment=13 MoveNearbyClearAll2
28101: segment=17 MoveNearbyClearAll2
28202: segment=19 MoveNearbyClearAll2
28303: segment=6 MoveNearbyClearAll2
28404: segment=10 MoveNearbyClearAll2
28505: seg/base=9/17 seg/base=11/21 MarkCoinStart
28606: seg/base=9/18 seg/base=11/22 MarkCoinEnd
287------------------x--x------x--------- move_nearby
28800: segment=13 MoveNearbyClearAll2
28901: segment=17 MoveNearbyClearAll2
29002: segment=19 MoveNearbyClearAll2
29103: segment=6 MoveNearbyClearAll2
29204: segment=10 MoveNearbyClearAll2
29305: seg/base=9/17 seg/base=11/21 MarkCoinStart
29406: seg/base=9/18 seg/base=11/22 MarkCoinEnd
295SkOpSegment::markDone id=17 (3403.39771,380 3403.40259,380) t=0 [33] (3403.39771,380) tEnd=1 newWindSum=? newOppSum=? oppSum=? windSum=? windValue=0 oppValue=0
296------------------x--x------x--------- correctEnds
29700: segment=13 MoveNearbyClearAll2
29801: segment=17 MoveNearbyClearAll2
29902: segment=19 MoveNearbyClearAll2
30003: segment=6 MoveNearbyClearAll2
30104: segment=10 MoveNearbyClearAll2
30205: seg/base=9/17 seg/base=11/21 MarkCoinStart
30306: seg/base=9/18 seg/base=11/22 MarkCoinEnd
304SkOpSegment::debugShowActiveSpans id=12 (1274,379.997498 3403.40015,379.997498) t=0 tEnd=1 windSum=? windValue=1
305SkOpSegment::debugShowActiveSpans id=14 (3403.40015,380.002502 1274,380.002502) t=0 tEnd=1 windSum=? windValue=1
306SkOpSegment::debugShowActiveSpans id=15 (1274,380.002502 1274,379.997498) t=0 tEnd=1 windSum=? windValue=1
307SkOpSegment::debugShowActiveSpans id=16 (3403.39771,760 3403.39771,380) t=0 tEnd=1 windSum=? windValue=1
308SkOpSegment::debugShowActiveSpans id=18 (3403.40259,380 3403.40259,760) t=0 tEnd=1 windSum=? windValue=1
309SkOpSegment::debugShowActiveSpans id=1 (559.002686,551 559.002686,570) t=0 tEnd=1 windSum=? windValue=1
310SkOpSegment::debugShowActiveSpans id=2 (559.002686,570 558.997681,570) t=0 tEnd=1 windSum=? windValue=1
311SkOpSegment::debugShowActiveSpans id=3 (558.997681,570 558.997681,551) t=0 tEnd=1 windSum=? windValue=1
312SkOpSegment::debugShowActiveSpans id=4 (558.997681,551 559.002686,551) t=0 tEnd=1 windSum=? windValue=1
313SkOpSegment::debugShowActiveSpans id=5 (364,759.997498 3403.40015,759.997498) t=0 tEnd=1 windSum=? windValue=1
314SkOpSegment::debugShowActiveSpans id=7 (3403.40015,760.002502 364,760.002502) t=0 tEnd=1 windSum=? windValue=1
315SkOpSegment::debugShowActiveSpans id=8 (364,760.002502 364,759.997498) t=0 tEnd=1 windSum=? windValue=1
316SkOpSegment::debugShowActiveSpans id=9 (3403.39771,6099 3403.39771,760) t=0 tEnd=1 windSum=? windValue=1
317SkOpSegment::debugShowActiveSpans id=11 (3403.40259,760 3403.39771,6099) t=0 tEnd=1 windSum=? windValue=1
318------------------x--x------x--------- addEndMovedSpans
31900: segment=13 MoveNearbyClearAll2
32001: segment=17 MoveNearbyClearAll2
32102: segment=19 MoveNearbyClearAll2
32203: segment=6 MoveNearbyClearAll2
32304: segment=10 MoveNearbyClearAll2
32405: seg/base=9/17 seg/base=11/21 MarkCoinStart
32506: seg/base=9/18 seg/base=11/22 MarkCoinEnd
326------------------x--x------x--------- expand
32700: segment=13 MoveNearbyClearAll2
32801: segment=17 MoveNearbyClearAll2
32902: segment=19 MoveNearbyClearAll2
33003: segment=6 MoveNearbyClearAll2
33104: segment=10 MoveNearbyClearAll2
33205: seg/base=9/17 seg/base=11/21 MarkCoinStart
33306: seg/base=9/18 seg/base=11/22 MarkCoinEnd
334------------------x--x------x--------- addExpanded
33500: segment=13 MoveNearbyClearAll2
33601: segment=17 MoveNearbyClearAll2
33702: segment=19 MoveNearbyClearAll2
33803: segment=6 MoveNearbyClearAll2
33904: segment=10 MoveNearbyClearAll2
34005: seg/base=9/17 seg/base=11/21 MarkCoinStart
34106: seg/base=9/18 seg/base=11/22 MarkCoinEnd
342------------------x--x------x--------- mark
34300: segment=13 MoveNearbyClearAll2
34401: segment=17 MoveNearbyClearAll2
34502: segment=19 MoveNearbyClearAll2
34603: segment=6 MoveNearbyClearAll2
34704: segment=10 MoveNearbyClearAll2
34805: seg/base=9/17 seg/base=11/21 MarkCoinStart
34906: seg/base=9/18 seg/base=11/22 MarkCoinEnd
350----------------------------x--------- missing_coincidence
35100: segment=13 MoveNearbyClearAll2
35201: segment=17 MoveNearbyClearAll2
35302: segment=19 MoveNearbyClearAll2
35403: segment=6 MoveNearbyClearAll2
35504: segment=10 MoveNearbyClearAll2
356----------------------------x--------- expand
35700: segment=13 MoveNearbyClearAll2
35801: segment=17 MoveNearbyClearAll2
35902: segment=19 MoveNearbyClearAll2
36003: segment=6 MoveNearbyClearAll2
36104: segment=10 MoveNearbyClearAll2
362----------------------------x--------- expand
36300: segment=13 MoveNearbyClearAll2
36401: segment=17 MoveNearbyClearAll2
36502: segment=19 MoveNearbyClearAll2
36603: segment=6 MoveNearbyClearAll2
36704: segment=10 MoveNearbyClearAll2
368----------------------------x--------- apply
36900: segment=13 MoveNearbyClearAll2
37001: segment=17 MoveNearbyClearAll2
37102: segment=19 MoveNearbyClearAll2
37203: segment=6 MoveNearbyClearAll2
37304: segment=10 MoveNearbyClearAll2
374SkOpSegment::markDone id=9 (3403.39771,6099 3403.39771,760) t=0 [17] (3403.39771,6099) tEnd=1 newWindSum=? newOppSum=? oppSum=? windSum=? windValue=0 oppValue=0
375SkOpSegment::markDone id=11 (3403.40259,760 3403.39771,6099) t=0 [21] (3403.40259,760) tEnd=1 newWindSum=? newOppSum=? oppSum=? windSum=? windValue=0 oppValue=0
376----------------------------x--------- findOverlaps
37700: segment=13 MoveNearbyClearAll2
37801: segment=17 MoveNearbyClearAll2
37902: segment=19 MoveNearbyClearAll2
38003: segment=6 MoveNearbyClearAll2
38104: segment=10 MoveNearbyClearAll2
382SkOpSegment::debugShowActiveSpans id=12 (1274,379.997498 3403.40015,379.997498) t=0 tEnd=1 windSum=? windValue=1
383SkOpSegment::debugShowActiveSpans id=14 (3403.40015,380.002502 1274,380.002502) t=0 tEnd=1 windSum=? windValue=1
384SkOpSegment::debugShowActiveSpans id=15 (1274,380.002502 1274,379.997498) t=0 tEnd=1 windSum=? windValue=1
385SkOpSegment::debugShowActiveSpans id=16 (3403.39771,760 3403.39771,380) t=0 tEnd=1 windSum=? windValue=1
386SkOpSegment::debugShowActiveSpans id=18 (3403.40259,380 3403.40259,760) t=0 tEnd=1 windSum=? windValue=1
387SkOpSegment::debugShowActiveSpans id=1 (559.002686,551 559.002686,570) t=0 tEnd=1 windSum=? windValue=1
388SkOpSegment::debugShowActiveSpans id=2 (559.002686,570 558.997681,570) t=0 tEnd=1 windSum=? windValue=1
389SkOpSegment::debugShowActiveSpans id=3 (558.997681,570 558.997681,551) t=0 tEnd=1 windSum=? windValue=1
390SkOpSegment::debugShowActiveSpans id=4 (558.997681,551 559.002686,551) t=0 tEnd=1 windSum=? windValue=1
391SkOpSegment::debugShowActiveSpans id=5 (364,759.997498 3403.40015,759.997498) t=0 tEnd=1 windSum=? windValue=1
392SkOpSegment::debugShowActiveSpans id=7 (3403.40015,760.002502 364,760.002502) t=0 tEnd=1 windSum=? windValue=1
393SkOpSegment::debugShowActiveSpans id=8 (364,760.002502 364,759.997498) t=0 tEnd=1 windSum=? windValue=1
394----------------------------x--------- calc_angles
39500: segment=13 MoveNearbyClearAll2
39601: segment=17 MoveNearbyClearAll2
39702: segment=19 MoveNearbyClearAll2
39803: segment=6 MoveNearbyClearAll2
39904: segment=10 MoveNearbyClearAll2
400SkOpSegment::sortAngles [12] tStart=1 [24]
401SkOpAngle::after [12/1] 15/15 tStart=1 tEnd=0 < [16/4] 23/23 tStart=1 tEnd=0 < [14/2] 15/15 tStart=0 tEnd=1 F 5
402SkOpAngle::afterPart {{{3403.39771,380}, {1273.99756,380}}} id=12
403SkOpAngle::afterPart {{{3403.39771,380}, {3403.39771,760}}} id=16
404SkOpAngle::afterPart {{{3403.39771,380}, {1273.99756,380}}} id=14
405SkOpSegment::sortAngles [14] tStart=0 [27]
406SkOpSegment::sortAngles [16] tStart=0 [31]
407SkOpAngle::after [16/3] 7/7 tStart=0 tEnd=1 < [7/7] 15/15 tStart=0 tEnd=1 < [18/5] 7/7 tStart=1 tEnd=0 F 5
408SkOpAngle::afterPart {{{3403.40015,760.002502}, {3403.40015,380.002502}}} id=16
409SkOpAngle::afterPart {{{3403.40015,760.002502}, {364,760.002502}}} id=7
410SkOpAngle::afterPart {{{3403.40015,760.002502}, {3403.40015,380.002502}}} id=18
411SkOpAngle::after [16/3] 7/7 tStart=0 tEnd=1 < [5/6] 15/15 tStart=1 tEnd=0 < [18/5] 7/7 tStart=1 tEnd=0 F 5
412SkOpAngle::afterPart {{{3403.40015,759.997498}, {3403.40015,379.997498}}} id=16
413SkOpAngle::afterPart {{{3403.40015,759.997498}, {364,759.997498}}} id=5
414SkOpAngle::afterPart {{{3403.40015,759.997498}, {3403.40015,379.997498}}} id=18
415SkOpAngle::after [18/5] 7/7 tStart=1 tEnd=0 < [5/6] 15/15 tStart=1 tEnd=0 < [7/7] 15/15 tStart=0 tEnd=1 T 7
416SkOpAngle::afterPart {{{3403.40015,759.997498}, {3403.40015,379.997498}}} id=18
417SkOpAngle::afterPart {{{3403.40015,759.997498}, {364,759.997498}}} id=5
418SkOpAngle::afterPart {{{3403.40015,759.997498}, {364,759.997498}}} id=7
419SkOpSegment::sortAngles [16] tStart=1 [32]
420SkOpSegment::sortAngles [18] tStart=1 [36]
421SkOpSegment::sortAngles [5] tStart=1 [10]
422SkOpSegment::sortAngles [7] tStart=0 [13]
423coinSpan - id=9 t=0 tEnd=1
424coinSpan + id=11 t=1 tEnd=0
425SkOpSpan::sortableTop dir=kTop seg=12 t=0.5 pt=(2338.7002,379.997498)
426SkOpSpan::sortableTop [0] valid=1 operand=1 span=23 ccw=1 seg=12 {{{1274, 379.997498f}, {3403.40015f, 379.997498f}}} t=0.5 pt=(2338.7002,379.997498) slope=(2129.40015,0)
427SkOpSegment::markWinding id=12 (1274,379.997498 3403.40015,379.997498) t=0 [23] (1274,379.997498) tEnd=1 newWindSum=-1 newOppSum=0 oppSum=0 windSum=-1 windValue=1 oppValue=0
428SkOpSegment::markWinding id=12 (1274,379.997498 3403.40015,379.997498) t=0 [23] (1274,379.997498) tEnd=1 newWindSum=-1 newOppSum=0 oppSum=0 windSum=-1 windValue=1 oppValue=0
429SkOpSegment::markWinding id=15 (1274,380.002502 1274,379.997498) t=0 [29] (1274,380.002502) tEnd=1 newWindSum=-1 newOppSum=0 oppSum=? windSum=? windValue=1 oppValue=0
430SkOpSegment::markWinding id=14 (3403.40015,380.002502 1274,380.002502) t=0 [27] (3403.40015,380.002502) tEnd=1 newWindSum=-1 newOppSum=0 oppSum=? windSum=? windValue=1 oppValue=0
431SkOpSegment::activeOp id=12 t=1 tEnd=0 op=union miFrom=0 miTo=0 suFrom=0 suTo=1 result=1
432SkOpSegment::findNextOp simple
433SkOpSegment::markDone id=12 (1274,379.997498 3403.40015,379.997498) t=0 [23] (1274,379.997498) tEnd=1 newWindSum=-1 newOppSum=0 oppSum=0 windSum=-1 windValue=1 oppValue=0
434bridgeOp current id=12 from=(3403.40015,379.997498) to=(1274,379.997498)
435SkOpSegment::findNextOp simple
436SkOpSegment::markDone id=15 (1274,380.002502 1274,379.997498) t=0 [29] (1274,380.002502) tEnd=1 newWindSum=-1 newOppSum=0 oppSum=0 windSum=-1 windValue=1 oppValue=0
437bridgeOp current id=15 from=(1274,379.997498) to=(1274,380.002502)
438path.moveTo(3403.40015,379.997498);
439path.lineTo(1274,379.997498);
440SkOpSegment::markDone id=14 (3403.40015,380.002502 1274,380.002502) t=0 [27] (3403.40015,380.002502) tEnd=1 newWindSum=-1 newOppSum=0 oppSum=0 windSum=-1 windValue=1 oppValue=0
441path.lineTo(1274,380.002502);
442SkOpSegment::debugShowActiveSpans id=16 (3403.39771,760 3403.39771,380) t=0 tEnd=1 windSum=? windValue=1
443SkOpSegment::debugShowActiveSpans id=18 (3403.40259,380 3403.40259,760) t=0 tEnd=1 windSum=? windValue=1
444SkOpSegment::debugShowActiveSpans id=1 (559.002686,551 559.002686,570) t=0 tEnd=1 windSum=? windValue=1
445SkOpSegment::debugShowActiveSpans id=2 (559.002686,570 558.997681,570) t=0 tEnd=1 windSum=? windValue=1
446SkOpSegment::debugShowActiveSpans id=3 (558.997681,570 558.997681,551) t=0 tEnd=1 windSum=? windValue=1
447SkOpSegment::debugShowActiveSpans id=4 (558.997681,551 559.002686,551) t=0 tEnd=1 windSum=? windValue=1
448SkOpSegment::debugShowActiveSpans id=5 (364,759.997498 3403.40015,759.997498) t=0 tEnd=1 windSum=? windValue=1
449SkOpSegment::debugShowActiveSpans id=7 (3403.40015,760.002502 364,760.002502) t=0 tEnd=1 windSum=? windValue=1
450SkOpSegment::debugShowActiveSpans id=8 (364,760.002502 364,759.997498) t=0 tEnd=1 windSum=? windValue=1
451SkOpSpan::sortableTop dir=kLeft seg=16 t=0.5 pt=(3403.39771,570)
452SkOpSpan::sortableTop [0] valid=0 operand=0 span=5 ccw=1 seg=3 {{{558.997681f, 570}, {558.997681f, 551}}} t=0 pt=(558.997681,570) slope=(0,0)
453SkOpSpan::sortableTop [1] valid=0 operand=0 span=-1 ccw=1 t=1 pt=(559.002686,570) slope=(0,0)
454SkOpSpan::sortableTop [2] valid=1 operand=1 span=31 ccw=1 seg=16 {{{3403.39771f, 760}, {3403.39771f, 380}}} t=0.5 pt=(3403.39771,570) slope=(0,-380)
455SkOpSpan::sortableTop dir=kLeft seg=18 t=0.5 pt=(3403.40259,570)
456SkOpSpan::sortableTop [0] valid=0 operand=0 span=5 ccw=1 seg=3 {{{558.997681f, 570}, {558.997681f, 551}}} t=0 pt=(558.997681,570) slope=(0,0)
457SkOpSpan::sortableTop [1] valid=0 operand=0 span=-1 ccw=1 t=1 pt=(559.002686,570) slope=(0,0)
458SkOpSpan::sortableTop [2] valid=1 operand=1 span=31 ccw=1 seg=16 {{{3403.39771f, 760}, {3403.39771f, 380}}} t=0.5 pt=(3403.39771,570) slope=(0,-380)
459SkOpSpan::sortableTop [3] valid=1 operand=1 span=35 ccw=0 seg=18 {{{3403.40259f, 380}, {3403.40259f, 760}}} t=0.5 pt=(3403.40259,570) slope=(0,380)
460SkOpSpan::sortableTop dir=kLeft seg=1 t=0.5 pt=(559.002686,560.5)
461SkOpSpan::sortableTop [0] valid=1 operand=0 span=5 ccw=1 seg=3 {{{558.997681f, 570}, {558.997681f, 551}}} t=0.5 pt=(558.997681,560.5) slope=(0,-19)
462SkOpSpan::sortableTop [1] valid=1 operand=0 span=1 ccw=0 seg=1 {{{559.002686f, 551}, {559.002686f, 570}}} t=0.5 pt=(559.002686,560.5) slope=(0,19)
463SkOpSegment::markWinding id=3 (558.997681,570 558.997681,551) t=0 [5] (558.997681,570) tEnd=1 newWindSum=-1 newOppSum=0 oppSum=0 windSum=-1 windValue=1 oppValue=0
464SkOpSegment::markWinding id=4 (558.997681,551 559.002686,551) t=0 [7] (558.997681,551) tEnd=1 newWindSum=-1 newOppSum=0 oppSum=? windSum=? windValue=1 oppValue=0
465SkOpSegment::markWinding id=1 (559.002686,551 559.002686,570) t=0 [1] (559.002686,551) tEnd=1 newWindSum=-1 newOppSum=0 oppSum=? windSum=? windValue=1 oppValue=0
466SkOpSegment::markWinding id=2 (559.002686,570 558.997681,570) t=0 [3] (559.002686,570) tEnd=1 newWindSum=-1 newOppSum=0 oppSum=? windSum=? windValue=1 oppValue=0
467SkOpSegment::markWinding id=3 (558.997681,570 558.997681,551) t=0 [5] (558.997681,570) tEnd=1 newWindSum=-1 newOppSum=0 oppSum=0 windSum=-1 windValue=1 oppValue=0
468SkOpSegment::activeOp id=1 t=1 tEnd=0 op=union miFrom=0 miTo=1 suFrom=0 suTo=0 result=1
469SkOpSegment::findNextOp simple
470SkOpSegment::markDone id=1 (559.002686,551 559.002686,570) t=0 [1] (559.002686,551) tEnd=1 newWindSum=-1 newOppSum=0 oppSum=0 windSum=-1 windValue=1 oppValue=0
471bridgeOp current id=1 from=(559.002686,570) to=(559.002686,551)
472SkOpSegment::findNextOp simple
473SkOpSegment::markDone id=4 (558.997681,551 559.002686,551) t=0 [7] (558.997681,551) tEnd=1 newWindSum=-1 newOppSum=0 oppSum=0 windSum=-1 windValue=1 oppValue=0
474bridgeOp current id=4 from=(559.002686,551) to=(558.997681,551)
475path.moveTo(559.002686,570);
476path.lineTo(559.002686,551);
477SkOpSegment::findNextOp simple
478SkOpSegment::markDone id=3 (558.997681,570 558.997681,551) t=0 [5] (558.997681,570) tEnd=1 newWindSum=-1 newOppSum=0 oppSum=0 windSum=-1 windValue=1 oppValue=0
479bridgeOp current id=3 from=(558.997681,551) to=(558.997681,570)
480path.lineTo(558.997681,551);
481SkOpSegment::findNextOp simple
482SkOpSegment::markDone id=2 (559.002686,570 558.997681,570) t=0 [3] (559.002686,570) tEnd=1 newWindSum=-1 newOppSum=0 oppSum=0 windSum=-1 windValue=1 oppValue=0
483bridgeOp current id=2 from=(558.997681,570) to=(559.002686,570)
484path.lineTo(558.997681,570);
485path.lineTo(559.002686,570);
486path.close();
487SkOpSegment::debugShowActiveSpans id=16 (3403.39771,760 3403.39771,380) t=0 tEnd=1 windSum=? windValue=1
488SkOpSegment::debugShowActiveSpans id=18 (3403.40259,380 3403.40259,760) t=0 tEnd=1 windSum=? windValue=1
489SkOpSegment::debugShowActiveSpans id=5 (364,759.997498 3403.40015,759.997498) t=0 tEnd=1 windSum=? windValue=1
490SkOpSegment::debugShowActiveSpans id=7 (3403.40015,760.002502 364,760.002502) t=0 tEnd=1 windSum=? windValue=1
491SkOpSegment::debugShowActiveSpans id=8 (364,760.002502 364,759.997498) t=0 tEnd=1 windSum=? windValue=1
492SkOpSpan::sortableTop dir=kTop seg=16 t=0.5 pt=(3403.39771,570)
493SkOpSpan::sortableTop [0] valid=1 operand=1 span=23 ccw=1 seg=12 {{{1274, 379.997498f}, {3403.40015f, 379.997498f}}} t=0.999998853 pt=(3403.39771,379.997498) slope=(2129.40015,0)
494SkOpSpan::sortableTop [1] valid=1 operand=1 span=27 ccw=0 seg=14 {{{3403.40015f, 380.002502f}, {1274, 380.002502f}}} t=1.146523e-06 pt=(3403.39771,380.002502) slope=(-2129.40015,0)
495SkOpSpan::sortableTop [2] valid=1 operand=1 span=31 ccw=0 seg=16 {{{3403.39771f, 760}, {3403.39771f, 380}}} t=0.5 pt=(3403.39771,570) slope=(0,-380)
496SkOpSegment::markWinding id=16 (3403.39771,760 3403.39771,380) t=0 [31] (3403.39771,760) tEnd=1 newWindSum=1 newOppSum=0 oppSum=0 windSum=1 windValue=1 oppValue=0
497SkOpSegment::markWinding id=16 (3403.39771,760 3403.39771,380) t=0 [31] (3403.39771,760) tEnd=1 newWindSum=1 newOppSum=0 oppSum=0 windSum=1 windValue=1 oppValue=0
498SkOpSegment::activeOp id=16 t=1 tEnd=0 op=union miFrom=0 miTo=0 suFrom=1 suTo=0 result=1
499SkOpSegment::markDone id=16 (3403.39771,760 3403.39771,380) t=0 [31] (3403.39771,760) tEnd=1 newWindSum=1 newOppSum=0 oppSum=0 windSum=1 windValue=1 oppValue=0
500SkOpSegment::debugShowActiveSpans id=18 (3403.40259,380 3403.40259,760) t=0 tEnd=1 windSum=? windValue=1
501SkOpSegment::debugShowActiveSpans id=5 (364,759.997498 3403.40015,759.997498) t=0 tEnd=1 windSum=? windValue=1
502SkOpSegment::debugShowActiveSpans id=7 (3403.40015,760.002502 364,760.002502) t=0 tEnd=1 windSum=? windValue=1
503SkOpSegment::debugShowActiveSpans id=8 (364,760.002502 364,759.997498) t=0 tEnd=1 windSum=? windValue=1
504SkOpSpan::sortableTop dir=kTop seg=18 t=0.5 pt=(3403.40259,570)
505SkOpSpan::sortableTop [0] valid=0 operand=0 span=-1 ccw=0 t=1 pt=(3403.40259,380) slope=(0,0)
506SkOpSpan::sortableTop [1] valid=1 operand=1 span=35 ccw=0 seg=18 {{{3403.40259f, 380}, {3403.40259f, 760}}} t=0.5 pt=(3403.40259,570) slope=(0,380)
507SkOpSpan::sortableTop dir=kTop seg=5 t=0.5 pt=(1883.70007,759.997498)
508SkOpSpan::sortableTop [0] valid=1 operand=1 span=23 ccw=1 seg=12 {{{1274, 379.997498f}, {3403.40015f, 379.997498f}}} t=0.286324801 pt=(1883.70007,379.997498) slope=(2129.40015,0)
509SkOpSpan::sortableTop [1] valid=1 operand=1 span=27 ccw=0 seg=14 {{{3403.40015f, 380.002502f}, {1274, 380.002502f}}} t=0.713675199 pt=(1883.70007,380.002502) slope=(-2129.40015,0)
510SkOpSpan::sortableTop [2] valid=1 operand=1 span=9 ccw=1 seg=5 {{{364, 759.997498f}, {3403.40015f, 759.997498f}}} t=0.5 pt=(1883.70007,759.997498) slope=(3039.40015,0)
511SkOpSegment::markWinding id=5 (364,759.997498 3403.40015,759.997498) t=0 [9] (364,759.997498) tEnd=1 newWindSum=-1 newOppSum=0 oppSum=0 windSum=-1 windValue=1 oppValue=0
512SkOpSegment::markWinding id=5 (364,759.997498 3403.40015,759.997498) t=0 [9] (364,759.997498) tEnd=1 newWindSum=-1 newOppSum=0 oppSum=0 windSum=-1 windValue=1 oppValue=0
513SkOpSegment::markWinding id=8 (364,760.002502 364,759.997498) t=0 [15] (364,760.002502) tEnd=1 newWindSum=-1 newOppSum=0 oppSum=? windSum=? windValue=1 oppValue=0
514SkOpSegment::markWinding id=7 (3403.40015,760.002502 364,760.002502) t=0 [13] (3403.40015,760.002502) tEnd=1 newWindSum=-1 newOppSum=0 oppSum=? windSum=? windValue=1 oppValue=0
515SkOpSegment::activeOp id=5 t=1 tEnd=0 op=union miFrom=0 miTo=0 suFrom=0 suTo=1 result=1
516SkOpSegment::findNextOp simple
517SkOpSegment::markDone id=5 (364,759.997498 3403.40015,759.997498) t=0 [9] (364,759.997498) tEnd=1 newWindSum=-1 newOppSum=0 oppSum=0 windSum=-1 windValue=1 oppValue=0
518bridgeOp current id=5 from=(3403.40015,759.997498) to=(364,759.997498)
519SkOpSegment::findNextOp simple
520SkOpSegment::markDone id=8 (364,760.002502 364,759.997498) t=0 [15] (364,760.002502) tEnd=1 newWindSum=-1 newOppSum=0 oppSum=0 windSum=-1 windValue=1 oppValue=0
521bridgeOp current id=8 from=(364,759.997498) to=(364,760.002502)
522path.moveTo(3403.40015,759.997498);
523path.lineTo(364,759.997498);
524SkOpSegment::markDone id=7 (3403.40015,760.002502 364,760.002502) t=0 [13] (3403.40015,760.002502) tEnd=1 newWindSum=-1 newOppSum=0 oppSum=0 windSum=-1 windValue=1 oppValue=0
525path.lineTo(364,760.002502);
526SkOpSegment::debugShowActiveSpans id=18 (3403.40259,380 3403.40259,760) t=0 tEnd=1 windSum=? windValue=1
527SkOpSpan::sortableTop dir=kLeft seg=18 t=0.25 pt=(3403.40259,475)
528SkOpSpan::sortableTop [0] valid=1 operand=1 span=31 ccw=1 seg=16 {{{3403.39771f, 760}, {3403.39771f, 380}}} t=0.75 pt=(3403.39771,475) slope=(0,-380)
529SkOpSpan::sortableTop [1] valid=1 operand=1 span=35 ccw=0 seg=18 {{{3403.40259f, 380}, {3403.40259f, 760}}} t=0.25 pt=(3403.40259,475) slope=(0,380)
530SkOpSegment::markWinding id=18 (3403.40259,380 3403.40259,760) t=0 [35] (3403.40259,380) tEnd=1 newWindSum=-1 newOppSum=0 oppSum=0 windSum=-1 windValue=1 oppValue=0
531SkOpSegment::markWinding id=18 (3403.40259,380 3403.40259,760) t=0 [35] (3403.40259,380) tEnd=1 newWindSum=-1 newOppSum=0 oppSum=0 windSum=-1 windValue=1 oppValue=0
532SkOpSegment::activeOp id=18 t=1 tEnd=0 op=union miFrom=0 miTo=0 suFrom=0 suTo=1 result=1
533SkOpSegment::markDone id=18 (3403.40259,380 3403.40259,760) t=0 [35] (3403.40259,380) tEnd=1 newWindSum=-1 newOppSum=0 oppSum=0 windSum=-1 windValue=1 oppValue=0
534</div>
535
caryclarkdac1d172014-06-17 05:15:38 -0700536</div>
537
538<script type="text/javascript">
539
caryclark55888e42016-07-18 10:01:36 -0700540 var testDivs = [
Cary Clark1d314432018-07-10 10:57:54 -0400541 filinmangust14,
Cary Clark3a4a3212018-06-06 15:22:08 -0400542 halbug,
caryclark30b9fdd2016-08-31 14:36:29 -0700543 ];
caryclarkdac1d172014-06-17 05:15:38 -0700544
545var decimal_places = 3; // make this 3 to show more precision
546
547var tests = [];
548var testLines = [];
549var testTitles = [];
550var testIndex = 0;
551var ctx;
552
553var xmin, xmax, focusXmin, focusXmax;
554var ymin, ymax, focusYmin, focusYmax;
555var scale;
556var mouseX, mouseY;
557var srcLeft, srcTop;
558var screenWidth, screenHeight;
caryclark1049f122015-04-20 08:31:59 -0700559var drawnPts, drawnLines, drawnQuads, drawnConics, drawnCubics;
caryclarkdac1d172014-06-17 05:15:38 -0700560var curveT = 0;
561
562var pt_labels = 2;
563var collect_bounds = false;
564var control_lines = 0;
565var curve_t = false;
566var debug_xy = 1;
567var focus_enabled = false;
568var focus_on_selection = false;
569var step_limit = 0;
570var draw_active = false;
571var draw_add = false;
572var draw_angle = 0;
caryclark624637c2015-05-11 07:21:27 -0700573var draw_coincidence = false;
caryclarkdac1d172014-06-17 05:15:38 -0700574var draw_deriviatives = 0;
Cary Clarkff114282016-12-14 11:56:16 -0500575var draw_direction = false;
caryclarkdac1d172014-06-17 05:15:38 -0700576var draw_hints = false;
caryclarkdac1d172014-06-17 05:15:38 -0700577var draw_id = false;
578var draw_intersection = 0;
579var draw_intersectT = false;
580var draw_legend = true;
581var draw_log = false;
582var draw_mark = false;
583var draw_midpoint = false;
584var draw_op = 0;
585var draw_sequence = false;
586var draw_sort = 0;
caryclark03b03ca2015-04-23 09:13:37 -0700587var draw_top = false;
caryclarkdac1d172014-06-17 05:15:38 -0700588var draw_path = 3;
589var draw_computed = 0;
590var retina_scale = !!window.devicePixelRatio;
591
592var activeCount = 0;
593var addCount = 0;
594var angleCount = 0;
caryclark624637c2015-05-11 07:21:27 -0700595var coinCount = 0;
caryclarkdac1d172014-06-17 05:15:38 -0700596var opCount = 0;
597var sectCount = 0;
598var sortCount = 0;
caryclark03b03ca2015-04-23 09:13:37 -0700599var topCount = 0;
caryclarkdac1d172014-06-17 05:15:38 -0700600var markCount = 0;
601var activeMax = 0;
602var addMax = 0;
603var angleMax = 0;
caryclark624637c2015-05-11 07:21:27 -0700604var coinMax = 0;
caryclarkdac1d172014-06-17 05:15:38 -0700605var sectMax = 0;
606var sectMax2 = 0;
607var sortMax = 0;
caryclark03b03ca2015-04-23 09:13:37 -0700608var topMax = 0;
caryclarkdac1d172014-06-17 05:15:38 -0700609var markMax = 0;
610var opMax = 0;
611var stepMax = 0;
612var lastIndex = 0;
613var hasPath = false;
caryclark26ad22a2015-10-16 09:03:38 -0700614var hasAlignedPath = false;
caryclarkdac1d172014-06-17 05:15:38 -0700615var hasComputedPath = false;
caryclark54359292015-03-26 07:52:43 -0700616var angleBetween = false;
617var afterIndex = 0;
caryclarkdac1d172014-06-17 05:15:38 -0700618
619var firstActiveSpan = -1;
620var logStart = -1;
621var logRange = 0;
622
623var SPAN_ID = 0;
624var SPAN_X1 = SPAN_ID + 1;
625var SPAN_Y1 = SPAN_X1 + 1;
626var SPAN_X2 = SPAN_Y1 + 1;
627var SPAN_Y2 = SPAN_X2 + 1;
caryclark1049f122015-04-20 08:31:59 -0700628
caryclark55888e42016-07-18 10:01:36 -0700629var SPAN_L_TX = SPAN_Y2 + 1;
caryclarkdac1d172014-06-17 05:15:38 -0700630var SPAN_L_TY = SPAN_L_TX + 1;
caryclark55888e42016-07-18 10:01:36 -0700631var SPAN_L_OTHER = SPAN_L_TY + 1;
caryclarkdac1d172014-06-17 05:15:38 -0700632var SPAN_L_OTHERT = SPAN_L_OTHER + 1;
633var SPAN_L_OTHERI = SPAN_L_OTHERT + 1;
634var SPAN_L_SUM = SPAN_L_OTHERI + 1;
635var SPAN_L_VAL = SPAN_L_SUM + 1;
636var SPAN_L_OPP = SPAN_L_VAL + 1;
637
638var SPAN_X3 = SPAN_Y2 + 1;
639var SPAN_Y3 = SPAN_X3 + 1;
caryclark1049f122015-04-20 08:31:59 -0700640
caryclark55888e42016-07-18 10:01:36 -0700641var SPAN_Q_TX = SPAN_Y3 + 1;
caryclarkdac1d172014-06-17 05:15:38 -0700642var SPAN_Q_TY = SPAN_Q_TX + 1;
caryclark55888e42016-07-18 10:01:36 -0700643var SPAN_Q_OTHER = SPAN_Q_TY + 1;
caryclarkdac1d172014-06-17 05:15:38 -0700644var SPAN_Q_OTHERT = SPAN_Q_OTHER + 1;
645var SPAN_Q_OTHERI = SPAN_Q_OTHERT + 1;
646var SPAN_Q_SUM = SPAN_Q_OTHERI + 1;
647var SPAN_Q_VAL = SPAN_Q_SUM + 1;
648var SPAN_Q_OPP = SPAN_Q_VAL + 1;
649
caryclark1049f122015-04-20 08:31:59 -0700650var SPAN_K_W = SPAN_Y3 + 1;
caryclark55888e42016-07-18 10:01:36 -0700651var SPAN_K_TX = SPAN_K_W + 1;
caryclark1049f122015-04-20 08:31:59 -0700652var SPAN_K_TY = SPAN_K_TX + 1;
caryclark55888e42016-07-18 10:01:36 -0700653var SPAN_K_OTHER = SPAN_K_TY + 1;
caryclark1049f122015-04-20 08:31:59 -0700654var SPAN_K_OTHERT = SPAN_K_OTHER + 1;
655var SPAN_K_OTHERI = SPAN_K_OTHERT + 1;
656var SPAN_K_SUM = SPAN_K_OTHERI + 1;
657var SPAN_K_VAL = SPAN_K_SUM + 1;
658var SPAN_K_OPP = SPAN_K_VAL + 1;
659
caryclarkdac1d172014-06-17 05:15:38 -0700660var SPAN_X4 = SPAN_Y3 + 1;
661var SPAN_Y4 = SPAN_X4 + 1;
caryclark1049f122015-04-20 08:31:59 -0700662
caryclark55888e42016-07-18 10:01:36 -0700663var SPAN_C_TX = SPAN_Y4 + 1;
caryclarkdac1d172014-06-17 05:15:38 -0700664var SPAN_C_TY = SPAN_C_TX + 1;
caryclark55888e42016-07-18 10:01:36 -0700665var SPAN_C_OTHER = SPAN_C_TY + 1;
caryclarkdac1d172014-06-17 05:15:38 -0700666var SPAN_C_OTHERT = SPAN_C_OTHER + 1;
667var SPAN_C_OTHERI = SPAN_C_OTHERT + 1;
668var SPAN_C_SUM = SPAN_C_OTHERI + 1;
669var SPAN_C_VAL = SPAN_C_SUM + 1;
670var SPAN_C_OPP = SPAN_C_VAL + 1;
671
672var ACTIVE_LINE_SPAN = 1;
673var ACTIVE_QUAD_SPAN = ACTIVE_LINE_SPAN + 1;
caryclark1049f122015-04-20 08:31:59 -0700674var ACTIVE_CONIC_SPAN = ACTIVE_QUAD_SPAN + 1;
675var ACTIVE_CUBIC_SPAN = ACTIVE_CONIC_SPAN + 1;
caryclarkdac1d172014-06-17 05:15:38 -0700676
677var ADD_MOVETO = ACTIVE_CUBIC_SPAN + 1;
678var ADD_LINETO = ADD_MOVETO + 1;
679var ADD_QUADTO = ADD_LINETO + 1;
caryclark1049f122015-04-20 08:31:59 -0700680var ADD_CONICTO = ADD_QUADTO + 1;
681var ADD_CUBICTO = ADD_CONICTO + 1;
caryclarkdac1d172014-06-17 05:15:38 -0700682var ADD_CLOSE = ADD_CUBICTO + 1;
683var ADD_FILL = ADD_CLOSE + 1;
684
685var PATH_LINE = ADD_FILL + 1;
686var PATH_QUAD = PATH_LINE + 1;
caryclark1049f122015-04-20 08:31:59 -0700687var PATH_CONIC = PATH_QUAD + 1;
688var PATH_CUBIC = PATH_CONIC + 1;
caryclarkdac1d172014-06-17 05:15:38 -0700689
690var INTERSECT_LINE = PATH_CUBIC + 1;
691var INTERSECT_LINE_2 = INTERSECT_LINE + 1;
692var INTERSECT_LINE_NO = INTERSECT_LINE_2 + 1;
693var INTERSECT_QUAD_LINE = INTERSECT_LINE_NO + 1;
694var INTERSECT_QUAD_LINE_2 = INTERSECT_QUAD_LINE + 1;
695var INTERSECT_QUAD_LINE_NO = INTERSECT_QUAD_LINE_2 + 1;
696var INTERSECT_QUAD = INTERSECT_QUAD_LINE_NO + 1;
697var INTERSECT_QUAD_2 = INTERSECT_QUAD + 1;
698var INTERSECT_QUAD_NO = INTERSECT_QUAD_2 + 1;
caryclark1049f122015-04-20 08:31:59 -0700699var INTERSECT_CONIC_LINE = INTERSECT_QUAD_NO + 1;
700var INTERSECT_CONIC_LINE_2 = INTERSECT_CONIC_LINE + 1;
701var INTERSECT_CONIC_LINE_NO = INTERSECT_CONIC_LINE_2 + 1;
caryclark55888e42016-07-18 10:01:36 -0700702var INTERSECT_CONIC_QUAD = INTERSECT_CONIC_LINE_NO + 1;
703var INTERSECT_CONIC_QUAD_2 = INTERSECT_CONIC_QUAD + 1;
caryclark6c3b9cd2016-09-26 05:36:58 -0700704var INTERSECT_CONIC_QUAD_3 = INTERSECT_CONIC_QUAD_2 + 1;
705var INTERSECT_CONIC_QUAD_4 = INTERSECT_CONIC_QUAD_3 + 1;
706var INTERSECT_CONIC_QUAD_NO = INTERSECT_CONIC_QUAD_4 + 1;
caryclark55888e42016-07-18 10:01:36 -0700707var INTERSECT_CONIC = INTERSECT_CONIC_QUAD_NO + 1;
caryclark1049f122015-04-20 08:31:59 -0700708var INTERSECT_CONIC_2 = INTERSECT_CONIC + 1;
709var INTERSECT_CONIC_NO = INTERSECT_CONIC_2 + 1;
710var INTERSECT_SELF_CUBIC = INTERSECT_CONIC_NO + 1;
caryclarkdac1d172014-06-17 05:15:38 -0700711var INTERSECT_SELF_CUBIC_NO = INTERSECT_SELF_CUBIC + 1;
712var INTERSECT_CUBIC_LINE = INTERSECT_SELF_CUBIC_NO + 1;
713var INTERSECT_CUBIC_LINE_2 = INTERSECT_CUBIC_LINE + 1;
714var INTERSECT_CUBIC_LINE_3 = INTERSECT_CUBIC_LINE_2 + 1;
715var INTERSECT_CUBIC_LINE_NO = INTERSECT_CUBIC_LINE_3 + 1;
716var INTERSECT_CUBIC_QUAD = INTERSECT_CUBIC_LINE_NO + 1;
717var INTERSECT_CUBIC_QUAD_2 = INTERSECT_CUBIC_QUAD + 1;
718var INTERSECT_CUBIC_QUAD_3 = INTERSECT_CUBIC_QUAD_2 + 1;
719var INTERSECT_CUBIC_QUAD_4 = INTERSECT_CUBIC_QUAD_3 + 1;
720var INTERSECT_CUBIC_QUAD_NO = INTERSECT_CUBIC_QUAD_4 + 1;
721var INTERSECT_CUBIC = INTERSECT_CUBIC_QUAD_NO + 1;
722var INTERSECT_CUBIC_2 = INTERSECT_CUBIC + 1;
723var INTERSECT_CUBIC_3 = INTERSECT_CUBIC_2 + 1;
724var INTERSECT_CUBIC_4 = INTERSECT_CUBIC_3 + 1;
725// FIXME: add cubic 5- 9
726var INTERSECT_CUBIC_NO = INTERSECT_CUBIC_4 + 1;
727
728var SORT_UNARY = INTERSECT_CUBIC_NO + 1;
729var SORT_BINARY = SORT_UNARY + 1;
730
731var OP_DIFFERENCE = SORT_BINARY + 1;
732var OP_INTERSECT = OP_DIFFERENCE + 1;
733var OP_UNION = OP_INTERSECT + 1;
734var OP_XOR = OP_UNION + 1;
735
736var MARK_LINE = OP_XOR + 1;
737var MARK_QUAD = MARK_LINE + 1;
caryclark1049f122015-04-20 08:31:59 -0700738var MARK_CONIC = MARK_QUAD + 1;
739var MARK_CUBIC = MARK_CONIC + 1;
caryclarkdac1d172014-06-17 05:15:38 -0700740var MARK_DONE_LINE = MARK_CUBIC + 1;
741var MARK_DONE_QUAD = MARK_DONE_LINE + 1;
caryclark1049f122015-04-20 08:31:59 -0700742var MARK_DONE_CONIC = MARK_DONE_QUAD + 1;
743var MARK_DONE_CUBIC = MARK_DONE_CONIC + 1;
caryclarkdac1d172014-06-17 05:15:38 -0700744var MARK_UNSORTABLE_LINE = MARK_DONE_CUBIC + 1;
745var MARK_UNSORTABLE_QUAD = MARK_UNSORTABLE_LINE + 1;
caryclark1049f122015-04-20 08:31:59 -0700746var MARK_UNSORTABLE_CONIC = MARK_UNSORTABLE_QUAD + 1;
747var MARK_UNSORTABLE_CUBIC = MARK_UNSORTABLE_CONIC + 1;
caryclarkdac1d172014-06-17 05:15:38 -0700748var MARK_SIMPLE_LINE = MARK_UNSORTABLE_CUBIC + 1;
749var MARK_SIMPLE_QUAD = MARK_SIMPLE_LINE + 1;
caryclark1049f122015-04-20 08:31:59 -0700750var MARK_SIMPLE_CONIC = MARK_SIMPLE_QUAD + 1;
751var MARK_SIMPLE_CUBIC = MARK_SIMPLE_CONIC + 1;
caryclarkdac1d172014-06-17 05:15:38 -0700752var MARK_SIMPLE_DONE_LINE = MARK_SIMPLE_CUBIC + 1;
753var MARK_SIMPLE_DONE_QUAD = MARK_SIMPLE_DONE_LINE + 1;
caryclark1049f122015-04-20 08:31:59 -0700754var MARK_SIMPLE_DONE_CONIC = MARK_SIMPLE_DONE_QUAD + 1;
755var MARK_SIMPLE_DONE_CUBIC = MARK_SIMPLE_DONE_CONIC + 1;
caryclarkdac1d172014-06-17 05:15:38 -0700756var MARK_DONE_UNARY_LINE = MARK_SIMPLE_DONE_CUBIC + 1;
757var MARK_DONE_UNARY_QUAD = MARK_DONE_UNARY_LINE + 1;
caryclark1049f122015-04-20 08:31:59 -0700758var MARK_DONE_UNARY_CONIC = MARK_DONE_UNARY_QUAD + 1;
759var MARK_DONE_UNARY_CUBIC = MARK_DONE_UNARY_CONIC + 1;
caryclarkdac1d172014-06-17 05:15:38 -0700760var MARK_ANGLE_LAST = MARK_DONE_UNARY_CUBIC + 1;
761
762var COMPUTED_SET_1 = MARK_ANGLE_LAST + 1;
763var COMPUTED_SET_2 = COMPUTED_SET_1 + 1;
764
caryclark624637c2015-05-11 07:21:27 -0700765var ANGLE_AFTER = COMPUTED_SET_2 + 1;
caryclark54359292015-03-26 07:52:43 -0700766var ANGLE_AFTERPART = ANGLE_AFTER + 1;
caryclarkdac1d172014-06-17 05:15:38 -0700767
caryclark54359292015-03-26 07:52:43 -0700768var ACTIVE_OP = ANGLE_AFTERPART + 1;
caryclarkdac1d172014-06-17 05:15:38 -0700769
caryclark624637c2015-05-11 07:21:27 -0700770var COIN_MAIN_SPAN = ACTIVE_OP + 1;
771var COIN_OPP_SPAN = COIN_MAIN_SPAN + 1;
772
773var FRAG_TYPE_LAST = COIN_OPP_SPAN;
caryclarkdac1d172014-06-17 05:15:38 -0700774
775var REC_TYPE_UNKNOWN = -1;
776var REC_TYPE_PATH = 0;
caryclark54359292015-03-26 07:52:43 -0700777var REC_TYPE_PATH2 = 1;
778var REC_TYPE_SECT = 2;
779var REC_TYPE_ACTIVE = 3;
780var REC_TYPE_ADD = 4;
781var REC_TYPE_SORT = 5;
782var REC_TYPE_OP = 6;
783var REC_TYPE_MARK = 7;
784var REC_TYPE_COMPUTED = 8;
785var REC_TYPE_COIN = 9;
786var REC_TYPE_ANGLE = 10;
787var REC_TYPE_ACTIVE_OP = 11;
788var REC_TYPE_AFTERPART = 12;
caryclark03b03ca2015-04-23 09:13:37 -0700789var REC_TYPE_TOP = 13;
caryclark624637c2015-05-11 07:21:27 -0700790var REC_TYPE_COINCIDENCE = 14;
caryclark26ad22a2015-10-16 09:03:38 -0700791var REC_TYPE_ALIGNED = 15;
792var REC_TYPE_LAST = REC_TYPE_ALIGNED;
caryclarkdac1d172014-06-17 05:15:38 -0700793
794function strs_to_nums(strs) {
795 var result = [];
796 for (var idx = 1; idx < strs.length; ++idx) {
797 var str = strs[idx];
798 var num = parseFloat(str);
799 if (isNaN(num)) {
800 result.push(str);
801 } else {
802 result.push(num);
803 }
804 }
805 return result;
806}
807
808function filter_str_by(id, str, regex, array) {
809 if (regex.test(str)) {
810 var strs = regex.exec(str);
811 var result = strs_to_nums(strs);
812 array.push(id);
813 array.push(result);
814 return true;
815 }
816 return false;
817}
818
819function construct_regexp2(pattern) {
820 var escape = pattern.replace(/[-/\\^$*+?.()|[\]{}]/g, '\\$&');
821 escape = escape.replace(/UNSORTABLE/g, "\\*\\*\\* UNSORTABLE \\*\\*\\*");
822 escape = escape.replace(/CUBIC_VAL/g, "\\(P_VAL P_VAL P_VAL P_VAL\\)");
caryclark1049f122015-04-20 08:31:59 -0700823 escape = escape.replace(/CONIC_VAL/g, "\\(P_VAL P_VAL P_VAL W_VAL\\)");
caryclarkdac1d172014-06-17 05:15:38 -0700824 escape = escape.replace(/QUAD_VAL/g, "\\(P_VAL P_VAL P_VAL\\)");
825 escape = escape.replace(/LINE_VAL/g, "\\(P_VAL P_VAL\\)");
826 escape = escape.replace(/FILL_TYPE/g, "SkPath::k[a-zA-Z]+_FillType");
caryclark54359292015-03-26 07:52:43 -0700827 escape = escape.replace(/PTR_VAL/g, "0x[0-9A-F]+");
caryclarkdac1d172014-06-17 05:15:38 -0700828 escape = escape.replace(/PT_VAL/g, "\\(P_VAL\\)");
829 escape = escape.replace(/P_VAL/g, "(-?\\d+\\.?\\d*(?:e-?\\d+)?)[Ff]?, ?(-?\\d+\\.?\\d*(?:e-?\\d+)?)[Ff]?");
830 escape = escape.replace(/T_VAL/g, "(-?\\d+\\.?\\d*(?:e-?\\d+)?)");
caryclark1049f122015-04-20 08:31:59 -0700831 escape = escape.replace(/W_VAL/g, "(-?\\d+\\.?\\d*(?:e-?\\d+)?)[Ff]?");
caryclarkdac1d172014-06-17 05:15:38 -0700832 escape = escape.replace(/PATH/g, "pathB?");
caryclark1049f122015-04-20 08:31:59 -0700833 escape = escape.replace(/IDX/g, "(-?\\d+)");
caryclarkdac1d172014-06-17 05:15:38 -0700834 escape = escape.replace(/NUM/g, "(-?\\d+)");
835 escape = escape.replace(/OPT/g, "(\\?|-?\\d+)");
836 return new RegExp(escape, 'i');
837}
838
839function construct_regexp2c(pattern) {
840 var escape = pattern.replace(/[-/\\^$*+?.()|[\]{}]/g, '\\$&');
841 escape = escape.replace(/UNSORTABLE/g, "\\*\\*\\* UNSORTABLE \\*\\*\\*");
caryclark54359292015-03-26 07:52:43 -0700842 escape = escape.replace(/CUBIC_VAL/g, "(?:\\$\\d = )?\\{\\{\\{P_VAL\\}, \\{P_VAL\\}, \\{P_VAL\\}, \\{P_VAL\\}\\}\\}");
caryclark1049f122015-04-20 08:31:59 -0700843 escape = escape.replace(/CONIC_VAL/g, "(?:\\$\\d = )?\\{\\{\\{\\{P_VAL\\}, \\{P_VAL\\}, \\{P_VAL\\}\\}\\}, W_VAL\\}");
caryclark54359292015-03-26 07:52:43 -0700844 escape = escape.replace(/QUAD_VAL/g, "(?:\\$\\d = )?\\{\\{\\{P_VAL\\}, \\{P_VAL\\}, \\{P_VAL\\}\\}\\}");
845 escape = escape.replace(/LINE_VAL/g, "(?:\\$\\d = )?\\{\\{\\{P_VAL\\}, \\{P_VAL\\}\\}\\}");
caryclarkdac1d172014-06-17 05:15:38 -0700846 escape = escape.replace(/FILL_TYPE/g, "SkPath::k[a-zA-Z]+_FillType");
caryclark54359292015-03-26 07:52:43 -0700847 escape = escape.replace(/PTR_VAL/g, "0x[0-9A-F]+");
caryclarkdac1d172014-06-17 05:15:38 -0700848 escape = escape.replace(/PT_VAL/g, "\\{\\{P_VAL\\}\\}");
caryclark54359292015-03-26 07:52:43 -0700849 escape = escape.replace(/P_VAL/g, "(?:f?[xX] = )?(-?\\d+\\.?\\d*(?:e-?\\d+)?)[Ff]?, *(?: f?[yY] = )?(-?\\d+\\.?\\d*(?:e-?\\d+)?)[Ff]?");
caryclarkdac1d172014-06-17 05:15:38 -0700850 escape = escape.replace(/T_VAL/g, "(-?\\d+\\.?\\d*(?:e-?\\d+)?)");
caryclark1049f122015-04-20 08:31:59 -0700851 escape = escape.replace(/W_VAL/g, "(-?\\d+\\.?\\d*(?:e-?\\d+)?)[Ff]?");
caryclarkdac1d172014-06-17 05:15:38 -0700852 escape = escape.replace(/OPER/g, "[a-z]+");
853 escape = escape.replace(/PATH/g, "pathB?");
854 escape = escape.replace(/T_F/g, "([TF])");
caryclark1049f122015-04-20 08:31:59 -0700855 escape = escape.replace(/IDX/g, "(-?\\d+)");
caryclarkdac1d172014-06-17 05:15:38 -0700856 escape = escape.replace(/NUM/g, "(-?\\d+)");
857 escape = escape.replace(/OPT/g, "(\\?|-?\\d+)");
858 return new RegExp(escape, 'i');
859}
860
861function match_regexp(str, lineNo, array, id, pattern) {
862 var regex = construct_regexp2(pattern);
863 if (filter_str_by(id, str, regex, array)) {
864 return true;
865 }
866 regex = construct_regexp2c(pattern);
867 return filter_str_by(id, str, regex, array);
868}
869
870function endsWith(str, suffix) {
871 return str.indexOf(suffix, str.length - suffix.length) !== -1;
872}
873
874function parse_all(test) {
875 var lines = test.match(/[^\r\n]+/g);
876 var records = []; // a rec can be the original paths, a set of intersections, a set of active spans, a sort, or a path add
877 var record = [];
878 var recType = REC_TYPE_UNKNOWN;
879 var lastLineNo;
880 var moveX, moveY;
881 for (var lineNo = 0; lineNo < lines.length; ++lineNo) {
882 var line = lines[lineNo];
883 if (line.length == 0) {
884 continue;
885 }
886 var opStart = "SkOpSegment::";
887 if (line.lastIndexOf(opStart, 0) === 0) {
888 line = line.substr(opStart.length);
889 }
890 var angleStart = "SkOpAngle::";
891 if (line.lastIndexOf(angleStart, 0) === 0) {
892 line = line.substr(angleStart.length);
893 }
caryclark624637c2015-05-11 07:21:27 -0700894 var coinStart = "SkOpCoincidence::";
895 if (line.lastIndexOf(coinStart, 0) === 0) {
896 line = line.substr(coinStart.length);
897 }
caryclark54359292015-03-26 07:52:43 -0700898 var type = line.lastIndexOf("debugShowActiveSpans", 0) === 0 ? REC_TYPE_ACTIVE
caryclark624637c2015-05-11 07:21:27 -0700899 : line.lastIndexOf("debugShowCoincidence", 0) === 0 ? REC_TYPE_COINCIDENCE
caryclark54359292015-03-26 07:52:43 -0700900 : line.lastIndexOf("((SkOpSegment*)", 0) === 0 ? REC_TYPE_PATH2
caryclark55888e42016-07-18 10:01:36 -0700901 : line.lastIndexOf("debugShowTs", 0) === 0 ? REC_TYPE_COIN
caryclark54359292015-03-26 07:52:43 -0700902 : line.lastIndexOf("afterPart", 0) === 0 ? REC_TYPE_AFTERPART
caryclarkdac1d172014-06-17 05:15:38 -0700903 : line.lastIndexOf("debugShow", 0) === 0 ? REC_TYPE_SECT
904 : line.lastIndexOf("activeOp", 0) === 0 ? REC_TYPE_ACTIVE_OP
905 : line.lastIndexOf("computed", 0) === 0 ? REC_TYPE_COMPUTED
906 : line.lastIndexOf("debugOne", 0) === 0 ? REC_TYPE_SORT
caryclark26ad22a2015-10-16 09:03:38 -0700907 : line.lastIndexOf("aligned=", 0) === 0 ? REC_TYPE_ALIGNED
caryclarkdac1d172014-06-17 05:15:38 -0700908 : line.lastIndexOf("dumpOne", 0) === 0 ? REC_TYPE_SORT
caryclark03b03ca2015-04-23 09:13:37 -0700909 : line.lastIndexOf("findTop", 0) === 0 ? REC_TYPE_TOP
caryclarkdac1d172014-06-17 05:15:38 -0700910 : line.lastIndexOf("pathB.", 0) === 0 ? REC_TYPE_ADD
911 : line.lastIndexOf("path.", 0) === 0 ? REC_TYPE_ADD
Cary Clark59d5a0e2017-01-23 14:38:52 +0000912 : line.lastIndexOf("after", 0) === 0 ? REC_TYPE_ANGLE
caryclarkdac1d172014-06-17 05:15:38 -0700913 : line.lastIndexOf("mark", 0) === 0 ? REC_TYPE_MARK
914 : line.lastIndexOf(" {{", 0) === 0 ? REC_TYPE_COMPUTED
caryclark54359292015-03-26 07:52:43 -0700915 : line.lastIndexOf("seg=", 0) === 0 ? REC_TYPE_PATH
caryclarkdac1d172014-06-17 05:15:38 -0700916 : line.lastIndexOf("op", 0) === 0 ? REC_TYPE_OP
917 : line.lastIndexOf("$", 0) === 0 ? REC_TYPE_PATH
918 : REC_TYPE_UNKNOWN;
919 if (recType != type || recType == REC_TYPE_ADD || recType == REC_TYPE_SECT
920 || recType == REC_TYPE_ACTIVE_OP || recType == REC_TYPE_ANGLE) {
921 if (recType != REC_TYPE_UNKNOWN) {
922 records.push(recType);
923 records.push(lastLineNo);
924 records.push(record);
925 }
926 record = [];
927 recType = type;
928 lastLineNo = lineNo;
929 }
930 var found = false;
931 switch (recType) {
932 case REC_TYPE_ACTIVE:
933 found = match_regexp(line, lineNo, record, ACTIVE_LINE_SPAN, "debugShowActiveSpans" +
caryclark55888e42016-07-18 10:01:36 -0700934" id=IDX LINE_VAL t=T_VAL tEnd=T_VAL windSum=OPT windValue=IDX"
caryclarkdac1d172014-06-17 05:15:38 -0700935 ) || match_regexp(line, lineNo, record, ACTIVE_QUAD_SPAN, "debugShowActiveSpans" +
caryclark55888e42016-07-18 10:01:36 -0700936" id=IDX QUAD_VAL t=T_VAL tEnd=T_VAL windSum=OPT windValue=IDX"
caryclark1049f122015-04-20 08:31:59 -0700937 ) || match_regexp(line, lineNo, record, ACTIVE_CONIC_SPAN, "debugShowActiveSpans" +
caryclark55888e42016-07-18 10:01:36 -0700938" id=IDX CONIC_VAL t=T_VAL tEnd=T_VAL windSum=OPT windValue=IDX"
caryclarkdac1d172014-06-17 05:15:38 -0700939 ) || match_regexp(line, lineNo, record, ACTIVE_CUBIC_SPAN, "debugShowActiveSpans" +
caryclark55888e42016-07-18 10:01:36 -0700940" id=IDX CUBIC_VAL t=T_VAL tEnd=T_VAL windSum=OPT windValue=IDX"
caryclark624637c2015-05-11 07:21:27 -0700941 ) || match_regexp(line, lineNo, record, ACTIVE_LINE_SPAN, "debugShowActiveSpans" +
caryclark55888e42016-07-18 10:01:36 -0700942" id=IDX LINE_VAL t=T_VAL tEnd=T_VAL windSum=OPT oppSum=OPT windValue=IDX oppValue=NUM"
caryclark624637c2015-05-11 07:21:27 -0700943 ) || match_regexp(line, lineNo, record, ACTIVE_QUAD_SPAN, "debugShowActiveSpans" +
caryclark55888e42016-07-18 10:01:36 -0700944" id=IDX QUAD_VAL t=T_VAL tEnd=T_VAL windSum=OPT oppSum=OPT windValue=IDX oppValue=NUM"
caryclark624637c2015-05-11 07:21:27 -0700945 ) || match_regexp(line, lineNo, record, ACTIVE_CONIC_SPAN, "debugShowActiveSpans" +
caryclark55888e42016-07-18 10:01:36 -0700946" id=IDX CONIC_VAL t=T_VAL tEnd=T_VAL windSum=OPT oppSum=OPT windValue=IDX oppValue=NUM"
caryclark624637c2015-05-11 07:21:27 -0700947 ) || match_regexp(line, lineNo, record, ACTIVE_CUBIC_SPAN, "debugShowActiveSpans" +
caryclark55888e42016-07-18 10:01:36 -0700948" id=IDX CUBIC_VAL t=T_VAL tEnd=T_VAL windSum=OPT oppSum=OPT windValue=IDX oppValue=NUM"
caryclarkdac1d172014-06-17 05:15:38 -0700949 );
950 break;
951 case REC_TYPE_ACTIVE_OP:
952 found = match_regexp(line, lineNo, record, ACTIVE_OP, "activeOp" +
953" id=IDX t=T_VAL tEnd=T_VAL op=OPER miFrom=NUM miTo=NUM suFrom=NUM suTo=NUM result=IDX"
954 );
955 break;
956 case REC_TYPE_ADD:
957 if (match_regexp(line, lineNo, record, ADD_MOVETO, "PATH.moveTo(P_VAL);")) {
958 moveX = record[1][0];
959 moveY = record[1][1];
960 found = true;
961 } else if (match_regexp(line, lineNo, record, ADD_LINETO, "PATH.lineTo(P_VAL);")) {
962 record[1].unshift(moveY);
963 record[1].unshift(moveX);
964 moveX = record[1][2];
965 moveY = record[1][3];
966 found = true;
967 } else if (match_regexp(line, lineNo, record, ADD_QUADTO, "PATH.quadTo(P_VAL, P_VAL);")) {
968 record[1].unshift(moveY);
969 record[1].unshift(moveX);
970 moveX = record[1][4];
971 moveY = record[1][5];
972 found = true;
caryclark1049f122015-04-20 08:31:59 -0700973 } else if (match_regexp(line, lineNo, record, ADD_CONICTO, "PATH.conicTo(P_VAL, P_VAL, T_VAL);")) {
974 record[1].unshift(moveY);
975 record[1].unshift(moveX);
976 moveX = record[1][4];
977 moveY = record[1][5];
978 found = true;
caryclarkdac1d172014-06-17 05:15:38 -0700979 } else if (match_regexp(line, lineNo, record, ADD_CUBICTO, "PATH.cubicTo(P_VAL, P_VAL, P_VAL);")) {
980 record[1].unshift(moveY);
981 record[1].unshift(moveX);
982 moveX = record[1][6];
983 moveY = record[1][7];
984 found = true;
985 } else if (match_regexp(line, lineNo, record, ADD_FILL, "PATH.setFillType(FILL_TYPE);")) {
986 found = true;
987 } else {
988 found = match_regexp(line, lineNo, record, ADD_CLOSE, "PATH.close();");
989 }
990 break;
caryclark54359292015-03-26 07:52:43 -0700991 case REC_TYPE_AFTERPART:
Cary Clarkff114282016-12-14 11:56:16 -0500992 found = match_regexp(line, lineNo, record, PATH_LINE, "afterPart LINE_VAL id=IDX")
993 || match_regexp(line, lineNo, record, PATH_QUAD, "afterPart QUAD_VAL id=IDX")
994 || match_regexp(line, lineNo, record, PATH_CONIC, "afterPart CONIC_VAL id=IDX")
995 || match_regexp(line, lineNo, record, PATH_CUBIC, "afterPart CUBIC_VAL id=IDX")
caryclark54359292015-03-26 07:52:43 -0700996 break;
caryclark26ad22a2015-10-16 09:03:38 -0700997 case REC_TYPE_ALIGNED:
998 found = match_regexp(line, lineNo, record, PATH_LINE, "aligned=IDX LINE_VAL"
999 ) || match_regexp(line, lineNo, record, PATH_QUAD, "aligned=IDX QUAD_VAL"
1000 ) || match_regexp(line, lineNo, record, PATH_CONIC, "aligned=IDX CONIC_VAL"
1001 ) || match_regexp(line, lineNo, record, PATH_CUBIC, "aligned=IDX CUBIC_VAL"
1002 );
1003 break;
caryclarkdac1d172014-06-17 05:15:38 -07001004 case REC_TYPE_ANGLE:
Cary Clark59d5a0e2017-01-23 14:38:52 +00001005 found = match_regexp(line, lineNo, record, ANGLE_AFTER, "after " +
caryclarkdac1d172014-06-17 05:15:38 -07001006"[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");
1007 break;
1008 case REC_TYPE_COIN:
1009 found = true;
1010 break;
caryclark624637c2015-05-11 07:21:27 -07001011 case REC_TYPE_COINCIDENCE:
1012 found = match_regexp(line, lineNo, record, COIN_MAIN_SPAN, "debugShowCoincidence" +
1013" + id=IDX t=T_VAL tEnd=T_VAL"
1014 ) || match_regexp(line, lineNo, record, COIN_OPP_SPAN, "debugShowCoincidence" +
1015" - id=IDX t=T_VAL tEnd=T_VAL"
1016 );
1017 break;
caryclarkdac1d172014-06-17 05:15:38 -07001018 case REC_TYPE_COMPUTED:
1019 found = line == "computed quadratics given"
1020 || match_regexp(line, lineNo, record, COMPUTED_SET_1, "computed quadratics set 1"
1021 ) || match_regexp(line, lineNo, record, COMPUTED_SET_2, "computed quadratics set 2"
1022 ) || match_regexp(line, lineNo, record, PATH_QUAD, " QUAD_VAL,"
caryclark1049f122015-04-20 08:31:59 -07001023 ) || match_regexp(line, lineNo, record, PATH_CONIC, " CONIC_VAL,"
caryclarkdac1d172014-06-17 05:15:38 -07001024 ) || match_regexp(line, lineNo, record, PATH_CUBIC, " CUBIC_VAL,"
1025 );
1026 break;
1027 case REC_TYPE_PATH:
caryclark54359292015-03-26 07:52:43 -07001028 found = match_regexp(line, lineNo, record, PATH_LINE, "seg=IDX LINE_VAL"
1029 ) || match_regexp(line, lineNo, record, PATH_QUAD, "seg=IDX QUAD_VAL"
caryclark1049f122015-04-20 08:31:59 -07001030 ) || match_regexp(line, lineNo, record, PATH_CONIC, "seg=IDX CONIC_VAL"
caryclark54359292015-03-26 07:52:43 -07001031 ) || match_regexp(line, lineNo, record, PATH_CUBIC, "seg=IDX CUBIC_VAL"
1032 );
1033 break;
1034 case REC_TYPE_PATH2:
1035 found = match_regexp(line, lineNo, record, PATH_LINE, "((SkOpSegment*) PTR_VAL) [IDX] {LINE_VAL}"
1036 ) || match_regexp(line, lineNo, record, PATH_QUAD, "((SkOpSegment*) PTR_VAL) [IDX] {QUAD_VAL}"
caryclark1049f122015-04-20 08:31:59 -07001037 ) || match_regexp(line, lineNo, record, PATH_CONIC, "((SkOpSegment*) PTR_VAL) [IDX] {CONIC_VAL}"
caryclark54359292015-03-26 07:52:43 -07001038 ) || match_regexp(line, lineNo, record, PATH_CUBIC, "((SkOpSegment*) PTR_VAL) [IDX] {CUBIC_VAL}"
caryclarkdac1d172014-06-17 05:15:38 -07001039 );
1040 break;
1041 case REC_TYPE_SECT:
1042 found = match_regexp(line, lineNo, record, INTERSECT_LINE, "debugShowLineIntersection" +
1043" wtTs[0]=T_VAL LINE_VAL PT_VAL wnTs[0]=T_VAL LINE_VAL"
1044 ) || match_regexp(line, lineNo, record, INTERSECT_LINE_2, "debugShowLineIntersection" +
1045" wtTs[0]=T_VAL LINE_VAL PT_VAL wtTs[1]=T_VAL PT_VAL wnTs[0]=T_VAL LINE_VAL wnTs[1]=T_VAL"
1046 ) || match_regexp(line, lineNo, record, INTERSECT_LINE_NO, "debugShowLineIntersection" +
1047" no intersect LINE_VAL LINE_VAL"
1048 ) || match_regexp(line, lineNo, record, INTERSECT_QUAD_LINE, "debugShowQuadLineIntersection" +
1049" wtTs[0]=T_VAL QUAD_VAL PT_VAL wnTs[0]=T_VAL LINE_VAL"
1050 ) || match_regexp(line, lineNo, record, INTERSECT_QUAD_LINE_2, "debugShowQuadLineIntersection" +
1051" wtTs[0]=T_VAL QUAD_VAL PT_VAL wtTs[1]=T_VAL PT_VAL wnTs[0]=T_VAL LINE_VAL wnTs[1]=T_VAL"
1052 ) || match_regexp(line, lineNo, record, INTERSECT_QUAD_LINE_NO, "debugShowQuadLineIntersection" +
1053" no intersect QUAD_VAL LINE_VAL"
1054 ) || match_regexp(line, lineNo, record, INTERSECT_QUAD, "debugShowQuadIntersection" +
1055" wtTs[0]=T_VAL QUAD_VAL PT_VAL wnTs[0]=T_VAL QUAD_VAL"
1056 ) || match_regexp(line, lineNo, record, INTERSECT_QUAD_2, "debugShowQuadIntersection" +
1057" wtTs[0]=T_VAL QUAD_VAL PT_VAL wtTs[1]=T_VAL PT_VAL wnTs[0]=T_VAL QUAD_VAL wnTs[1]=T_VAL"
1058 ) || match_regexp(line, lineNo, record, INTERSECT_QUAD_NO, "debugShowQuadIntersection" +
1059" no intersect QUAD_VAL QUAD_VAL"
caryclark55888e42016-07-18 10:01:36 -07001060
caryclark1049f122015-04-20 08:31:59 -07001061 ) || match_regexp(line, lineNo, record, INTERSECT_CONIC_LINE, "debugShowConicLineIntersection" +
1062" wtTs[0]=T_VAL CONIC_VAL PT_VAL wnTs[0]=T_VAL LINE_VAL"
1063 ) || match_regexp(line, lineNo, record, INTERSECT_CONIC_LINE_2, "debugShowConicLineIntersection" +
1064" wtTs[0]=T_VAL CONIC_VAL PT_VAL wtTs[1]=T_VAL PT_VAL wnTs[0]=T_VAL LINE_VAL wnTs[1]=T_VAL"
1065 ) || match_regexp(line, lineNo, record, INTERSECT_CONIC_LINE_NO, "debugShowConicLineIntersection" +
1066" no intersect CONIC_VAL LINE_VAL"
caryclark55888e42016-07-18 10:01:36 -07001067
1068 ) || match_regexp(line, lineNo, record, INTERSECT_CONIC_QUAD, "debugShowConicQuadIntersection" +
1069" wtTs[0]=T_VAL CONIC_VAL PT_VAL wnTs[0]=T_VAL QUAD_VAL"
1070 ) || match_regexp(line, lineNo, record, INTERSECT_CONIC_QUAD_2, "debugShowConicQuadIntersection" +
1071" wtTs[0]=T_VAL CONIC_VAL PT_VAL wtTs[1]=T_VAL PT_VAL wnTs[0]=T_VAL QUAD_VAL wnTs[1]=T_VAL"
caryclark6c3b9cd2016-09-26 05:36:58 -07001072 ) || match_regexp(line, lineNo, record, INTERSECT_CONIC_QUAD_3, "debugShowConicQuadIntersection" +
1073" 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"
1074 ) || match_regexp(line, lineNo, record, INTERSECT_CONIC_QUAD_4, "debugShowConicQuadIntersection" +
1075" 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"
caryclark55888e42016-07-18 10:01:36 -07001076 ) || match_regexp(line, lineNo, record, INTERSECT_CONIC_QUAD_NO, "debugShowConicQuadIntersection" +
1077" no intersect CONIC_VAL QUAD_VAL"
1078
caryclark1049f122015-04-20 08:31:59 -07001079 ) || match_regexp(line, lineNo, record, INTERSECT_CONIC, "debugShowConicIntersection" +
1080" wtTs[0]=T_VAL CONIC_VAL PT_VAL wnTs[0]=T_VAL CONIC_VAL"
1081 ) || match_regexp(line, lineNo, record, INTERSECT_CONIC_2, "debugShowConicIntersection" +
1082" wtTs[0]=T_VAL CONIC_VAL PT_VAL wtTs[1]=T_VAL PT_VAL wnTs[0]=T_VAL CONIC_VAL wnTs[1]=T_VAL"
1083 ) || match_regexp(line, lineNo, record, INTERSECT_CONIC_NO, "debugShowConicIntersection" +
1084" no intersect CONIC_VAL CONIC_VAL"
caryclarkdac1d172014-06-17 05:15:38 -07001085 ) || match_regexp(line, lineNo, record, INTERSECT_CUBIC_LINE, "debugShowCubicLineIntersection" +
1086" wtTs[0]=T_VAL CUBIC_VAL PT_VAL wnTs[0]=T_VAL LINE_VAL"
1087 ) || match_regexp(line, lineNo, record, INTERSECT_CUBIC_LINE_2, "debugShowCubicLineIntersection" +
1088" wtTs[0]=T_VAL CUBIC_VAL PT_VAL wtTs[1]=T_VAL PT_VAL wnTs[0]=T_VAL LINE_VAL wnTs[1]=T_VAL"
1089 ) || match_regexp(line, lineNo, record, INTERSECT_CUBIC_LINE_3, "debugShowCubicLineIntersection" +
1090" 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"
1091 ) || match_regexp(line, lineNo, record, INTERSECT_CUBIC_LINE_NO, "debugShowCubicLineIntersection" +
1092" no intersect CUBIC_VAL LINE_VAL"
1093 ) || match_regexp(line, lineNo, record, INTERSECT_CUBIC_QUAD, "debugShowCubicQuadIntersection" +
1094" wtTs[0]=T_VAL CUBIC_VAL PT_VAL wnTs[0]=T_VAL QUAD_VAL"
1095 ) || match_regexp(line, lineNo, record, INTERSECT_CUBIC_QUAD_2, "debugShowCubicQuadIntersection" +
1096" wtTs[0]=T_VAL CUBIC_VAL PT_VAL wtTs[1]=T_VAL PT_VAL wnTs[0]=T_VAL QUAD_VAL wnTs[1]=T_VAL"
1097 ) || match_regexp(line, lineNo, record, INTERSECT_CUBIC_QUAD_3, "debugShowCubicQuadIntersection" +
1098" 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"
1099 ) || match_regexp(line, lineNo, record, INTERSECT_CUBIC_QUAD_4, "debugShowCubicQuadIntersection" +
1100" 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"
1101 ) || match_regexp(line, lineNo, record, INTERSECT_CUBIC_QUAD_NO, "debugShowCubicQuadIntersection" +
1102" no intersect CUBIC_VAL QUAD_VAL"
1103 ) || match_regexp(line, lineNo, record, INTERSECT_CUBIC, "debugShowCubicIntersection" +
1104" wtTs[0]=T_VAL CUBIC_VAL PT_VAL wnTs[0]=T_VAL CUBIC_VAL"
1105 ) || match_regexp(line, lineNo, record, INTERSECT_CUBIC_2, "debugShowCubicIntersection" +
1106" wtTs[0]=T_VAL CUBIC_VAL PT_VAL wtTs[1]=T_VAL PT_VAL wnTs[0]=T_VAL CUBIC_VAL wnTs[1]=T_VAL"
1107 ) || match_regexp(line, lineNo, record, INTERSECT_CUBIC_3, "debugShowCubicIntersection" +
1108" 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"
1109 ) || match_regexp(line, lineNo, record, INTERSECT_CUBIC_4, "debugShowCubicIntersection" +
1110" 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"
1111 ) || match_regexp(line, lineNo, record, INTERSECT_CUBIC_NO, "debugShowCubicIntersection" +
1112" no intersect CUBIC_VAL CUBIC_VAL"
1113 ) || match_regexp(line, lineNo, record, INTERSECT_SELF_CUBIC, "debugShowCubicIntersection" +
1114" wtTs[0]=T_VAL CUBIC_VAL PT_VAL wtTs[1]=T_VAL"
1115 ) || match_regexp(line, lineNo, record, INTERSECT_SELF_CUBIC_NO, "debugShowCubicIntersection" +
1116" no self intersect CUBIC_VAL"
1117 );
1118 break;
1119 case REC_TYPE_SORT:
1120 var hasDone = / done/.test(line);
1121 var hasUnorderable = / unorderable/.test(line);
1122 var hasSmall = / small/.test(line);
1123 var hasTiny = / tiny/.test(line);
1124 var hasOperand = / operand/.test(line);
1125 var hasStop = / stop/.test(line);
1126 line.replace(/[ a-z]+$/, "");
1127 found = match_regexp(line, lineNo, record, SORT_UNARY, "debugOne" +
1128" [IDX/IDX] next=IDX/IDX sect=IDX/IDX s=T_VAL [IDX] e=T_VAL [IDX] sgn=NUM windVal=IDX windSum=OPT"
1129 ) || match_regexp(line, lineNo, record, SORT_BINARY, "debugOne" +
1130" [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"
1131 ) || match_regexp(line, lineNo, record, SORT_UNARY, "dumpOne" +
1132" [IDX/IDX] next=IDX/IDX sect=NUM/NUM s=T_VAL [IDX] e=T_VAL [IDX] sgn=NUM windVal=IDX windSum=OPT"
1133 ) || match_regexp(line, lineNo, record, SORT_BINARY, "dumpOne" +
1134" [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"
1135 );
1136 if (found) {
1137 record[1].push(hasDone);
1138 record[1].push(hasUnorderable);
1139 record[1].push(hasSmall);
1140 record[1].push(hasTiny);
1141 record[1].push(hasOperand);
1142 record[1].push(hasStop);
1143 }
1144 break;
caryclark03b03ca2015-04-23 09:13:37 -07001145 case REC_TYPE_TOP:
1146 found = match_regexp(line, lineNo, record, ACTIVE_OP, "findTop" +
1147" id=IDX s=T_VAL e=T_VAL cw=NUM swap=NUM inflections=NUM monotonic=NUM"
1148 ) || 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 );
1153 break;
caryclarkdac1d172014-06-17 05:15:38 -07001154 case REC_TYPE_MARK:
1155 found = match_regexp(line, lineNo, record, MARK_LINE, "markWinding" +
caryclark54359292015-03-26 07:52:43 -07001156" id=IDX LINE_VAL t=T_VAL [IDX] PT_VAL tEnd=T_VAL newWindSum=NUM newOppSum=OPT oppSum=OPT windSum=OPT windValue=IDX"
caryclarkdac1d172014-06-17 05:15:38 -07001157 ) || match_regexp(line, lineNo, record, MARK_QUAD, "markWinding" +
caryclark54359292015-03-26 07:52:43 -07001158" id=IDX QUAD_VAL t=T_VAL [IDX] PT_VAL tEnd=T_VAL newWindSum=NUM newOppSum=OPT oppSum=OPT windSum=OPT windValue=IDX"
caryclark1049f122015-04-20 08:31:59 -07001159 ) || match_regexp(line, lineNo, record, MARK_CONIC, "markWinding" +
1160" id=IDX CONIC_VAL t=T_VAL [IDX] PT_VAL tEnd=T_VAL newWindSum=NUM newOppSum=OPT oppSum=OPT windSum=OPT windValue=IDX"
caryclarkdac1d172014-06-17 05:15:38 -07001161 ) || match_regexp(line, lineNo, record, MARK_CUBIC, "markWinding" +
caryclark54359292015-03-26 07:52:43 -07001162" id=IDX CUBIC_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_DONE_LINE, "markDone" +
1164" 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"
1165 ) || match_regexp(line, lineNo, record, MARK_DONE_QUAD, "markDone" +
1166" 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"
caryclark1049f122015-04-20 08:31:59 -07001167 ) || match_regexp(line, lineNo, record, MARK_DONE_CONIC, "markDone" +
1168" 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"
caryclark54359292015-03-26 07:52:43 -07001169 ) || match_regexp(line, lineNo, record, MARK_DONE_CUBIC, "markDone" +
1170" 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"
caryclarkdac1d172014-06-17 05:15:38 -07001171 ) || match_regexp(line, lineNo, record, MARK_SIMPLE_LINE, "markWinding" +
1172" id=IDX LINE_VAL t=T_VAL [IDX] PT_VAL tEnd=T_VAL newWindSum=NUM windSum=OPT windValue=IDX"
1173 ) || match_regexp(line, lineNo, record, MARK_SIMPLE_QUAD, "markWinding" +
1174" id=IDX QUAD_VAL t=T_VAL [IDX] PT_VAL tEnd=T_VAL newWindSum=NUM windSum=OPT windValue=IDX"
caryclark1049f122015-04-20 08:31:59 -07001175 ) || match_regexp(line, lineNo, record, MARK_SIMPLE_CONIC, "markWinding" +
1176" id=IDX CONIC_VAL t=T_VAL [IDX] PT_VAL tEnd=T_VAL newWindSum=NUM windSum=OPT windValue=IDX"
caryclarkdac1d172014-06-17 05:15:38 -07001177 ) || match_regexp(line, lineNo, record, MARK_SIMPLE_CUBIC, "markWinding" +
1178" id=IDX CUBIC_VAL t=T_VAL [IDX] PT_VAL tEnd=T_VAL newWindSum=NUM windSum=OPT windValue=IDX"
caryclarkdac1d172014-06-17 05:15:38 -07001179 ) || match_regexp(line, lineNo, record, MARK_ANGLE_LAST, "markAngle" +
caryclark1049f122015-04-20 08:31:59 -07001180" last segment=IDX span=IDX"
caryclark54359292015-03-26 07:52:43 -07001181 ) || match_regexp(line, lineNo, record, MARK_ANGLE_LAST, "markAngle" +
caryclark55888e42016-07-18 10:01:36 -07001182" last seg=IDX span=IDX"
1183 ) || match_regexp(line, lineNo, record, MARK_ANGLE_LAST, "markAngle" +
1184" last segment=IDX span=IDX windSum=OPT"
1185 ) || match_regexp(line, lineNo, record, MARK_ANGLE_LAST, "markAngle" +
1186" last seg=IDX span=IDX windSum=OPT"
1187 );
caryclarkdac1d172014-06-17 05:15:38 -07001188 break;
1189 case REC_TYPE_OP:
1190 if (line.lastIndexOf("oppSign oppSign=", 0) === 0
1191 || line.lastIndexOf("operator<", 0) === 0) {
1192 found = true;
1193 break;
1194 }
caryclark54359292015-03-26 07:52:43 -07001195 found = match_regexp(line, lineNo, record, OP_DIFFERENCE, "op diff"
caryclarkdac1d172014-06-17 05:15:38 -07001196 ) || match_regexp(line, lineNo, record, OP_INTERSECT, "op intersect"
caryclark54359292015-03-26 07:52:43 -07001197 ) || match_regexp(line, lineNo, record, OP_INTERSECT, "op sect"
caryclarkdac1d172014-06-17 05:15:38 -07001198 ) || match_regexp(line, lineNo, record, OP_UNION, "op union"
1199 ) || match_regexp(line, lineNo, record, OP_XOR, "op xor"
1200 );
1201 break;
1202 case REC_TYPE_UNKNOWN:
1203 found = true;
1204 break;
1205 }
1206 if (!found) {
1207 console.log(line + " [" + lineNo + "] of type " + type + " not found");
1208 }
1209 }
1210 if (recType != REC_TYPE_UNKNOWN) {
1211 records.push(recType);
1212 records.push(lastLineNo);
1213 records.push(record);
1214 }
1215 if (records.length >= 1) {
1216 tests[testIndex] = records;
1217 testLines[testIndex] = lines;
1218 }
1219}
1220
1221function init(test) {
1222 var canvas = document.getElementById('canvas');
1223 if (!canvas.getContext) return;
1224 ctx = canvas.getContext('2d');
1225 var resScale = retina_scale && window.devicePixelRatio ? window.devicePixelRatio : 1;
1226 var unscaledWidth = window.innerWidth - 20;
1227 var unscaledHeight = window.innerHeight - 20;
1228 screenWidth = unscaledWidth;
1229 screenHeight = unscaledHeight;
1230 canvas.width = unscaledWidth * resScale;
1231 canvas.height = unscaledHeight * resScale;
1232 canvas.style.width = unscaledWidth + 'px';
1233 canvas.style.height = unscaledHeight + 'px';
1234 if (resScale != 1) {
1235 ctx.scale(resScale, resScale);
1236 }
1237 xmin = Infinity;
1238 xmax = -Infinity;
1239 ymin = Infinity;
1240 ymax = -Infinity;
caryclark26ad22a2015-10-16 09:03:38 -07001241 hasPath = hasAlignedPath = hasComputedPath = false;
caryclarkdac1d172014-06-17 05:15:38 -07001242 firstActiveSpan = -1;
1243 for (var tIndex = 0; tIndex < test.length; tIndex += 3) {
1244 var recType = test[tIndex];
1245 if (!typeof recType == 'number' || recType < REC_TYPE_UNKNOWN || recType > REC_TYPE_LAST) {
1246 console.log("unknown rec type: " + recType);
1247 throw "stop execution";
1248 }
1249 var records = test[tIndex + 2];
1250 for (var recordIndex = 0; recordIndex < records.length; recordIndex += 2) {
1251 var fragType = records[recordIndex];
1252 if (!typeof fragType == 'number' || fragType < 1 || fragType > FRAG_TYPE_LAST) {
1253 console.log("unknown in range frag type: " + fragType);
1254 throw "stop execution";
1255 }
1256 var frags = records[recordIndex + 1];
1257 var first = 0;
1258 var last = -1;
1259 var first2 = 0;
1260 var last2 = 0;
1261 switch (recType) {
caryclark26ad22a2015-10-16 09:03:38 -07001262 case REC_TYPE_ALIGNED:
1263 hasAlignedPath = true;
caryclarkdac1d172014-06-17 05:15:38 -07001264 case REC_TYPE_COMPUTED:
1265 if (fragType == COMPUTED_SET_1 || fragType == COMPUTED_SET_2) {
1266 break;
1267 }
caryclark26ad22a2015-10-16 09:03:38 -07001268 if (REC_TYPE_COMPUTED == recType) {
1269 hasComputedPath = true;
1270 }
caryclarkdac1d172014-06-17 05:15:38 -07001271 case REC_TYPE_PATH:
caryclark54359292015-03-26 07:52:43 -07001272 first = 1;
caryclarkdac1d172014-06-17 05:15:38 -07001273 switch (fragType) {
1274 case PATH_LINE:
caryclark54359292015-03-26 07:52:43 -07001275 last = 5;
caryclarkdac1d172014-06-17 05:15:38 -07001276 break;
caryclark1049f122015-04-20 08:31:59 -07001277 case PATH_CONIC:
caryclarkdac1d172014-06-17 05:15:38 -07001278 case PATH_QUAD:
caryclark54359292015-03-26 07:52:43 -07001279 last = 7;
caryclarkdac1d172014-06-17 05:15:38 -07001280 break;
1281 case PATH_CUBIC:
caryclark54359292015-03-26 07:52:43 -07001282 last = 9;
caryclarkdac1d172014-06-17 05:15:38 -07001283 break;
1284 default:
caryclark55888e42016-07-18 10:01:36 -07001285 console.log("unknown " + (recType == REC_TYPE_PATH ? "REC_TYPE_PATH"
caryclarkdac1d172014-06-17 05:15:38 -07001286 : "REC_TYPE_COMPUTED") + " frag type:" + fragType);
1287 throw "stop execution";
1288 }
1289 if (recType == REC_TYPE_PATH) {
1290 hasPath = true;
1291 }
1292 break;
caryclark54359292015-03-26 07:52:43 -07001293 case REC_TYPE_PATH2:
1294 first = 1;
1295 switch (fragType) {
1296 case PATH_LINE:
1297 last = 5;
1298 break;
caryclark1049f122015-04-20 08:31:59 -07001299 case PATH_CONIC:
caryclark54359292015-03-26 07:52:43 -07001300 case PATH_QUAD:
1301 last = 7;
1302 break;
1303 case PATH_CUBIC:
1304 last = 9;
1305 break;
1306 default:
caryclark55888e42016-07-18 10:01:36 -07001307 console.log("unknown " + (recType == REC_TYPE_PATH2 ? "REC_TYPE_PATH2"
caryclark54359292015-03-26 07:52:43 -07001308 : "REC_TYPE_COMPUTED") + " frag type:" + fragType);
1309 throw "stop execution";
1310 }
1311 if (recType == REC_TYPE_PATH2) {
1312 hasPath = true;
1313 }
1314 break;
caryclarkdac1d172014-06-17 05:15:38 -07001315 case REC_TYPE_ACTIVE:
1316 if (firstActiveSpan < 0) {
1317 firstActiveSpan = tIndex;
1318 }
1319 first = 1;
1320 switch (fragType) {
1321 case ACTIVE_LINE_SPAN:
1322 last = 5;
1323 break;
caryclark1049f122015-04-20 08:31:59 -07001324 case ACTIVE_CONIC_SPAN:
caryclarkdac1d172014-06-17 05:15:38 -07001325 case ACTIVE_QUAD_SPAN:
1326 last = 7;
1327 break;
1328 case ACTIVE_CUBIC_SPAN:
1329 last = 9;
1330 break;
1331 default:
1332 console.log("unknown REC_TYPE_ACTIVE frag type: " + fragType);
1333 throw "stop execution";
1334 }
1335 break;
1336 case REC_TYPE_ADD:
1337 switch (fragType) {
1338 case ADD_MOVETO:
1339 break;
1340 case ADD_LINETO:
1341 last = 4;
1342 break;
caryclark1049f122015-04-20 08:31:59 -07001343 case ADD_CONICTO:
caryclarkdac1d172014-06-17 05:15:38 -07001344 case ADD_QUADTO:
1345 last = 6;
1346 break;
1347 case ADD_CUBICTO:
1348 last = 8;
1349 break;
1350 case ADD_CLOSE:
1351 case ADD_FILL:
1352 break;
1353 default:
1354 console.log("unknown REC_TYPE_ADD frag type: " + fragType);
1355 throw "stop execution";
1356 }
1357 break;
caryclark54359292015-03-26 07:52:43 -07001358 case REC_TYPE_AFTERPART:
1359 switch (fragType) {
1360 case PATH_LINE:
1361 last = 4;
1362 break;
caryclark1049f122015-04-20 08:31:59 -07001363 case PATH_CONIC:
caryclark54359292015-03-26 07:52:43 -07001364 case PATH_QUAD:
1365 last = 6;
1366 break;
1367 case PATH_CUBIC:
1368 last = 8;
1369 break;
1370 default:
1371 console.log("unknown REC_TYPE_ACTIVEPART frag type: " + fragType);
1372 throw "stop execution";
1373 }
1374 break;
caryclarkdac1d172014-06-17 05:15:38 -07001375 case REC_TYPE_SECT:
1376 switch (fragType) {
1377 case INTERSECT_LINE:
1378 first = 1; last = 5; first2 = 8; last2 = 12;
1379 break;
1380 case INTERSECT_LINE_2:
1381 first = 1; last = 5; first2 = 11; last2 = 15;
1382 break;
1383 case INTERSECT_LINE_NO:
1384 first = 0; last = 4; first2 = 4; last2 = 8;
1385 break;
caryclark1049f122015-04-20 08:31:59 -07001386 case INTERSECT_CONIC_LINE:
1387 first = 1; last = 7; first2 = 11; last2 = 15;
1388 break;
caryclarkdac1d172014-06-17 05:15:38 -07001389 case INTERSECT_QUAD_LINE:
1390 first = 1; last = 7; first2 = 10; last2 = 14;
1391 break;
caryclark1049f122015-04-20 08:31:59 -07001392 case INTERSECT_CONIC_LINE_2:
1393 first = 1; last = 7; first2 = 14; last2 = 18;
1394 break;
caryclarkdac1d172014-06-17 05:15:38 -07001395 case INTERSECT_QUAD_LINE_2:
1396 first = 1; last = 7; first2 = 13; last2 = 17;
1397 break;
caryclark1049f122015-04-20 08:31:59 -07001398 case INTERSECT_CONIC_LINE_NO:
1399 first = 0; last = 6; first2 = 7; last2 = 11;
1400 break;
caryclarkdac1d172014-06-17 05:15:38 -07001401 case INTERSECT_QUAD_LINE_NO:
1402 first = 0; last = 6; first2 = 6; last2 = 10;
1403 break;
caryclark1049f122015-04-20 08:31:59 -07001404 case INTERSECT_CONIC:
1405 first = 1; last = 7; first2 = 11; last2 = 17;
1406 break;
caryclarkdac1d172014-06-17 05:15:38 -07001407 case INTERSECT_QUAD:
1408 first = 1; last = 7; first2 = 10; last2 = 16;
1409 break;
caryclark1049f122015-04-20 08:31:59 -07001410 case INTERSECT_CONIC_2:
1411 first = 1; last = 7; first2 = 14; last2 = 20;
1412 break;
caryclarkdac1d172014-06-17 05:15:38 -07001413 case INTERSECT_QUAD_2:
1414 first = 1; last = 7; first2 = 13; last2 = 19;
1415 break;
caryclark1049f122015-04-20 08:31:59 -07001416 case INTERSECT_CONIC_NO:
1417 first = 0; last = 6; first2 = 7; last2 = 13;
1418 break;
caryclarkdac1d172014-06-17 05:15:38 -07001419 case INTERSECT_QUAD_NO:
1420 first = 0; last = 6; first2 = 6; last2 = 12;
1421 break;
1422 case INTERSECT_SELF_CUBIC:
1423 first = 1; last = 9;
1424 break;
1425 case INTERSECT_SELF_CUBIC_NO:
1426 first = 0; last = 8;
1427 break;
1428 case INTERSECT_CUBIC_LINE:
1429 first = 1; last = 9; first2 = 12; last2 = 16;
1430 break;
1431 case INTERSECT_CUBIC_LINE_2:
1432 first = 1; last = 9; first2 = 15; last2 = 19;
1433 break;
1434 case INTERSECT_CUBIC_LINE_3:
1435 first = 1; last = 9; first2 = 18; last2 = 22;
1436 break;
1437 case INTERSECT_CUBIC_LINE_NO:
1438 first = 0; last = 8; first2 = 8; last2 = 12;
1439 break;
caryclark55888e42016-07-18 10:01:36 -07001440 case INTERSECT_CONIC_QUAD:
1441 first = 1; last = 7; first2 = 11; last2 = 17;
1442 break;
1443 case INTERSECT_CONIC_QUAD_2:
1444 first = 1; last = 7; first2 = 14; last2 = 20;
1445 break;
caryclark6c3b9cd2016-09-26 05:36:58 -07001446 case INTERSECT_CONIC_QUAD_3:
1447 first = 1; last = 7; first2 = 17; last2 = 23;
1448 break;
1449 case INTERSECT_CONIC_QUAD_4:
1450 first = 1; last = 7; first2 = 20; last2 = 26;
1451 break;
caryclark55888e42016-07-18 10:01:36 -07001452 case INTERSECT_CONIC_QUAD_NO:
1453 first = 0; last = 6; first2 = 7; last2 = 13;
1454 break;
caryclarkdac1d172014-06-17 05:15:38 -07001455 case INTERSECT_CUBIC_QUAD:
1456 first = 1; last = 9; first2 = 12; last2 = 18;
1457 break;
1458 case INTERSECT_CUBIC_QUAD_2:
1459 first = 1; last = 9; first2 = 15; last2 = 21;
1460 break;
1461 case INTERSECT_CUBIC_QUAD_3:
1462 first = 1; last = 9; first2 = 18; last2 = 24;
1463 break;
1464 case INTERSECT_CUBIC_QUAD_4:
1465 first = 1; last = 9; first2 = 21; last2 = 27;
1466 break;
1467 case INTERSECT_CUBIC_QUAD_NO:
1468 first = 0; last = 8; first2 = 8; last2 = 14;
1469 break;
1470 case INTERSECT_CUBIC:
1471 first = 1; last = 9; first2 = 12; last2 = 20;
1472 break;
1473 case INTERSECT_CUBIC_2:
1474 first = 1; last = 9; first2 = 15; last2 = 23;
1475 break;
1476 case INTERSECT_CUBIC_3:
1477 first = 1; last = 9; first2 = 18; last2 = 26;
1478 break;
1479 case INTERSECT_CUBIC_4:
1480 first = 1; last = 9; first2 = 21; last2 = 29;
1481 break;
1482 case INTERSECT_CUBIC_NO:
1483 first = 0; last = 8; first2 = 8; last2 = 16;
1484 break;
1485 default:
1486 console.log("unknown REC_TYPE_SECT frag type: " + fragType);
1487 throw "stop execution";
1488 }
1489 break;
1490 default:
1491 continue;
1492 }
1493 for (var idx = first; idx < last; idx += 2) {
1494 xmin = Math.min(xmin, frags[idx]);
1495 xmax = Math.max(xmax, frags[idx]);
1496 ymin = Math.min(ymin, frags[idx + 1]);
1497 ymax = Math.max(ymax, frags[idx + 1]);
1498 }
1499 for (var idx = first2; idx < last2; idx += 2) {
1500 xmin = Math.min(xmin, frags[idx]);
1501 xmax = Math.max(xmax, frags[idx]);
1502 ymin = Math.min(ymin, frags[idx + 1]);
1503 ymax = Math.max(ymax, frags[idx + 1]);
1504 }
1505 }
1506 }
1507 var angleBounds = [Infinity, Infinity, -Infinity, -Infinity];
1508 for (var tIndex = 0; tIndex < test.length; tIndex += 3) {
1509 var recType = test[tIndex];
1510 var records = test[tIndex + 2];
1511 for (var recordIndex = 0; recordIndex < records.length; recordIndex += 2) {
1512 var fragType = records[recordIndex];
1513 var frags = records[recordIndex + 1];
1514 switch (recType) {
1515 case REC_TYPE_ACTIVE_OP:
1516 if (!draw_op) {
1517 break;
1518 }
1519 {
1520 var curve = curvePartialByID(test, frags[0], frags[1], frags[2]);
1521 curve_extremes(curve, angleBounds);
1522 }
1523 break;
1524 case REC_TYPE_ANGLE:
1525 if (!draw_angle) {
1526 break;
1527 }
caryclark54359292015-03-26 07:52:43 -07001528 {
caryclarkdac1d172014-06-17 05:15:38 -07001529 var curve = curvePartialByID(test, frags[0], frags[4], frags[5]);
1530 curve_extremes(curve, angleBounds);
1531 curve = curvePartialByID(test, frags[6], frags[10], frags[11]);
1532 curve_extremes(curve, angleBounds);
1533 curve = curvePartialByID(test, frags[12], frags[16], frags[17]);
1534 }
1535 break;
caryclark624637c2015-05-11 07:21:27 -07001536 case REC_TYPE_COINCIDENCE:
1537 if (!draw_coincidence) {
1538 break;
1539 }
1540 {
1541 var curve = curvePartialByID(test, frags[0], frags[1], frags[2]);
1542 curve_extremes(curve, angleBounds);
1543 }
1544 break;
caryclarkdac1d172014-06-17 05:15:38 -07001545 case REC_TYPE_SORT:
1546 if (!draw_sort) {
1547 break;
1548 }
1549 if (fragType == SORT_UNARY || fragType == SORT_BINARY) {
1550 var curve = curvePartialByID(test, frags[0], frags[6], frags[8]);
1551 curve_extremes(curve, angleBounds);
1552 }
1553 break;
caryclark03b03ca2015-04-23 09:13:37 -07001554 case REC_TYPE_TOP:
1555 if (!draw_top) {
1556 break;
1557 }
1558 {
1559 var curve = curvePartialByID(test, frags[0], frags[1], frags[2]);
1560 curve_extremes(curve, angleBounds);
1561 }
1562 break;
caryclarkdac1d172014-06-17 05:15:38 -07001563 }
1564 }
1565 }
1566 xmin = Math.min(xmin, angleBounds[0]);
1567 ymin = Math.min(ymin, angleBounds[1]);
1568 xmax = Math.max(xmax, angleBounds[2]);
1569 ymax = Math.max(ymax, angleBounds[3]);
1570 setScale(xmin, xmax, ymin, ymax);
1571 if (hasPath == false && hasComputedPath == true && !draw_computed) {
caryclark1049f122015-04-20 08:31:59 -07001572 draw_computed = 7; // show quadratics, conics, and cubics
caryclarkdac1d172014-06-17 05:15:38 -07001573 }
1574 if (hasPath == true && hasComputedPath == false && draw_computed) {
1575 draw_computed = 0;
1576 }
1577}
1578
caryclark26ad22a2015-10-16 09:03:38 -07001579function curveByIDMatch(test, id, recMatch) {
caryclark54359292015-03-26 07:52:43 -07001580 var tIndex = -3;
1581 while ((tIndex += 3) < test.length) {
caryclarkdac1d172014-06-17 05:15:38 -07001582 var recType = test[tIndex];
caryclark54359292015-03-26 07:52:43 -07001583 if (recType == REC_TYPE_OP) {
1584 continue;
1585 }
caryclark26ad22a2015-10-16 09:03:38 -07001586 if (recType != recMatch) {
caryclarkdac1d172014-06-17 05:15:38 -07001587 return [];
1588 }
1589 var records = test[tIndex + 2];
1590 for (var recordIndex = 0; recordIndex < records.length; recordIndex += 2) {
1591 var fragType = records[recordIndex];
1592 var frags = records[recordIndex + 1];
1593 if (frags[0] == id) {
1594 switch (fragType) {
caryclark54359292015-03-26 07:52:43 -07001595 case PATH_LINE:
caryclarkdac1d172014-06-17 05:15:38 -07001596 return [frags[1], frags[2], frags[3], frags[4]];
caryclark54359292015-03-26 07:52:43 -07001597 case PATH_QUAD:
caryclarkdac1d172014-06-17 05:15:38 -07001598 return [frags[1], frags[2], frags[3], frags[4],
1599 frags[5], frags[6]];
caryclark1049f122015-04-20 08:31:59 -07001600 case PATH_CONIC:
1601 return [frags[1], frags[2], frags[3], frags[4],
1602 frags[5], frags[6], frags[7]];
caryclark54359292015-03-26 07:52:43 -07001603 case PATH_CUBIC:
caryclarkdac1d172014-06-17 05:15:38 -07001604 return [frags[1], frags[2], frags[3], frags[4],
1605 frags[5], frags[6], frags[7], frags[8]];
1606 }
1607 }
1608 }
caryclarkdac1d172014-06-17 05:15:38 -07001609 }
1610 return [];
1611}
1612
caryclark26ad22a2015-10-16 09:03:38 -07001613function curveByID(test, id) {
1614 var result = draw_path >= 4 ? curveByIDMatch(test, id, REC_TYPE_ALIGNED) : [];
1615 if (!result.length) {
1616 result = curveByIDMatch(test, id, REC_TYPE_PATH);
1617 }
1618 return result;
1619}
1620
1621function curvePartialByIDMatch(test, id, t0, t1, recMatch) {
caryclark54359292015-03-26 07:52:43 -07001622 var tIndex = -3;
1623 while ((tIndex += 3) < test.length) {
caryclarkdac1d172014-06-17 05:15:38 -07001624 var recType = test[tIndex];
caryclark54359292015-03-26 07:52:43 -07001625 if (recType == REC_TYPE_OP) {
1626 continue;
1627 }
caryclark26ad22a2015-10-16 09:03:38 -07001628 if (recType != recMatch) {
caryclarkdac1d172014-06-17 05:15:38 -07001629 return [];
1630 }
1631 var records = test[tIndex + 2];
1632 for (var recordIndex = 0; recordIndex < records.length; recordIndex += 2) {
1633 var fragType = records[recordIndex];
1634 var frags = records[recordIndex + 1];
1635 if (frags[0] == id) {
1636 switch (fragType) {
caryclark54359292015-03-26 07:52:43 -07001637 case PATH_LINE:
caryclarkdac1d172014-06-17 05:15:38 -07001638 return linePartial(frags[1], frags[2], frags[3], frags[4], t0, t1);
caryclark54359292015-03-26 07:52:43 -07001639 case PATH_QUAD:
caryclarkdac1d172014-06-17 05:15:38 -07001640 return quadPartial(frags[1], frags[2], frags[3], frags[4],
1641 frags[5], frags[6], t0, t1);
caryclark1049f122015-04-20 08:31:59 -07001642 case PATH_CONIC:
1643 return conicPartial(frags[1], frags[2], frags[3], frags[4],
1644 frags[5], frags[6], frags[7], t0, t1);
caryclark54359292015-03-26 07:52:43 -07001645 case PATH_CUBIC:
caryclarkdac1d172014-06-17 05:15:38 -07001646 return cubicPartial(frags[1], frags[2], frags[3], frags[4],
1647 frags[5], frags[6], frags[7], frags[8], t0, t1);
1648 }
1649 }
1650 }
caryclarkdac1d172014-06-17 05:15:38 -07001651 }
1652 return [];
1653}
1654
caryclark26ad22a2015-10-16 09:03:38 -07001655function curvePartialByID(test, id, t0, t1) {
1656 var result = draw_path >= 4 ? curvePartialByIDMatch(test, id, t0, t1, REC_TYPE_ALIGNED) : [];
1657 if (!result.length) {
1658 result = curvePartialByIDMatch(test, id, t0, t1, REC_TYPE_PATH);
1659 }
1660 return result;
1661}
1662
1663function idByCurveIDMatch(test, frag, type, recMatch) {
caryclark54359292015-03-26 07:52:43 -07001664 var tIndex = 0;
caryclarkdac1d172014-06-17 05:15:38 -07001665 while (tIndex < test.length) {
1666 var recType = test[tIndex];
caryclark26ad22a2015-10-16 09:03:38 -07001667 if (recType != recMatch) {
caryclark54359292015-03-26 07:52:43 -07001668 ++tIndex;
1669 continue;
caryclarkdac1d172014-06-17 05:15:38 -07001670 }
1671 var records = test[tIndex + 2];
1672 for (var recordIndex = 0; recordIndex < records.length; recordIndex += 2) {
1673 var fragType = records[recordIndex];
1674 var frags = records[recordIndex + 1];
caryclark54359292015-03-26 07:52:43 -07001675 if (frag.length != frags.length - 1) {
1676 continue;
1677 }
caryclarkdac1d172014-06-17 05:15:38 -07001678 switch (fragType) {
caryclark54359292015-03-26 07:52:43 -07001679 case PATH_LINE:
caryclarkdac1d172014-06-17 05:15:38 -07001680 if (frag[0] != frags[1] || frag[1] != frags[2]
1681 || frag[2] != frags[3] || frag[3] != frags[4]) {
1682 continue;
1683 }
1684 return frags[0];
caryclark54359292015-03-26 07:52:43 -07001685 case PATH_QUAD:
caryclarkdac1d172014-06-17 05:15:38 -07001686 if (frag[0] != frags[1] || frag[1] != frags[2]
1687 || frag[2] != frags[3] || frag[3] != frags[4]
1688 || frag[4] != frags[5] || frag[5] != frags[6]) {
1689 continue;
1690 }
1691 return frags[0];
caryclark1049f122015-04-20 08:31:59 -07001692 case PATH_CONIC:
1693 if (frag[0] != frags[1] || frag[1] != frags[2]
1694 || frag[2] != frags[3] || frag[3] != frags[4]
1695 || frag[4] != frags[5] || frag[5] != frags[6]
1696 || frag[6] != frags[7]) {
1697 continue;
1698 }
1699 return frags[0];
caryclark54359292015-03-26 07:52:43 -07001700 case PATH_CUBIC:
caryclarkdac1d172014-06-17 05:15:38 -07001701 if (frag[0] != frags[1] || frag[1] != frags[2]
1702 || frag[2] != frags[3] || frag[3] != frags[4]
1703 || frag[4] != frags[5] || frag[5] != frags[6]
1704 || frag[6] != frags[7] || frag[7] != frags[8]) {
1705 continue;
1706 }
1707 return frags[0];
1708 }
1709 }
1710 ++tIndex;
1711 }
1712 return -1;
1713}
1714
caryclark26ad22a2015-10-16 09:03:38 -07001715function idByCurve(test, frag, type) {
1716 var result = draw_path >= 4 ? idByCurveIDMatch(test, frag, type, REC_TYPE_ALIGNED) : [];
1717 if (!result.length) {
1718 result = idByCurveIDMatch(test, frag, type, REC_TYPE_PATH);
1719 }
1720 return result;
1721}
1722
caryclarkdac1d172014-06-17 05:15:38 -07001723function curve_extremes(curve, bounds) {
caryclark1049f122015-04-20 08:31:59 -07001724 var length = curve.length == 7 ? 6 : curve.length;
caryclarked0935a2015-10-22 07:23:52 -07001725 for (var index = 0; index < length; index += 2) {
caryclarkdac1d172014-06-17 05:15:38 -07001726 var x = curve[index];
1727 var y = curve[index + 1];
1728 bounds[0] = Math.min(bounds[0], x);
1729 bounds[1] = Math.min(bounds[1], y);
1730 bounds[2] = Math.max(bounds[2], x);
1731 bounds[3] = Math.max(bounds[3], y);
1732 }
1733}
1734
1735function setScale(x0, x1, y0, y1) {
1736 var srcWidth = x1 - x0;
1737 var srcHeight = y1 - y0;
1738 var usableWidth = screenWidth;
1739 var xDigits = Math.ceil(Math.log(Math.abs(xmax)) / Math.log(10));
1740 var yDigits = Math.ceil(Math.log(Math.abs(ymax)) / Math.log(10));
1741 usableWidth -= (xDigits + yDigits) * 10;
1742 usableWidth -= decimal_places * 10;
1743 if (draw_legend) {
1744 usableWidth -= 40;
1745 }
1746 var hscale = usableWidth / srcWidth;
1747 var vscale = screenHeight / srcHeight;
1748 scale = Math.min(hscale, vscale);
1749 var invScale = 1 / scale;
1750 var sxmin = x0 - invScale * 5;
1751 var symin = y0 - invScale * 10;
1752 var sxmax = x1 + invScale * (6 * decimal_places + 10);
1753 var symax = y1 + invScale * 10;
1754 srcWidth = sxmax - sxmin;
1755 srcHeight = symax - symin;
1756 hscale = usableWidth / srcWidth;
1757 vscale = screenHeight / srcHeight;
1758 scale = Math.min(hscale, vscale);
1759 srcLeft = sxmin;
1760 srcTop = symin;
1761}
1762
1763function drawArc(curve, op, from, to) {
1764 var type = PATH_LINE + (curve.length / 2 - 2);
1765 var pt = pointAtT(curve, type, op ? 0.4 : 0.6);
1766 var dy = pt.y - curve[1];
1767 var dx = pt.x - curve[0];
1768 var dist = Math.sqrt(dy * dy + dx * dx);
1769 var _dist = dist * scale;
1770 var angle = Math.atan2(dy, dx);
1771 var _px = (curve[0] - srcLeft) * scale;
1772 var _py = (curve[1] - srcTop) * scale;
1773 var divisor = 4;
1774 var endDist;
1775 do {
1776 var ends = [];
1777 for (var index = -1; index <= 1; index += 2) {
1778 var px = Math.cos(index * Math.PI / divisor);
1779 var py = Math.sin(index * Math.PI / divisor);
1780 ends.push(px);
1781 ends.push(py);
1782 }
1783 var endDx = (ends[2] - ends[0]) * scale * dist;
1784 var endDy = (ends[3] - ends[1]) * scale * dist;
1785 endDist = Math.sqrt(endDx * endDx + endDy * endDy);
1786 if (endDist < 100) {
1787 break;
1788 }
1789 divisor *= 2;
1790 } while (true);
1791 if (endDist < 30) {
1792 return;
1793 }
1794 if (op) {
1795 divisor *= 2;
1796 }
1797 ctx.strokeStyle = op ? "rgba(210,0,45, 0.4)" : "rgba(90,90,90, 0.5)";
1798 ctx.beginPath();
1799 ctx.arc(_px, _py, _dist, angle - Math.PI / divisor, angle + Math.PI / divisor, false);
1800 ctx.stroke();
1801 var saveAlign = ctx.textAlign;
1802 var saveStyle = ctx.fillStyle;
1803 var saveFont = ctx.font;
1804 ctx.textAlign = "center";
1805 ctx.fillStyle = "black";
1806 ctx.font = "normal 24px Arial";
1807 divisor *= 0.8;
1808 for (var index = -1; index <= 1; index += 2) {
1809 var px = curve[0] + Math.cos(angle + index * Math.PI / divisor) * dist;
1810 var py = curve[1] + Math.sin(angle + index * Math.PI / divisor) * dist;
1811 var _px = (px - srcLeft) * scale;
1812 var _py = (py - srcTop) * scale;
1813 ctx.fillText(index < 0 ? to.toString() : from.toString(), _px, _py + 8);
1814 }
1815 ctx.textAlign = saveAlign;
1816 ctx.fillStyle = saveStyle;
1817 ctx.font = saveFont;
1818}
1819
1820function drawPoint(px, py, end) {
caryclark1049f122015-04-20 08:31:59 -07001821 var length = drawnPts.length == 7 ? 6 : drawnPts.length;
1822 for (var pts = 0; pts < length; pts += 2) {
caryclarkdac1d172014-06-17 05:15:38 -07001823 var x = drawnPts[pts];
1824 var y = drawnPts[pts + 1];
1825 if (px == x && py == y) {
1826 return;
1827 }
1828 }
1829 drawnPts.push(px);
1830 drawnPts.push(py);
1831 var label = px.toFixed(decimal_places) + ", " + py.toFixed(decimal_places);
1832 var _px = (px - srcLeft) * scale;
1833 var _py = (py - srcTop) * scale;
1834 ctx.beginPath();
1835 ctx.arc(_px, _py, 3, 0, Math.PI*2, true);
1836 ctx.closePath();
1837 if (end) {
1838 ctx.fill();
1839 } else {
1840 ctx.stroke();
1841 }
1842 if (debug_xy) {
1843 ctx.textAlign = "left";
1844 ctx.fillText(label, _px + 5, _py);
1845 }
1846}
1847
caryclark1049f122015-04-20 08:31:59 -07001848function coordCount(curveType) {
1849 switch (curveType) {
1850 case PATH_LINE:
1851 return 4;
1852 case PATH_QUAD:
1853 return 6;
1854 case PATH_CONIC:
1855 return 6;
1856 case PATH_CUBIC:
1857 return 8;
1858 }
1859 return -1;
1860}
1861
caryclarkdac1d172014-06-17 05:15:38 -07001862function drawPoints(ptArray, curveType, drawControls) {
caryclark1049f122015-04-20 08:31:59 -07001863 var count = coordCount(curveType);
caryclarkdac1d172014-06-17 05:15:38 -07001864 for (var idx = 0; idx < count; idx += 2) {
1865 if (!drawControls && idx != 0 && idx != count - 2) {
1866 continue;
1867 }
1868 drawPoint(ptArray[idx], ptArray[idx + 1], idx == 0 || idx == count - 2);
1869 }
1870}
1871
1872function drawControlLines(curve, curveType, drawEnd) {
1873 if (curveType == PATH_LINE) {
1874 return;
1875 }
1876 ctx.strokeStyle = "rgba(0,0,0, 0.3)";
1877 drawLine(curve[0], curve[1], curve[2], curve[3]);
1878 drawLine(curve[2], curve[3], curve[4], curve[5]);
1879 if (curveType == PATH_CUBIC) {
1880 drawLine(curve[4], curve[5], curve[6], curve[7]);
1881 if (drawEnd > 1) {
1882 drawLine(curve[6], curve[7], curve[0], curve[1]);
1883 if (drawEnd > 2) {
1884 drawLine(curve[0], curve[1], curve[4], curve[5]);
1885 drawLine(curve[6], curve[7], curve[2], curve[3]);
1886 }
1887 }
1888 } else if (drawEnd > 1) {
1889 drawLine(curve[4], curve[5], curve[0], curve[1]);
1890 }
1891}
1892
1893function pointAtT(curve, curveType, t) {
1894 var xy = {};
1895 switch (curveType) {
1896 case PATH_LINE:
1897 var a = 1 - t;
1898 var b = t;
1899 xy.x = a * curve[0] + b * curve[2];
1900 xy.y = a * curve[1] + b * curve[3];
1901 break;
1902 case PATH_QUAD:
1903 var one_t = 1 - t;
1904 var a = one_t * one_t;
1905 var b = 2 * one_t * t;
1906 var c = t * t;
1907 xy.x = a * curve[0] + b * curve[2] + c * curve[4];
1908 xy.y = a * curve[1] + b * curve[3] + c * curve[5];
1909 break;
caryclark1049f122015-04-20 08:31:59 -07001910 case PATH_CONIC:
1911 var one_t = 1 - t;
1912 var a = one_t * one_t;
1913 var b = 2 * one_t * t;
1914 var c = t * t;
1915 xy.x = a * curve[0] + b * curve[2] * curve[6] + c * curve[4];
1916 xy.y = a * curve[1] + b * curve[3] * curve[6] + c * curve[5];
1917 var d = a + b * curve[6] + c;
1918 xy.x /= d;
1919 xy.y /= d;
1920 break;
caryclarkdac1d172014-06-17 05:15:38 -07001921 case PATH_CUBIC:
1922 var one_t = 1 - t;
1923 var one_t2 = one_t * one_t;
1924 var a = one_t2 * one_t;
1925 var b = 3 * one_t2 * t;
1926 var t2 = t * t;
1927 var c = 3 * one_t * t2;
1928 var d = t2 * t;
1929 xy.x = a * curve[0] + b * curve[2] + c * curve[4] + d * curve[6];
1930 xy.y = a * curve[1] + b * curve[3] + c * curve[5] + d * curve[7];
1931 break;
1932 }
1933 return xy;
1934}
caryclark55888e42016-07-18 10:01:36 -07001935
caryclarkdac1d172014-06-17 05:15:38 -07001936function drawPointAtT(curve, curveType) {
1937 var x, y;
1938 var xy = pointAtT(curve, curveType, curveT);
1939 drawPoint(xy.x, xy.y, true);
1940 if (!draw_intersectT) {
1941 return;
1942 }
1943 ctx.fillStyle = "red";
1944 drawTAtPointUp(xy.x, xy.y, curveT);
1945}
1946
1947function drawTAtPointUp(px, py, t) {
1948 var label = t.toFixed(decimal_places);
1949 var _px = (px - srcLeft)* scale;
1950 var _py = (py - srcTop) * scale;
1951 ctx.fillText(label, _px + 5, _py - 10);
1952}
1953
1954function drawTAtPointDown(px, py, t) {
1955 var label = t.toFixed(decimal_places);
1956 var _px = (px - srcLeft)* scale;
1957 var _py = (py - srcTop) * scale;
1958 ctx.fillText(label, _px + 5, _py + 10);
1959}
1960
1961function alreadyDrawnLine(x1, y1, x2, y2) {
1962 if (collect_bounds) {
1963 if (focus_enabled) {
1964 focusXmin = Math.min(focusXmin, x1, x2);
1965 focusYmin = Math.min(focusYmin, y1, y2);
1966 focusXmax = Math.max(focusXmax, x1, x2);
1967 focusYmax = Math.max(focusYmax, y1, y2);
1968 }
1969 return true;
1970 }
1971 for (var pts = 0; pts < drawnLines.length; pts += 4) {
1972 if (x1 == drawnLines[pts] && y1 == drawnLines[pts + 1]
1973 && x2 == drawnLines[pts + 2] && y2 == drawnLines[pts + 3]) {
1974 return true;
1975 }
1976 }
1977 drawnLines.push(x1);
1978 drawnLines.push(y1);
1979 drawnLines.push(x2);
1980 drawnLines.push(y2);
1981 return false;
1982}
1983
1984function drawLine(x1, y1, x2, y2) {
1985 if (alreadyDrawnLine(x1, y1, x2, y2)) {
1986 return;
1987 }
1988 ctx.beginPath();
1989 ctx.moveTo((x1 - srcLeft) * scale,
1990 (y1 - srcTop) * scale);
1991 ctx.lineTo((x2 - srcLeft) * scale,
1992 (y2 - srcTop) * scale);
1993 ctx.stroke();
1994}
1995
1996function linePartial(x1, y1, x2, y2, t1, t2) {
1997 var dx = x1 - x2;
1998 var dy = y1 - y2;
1999 var array = [
2000 x1 - t1 * dx,
2001 y1 - t1 * dy,
2002 x1 - t2 * dx,
2003 y1 - t2 * dy
2004 ];
2005 return array;
2006}
2007
2008function drawLinePartial(x1, y1, x2, y2, t1, t2) {
2009 var a = linePartial(x1, y1, x2, y2, t1, t2);
2010 var ax = a[0];
2011 var ay = a[1];
2012 var bx = a[2];
2013 var by = a[3];
2014 if (alreadyDrawnLine(ax, ay, bx, by)) {
2015 return;
2016 }
2017 ctx.beginPath();
2018 ctx.moveTo((ax - srcLeft) * scale,
2019 (ay - srcTop) * scale);
2020 ctx.lineTo((bx - srcLeft) * scale,
2021 (by - srcTop) * scale);
2022 ctx.stroke();
2023}
2024
2025function alreadyDrawnQuad(x1, y1, x2, y2, x3, y3) {
2026 if (collect_bounds) {
2027 if (focus_enabled) {
2028 focusXmin = Math.min(focusXmin, x1, x2, x3);
2029 focusYmin = Math.min(focusYmin, y1, y2, y3);
2030 focusXmax = Math.max(focusXmax, x1, x2, x3);
2031 focusYmax = Math.max(focusYmax, y1, y2, y3);
2032 }
2033 return true;
2034 }
2035 for (var pts = 0; pts < drawnQuads.length; pts += 6) {
2036 if (x1 == drawnQuads[pts] && y1 == drawnQuads[pts + 1]
2037 && x2 == drawnQuads[pts + 2] && y2 == drawnQuads[pts + 3]
2038 && x3 == drawnQuads[pts + 4] && y3 == drawnQuads[pts + 5]) {
2039 return true;
2040 }
2041 }
2042 drawnQuads.push(x1);
2043 drawnQuads.push(y1);
2044 drawnQuads.push(x2);
2045 drawnQuads.push(y2);
2046 drawnQuads.push(x3);
2047 drawnQuads.push(y3);
2048 return false;
2049}
2050
2051function drawQuad(x1, y1, x2, y2, x3, y3) {
2052 if (alreadyDrawnQuad(x1, y1, x2, y2, x3, y3)) {
2053 return;
2054 }
2055 ctx.beginPath();
2056 ctx.moveTo((x1 - srcLeft) * scale,
2057 (y1 - srcTop) * scale);
2058 ctx.quadraticCurveTo((x2 - srcLeft) * scale,
2059 (y2 - srcTop) * scale,
2060 (x3 - srcLeft) * scale,
2061 (y3 - srcTop) * scale);
2062 ctx.stroke();
2063}
2064
2065function interp(A, B, t) {
2066 return A + (B - A) * t;
2067}
2068
2069function interp_quad_coords(x1, x2, x3, t)
2070{
2071 var ab = interp(x1, x2, t);
2072 var bc = interp(x2, x3, t);
2073 var abc = interp(ab, bc, t);
2074 return abc;
2075}
2076
2077function quadPartial(x1, y1, x2, y2, x3, y3, t1, t2) {
2078 var ax = interp_quad_coords(x1, x2, x3, t1);
2079 var ay = interp_quad_coords(y1, y2, y3, t1);
2080 var dx = interp_quad_coords(x1, x2, x3, (t1 + t2) / 2);
2081 var dy = interp_quad_coords(y1, y2, y3, (t1 + t2) / 2);
2082 var cx = interp_quad_coords(x1, x2, x3, t2);
2083 var cy = interp_quad_coords(y1, y2, y3, t2);
2084 var bx = 2*dx - (ax + cx)/2;
2085 var by = 2*dy - (ay + cy)/2;
2086 var array = [
2087 ax, ay, bx, by, cx, cy
2088 ];
2089 return array;
2090}
2091
2092function drawQuadPartial(x1, y1, x2, y2, x3, y3, t1, t2) {
2093 var a = quadPartial(x1, y1, x2, y2, x3, y3, t1, t2);
2094 var ax = a[0];
2095 var ay = a[1];
2096 var bx = a[2];
2097 var by = a[3];
2098 var cx = a[4];
2099 var cy = a[5];
2100 if (alreadyDrawnQuad(ax, ay, bx, by, cx, cy)) {
2101 return;
2102 }
2103 ctx.beginPath();
2104 ctx.moveTo((ax - srcLeft) * scale,
2105 (ay - srcTop) * scale);
2106 ctx.quadraticCurveTo((bx - srcLeft) * scale,
2107 (by - srcTop) * scale,
2108 (cx - srcLeft) * scale,
2109 (cy - srcTop) * scale);
2110 ctx.stroke();
2111}
2112
caryclark1049f122015-04-20 08:31:59 -07002113function alreadyDrawnConic(x1, y1, x2, y2, x3, y3, w) {
2114 if (collect_bounds) {
2115 if (focus_enabled) {
2116 focusXmin = Math.min(focusXmin, x1, x2, x3);
2117 focusYmin = Math.min(focusYmin, y1, y2, y3);
2118 focusXmax = Math.max(focusXmax, x1, x2, x3);
2119 focusYmax = Math.max(focusYmax, y1, y2, y3);
2120 }
2121 return true;
2122 }
2123 for (var pts = 0; pts < drawnConics.length; pts += 8) {
2124 if (x1 == drawnConics[pts] && y1 == drawnCubics[pts + 1]
caryclark55888e42016-07-18 10:01:36 -07002125 && x2 == drawnCubics[pts + 2] && y2 == drawnCubics[pts + 3]
2126 && x3 == drawnCubics[pts + 4] && y3 == drawnCubics[pts + 5]
caryclark1049f122015-04-20 08:31:59 -07002127 && w == drawnCubics[pts + 6]) {
2128 return true;
2129 }
2130 }
2131 drawnConics.push(x1);
2132 drawnConics.push(y1);
2133 drawnConics.push(x2);
2134 drawnConics.push(y2);
2135 drawnConics.push(x3);
2136 drawnConics.push(y3);
2137 drawnCubics.push(w);
2138 return false;
2139}
2140
2141var kMaxConicToQuadPOW2 = 5;
2142
2143function computeQuadPOW2(curve, tol) {
2144 var a = curve[6] - 1;
2145 var k = a / (4 * (2 + a));
2146 var x = k * (curve[0] - 2 * curve[2] + curve[4]);
2147 var y = k * (curve[1] - 2 * curve[3] + curve[5]);
2148
2149 var error = Math.sqrt(x * x + y * y);
2150 var pow2;
2151 for (pow2 = 0; pow2 < kMaxConicToQuadPOW2; ++pow2) {
2152 if (error <= tol) {
2153 break;
2154 }
2155 error *= 0.25;
2156 }
2157 return pow2;
2158}
2159
2160function subdivide_w_value(w) {
2161 return Math.sqrt(0.5 + w * 0.5);
2162}
2163
2164function chop(curve, part1, part2) {
2165 var w = curve[6];
2166 var scale = 1 / (1 + w);
2167 part1[0] = curve[0];
2168 part1[1] = curve[1];
2169 part1[2] = (curve[0] + curve[2] * w) * scale;
2170 part1[3] = (curve[1] + curve[3] * w) * scale;
2171 part1[4] = part2[0] = (curve[0] + (curve[2] * w) * 2 + curve[4]) * scale * 0.5;
2172 part1[5] = part2[1] = (curve[1] + (curve[3] * w) * 2 + curve[5]) * scale * 0.5;
2173 part2[2] = (curve[2] * w + curve[4]) * scale;
2174 part2[3] = (curve[3] * w + curve[5]) * scale;
2175 part2[4] = curve[4];
2176 part2[5] = curve[5];
2177 part1[6] = part2[6] = subdivide_w_value(w);
2178}
2179
2180function subdivide(curve, level, pts) {
2181 if (0 == level) {
2182 pts.push(curve[2]);
2183 pts.push(curve[3]);
2184 pts.push(curve[4]);
2185 pts.push(curve[5]);
2186 } else {
2187 var part1 = [], part2 = [];
2188 chop(curve, part1, part2);
2189 --level;
2190 subdivide(part1, level, pts);
2191 subdivide(part2, level, pts);
2192 }
2193}
2194
2195function chopIntoQuadsPOW2(curve, pow2, pts) {
2196 subdivide(curve, pow2, pts);
2197 return 1 << pow2;
2198}
2199
2200function drawConicWithQuads(x1, y1, x2, y2, x3, y3, w) {
2201 if (alreadyDrawnConic(x1, y1, x2, y2, x3, y3, w)) {
2202 return;
2203 }
2204 ctx.beginPath();
2205 ctx.moveTo((x1 - srcLeft) * scale,
2206 (y1 - srcTop) * scale);
2207 var tol = 1 / scale;
2208 var curve = [x1, y1, x2, y2, x3, y3, w];
2209 var pow2 = computeQuadPOW2(curve, tol);
2210 var pts = [];
2211 chopIntoQuadsPOW2(curve, pow2, pts);
2212 for (var i = 0; i < pts.length; i += 4) {
2213 ctx.quadraticCurveTo(
2214 (pts[i + 0] - srcLeft) * scale, (pts[i + 1] - srcTop) * scale,
2215 (pts[i + 2] - srcLeft) * scale, (pts[i + 3] - srcTop) * scale);
2216 }
2217 ctx.stroke();
2218}
2219
2220function conic_eval_numerator(x1, x2, x3, w, t) {
2221 var src2w = x2 * w;
2222 var C = x1;
2223 var A = x3 - 2 * src2w + C;
2224 var B = 2 * (src2w - C);
2225 return (A * t + B) * t + C;
2226}
2227
2228
2229function conic_eval_denominator(w, t) {
2230 var B = 2 * (w - 1);
2231 var C = 1;
2232 var A = -B;
2233 return (A * t + B) * t + C;
2234}
2235
2236function conicPartial(x1, y1, x2, y2, x3, y3, w, t1, t2) {
2237 var ax = conic_eval_numerator(x1, x2, x3, w, t1);
2238 var ay = conic_eval_numerator(y1, y2, y3, w, t1);
2239 var az = conic_eval_denominator(w, t1);
2240 var midT = (t1 + t2) / 2;
2241 var dx = conic_eval_numerator(x1, x2, x3, w, midT);
2242 var dy = conic_eval_numerator(y1, y2, y3, w, midT);
2243 var dz = conic_eval_denominator(w, midT);
2244 var cx = conic_eval_numerator(x1, x2, x3, w, t2);
2245 var cy = conic_eval_numerator(y1, y2, y3, w, t2);
2246 var cz = conic_eval_denominator(w, t2);
2247 var bx = 2 * dx - (ax + cx) / 2;
2248 var by = 2 * dy - (ay + cy) / 2;
2249 var bz = 2 * dz - (az + cz) / 2;
2250 var dt = t2 - t1;
2251 var dt_1 = 1 - dt;
caryclark1049f122015-04-20 08:31:59 -07002252 var array = [
caryclarked0935a2015-10-22 07:23:52 -07002253 ax / az, ay / az, bx / bz, by / bz, cx / cz, cy / cz, 0
caryclark1049f122015-04-20 08:31:59 -07002254 ];
caryclarked0935a2015-10-22 07:23:52 -07002255 var dMidAC = { x:(array[0] + array[4]) / 2, y:(array[1] + array[5]) / 2 };
2256 var dMid = { x:dx / dz, y:dy / dz };
2257 var dWNumer = { x:dMidAC.x - dMid.x, y:dMidAC.y - dMid.y };
2258 var dWDenom = { x:dMid.x - array[2], y:dMid.y - array[3] };
2259 var partW = Math.sqrt(dWNumer.x * dWNumer.x + dWNumer.y * dWNumer.y)
2260 / Math.sqrt(dWDenom.x * dWDenom.x + dWDenom.y * dWDenom.y);
2261 array[6] = partW;
caryclark1049f122015-04-20 08:31:59 -07002262 return array;
2263}
caryclark55888e42016-07-18 10:01:36 -07002264
caryclark1049f122015-04-20 08:31:59 -07002265function drawConicPartial(x1, y1, x2, y2, x3, y3, w, t1, t2) {
2266 var a = conicPartial(x1, y1, x2, y2, x3, y3, w, t1, t2);
2267 var ax = a[0];
2268 var ay = a[1];
2269 var bx = a[2];
2270 var by = a[3];
2271 var cx = a[4];
2272 var cy = a[5];
2273 var w_ = a[6];
2274 drawConicWithQuads(ax, ay, bx, by, cx, cy, w_);
2275}
2276
caryclarkdac1d172014-06-17 05:15:38 -07002277function alreadyDrawnCubic(x1, y1, x2, y2, x3, y3, x4, y4) {
2278 if (collect_bounds) {
2279 if (focus_enabled) {
2280 focusXmin = Math.min(focusXmin, x1, x2, x3, x4);
2281 focusYmin = Math.min(focusYmin, y1, y2, y3, y4);
2282 focusXmax = Math.max(focusXmax, x1, x2, x3, x4);
2283 focusYmax = Math.max(focusYmax, y1, y2, y3, y4);
2284 }
2285 return true;
2286 }
2287 for (var pts = 0; pts < drawnCubics.length; pts += 8) {
2288 if (x1 == drawnCubics[pts] && y1 == drawnCubics[pts + 1]
caryclark55888e42016-07-18 10:01:36 -07002289 && x2 == drawnCubics[pts + 2] && y2 == drawnCubics[pts + 3]
2290 && x3 == drawnCubics[pts + 4] && y3 == drawnCubics[pts + 5]
caryclarkdac1d172014-06-17 05:15:38 -07002291 && x4 == drawnCubics[pts + 6] && y4 == drawnCubics[pts + 7]) {
2292 return true;
2293 }
2294 }
2295 drawnCubics.push(x1);
2296 drawnCubics.push(y1);
2297 drawnCubics.push(x2);
2298 drawnCubics.push(y2);
2299 drawnCubics.push(x3);
2300 drawnCubics.push(y3);
2301 drawnCubics.push(x4);
2302 drawnCubics.push(y4);
2303 return false;
2304}
2305
2306function drawCubic(x1, y1, x2, y2, x3, y3, x4, y4) {
2307 if (alreadyDrawnCubic(x1, y1, x2, y2, x3, y3, x4, y4)) {
2308 return;
2309 }
2310 ctx.beginPath();
2311 ctx.moveTo((x1 - srcLeft) * scale,
2312 (y1 - srcTop) * scale);
2313 ctx.bezierCurveTo((x2 - srcLeft) * scale,
2314 (y2 - srcTop) * scale,
2315 (x3 - srcLeft) * scale,
2316 (y3 - srcTop) * scale,
2317 (x4 - srcLeft) * scale,
2318 (y4 - srcTop) * scale);
2319 ctx.stroke();
2320}
2321
2322function interp_cubic_coords(x1, x2, x3, x4, t)
2323{
2324 var ab = interp(x1, x2, t);
2325 var bc = interp(x2, x3, t);
2326 var cd = interp(x3, x4, t);
2327 var abc = interp(ab, bc, t);
2328 var bcd = interp(bc, cd, t);
2329 var abcd = interp(abc, bcd, t);
2330 return abcd;
2331}
2332
2333function cubicPartial(x1, y1, x2, y2, x3, y3, x4, y4, t1, t2) {
2334 var ax = interp_cubic_coords(x1, x2, x3, x4, t1);
2335 var ay = interp_cubic_coords(y1, y2, y3, y4, t1);
2336 var ex = interp_cubic_coords(x1, x2, x3, x4, (t1*2+t2)/3);
2337 var ey = interp_cubic_coords(y1, y2, y3, y4, (t1*2+t2)/3);
2338 var fx = interp_cubic_coords(x1, x2, x3, x4, (t1+t2*2)/3);
2339 var fy = interp_cubic_coords(y1, y2, y3, y4, (t1+t2*2)/3);
2340 var dx = interp_cubic_coords(x1, x2, x3, x4, t2);
2341 var dy = interp_cubic_coords(y1, y2, y3, y4, t2);
2342 var mx = ex * 27 - ax * 8 - dx;
2343 var my = ey * 27 - ay * 8 - dy;
2344 var nx = fx * 27 - ax - dx * 8;
2345 var ny = fy * 27 - ay - dy * 8;
2346 var bx = (mx * 2 - nx) / 18;
2347 var by = (my * 2 - ny) / 18;
2348 var cx = (nx * 2 - mx) / 18;
2349 var cy = (ny * 2 - my) / 18;
2350 var array = [
2351 ax, ay, bx, by, cx, cy, dx, dy
2352 ];
2353 return array;
2354}
caryclark55888e42016-07-18 10:01:36 -07002355
caryclarkdac1d172014-06-17 05:15:38 -07002356function drawCubicPartial(x1, y1, x2, y2, x3, y3, x4, y4, t1, t2) {
2357 var a = cubicPartial(x1, y1, x2, y2, x3, y3, x4, y4, t1, t2);
2358 var ax = a[0];
2359 var ay = a[1];
2360 var bx = a[2];
2361 var by = a[3];
2362 var cx = a[4];
2363 var cy = a[5];
2364 var dx = a[6];
2365 var dy = a[7];
2366 if (alreadyDrawnCubic(ax, ay, bx, by, cx, cy, dx, dy)) {
2367 return;
2368 }
2369 ctx.beginPath();
2370 ctx.moveTo((ax - srcLeft) * scale,
2371 (ay - srcTop) * scale);
2372 ctx.bezierCurveTo((bx - srcLeft) * scale,
2373 (by - srcTop) * scale,
2374 (cx - srcLeft) * scale,
2375 (cy - srcTop) * scale,
2376 (dx - srcLeft) * scale,
2377 (dy - srcTop) * scale);
2378 ctx.stroke();
2379}
2380
2381function drawCurve(c) {
2382 switch (c.length) {
2383 case 4:
2384 drawLine(c[0], c[1], c[2], c[3]);
2385 break;
2386 case 6:
2387 drawQuad(c[0], c[1], c[2], c[3], c[4], c[5]);
2388 break;
caryclark1049f122015-04-20 08:31:59 -07002389 case 7:
2390 drawConicWithQuads(c[0], c[1], c[2], c[3], c[4], c[5], c[6]);
2391 break;
caryclarkdac1d172014-06-17 05:15:38 -07002392 case 8:
2393 drawCubic(c[0], c[1], c[2], c[3], c[4], c[5], c[6], c[7]);
2394 break;
2395 }
2396}
2397
2398function boundsWidth(pts) {
2399 var min = pts[0];
2400 var max = pts[0];
caryclark1049f122015-04-20 08:31:59 -07002401 var length = pts.length == 7 ? 6 : pts.length;
2402 for (var idx = 2; idx < length; idx += 2) {
caryclarkdac1d172014-06-17 05:15:38 -07002403 min = Math.min(min, pts[idx]);
2404 max = Math.max(max, pts[idx]);
2405 }
2406 return max - min;
2407}
2408
2409function boundsHeight(pts) {
2410 var min = pts[1];
2411 var max = pts[1];
caryclark1049f122015-04-20 08:31:59 -07002412 var length = pts.length == 7 ? 6 : pts.length;
2413 for (var idx = 3; idx < length; idx += 2) {
caryclarkdac1d172014-06-17 05:15:38 -07002414 min = Math.min(min, pts[idx]);
2415 max = Math.max(max, pts[idx]);
2416 }
2417 return max - min;
2418}
2419
2420function tangent(pts) {
2421 var dx = pts[2] - pts[0];
2422 var dy = pts[3] - pts[1];
2423 if (dx == 0 && dy == 0 && pts.length > 4) {
2424 dx = pts[4] - pts[0];
2425 dy = pts[5] - pts[1];
caryclark1049f122015-04-20 08:31:59 -07002426 if (dx == 0 && dy == 0 && pts.length == 8) {
caryclarkdac1d172014-06-17 05:15:38 -07002427 dx = pts[6] - pts[0];
2428 dy = pts[7] - pts[1];
2429 }
2430 }
2431 return Math.atan2(-dy, dx);
2432}
2433
2434function hodograph(cubic) {
2435 var hodo = [];
2436 hodo[0] = 3 * (cubic[2] - cubic[0]);
2437 hodo[1] = 3 * (cubic[3] - cubic[1]);
2438 hodo[2] = 3 * (cubic[4] - cubic[2]);
2439 hodo[3] = 3 * (cubic[5] - cubic[3]);
2440 hodo[4] = 3 * (cubic[6] - cubic[4]);
2441 hodo[5] = 3 * (cubic[7] - cubic[5]);
2442 return hodo;
2443}
2444
2445function hodograph2(cubic) {
2446 var quad = hodograph(cubic);
2447 var hodo = [];
2448 hodo[0] = 2 * (quad[2] - quad[0]);
2449 hodo[1] = 2 * (quad[3] - quad[1]);
2450 hodo[2] = 2 * (quad[4] - quad[2]);
2451 hodo[3] = 2 * (quad[5] - quad[3]);
2452 return hodo;
2453}
2454
2455function quadraticRootsReal(A, B, C, s) {
2456 if (A == 0) {
2457 if (B == 0) {
2458 s[0] = 0;
2459 return C == 0;
2460 }
2461 s[0] = -C / B;
2462 return 1;
2463 }
2464 /* normal form: x^2 + px + q = 0 */
2465 var p = B / (2 * A);
2466 var q = C / A;
2467 var p2 = p * p;
2468 if (p2 < q) {
2469 return 0;
2470 }
2471 var sqrt_D = 0;
2472 if (p2 > q) {
2473 sqrt_D = sqrt(p2 - q);
2474 }
2475 s[0] = sqrt_D - p;
2476 s[1] = -sqrt_D - p;
2477 return 1 + s[0] != s[1];
2478}
2479
2480function add_valid_ts(s, realRoots, t) {
2481 var foundRoots = 0;
2482 for (var index = 0; index < realRoots; ++index) {
2483 var tValue = s[index];
2484 if (tValue >= 0 && tValue <= 1) {
2485 for (var idx2 = 0; idx2 < foundRoots; ++idx2) {
2486 if (t[idx2] != tValue) {
2487 t[foundRoots++] = tValue;
2488 }
2489 }
2490 }
2491 }
2492 return foundRoots;
2493}
2494
2495function quadraticRootsValidT(a, b, c, t) {
2496 var s = [];
2497 var realRoots = quadraticRootsReal(A, B, C, s);
2498 var foundRoots = add_valid_ts(s, realRoots, t);
2499 return foundRoots != 0;
2500}
2501
2502function find_cubic_inflections(cubic, tValues) {
2503 var Ax = src[2] - src[0];
2504 var Ay = src[3] - src[1];
2505 var Bx = src[4] - 2 * src[2] + src[0];
2506 var By = src[5] - 2 * src[3] + src[1];
2507 var Cx = src[6] + 3 * (src[2] - src[4]) - src[0];
2508 var Cy = src[7] + 3 * (src[3] - src[5]) - src[1];
2509 return quadraticRootsValidT(Bx * Cy - By * Cx, (Ax * Cy - Ay * Cx),
2510 Ax * By - Ay * Bx, tValues);
2511}
2512
2513function dxy_at_t(curve, type, t) {
2514 var dxy = {};
Cary Clarkff114282016-12-14 11:56:16 -05002515 if (type == PATH_LINE) {
2516 dxy.x = curve[2] - curve[0];
2517 dxy.y = curve[3] - curve[1];
2518 } else if (type == PATH_QUAD) {
caryclarkdac1d172014-06-17 05:15:38 -07002519 var a = t - 1;
2520 var b = 1 - 2 * t;
2521 var c = t;
2522 dxy.x = a * curve[0] + b * curve[2] + c * curve[4];
2523 dxy.y = a * curve[1] + b * curve[3] + c * curve[5];
caryclark1049f122015-04-20 08:31:59 -07002524 } else if (type == PATH_CONIC) {
2525 var p20x = curve[4] - curve[0];
2526 var p20y = curve[5] - curve[1];
2527 var p10xw = (curve[2] - curve[0]) * curve[6];
2528 var p10yw = (curve[3] - curve[1]) * curve[6];
2529 var coeff0x = curve[6] * p20x - p20x;
2530 var coeff0y = curve[6] * p20y - p20y;
2531 var coeff1x = p20x - 2 * p10xw;
2532 var coeff1y = p20y - 2 * p10yw;
2533 dxy.x = t * (t * coeff0x + coeff1x) + p10xw;
2534 dxy.y = t * (t * coeff0y + coeff1y) + p10yw;
caryclarkdac1d172014-06-17 05:15:38 -07002535 } else if (type == PATH_CUBIC) {
2536 var one_t = 1 - t;
2537 var a = curve[0];
2538 var b = curve[2];
2539 var c = curve[4];
2540 var d = curve[6];
2541 dxy.x = 3 * ((b - a) * one_t * one_t + 2 * (c - b) * t * one_t + (d - c) * t * t);
2542 a = curve[1];
2543 b = curve[3];
2544 c = curve[5];
2545 d = curve[7];
2546 dxy.y = 3 * ((b - a) * one_t * one_t + 2 * (c - b) * t * one_t + (d - c) * t * t);
2547 }
2548 return dxy;
2549}
2550
Ben Wagner29380bd2017-10-09 14:43:00 -04002551function dpt_at_t(curve, t) {
Cary Clarkff114282016-12-14 11:56:16 -05002552 var type = PATH_LINE + (curve.length / 2 - 2);
Ben Wagner29380bd2017-10-09 14:43:00 -04002553 return dxy_at_t(curve, type, t);
Cary Clarkff114282016-12-14 11:56:16 -05002554}
2555
caryclarkdac1d172014-06-17 05:15:38 -07002556function drawLabel(num, px, py) {
2557 ctx.beginPath();
2558 ctx.arc(px, py, 8, 0, Math.PI*2, true);
2559 ctx.closePath();
2560 ctx.strokeStyle = "rgba(0,0,0, 0.4)";
2561 ctx.lineWidth = num == 0 || num == 3 ? 2 : 1;
2562 ctx.stroke();
2563 ctx.fillStyle = "black";
2564 ctx.font = "normal 10px Arial";
2565 // ctx.rotate(0.001);
2566 ctx.fillText(num, px - 2, py + 3);
2567 // ctx.rotate(-0.001);
2568}
2569
2570function drawLabelX(ymin, num, loc) {
2571 var px = (loc - srcLeft) * scale;
2572 var py = (ymin - srcTop) * scale - 20;
2573 drawLabel(num, px, py);
2574}
2575
2576function drawLabelY(xmin, num, loc) {
2577 var px = (xmin - srcLeft) * scale - 20;
2578 var py = (loc - srcTop) * scale;
2579 drawLabel(num, px, py);
2580}
2581
2582function drawHodoOrigin(hx, hy, hMinX, hMinY, hMaxX, hMaxY) {
2583 ctx.beginPath();
2584 ctx.moveTo(hx, hy - 100);
2585 ctx.lineTo(hx, hy);
2586 ctx.strokeStyle = hMinY < 0 ? "green" : "blue";
2587 ctx.stroke();
2588 ctx.beginPath();
2589 ctx.moveTo(hx, hy);
2590 ctx.lineTo(hx, hy + 100);
2591 ctx.strokeStyle = hMaxY > 0 ? "green" : "blue";
2592 ctx.stroke();
2593 ctx.beginPath();
2594 ctx.moveTo(hx - 100, hy);
2595 ctx.lineTo(hx, hy);
2596 ctx.strokeStyle = hMinX < 0 ? "green" : "blue";
2597 ctx.stroke();
2598 ctx.beginPath();
2599 ctx.moveTo(hx, hy);
2600 ctx.lineTo(hx + 100, hy);
2601 ctx.strokeStyle = hMaxX > 0 ? "green" : "blue";
2602 ctx.stroke();
2603}
2604
2605function scalexy(x, y, mag) {
2606 var length = Math.sqrt(x * x + y * y);
2607 return mag / length;
2608}
2609
caryclark03b03ca2015-04-23 09:13:37 -07002610function drawArrow(x, y, dx, dy, s) {
2611 var dscale = scalexy(dx, dy, 1 / scale * 100 * s);
caryclarkdac1d172014-06-17 05:15:38 -07002612 dx *= dscale;
2613 dy *= dscale;
2614 ctx.beginPath();
2615 ctx.moveTo((x - srcLeft) * scale, (y - srcTop) * scale);
2616 x += dx;
2617 y += dy;
2618 ctx.lineTo((x - srcLeft) * scale, (y - srcTop) * scale);
2619 dx /= 10;
2620 dy /= 10;
2621 ctx.lineTo((x - dy - srcLeft) * scale, (y + dx - srcTop) * scale);
2622 ctx.lineTo((x + dx * 2 - srcLeft) * scale, (y + dy * 2 - srcTop) * scale);
2623 ctx.lineTo((x + dy - srcLeft) * scale, (y - dx - srcTop) * scale);
2624 ctx.lineTo((x - srcLeft) * scale, (y - srcTop) * scale);
2625 ctx.strokeStyle = "rgba(0,75,0, 0.4)";
2626 ctx.stroke();
2627}
2628
2629function x_at_t(curve, t) {
2630 var one_t = 1 - t;
2631 if (curve.length == 4) {
2632 return one_t * curve[0] + t * curve[2];
2633 }
2634 var one_t2 = one_t * one_t;
2635 var t2 = t * t;
2636 if (curve.length == 6) {
2637 return one_t2 * curve[0] + 2 * one_t * t * curve[2] + t2 * curve[4];
2638 }
caryclark1049f122015-04-20 08:31:59 -07002639 if (curve.length == 7) {
2640 return (one_t2 * curve[0] + 2 * one_t * t * curve[2] * curve[6] + t2 * curve[4])
2641 / (one_t2 +2 * one_t * t * curve[6] + t2);
2642 }
caryclarkdac1d172014-06-17 05:15:38 -07002643 var a = one_t2 * one_t;
2644 var b = 3 * one_t2 * t;
2645 var c = 3 * one_t * t2;
2646 var d = t2 * t;
2647 return a * curve[0] + b * curve[2] + c * curve[4] + d * curve[6];
2648}
2649
2650function y_at_t(curve, t) {
2651 var one_t = 1 - t;
2652 if (curve.length == 4) {
2653 return one_t * curve[1] + t * curve[3];
2654 }
2655 var one_t2 = one_t * one_t;
2656 var t2 = t * t;
2657 if (curve.length == 6) {
2658 return one_t2 * curve[1] + 2 * one_t * t * curve[3] + t2 * curve[5];
2659 }
caryclark1049f122015-04-20 08:31:59 -07002660 if (curve.length == 7) {
2661 return (one_t2 * curve[1] + 2 * one_t * t * curve[3] * curve[6] + t2 * curve[5])
2662 / (one_t2 +2 * one_t * t * curve[6] + t2);
2663 }
caryclarkdac1d172014-06-17 05:15:38 -07002664 var a = one_t2 * one_t;
2665 var b = 3 * one_t2 * t;
2666 var c = 3 * one_t * t2;
2667 var d = t2 * t;
2668 return a * curve[1] + b * curve[3] + c * curve[5] + d * curve[7];
2669}
2670
Ben Wagner29380bd2017-10-09 14:43:00 -04002671function pt_at_t(curve, t) {
2672 var pt = {};
2673 pt.x = x_at_t(curve, t);
2674 pt.y = y_at_t(curve, t);
2675 return pt;
Cary Clarkff114282016-12-14 11:56:16 -05002676}
2677
2678function drawOrder(curve, t, label) {
2679 var px = x_at_t(curve, t);
2680 var py = y_at_t(curve, t);
caryclarkdac1d172014-06-17 05:15:38 -07002681 var _px = (px - srcLeft) * scale;
2682 var _py = (py - srcTop) * scale;
2683 ctx.beginPath();
2684 ctx.arc(_px, _py, 15, 0, Math.PI * 2, true);
2685 ctx.closePath();
2686 ctx.fillStyle = "white";
2687 ctx.fill();
2688 if (label == 'L') {
2689 ctx.strokeStyle = "rgba(255,0,0, 1)";
2690 ctx.fillStyle = "rgba(255,0,0, 1)";
2691 } else {
2692 ctx.strokeStyle = "rgba(0,0,255, 1)";
2693 ctx.fillStyle = "rgba(0,0,255, 1)";
2694 }
2695 ctx.stroke();
2696 ctx.font = "normal 16px Arial";
2697 ctx.textAlign = "center";
2698 ctx.fillText(label, _px, _py + 5);
2699 ctx.font = "normal 10px Arial";
2700}
2701
Ben Wagner29380bd2017-10-09 14:43:00 -04002702function drawVisibleOrder(curve, label) {
2703 var s = pt_at_t(curve, 0);
2704 var e = pt_at_t(curve, 1);
2705 var sOn = ptOnScreen(s);
2706 var eOn = ptOnScreen(e);
2707 var defaultT = 0.85;
2708 if (sOn && eOn)
2709 return drawOrder(curve, defaultT, label);
2710 if (sOn || eOn) {
2711 if (eOn) {
2712 defaultT = 1 - defaultT;
2713 }
2714 var step = sOn ? -defaultT / 2 : (1 - defaultT) / 2;
2715 var t = defaultT;
2716 var tries = 16;
2717 do {
2718 var mid = pt_at_t(curve, t);
2719 if (ptOnScreen(mid))
2720 return drawOrder(curve, t, label);
2721 t += step;
2722 step /= 2;
2723 } while (--tries > 0);
2724 drawOrder(curve, defaultT, label);
2725 }
2726 // scattershot until we find a visible point
2727 var denom = 2; // visit odd number num / denom to hit unique pts
2728 var tries = 6; // tries 1/2, 1/4, 3/4, 1/8, 3/8, 5/8, 7/8, 1/16 ...
2729 do {
2730 for (var numer = 1; numer < denom; numer += 2) {
2731 var t = numer / denom + 0.1;
2732 if (t >= 1) {
2733 break;
2734 }
2735 var mid = pt_at_t(curve, t);
2736 if (ptOnScreen(mid))
2737 return drawOrder(curve, t, label);
2738 }
2739 denom *= 2;
2740 } while (--tries > 0);
2741 drawOrder(curve, defaultT, label);
Cary Clarkff114282016-12-14 11:56:16 -05002742}
2743
Ben Wagner29380bd2017-10-09 14:43:00 -04002744function set_length(pt, newLen) {
2745 var len = Math.sqrt(pt.x * pt.x + pt.y * pt.y);
2746 var scale = newLen / len;
2747 var newPt = { x: pt.x * scale, y: pt.y * scale };
2748 return newPt;
Cary Clarkff114282016-12-14 11:56:16 -05002749}
2750
Ben Wagner29380bd2017-10-09 14:43:00 -04002751function drawDirection(curve, t) {
Cary Clarkff114282016-12-14 11:56:16 -05002752 var d = dpt_at_t(curve, t);
2753 d = set_length(d, 16);
Ben Wagner29380bd2017-10-09 14:43:00 -04002754 var pt = localToGlobal(pt_at_t(curve, t));
Cary Clarkff114282016-12-14 11:56:16 -05002755 ctx.beginPath();
2756 ctx.moveTo(pt.x - d.y, pt.y + d.x);
2757 ctx.lineTo(pt.x + d.x, pt.y + d.y);
2758 ctx.lineTo(pt.x + d.y, pt.y - d.x);
2759 ctx.strokeStyle = "rgba(0,75,0, 0.4)";
2760 ctx.stroke();
2761}
2762
Ben Wagner29380bd2017-10-09 14:43:00 -04002763function drawVisibleDirection(curve) {
2764 var s = pt_at_t(curve, 0);
2765 var e = pt_at_t(curve, 1);
2766 var sOn = ptOnScreen(s);
2767 var eOn = ptOnScreen(e);
2768 var defaultT = 0.65;
2769 if (sOn && eOn) {
2770 return drawDirection(curve, defaultT);
2771 }
2772 if (sOn || eOn) {
2773 if (eOn) {
2774 defaultT = 1 - defaultT;
2775 }
2776 var step = sOn ? -defaultT / 2 : (1 - defaultT) / 2;
2777 var t = defaultT;
2778 var tries = 16;
2779 do {
2780 var mid = pt_at_t(curve, t);
2781 if (ptOnScreen(mid))
2782 return drawDirection(curve, t);
2783 t += step;
2784 step /= 2;
2785 } while (--tries > 0);
2786 drawDirection(curve, defaultT);
2787 }
2788 // scattershot until we find a visible point
2789 var denom = 2; // visit odd number num / denom to hit unique pts
2790 var tries = 6; // tries 1/2, 1/4, 3/4, 1/8, 3/8, 5/8, 7/8, 1/16 ...
2791 do {
2792 for (var numer = 1; numer < denom; numer += 2) {
2793 var t = numer / denom + 0.1;
2794 if (t >= 1) {
2795 break;
2796 }
2797 var mid = pt_at_t(curve, t);
2798 if (ptOnScreen(mid))
2799 return drawDirection(curve, t);
2800 }
2801 denom *= 2;
2802 } while (--tries > 0);
2803 drawDirection(curve, defaultT);
Cary Clarkff114282016-12-14 11:56:16 -05002804}
2805
2806function drawID(curve, t, id) {
2807 var px = x_at_t(curve, t);
2808 var py = y_at_t(curve, t);
caryclarkdac1d172014-06-17 05:15:38 -07002809 var _px = (px - srcLeft) * scale;
2810 var _py = (py - srcTop) * scale;
2811 draw_id_at(id, _px, _py);
2812}
2813
Ben Wagner29380bd2017-10-09 14:43:00 -04002814function localToGlobal(local) {
2815 var global = {};
2816 global.x = (local.x - srcLeft) * scale;
2817 global.y = (local.y - srcTop) * scale;
2818 return global;
Cary Clarkff114282016-12-14 11:56:16 -05002819}
2820
Ben Wagner29380bd2017-10-09 14:43:00 -04002821function ptOnScreen(local) {
2822 var pt = localToGlobal(local);
2823 return 10 <= pt.x && pt.x <= screenWidth - 10
2824 && 10 <= pt.y && pt.y <= screenHeight - 10;
Cary Clarkff114282016-12-14 11:56:16 -05002825}
2826
Ben Wagner29380bd2017-10-09 14:43:00 -04002827function drawVisibleID(curve, defaultT, id) {
2828 // determine if either or both ends are visible
2829 var s = pt_at_t(curve, 0);
2830 var e = pt_at_t(curve, 1);
2831 var sOn = ptOnScreen(s);
2832 var eOn = ptOnScreen(e);
2833 if (sOn && eOn)
2834 return drawID(curve, defaultT, id);
2835 if (sOn || eOn) {
2836 var step = sOn ? -defaultT / 2 : (1 - defaultT) / 2;
2837 var t = defaultT;
2838 var tries = 16;
2839 do {
2840 var mid = pt_at_t(curve, t);
2841 if (ptOnScreen(mid))
2842 return drawID(curve, t, id);
2843 t += step;
2844 step /= 2;
2845 } while (--tries > 0);
2846 drawID(curve, defaultT, id);
2847 }
2848 // scattershot until we find a visible point
2849 var denom = 2; // visit odd number num / denom to hit unique pts
2850 var tries = 6; // tries 1/2, 1/4, 3/4, 1/8, 3/8, 5/8, 7/8, 1/16 ...
2851 do {
2852 for (var numer = 1; numer < denom; numer += 2) {
2853 var t = numer / denom;
2854 var mid = pt_at_t(curve, t);
2855 if (ptOnScreen(mid))
2856 return drawID(curve, t, id);
2857 }
2858 denom *= 2;
2859 } while (--tries > 0);
2860 drawID(curve, defaultT, id);
Cary Clarkff114282016-12-14 11:56:16 -05002861}
2862
caryclarkdac1d172014-06-17 05:15:38 -07002863function draw_id_at(id, _px, _py) {
2864 ctx.beginPath();
2865 ctx.arc(_px, _py, 15, 0, Math.PI * 2, true);
2866 ctx.closePath();
2867 ctx.fillStyle = "white";
2868 ctx.fill();
2869 ctx.strokeStyle = "rgba(127,127,0, 1)";
2870 ctx.fillStyle = "rgba(127,127,0, 1)";
2871 ctx.stroke();
2872 ctx.font = "normal 16px Arial";
2873 ctx.textAlign = "center";
2874 ctx.fillText(id, _px, _py + 5);
2875 ctx.font = "normal 10px Arial";
2876}
2877
2878function drawLinePartialID(id, x1, y1, x2, y2, t1, t2) {
2879 var curve = [x1, y1, x2, y2];
2880 drawCurvePartialID(id, curve, t1, t2);
2881}
2882
caryclark55888e42016-07-18 10:01:36 -07002883function drawLineID(id, x1, y1, x2, y2) {
2884 drawLinePartialID(id, x1, y1, x2, y2, 0, 1);
2885}
2886
caryclarkdac1d172014-06-17 05:15:38 -07002887function drawQuadPartialID(id, x1, y1, x2, y2, x3, y3, t1, t2) {
2888 var curve = [x1, y1, x2, y2, x3, y3];
2889 drawCurvePartialID(id, curve, t1, t2);
2890}
2891
caryclark55888e42016-07-18 10:01:36 -07002892function drawQuadID(id, x1, y1, x2, y2, x3, y3) {
2893 drawQuadPartialID(id, x1, y1, x2, y2, x3, y3, 0, 1);
2894}
2895
caryclark1049f122015-04-20 08:31:59 -07002896function drawConicPartialID(id, x1, y1, x2, y2, x3, y3, w, t1, t2) {
2897 var curve = [x1, y1, x2, y2, x3, y3, w];
2898 drawCurvePartialID(id, curve, t1, t2);
2899}
2900
caryclark55888e42016-07-18 10:01:36 -07002901function drawConicID(id, x1, y1, x2, y2, x3, y3, w) {
2902 drawConicPartialID(id, x1, y1, x2, y2, x3, y3, w, 0, 1);
2903}
2904
caryclarkdac1d172014-06-17 05:15:38 -07002905function drawCubicPartialID(id, x1, y1, x2, y2, x3, y3, x4, y4, t1, t2) {
2906 var curve = [x1, y1, x2, y2, x3, y3, x4, y4];
2907 drawCurvePartialID(id, curve, t1, t2);
2908}
2909
caryclark55888e42016-07-18 10:01:36 -07002910function drawCubicID(id, x1, y1, x2, y2, x3, y3, x4, y4) {
2911 drawCubicPartialID(id, x1, y1, x2, y2, x3, y3, x4, y4, 0, 1);
2912}
2913
caryclarkdac1d172014-06-17 05:15:38 -07002914function drawCurvePartialID(id, curve, t1, t2) {
Cary Clarkff114282016-12-14 11:56:16 -05002915 drawVisibleID(curve, (t1 + t2) / 2, id);
caryclarkdac1d172014-06-17 05:15:38 -07002916}
2917
2918function drawCurveSpecials(test, curve, type) {
2919 if (pt_labels) {
2920 drawPoints(curve, type, pt_labels == 2);
2921 }
2922 if (control_lines != 0) {
2923 drawControlLines(curve, type, control_lines);
2924 }
2925 if (curve_t) {
2926 drawPointAtT(curve, type);
2927 }
2928 if (draw_midpoint) {
2929 var mid = pointAtT(curve, type, 0.5);
2930 drawPoint(mid.x, mid.y, true);
2931 }
2932 if (draw_id) {
2933 var id = idByCurve(test, curve, type);
2934 if (id >= 0) {
Cary Clarkff114282016-12-14 11:56:16 -05002935 drawVisibleID(curve, 0.5, id);
caryclarkdac1d172014-06-17 05:15:38 -07002936 }
2937 }
Ben Wagner29380bd2017-10-09 14:43:00 -04002938 if (draw_direction) {
2939 drawVisibleDirection(curve);
Cary Clarkff114282016-12-14 11:56:16 -05002940 }
caryclarkdac1d172014-06-17 05:15:38 -07002941 if (type == PATH_LINE) {
2942 return;
2943 }
2944 if (draw_deriviatives > 0) {
2945 var d = dxy_at_t(curve, type, 0);
caryclark03b03ca2015-04-23 09:13:37 -07002946 drawArrow(curve[0], curve[1], d.x, d.y, 1);
caryclarkdac1d172014-06-17 05:15:38 -07002947 if (draw_deriviatives == 2) {
2948 d = dxy_at_t(curve, type, 1);
2949 if (type == PATH_CUBIC) {
caryclark03b03ca2015-04-23 09:13:37 -07002950 drawArrow(curve[6], curve[7], d.x, d.y, 1);
caryclarkdac1d172014-06-17 05:15:38 -07002951 } else {
caryclark03b03ca2015-04-23 09:13:37 -07002952 drawArrow(curve[4], curve[5], d.x, d.y, 1);
caryclarkdac1d172014-06-17 05:15:38 -07002953 }
2954 }
2955 if (draw_midpoint) {
2956 var mid = pointAtT(curve, type, 0.5);
2957 d = dxy_at_t(curve, type, 0.5);
caryclark03b03ca2015-04-23 09:13:37 -07002958 drawArrow(mid.x, mid.y, d.x, d.y, 1);
caryclarkdac1d172014-06-17 05:15:38 -07002959 }
2960 }
2961 if (type != PATH_CUBIC) {
2962 return;
2963 }
caryclarkdac1d172014-06-17 05:15:38 -07002964 if (draw_sequence) {
2965 var ymin = Math.min(curve[1], curve[3], curve[5], curve[7]);
2966 for (var i = 0; i < 8; i+= 2) {
2967 drawLabelX(ymin, i >> 1, curve[i]);
2968 }
2969 var xmin = Math.min(curve[0], curve[2], curve[4], curve[6]);
2970 for (var i = 1; i < 8; i+= 2) {
2971 drawLabelY(xmin, i >> 1, curve[i]);
2972 }
2973 }
2974}
2975
2976function logCurves(test) {
2977 for (curves in test) {
2978 var curve = test[curves];
2979 dumpCurve(curve);
2980 }
2981}
2982
2983function curveToString(curve) {
2984 var str = "{{";
caryclark1049f122015-04-20 08:31:59 -07002985 var length = curve.length == 7 ? 6 : curve.length;
2986 if (curve.length == 7) {
2987 str += "{";
2988 }
2989 for (i = 0; i < length; i += 2) {
caryclarkdac1d172014-06-17 05:15:38 -07002990 str += curve[i].toFixed(decimal_places) + "," + curve[i + 1].toFixed(decimal_places);
2991 if (i < curve.length - 2) {
2992 str += "}, {";
2993 }
2994 }
caryclark1049f122015-04-20 08:31:59 -07002995 str += "}";
2996 if (curve.length == 7) {
2997 str += "}, " + curve[6].toFixed(decimal_places);
2998 }
2999 str += "}";
caryclarkdac1d172014-06-17 05:15:38 -07003000 return str;
3001}
3002
3003function dumpCurve(curve) {
3004 console.log(curveToString(curve));
3005}
3006
3007function draw(test, lines, title) {
3008 ctx.fillStyle = "rgba(0,0,0, 0.1)";
3009 ctx.font = "normal 50px Arial";
3010 ctx.textAlign = "left";
3011 ctx.fillText(title, 50, 50);
3012 ctx.font = "normal 10px Arial";
3013 ctx.lineWidth = "1.001"; "0.999";
3014 var secondPath = test.length;
3015 var closeCount = 0;
3016 logStart = -1;
3017 logRange = 0;
3018 // find last active rec type at this step
3019 var curType = test[0];
3020 var curStep = 0;
3021 var hasOp = false;
3022 var lastActive = 0;
3023 var lastAdd = 0;
caryclark624637c2015-05-11 07:21:27 -07003024 var lastCoin = 0;
caryclarkdac1d172014-06-17 05:15:38 -07003025 var lastSect = 0;
3026 var lastSort = 0;
3027 var lastMark = 0;
caryclark03b03ca2015-04-23 09:13:37 -07003028 var lastTop = 0;
caryclarkdac1d172014-06-17 05:15:38 -07003029 activeCount = 0;
3030 addCount = 0;
3031 angleCount = 0;
3032 opCount = 0;
3033 sectCount = 0;
3034 sortCount = 0;
caryclark03b03ca2015-04-23 09:13:37 -07003035 topCount = 0;
caryclarkdac1d172014-06-17 05:15:38 -07003036 markCount = 0;
3037 activeMax = 0;
3038 addMax = 0;
3039 angleMax = 0;
caryclark624637c2015-05-11 07:21:27 -07003040 coinMax = 0;
caryclarkdac1d172014-06-17 05:15:38 -07003041 opMax = 0;
3042 sectMax = 0;
3043 sectMax2 = 0;
3044 sortMax = 0;
caryclark03b03ca2015-04-23 09:13:37 -07003045 topMax = 0;
caryclarkdac1d172014-06-17 05:15:38 -07003046 markMax = 0;
3047 lastIndex = test.length - 3;
3048 for (var tIndex = 0; tIndex < test.length; tIndex += 3) {
3049 var recType = test[tIndex];
3050 if (!typeof recType == 'number' || recType < REC_TYPE_UNKNOWN || recType > REC_TYPE_LAST) {
3051 console.log("unknown rec type: " + recType);
3052 throw "stop execution";
3053 }
3054 // if (curType == recType && curType != REC_TYPE_ADD) {
3055 // continue;
3056 // }
3057 var inStepRange = step_limit == 0 || curStep < step_limit;
3058 curType = recType;
3059 if (recType == REC_TYPE_OP) {
3060 hasOp = true;
3061 continue;
3062 }
3063 if (recType == REC_TYPE_UNKNOWN) {
3064 // these types do not advance step
3065 continue;
3066 }
3067 var bumpStep = false;
3068 var records = test[tIndex + 2];
3069 var fragType = records[0];
3070 if (recType == REC_TYPE_ADD) {
3071 if (records.length != 2) {
3072 console.log("expect only two elements: " + records.length);
3073 throw "stop execution";
3074 }
3075 if (fragType == ADD_MOVETO || fragType == ADD_CLOSE) {
3076 continue;
3077 }
3078 ++addMax;
3079 if (!draw_add || !inStepRange) {
3080 continue;
3081 }
3082 lastAdd = tIndex;
3083 ++addCount;
3084 bumpStep = true;
3085 }
3086 if (recType == REC_TYPE_PATH && hasOp) {
3087 secondPath = tIndex;
3088 }
caryclark54359292015-03-26 07:52:43 -07003089 if (recType == REC_TYPE_PATH2 && hasOp) {
3090 secondPath = tIndex;
3091 }
caryclarkdac1d172014-06-17 05:15:38 -07003092 if (recType == REC_TYPE_ACTIVE) {
3093 ++activeMax;
3094 if (!draw_active || !inStepRange) {
3095 continue;
3096 }
3097 lastActive = tIndex;
3098 ++activeCount;
3099 bumpStep = true;
3100 }
3101 if (recType == REC_TYPE_ACTIVE_OP) {
3102 ++opMax;
3103 if (!draw_op || !inStepRange) {
3104 continue;
3105 }
3106 lastOp = tIndex;
3107 ++opCount;
3108 bumpStep = true;
3109 }
caryclark54359292015-03-26 07:52:43 -07003110 if (recType == REC_TYPE_AFTERPART) {
3111 if (draw_angle != 3 || !inStepRange) {
3112 continue;
3113 }
3114 lastAngle = tIndex;
3115 ++angleCount;
3116 bumpStep = true;
3117 }
caryclarkdac1d172014-06-17 05:15:38 -07003118 if (recType == REC_TYPE_ANGLE) {
3119 ++angleMax;
caryclark54359292015-03-26 07:52:43 -07003120 if (draw_angle == 0 || draw_angle == 3 || !inStepRange) {
caryclarkdac1d172014-06-17 05:15:38 -07003121 continue;
3122 }
3123 lastAngle = tIndex;
3124 ++angleCount;
3125 bumpStep = true;
3126 }
caryclark624637c2015-05-11 07:21:27 -07003127 if (recType == REC_TYPE_COINCIDENCE) {
3128 ++coinMax;
3129 if (!draw_coincidence || !inStepRange) {
3130 continue;
3131 }
3132 lastCoin = tIndex;
3133 ++coinCount;
3134 bumpStep = true;
3135 }
caryclarkdac1d172014-06-17 05:15:38 -07003136 if (recType == REC_TYPE_SECT) {
3137 if (records.length != 2) {
3138 console.log("expect only two elements: " + records.length);
3139 throw "stop execution";
3140 }
3141 ++sectMax;
3142 var sectBump = 1;
3143 switch (fragType) {
3144 case INTERSECT_LINE:
3145 case INTERSECT_QUAD_LINE:
3146 case INTERSECT_QUAD:
caryclark1049f122015-04-20 08:31:59 -07003147 case INTERSECT_CONIC_LINE:
caryclark55888e42016-07-18 10:01:36 -07003148 case INTERSECT_CONIC_QUAD:
caryclark1049f122015-04-20 08:31:59 -07003149 case INTERSECT_CONIC:
caryclarkdac1d172014-06-17 05:15:38 -07003150 case INTERSECT_SELF_CUBIC:
3151 case INTERSECT_CUBIC_LINE:
3152 case INTERSECT_CUBIC_QUAD:
3153 case INTERSECT_CUBIC:
3154 sectBump = 1;
3155 break;
3156 case INTERSECT_LINE_2:
3157 case INTERSECT_QUAD_LINE_2:
3158 case INTERSECT_QUAD_2:
caryclark1049f122015-04-20 08:31:59 -07003159 case INTERSECT_CONIC_LINE_2:
caryclark55888e42016-07-18 10:01:36 -07003160 case INTERSECT_CONIC_QUAD_2:
caryclark1049f122015-04-20 08:31:59 -07003161 case INTERSECT_CONIC_2:
caryclarkdac1d172014-06-17 05:15:38 -07003162 case INTERSECT_CUBIC_LINE_2:
3163 case INTERSECT_CUBIC_QUAD_2:
3164 case INTERSECT_CUBIC_2:
3165 sectBump = 2;
3166 break;
3167 case INTERSECT_LINE_NO:
3168 case INTERSECT_QUAD_LINE_NO:
3169 case INTERSECT_QUAD_NO:
caryclark1049f122015-04-20 08:31:59 -07003170 case INTERSECT_CONIC_LINE_NO:
caryclark55888e42016-07-18 10:01:36 -07003171 case INTERSECT_CONIC_QUAD_NO:
caryclark1049f122015-04-20 08:31:59 -07003172 case INTERSECT_CONIC_NO:
caryclarkdac1d172014-06-17 05:15:38 -07003173 case INTERSECT_SELF_CUBIC_NO:
3174 case INTERSECT_CUBIC_LINE_NO:
3175 case INTERSECT_CUBIC_QUAD_NO:
3176 case INTERSECT_CUBIC_NO:
3177 sectBump = 0;
3178 break;
caryclark6c3b9cd2016-09-26 05:36:58 -07003179 case INTERSECT_CONIC_QUAD_3:
caryclarkdac1d172014-06-17 05:15:38 -07003180 case INTERSECT_CUBIC_LINE_3:
3181 case INTERSECT_CUBIC_QUAD_3:
3182 case INTERSECT_CUBIC_3:
3183 sectBump = 3;
3184 break;
caryclark6c3b9cd2016-09-26 05:36:58 -07003185 case INTERSECT_CONIC_QUAD_4:
caryclarkdac1d172014-06-17 05:15:38 -07003186 case INTERSECT_CUBIC_QUAD_4:
3187 case INTERSECT_CUBIC_4:
3188 sectBump = 4;
3189 break;
3190 default:
3191 console.log("missing case " + records.length);
3192 throw "stop execution";
3193 }
3194 sectMax2 += sectBump;
3195 if (draw_intersection <= 1 || !inStepRange) {
3196 continue;
3197 }
3198 lastSect = tIndex;
3199 sectCount += sectBump;
3200 bumpStep = true;
3201 }
3202 if (recType == REC_TYPE_SORT) {
3203 ++sortMax;
3204 if (!draw_sort || !inStepRange) {
3205 continue;
3206 }
3207 lastSort = tIndex;
3208 ++sortCount;
3209 bumpStep = true;
3210 }
caryclark03b03ca2015-04-23 09:13:37 -07003211 if (recType == REC_TYPE_TOP) {
3212 ++topMax;
3213 if (!draw_top || !inStepRange) {
3214 continue;
3215 }
3216 lastTop = tIndex;
3217 ++topCount;
3218 bumpStep = true;
3219 }
caryclarkdac1d172014-06-17 05:15:38 -07003220 if (recType == REC_TYPE_MARK) {
3221 ++markMax;
3222 if (!draw_mark || !inStepRange) {
3223 continue;
3224 }
3225 lastMark = tIndex;
3226 ++markCount;
3227 bumpStep = true;
3228 }
3229 if (bumpStep) {
3230 lastIndex = tIndex;
3231 logStart = test[tIndex + 1];
3232 logRange = records.length / 2;
3233 ++curStep;
3234 }
3235 }
3236 stepMax = (draw_add ? addMax : 0)
3237 + (draw_active ? activeMax : 0)
reed0dc4dd62015-03-24 13:55:33 -07003238 + (draw_angle ? angleMax : 0)
caryclark624637c2015-05-11 07:21:27 -07003239 + (draw_coincidence ? coinMax : 0)
caryclark54359292015-03-26 07:52:43 -07003240 + (draw_op ? opMax : 0)
caryclarkdac1d172014-06-17 05:15:38 -07003241 + (draw_sort ? sortMax : 0)
caryclark03b03ca2015-04-23 09:13:37 -07003242 + (draw_top ? topMax : 0)
caryclarkdac1d172014-06-17 05:15:38 -07003243 + (draw_mark ? markMax : 0)
3244 + (draw_intersection == 2 ? sectMax : draw_intersection == 3 ? sectMax2 : 0);
3245 if (stepMax == 0) {
caryclark624637c2015-05-11 07:21:27 -07003246 stepMax = addMax + activeMax + angleMax + coinMax + opMax + sortMax + topMax + markMax;
caryclarkdac1d172014-06-17 05:15:38 -07003247 }
3248 drawnPts = [];
3249 drawnLines = [];
3250 drawnQuads = [];
caryclark1049f122015-04-20 08:31:59 -07003251 drawnConics = [];
caryclarkdac1d172014-06-17 05:15:38 -07003252 drawnCubics = [];
3253 focusXmin = focusYmin = Infinity;
3254 focusXmax = focusYmax = -Infinity;
3255 var pathIndex = 0;
3256 var opLetter = 'S';
3257 for (var tIndex = lastIndex; tIndex >= 0; tIndex -= 3) {
3258 var recType = test[tIndex];
3259 var records = test[tIndex + 2];
3260 for (var recordIndex = 0; recordIndex < records.length; recordIndex += 2) {
3261 var fragType = records[recordIndex];
3262 if (!typeof fragType == 'number' || fragType < 1 || fragType > FRAG_TYPE_LAST) {
3263 console.log("unknown in range frag type: " + fragType);
3264 throw "stop execution";
3265 }
3266 var frags = records[recordIndex + 1];
3267 focus_enabled = false;
3268 switch (recType) {
3269 case REC_TYPE_COMPUTED:
3270 if (draw_computed == 0) {
3271 continue;
3272 }
3273 ctx.lineWidth = 1;
3274 ctx.strokeStyle = pathIndex == 0 ? "black" : "red";
3275 ctx.fillStyle = "blue";
3276 var drawThis = false;
3277 switch (fragType) {
3278 case PATH_QUAD:
caryclark1049f122015-04-20 08:31:59 -07003279 if ((draw_computed & 0x9) == 1 || ((draw_computed & 8) != 0
3280 && (draw_computed & 7) == pathIndex)) {
caryclarkdac1d172014-06-17 05:15:38 -07003281 drawQuad(frags[0], frags[1], frags[2], frags[3],
3282 frags[4], frags[5]);
3283 drawThis = true;
3284 }
3285 break;
caryclark1049f122015-04-20 08:31:59 -07003286 case PATH_CONIC:
3287 if ((draw_computed & 0xA) == 2 || ((draw_computed & 8) != 0
3288 && (draw_computed & 7) == pathIndex)) {
3289 drawConicWithQuads(frags[0], frags[1], frags[2], frags[3],
3290 frags[4], frags[5], frags[6]);
3291 drawThis = true;
3292 }
3293 break;
caryclarkdac1d172014-06-17 05:15:38 -07003294 case PATH_CUBIC:
caryclark1049f122015-04-20 08:31:59 -07003295 if ((draw_computed & 0xC) == 4 || ((draw_computed & 8) != 0
3296 && (draw_computed & 7) == pathIndex)) {
caryclarkdac1d172014-06-17 05:15:38 -07003297 drawCubic(frags[0], frags[1], frags[2], frags[3],
3298 frags[4], frags[5], frags[6], frags[7]);
3299 drawThis = true;
3300 }
3301 ++pathIndex;
3302 break;
3303 case COMPUTED_SET_1:
3304 pathIndex = 0;
3305 break;
3306 case COMPUTED_SET_2:
3307 pathIndex = 1;
3308 break;
3309 default:
3310 console.log("unknown REC_TYPE_COMPUTED frag type: " + fragType);
3311 throw "stop execution";
3312 }
3313 if (!drawThis || collect_bounds) {
3314 break;
3315 }
3316 drawCurveSpecials(test, frags, fragType);
3317 break;
caryclark26ad22a2015-10-16 09:03:38 -07003318 case REC_TYPE_ALIGNED:
3319 if (draw_path < 4) {
3320 continue;
3321 }
caryclarkdac1d172014-06-17 05:15:38 -07003322 case REC_TYPE_PATH:
caryclark54359292015-03-26 07:52:43 -07003323 case REC_TYPE_PATH2:
caryclark26ad22a2015-10-16 09:03:38 -07003324 if (REC_TYPE_ALIGNED != recType && draw_path >= 4) {
3325 continue;
3326 }
caryclarkdac1d172014-06-17 05:15:38 -07003327 if (!draw_path) {
3328 continue;
3329 }
3330 var firstPath = tIndex < secondPath;
3331 if ((draw_path & (firstPath ? 1 : 2)) == 0) {
3332 continue;
3333 }
3334 ctx.lineWidth = 1;
3335 ctx.strokeStyle = firstPath ? "black" : "red";
3336 ctx.fillStyle = "blue";
caryclark55888e42016-07-18 10:01:36 -07003337 var frags2 = [];
caryclarkdac1d172014-06-17 05:15:38 -07003338 switch (fragType) {
3339 case PATH_LINE:
caryclark54359292015-03-26 07:52:43 -07003340 for (var i = 0; i < 4; ++ i) { frags2[i] = frags[i + 1]; }
3341 drawLine(frags2[0], frags2[1], frags2[2], frags2[3]);
caryclarkdac1d172014-06-17 05:15:38 -07003342 break;
3343 case PATH_QUAD:
caryclark54359292015-03-26 07:52:43 -07003344 for (var i = 0; i < 6; ++ i) { frags2[i] = frags[i + 1]; }
3345 drawQuad(frags2[0], frags2[1], frags2[2], frags2[3],
3346 frags2[4], frags2[5]);
caryclarkdac1d172014-06-17 05:15:38 -07003347 break;
caryclark1049f122015-04-20 08:31:59 -07003348 case PATH_CONIC:
3349 for (var i = 0; i < 7; ++ i) { frags2[i] = frags[i + 1]; }
3350 drawConicWithQuads(frags2[0], frags2[1], frags2[2], frags2[3],
3351 frags2[4], frags2[5], frags2[6]);
3352 break;
caryclarkdac1d172014-06-17 05:15:38 -07003353 case PATH_CUBIC:
caryclark54359292015-03-26 07:52:43 -07003354 for (var i = 0; i < 8; ++ i) { frags2[i] = frags[i + 1]; }
3355 drawCubic(frags2[0], frags2[1], frags2[2], frags2[3],
3356 frags2[4], frags2[5], frags2[6], frags2[7]);
caryclarkdac1d172014-06-17 05:15:38 -07003357 break;
3358 default:
caryclark26ad22a2015-10-16 09:03:38 -07003359 console.log("unknown " + recType + " frag type: " + fragType);
caryclarkdac1d172014-06-17 05:15:38 -07003360 throw "stop execution";
3361 }
3362 if (collect_bounds) {
3363 break;
3364 }
caryclark54359292015-03-26 07:52:43 -07003365 drawCurveSpecials(test, frags2, fragType);
caryclarkdac1d172014-06-17 05:15:38 -07003366 break;
3367 case REC_TYPE_OP:
3368 switch (fragType) {
3369 case OP_INTERSECT: opLetter = 'I'; break;
3370 case OP_DIFFERENCE: opLetter = 'D'; break;
3371 case OP_UNION: opLetter = 'U'; break;
3372 case OP_XOR: opLetter = 'X'; break;
3373 default:
3374 console.log("unknown REC_TYPE_OP frag type: " + fragType);
3375 throw "stop execution";
3376 }
3377 break;
3378 case REC_TYPE_ACTIVE:
3379 if (!draw_active || (step_limit > 0 && tIndex < lastActive)) {
3380 continue;
3381 }
3382 var x1 = frags[SPAN_X1];
3383 var y1 = frags[SPAN_Y1];
3384 var x2 = frags[SPAN_X2];
3385 var y2 = frags[SPAN_Y2];
caryclark55888e42016-07-18 10:01:36 -07003386 var x3, y3, x3, y4, w;
caryclarkdac1d172014-06-17 05:15:38 -07003387 ctx.lineWidth = 3;
3388 ctx.strokeStyle = "rgba(0,0,255, 0.3)";
3389 focus_enabled = true;
3390 switch (fragType) {
3391 case ACTIVE_LINE_SPAN:
caryclark55888e42016-07-18 10:01:36 -07003392 drawLine(x1, y1, x2, y2);
caryclarkdac1d172014-06-17 05:15:38 -07003393 if (draw_id) {
caryclark55888e42016-07-18 10:01:36 -07003394 drawLineID(frags[0], x1, y1, x2, y2);
3395 }
3396 if (pt_labels) {
3397 var curve = [x1, y1, x2, y2];
3398 ctx.fillStyle = "blue";
3399 drawPoints(curve, PATH_LINE, pt_labels == 2);
caryclarkdac1d172014-06-17 05:15:38 -07003400 }
3401 break;
3402 case ACTIVE_QUAD_SPAN:
3403 x3 = frags[SPAN_X3];
3404 y3 = frags[SPAN_Y3];
caryclark55888e42016-07-18 10:01:36 -07003405 drawQuad(x1, y1, x2, y2, x3, y3);
caryclarkdac1d172014-06-17 05:15:38 -07003406 if (draw_id) {
caryclark55888e42016-07-18 10:01:36 -07003407 drawQuadID(frags[0], x1, y1, x2, y2, x3, y3);
3408 }
3409 if (pt_labels) {
3410 var curve = [x1, y1, x2, y2, x3, y3];
3411 ctx.fillStyle = "blue";
3412 drawPoints(curve, PATH_QUAD, pt_labels == 2);
caryclarkdac1d172014-06-17 05:15:38 -07003413 }
3414 break;
caryclark1049f122015-04-20 08:31:59 -07003415 case ACTIVE_CONIC_SPAN:
3416 x3 = frags[SPAN_X3];
3417 y3 = frags[SPAN_Y3];
caryclark1049f122015-04-20 08:31:59 -07003418 w = frags[SPAN_K_W];
caryclark55888e42016-07-18 10:01:36 -07003419 drawConicWithQuads(x1, y1, x2, y2, x3, y3, w);
caryclark1049f122015-04-20 08:31:59 -07003420 if (draw_id) {
caryclark55888e42016-07-18 10:01:36 -07003421 drawConicID(frags[0], x1, y1, x2, y2, x3, y3, w);
3422 }
3423 if (pt_labels) {
3424 var curve = [x1, y1, x2, y2, x3, y3, w];
3425 ctx.fillStyle = "blue";
3426 drawPoints(curve, PATH_CONIC, pt_labels == 2);
caryclark1049f122015-04-20 08:31:59 -07003427 }
3428 break;
caryclarkdac1d172014-06-17 05:15:38 -07003429 case ACTIVE_CUBIC_SPAN:
3430 x3 = frags[SPAN_X3];
3431 y3 = frags[SPAN_Y3];
3432 x4 = frags[SPAN_X4];
3433 y4 = frags[SPAN_Y4];
caryclark55888e42016-07-18 10:01:36 -07003434 drawCubic(x1, y1, x2, y2, x3, y3, x4, y4);
caryclarkdac1d172014-06-17 05:15:38 -07003435 if (draw_id) {
caryclark55888e42016-07-18 10:01:36 -07003436 drawCubicID(frags[0], x1, y1, x2, y2, x3, y3, x4, y4);
3437 }
3438 if (pt_labels) {
3439 var curve = [x1, y1, x2, y2, x3, y3, x4, y4];
3440 ctx.fillStyle = "blue";
3441 drawPoints(curve, PATH_CUBIC, pt_labels == 2);
caryclarkdac1d172014-06-17 05:15:38 -07003442 }
3443 break;
3444 default:
3445 console.log("unknown REC_TYPE_ACTIVE frag type: " + fragType);
3446 throw "stop execution";
3447 }
3448 break;
3449 case REC_TYPE_ACTIVE_OP:
3450 if (!draw_op || (step_limit > 0 && tIndex < lastOp)) {
3451 continue;
3452 }
3453 focus_enabled = true;
3454 ctx.lineWidth = 3;
3455 var activeSpan = frags[7] == "1";
3456 ctx.strokeStyle = activeSpan ? "rgba(45,160,0, 0.3)" : "rgba(255,45,0, 0.5)";
3457 var curve = curvePartialByID(test, frags[0], frags[1], frags[2]);
3458 drawCurve(curve);
3459 if (draw_op > 1) {
3460 drawArc(curve, false, frags[3], frags[4]);
3461 drawArc(curve, true, frags[5], frags[6]);
3462 }
3463 break;
3464 case REC_TYPE_ADD:
3465 if (!draw_add) {
3466 continue;
3467 }
3468 ctx.lineWidth = 3;
3469 ctx.strokeStyle = closeCount == 0 ? "rgba(0,0,255, 0.3)"
3470 : closeCount == 1 ? "rgba(0,127,0, 0.3)"
3471 : closeCount == 2 ? "rgba(0,127,127, 0.3)"
3472 : closeCount == 3 ? "rgba(127,127,0, 0.3)"
3473 : "rgba(127,0,127, 0.3)";
3474 focus_enabled = true;
3475 switch (fragType) {
3476 case ADD_MOVETO:
3477 break;
3478 case ADD_LINETO:
3479 if (step_limit == 0 || tIndex >= lastAdd) {
3480 drawLine(frags[0], frags[1], frags[2], frags[3]);
3481 }
3482 break;
3483 case ADD_QUADTO:
3484 if (step_limit == 0 || tIndex >= lastAdd) {
3485 drawQuad(frags[0], frags[1], frags[2], frags[3], frags[4], frags[5]);
3486 }
3487 break;
caryclark1049f122015-04-20 08:31:59 -07003488 case ADD_CONICTO:
3489 if (step_limit == 0 || tIndex >= lastAdd) {
3490 drawConicWithQuads(frags[0], frags[1], frags[2], frags[3],
3491 frags[4], frags[5], frags[6]);
3492 }
3493 break;
caryclarkdac1d172014-06-17 05:15:38 -07003494 case ADD_CUBICTO:
3495 if (step_limit == 0 || tIndex >= lastAdd) {
3496 drawCubic(frags[0], frags[1], frags[2], frags[3],
3497 frags[4], frags[5], frags[6], frags[7]);
3498 }
3499 break;
3500 case ADD_CLOSE:
3501 ++closeCount;
3502 break;
3503 case ADD_FILL:
3504 break;
3505 default:
3506 console.log("unknown REC_TYPE_ADD frag type: " + fragType);
3507 throw "stop execution";
3508 }
3509 break;
3510 case REC_TYPE_ANGLE:
caryclark54359292015-03-26 07:52:43 -07003511 angleBetween = frags[18] == "T";
3512 afterIndex = 0;
3513 if (draw_angle == 0 || draw_angle == 3 || (step_limit > 0 && tIndex < lastAngle)) {
caryclarkdac1d172014-06-17 05:15:38 -07003514 continue;
3515 }
3516 focus_enabled = true;
3517 ctx.lineWidth = 3;
3518 ctx.strokeStyle = "rgba(127,45,127, 0.3)";
caryclark54359292015-03-26 07:52:43 -07003519 var leftCurve = curvePartialByID(test, frags[0], frags[4], frags[5]);
3520 var midCurve = curvePartialByID(test, frags[6], frags[10], frags[11]);
3521 var rightCurve = curvePartialByID(test, frags[12], frags[16], frags[17]);
caryclarkdac1d172014-06-17 05:15:38 -07003522 drawCurve(leftCurve);
3523 drawCurve(rightCurve);
caryclark54359292015-03-26 07:52:43 -07003524 ctx.strokeStyle = angleBetween ? "rgba(0,160,45, 0.3)" : "rgba(255,0,45, 0.5)";
caryclarkdac1d172014-06-17 05:15:38 -07003525 drawCurve(midCurve);
3526 if (draw_angle > 1) {
Cary Clarkff114282016-12-14 11:56:16 -05003527 drawVisibleOrder(leftCurve, 'L');
3528 drawVisibleOrder(rightCurve, 'R');
3529 }
Ben Wagner29380bd2017-10-09 14:43:00 -04003530 if (draw_id) {
3531 drawVisibleID(leftCurve, 0.5, frags[0]);
3532 drawVisibleID(midCurve, 0.5, frags[6]);
3533 drawVisibleID(rightCurve, 0.5, frags[12]);
caryclarkdac1d172014-06-17 05:15:38 -07003534 }
3535 break;
caryclark54359292015-03-26 07:52:43 -07003536 case REC_TYPE_AFTERPART:
3537 if (draw_angle != 3 || (step_limit > 0 && tIndex < lastAngle)) {
3538 continue;
3539 }
3540 ctx.strokeStyle = afterIndex == 0 ? "rgba(255,0,0, 1.0)"
3541 : (afterIndex == 1) == angleBetween ? "rgba(0,128,0, 1.0)"
Cary Clarkff114282016-12-14 11:56:16 -05003542 : "rgba(0,0,255, 1.0)";
3543 var curve;
3544 var id;
caryclark54359292015-03-26 07:52:43 -07003545 switch (fragType) {
3546 case PATH_LINE:
Cary Clarkff114282016-12-14 11:56:16 -05003547 curve = [ frags[0], frags[1], frags[2], frags[3] ];
3548 id = frags[4];
caryclark54359292015-03-26 07:52:43 -07003549 break;
3550 case PATH_QUAD:
Cary Clarkff114282016-12-14 11:56:16 -05003551 curve = [ frags[0], frags[1], frags[2], frags[3],
3552 frags[4], frags[5] ];
3553 id = frags[6];
caryclark54359292015-03-26 07:52:43 -07003554 break;
caryclark1049f122015-04-20 08:31:59 -07003555 case PATH_CONIC:
Cary Clarkff114282016-12-14 11:56:16 -05003556 curve = [ frags[0], frags[1], frags[2], frags[3],
3557 frags[4], frags[5], frags[6] ];
3558 id = frags[7];
caryclark1049f122015-04-20 08:31:59 -07003559 break;
caryclark54359292015-03-26 07:52:43 -07003560 case PATH_CUBIC:
Cary Clarkff114282016-12-14 11:56:16 -05003561 curve = [ frags[0], frags[1], frags[2], frags[3],
3562 frags[4], frags[5], frags[6], frags[7] ];
3563 id = frags[8];
caryclark54359292015-03-26 07:52:43 -07003564 break;
3565 default:
3566 console.log("unknown REC_TYPE_AFTERPART frag type: " + fragType);
3567 throw "stop execution";
3568 }
Cary Clarkff114282016-12-14 11:56:16 -05003569 drawCurve(curve);
Ben Wagner29380bd2017-10-09 14:43:00 -04003570 if (draw_id) {
3571 drawVisibleID(curve, 0.5, id);
Cary Clarkff114282016-12-14 11:56:16 -05003572 }
caryclark54359292015-03-26 07:52:43 -07003573 ++afterIndex;
3574 break;
caryclark624637c2015-05-11 07:21:27 -07003575 case REC_TYPE_COINCIDENCE:
3576 if (!draw_coincidence || (step_limit > 0 && tIndex < lastCoin)) {
3577 continue;
3578 }
3579 focus_enabled = true;
3580 ctx.lineWidth = 3;
3581 ctx.strokeStyle = "rgba(127,45,63, 0.3)";
3582 var curve = curvePartialByID(test, frags[0], frags[1], frags[2]);
3583 drawCurve(curve);
3584 break;
caryclarkdac1d172014-06-17 05:15:38 -07003585 case REC_TYPE_SECT:
3586 if (!draw_intersection) {
3587 continue;
3588 }
3589 if (draw_intersection != 1 && (step_limit > 0 && tIndex < lastSect)) {
3590 continue;
3591 }
3592 // draw_intersection == 1 : show all
3593 // draw_intersection == 2 : step == 0 ? show all : show intersection line #step
3594 // draw_intersection == 3 : step == 0 ? show all : show intersection #step
3595 ctx.lineWidth = 1;
3596 ctx.strokeStyle = "rgba(0,0,255, 0.3)";
3597 ctx.fillStyle = "blue";
3598 focus_enabled = true;
3599 var f = [];
3600 var c1s;
3601 var c1l;
3602 var c2s;
3603 var c2l;
3604 switch (fragType) {
3605 case INTERSECT_LINE:
3606 f.push(5, 6, 0, 7);
3607 c1s = 1; c1l = 4; c2s = 8; c2l = 4;
3608 break;
3609 case INTERSECT_LINE_2:
3610 f.push(5, 6, 0, 10);
3611 f.push(8, 9, 7, 15);
3612 c1s = 1; c1l = 4; c2s = 11; c2l = 4;
3613 break;
3614 case INTERSECT_LINE_NO:
3615 c1s = 0; c1l = 4; c2s = 4; c2l = 4;
3616 break;
3617 case INTERSECT_QUAD_LINE:
3618 f.push(7, 8, 0, 9);
3619 c1s = 1; c1l = 6; c2s = 10; c2l = 4;
3620 break;
3621 case INTERSECT_QUAD_LINE_2:
3622 f.push(7, 8, 0, 12);
3623 f.push(10, 11, 9, 17);
3624 c1s = 1; c1l = 6; c2s = 13; c2l = 4;
3625 break;
3626 case INTERSECT_QUAD_LINE_NO:
3627 c1s = 0; c1l = 6; c2s = 6; c2l = 4;
3628 break;
3629 case INTERSECT_QUAD:
3630 f.push(7, 8, 0, 9);
3631 c1s = 1; c1l = 6; c2s = 10; c2l = 6;
3632 break;
3633 case INTERSECT_QUAD_2:
3634 f.push(7, 8, 0, 12);
3635 f.push(10, 11, 9, 19);
3636 c1s = 1; c1l = 6; c2s = 13; c2l = 6;
3637 break;
3638 case INTERSECT_QUAD_NO:
3639 c1s = 0; c1l = 6; c2s = 6; c2l = 6;
3640 break;
caryclark1049f122015-04-20 08:31:59 -07003641 case INTERSECT_CONIC_LINE:
3642 f.push(8, 9, 0, 10);
3643 c1s = 1; c1l = 7; c2s = 11; c2l = 4;
3644 break;
3645 case INTERSECT_CONIC_LINE_2:
3646 f.push(8, 9, 0, 12);
3647 f.push(11, 12, 10, 18);
3648 c1s = 1; c1l = 7; c2s = 14; c2l = 4;
3649 break;
3650 case INTERSECT_CONIC_LINE_NO:
3651 c1s = 0; c1l = 7; c2s = 7; c2l = 4;
3652 break;
caryclark55888e42016-07-18 10:01:36 -07003653 case INTERSECT_CONIC_QUAD:
3654 f.push(8, 9, 0, 10);
3655 c1s = 1; c1l = 7; c2s = 11; c2l = 6;
3656 break;
3657 case INTERSECT_CONIC_QUAD_2:
3658 f.push(8, 9, 0, 12);
3659 f.push(11, 12, 10, 18);
3660 c1s = 1; c1l = 7; c2s = 14; c2l = 6;
3661 break;
caryclark6c3b9cd2016-09-26 05:36:58 -07003662 case INTERSECT_CONIC_QUAD_3:
3663 f.push(8, 9, 0, 15);
3664 f.push(11, 12, 10, 21);
3665 f.push(14, 15, 13, 22);
3666 c1s = 1; c1l = 7; c2s = 17; c2l = 6;
3667 break;
3668 case INTERSECT_CONIC_QUAD_4:
3669 f.push(8, 9, 0, 18);
3670 f.push(11, 12, 10, 24);
3671 f.push(14, 15, 13, 25);
3672 f.push(17, 18, 16, 26);
3673 c1s = 1; c1l = 7; c2s = 20; c2l = 6;
3674 break;
caryclark55888e42016-07-18 10:01:36 -07003675 case INTERSECT_CONIC_QUAD_NO:
3676 c1s = 0; c1l = 7; c2s = 7; c2l = 6;
3677 break;
caryclark1049f122015-04-20 08:31:59 -07003678 case INTERSECT_CONIC:
3679 f.push(8, 9, 0, 10);
3680 c1s = 1; c1l = 7; c2s = 11; c2l = 7;
3681 break;
3682 case INTERSECT_CONIC_2:
3683 f.push(8, 9, 0, 13);
3684 f.push(11, 12, 10, 21);
3685 c1s = 1; c1l = 7; c2s = 14; c2l = 7;
3686 break;
3687 case INTERSECT_CONIC_NO:
3688 c1s = 0; c1l = 7; c2s = 7; c2l = 7;
3689 break;
caryclarkdac1d172014-06-17 05:15:38 -07003690 case INTERSECT_SELF_CUBIC:
3691 f.push(9, 10, 0, 11);
3692 c1s = 1; c1l = 8; c2s = 0; c2l = 0;
3693 break;
3694 case INTERSECT_SELF_CUBIC_NO:
3695 c1s = 0; c1l = 8; c2s = 0; c2l = 0;
3696 break;
3697 case INTERSECT_CUBIC_LINE:
3698 f.push(9, 10, 0, 11);
3699 c1s = 1; c1l = 8; c2s = 12; c2l = 4;
3700 break;
3701 case INTERSECT_CUBIC_LINE_2:
3702 f.push(9, 10, 0, 14);
3703 f.push(12, 13, 11, 19);
3704 c1s = 1; c1l = 8; c2s = 15; c2l = 4;
3705 break;
3706 case INTERSECT_CUBIC_LINE_3:
3707 f.push(9, 10, 0, 17);
3708 f.push(12, 13, 11, 22);
3709 f.push(15, 16, 14, 23);
3710 c1s = 1; c1l = 8; c2s = 18; c2l = 4;
3711 break;
3712 case INTERSECT_CUBIC_QUAD_NO:
3713 c1s = 0; c1l = 8; c2s = 8; c2l = 6;
3714 break;
3715 case INTERSECT_CUBIC_QUAD:
3716 f.push(9, 10, 0, 11);
3717 c1s = 1; c1l = 8; c2s = 12; c2l = 6;
3718 break;
3719 case INTERSECT_CUBIC_QUAD_2:
3720 f.push(9, 10, 0, 14);
3721 f.push(12, 13, 11, 21);
3722 c1s = 1; c1l = 8; c2s = 15; c2l = 6;
3723 break;
3724 case INTERSECT_CUBIC_QUAD_3:
3725 f.push(9, 10, 0, 17);
3726 f.push(12, 13, 11, 24);
3727 f.push(15, 16, 14, 25);
3728 c1s = 1; c1l = 8; c2s = 18; c2l = 6;
3729 break;
3730 case INTERSECT_CUBIC_QUAD_4:
3731 f.push(9, 10, 0, 20);
3732 f.push(12, 13, 11, 27);
3733 f.push(15, 16, 14, 28);
3734 f.push(18, 19, 17, 29);
3735 c1s = 1; c1l = 8; c2s = 21; c2l = 6;
3736 break;
3737 case INTERSECT_CUBIC_LINE_NO:
3738 c1s = 0; c1l = 8; c2s = 8; c2l = 4;
3739 break;
3740 case INTERSECT_CUBIC:
3741 f.push(9, 10, 0, 11);
3742 c1s = 1; c1l = 8; c2s = 12; c2l = 8;
3743 break;
3744 case INTERSECT_CUBIC_2:
3745 f.push(9, 10, 0, 14);
3746 f.push(12, 13, 11, 23);
3747 c1s = 1; c1l = 8; c2s = 15; c2l = 8;
3748 break;
3749 case INTERSECT_CUBIC_3:
3750 f.push(9, 10, 0, 17);
3751 f.push(12, 13, 11, 26);
3752 f.push(15, 16, 14, 27);
3753 c1s = 1; c1l = 8; c2s = 18; c2l = 8;
3754 break;
3755 case INTERSECT_CUBIC_4:
3756 f.push(9, 10, 0, 20);
3757 f.push(12, 13, 11, 29);
3758 f.push(15, 16, 14, 30);
3759 f.push(18, 19, 17, 31);
3760 c1s = 1; c1l = 8; c2s = 21; c2l = 8;
3761 break;
3762 case INTERSECT_CUBIC_NO:
3763 c1s = 0; c1l = 8; c2s = 8; c2l = 8;
3764 break;
3765 default:
3766 console.log("unknown REC_TYPE_SECT frag type: " + fragType);
3767 throw "stop execution";
3768 }
3769 if (draw_intersection != 1) {
3770 var id = -1;
3771 var curve;
3772 switch (c1l) {
caryclark55888e42016-07-18 10:01:36 -07003773 case 4:
caryclarkdac1d172014-06-17 05:15:38 -07003774 drawLine(frags[c1s], frags[c1s + 1], frags[c1s + 2], frags[c1s + 3]);
3775 if (draw_id) {
3776 curve = [frags[c1s], frags[c1s + 1], frags[c1s + 2], frags[c1s + 3]];
3777 id = idByCurve(test, curve, PATH_LINE);
3778 }
3779 break;
3780 case 6:
3781 drawQuad(frags[c1s], frags[c1s + 1], frags[c1s + 2], frags[c1s + 3],
3782 frags[c1s + 4], frags[c1s + 5]);
3783 if (draw_id) {
3784 curve = [frags[c1s], frags[c1s + 1], frags[c1s + 2], frags[c1s + 3],
3785 frags[c1s + 4], frags[c1s + 5]];
3786 id = idByCurve(test, curve, PATH_QUAD);
3787 }
3788 break;
caryclark1049f122015-04-20 08:31:59 -07003789 case 7:
3790 drawConicWithQuads(frags[c1s], frags[c1s + 1], frags[c1s + 2], frags[c1s + 3],
3791 frags[c1s + 4], frags[c1s + 5], frags[c1s + 6]);
3792 if (draw_id) {
3793 curve = [frags[c1s], frags[c1s + 1], frags[c1s + 2], frags[c1s + 3],
3794 frags[c1s + 4], frags[c1s + 5], frags[c1s + 6]];
3795 id = idByCurve(test, curve, PATH_CONIC);
3796 }
3797 break;
caryclarkdac1d172014-06-17 05:15:38 -07003798 case 8:
3799 drawCubic(frags[c1s], frags[c1s + 1], frags[c1s + 2], frags[c1s + 3],
3800 frags[c1s + 4], frags[c1s + 5], frags[c1s + 6], frags[c1s + 7]);
3801 if (draw_id) {
3802 curve = [frags[c1s], frags[c1s + 1], frags[c1s + 2], frags[c1s + 3],
3803 frags[c1s + 4], frags[c1s + 5], frags[c1s + 6], frags[c1s + 7]];
3804 id = idByCurve(test, curve, PATH_CUBIC);
3805 }
3806 break;
3807 }
3808 if (id >= 0) {
Cary Clarkff114282016-12-14 11:56:16 -05003809 drawVisibleID(curve, 0.5, id);
caryclarkdac1d172014-06-17 05:15:38 -07003810 }
3811 id = -1;
3812 switch (c2l) {
3813 case 0:
3814 break;
caryclark55888e42016-07-18 10:01:36 -07003815 case 4:
caryclarkdac1d172014-06-17 05:15:38 -07003816 drawLine(frags[c2s], frags[c2s + 1], frags[c2s + 2], frags[c2s + 3]);
3817 if (draw_id) {
3818 curve = [frags[c2s], frags[c2s + 1], frags[c2s + 2], frags[c2s + 3]];
3819 id = idByCurve(test, curve, PATH_LINE);
3820 }
3821 break;
3822 case 6:
3823 drawQuad(frags[c2s], frags[c2s + 1], frags[c2s + 2], frags[c2s + 3],
3824 frags[c2s + 4], frags[c2s + 5]);
3825 if (draw_id) {
3826 curve = [frags[c2s], frags[c2s + 1], frags[c2s + 2], frags[c2s + 3],
3827 frags[c2s + 4], frags[c2s + 5]];
3828 id = idByCurve(test, curve, PATH_QUAD);
3829 }
3830 break;
caryclark1049f122015-04-20 08:31:59 -07003831 case 7:
3832 drawConicWithQuads(frags[c2s], frags[c2s + 1], frags[c2s + 2], frags[c2s + 3],
3833 frags[c2s + 4], frags[c2s + 5], frags[c2s + 6]);
3834 if (draw_id) {
3835 curve = [frags[c2s], frags[c2s + 1], frags[c2s + 2], frags[c2s + 3],
3836 frags[c2s + 4], frags[c2s + 5], frags[c2s + 6]];
3837 id = idByCurve(test, curve, PATH_CONIC);
3838 }
3839 break;
caryclarkdac1d172014-06-17 05:15:38 -07003840 case 8:
3841 drawCubic(frags[c2s], frags[c2s + 1], frags[c2s + 2], frags[c2s + 3],
3842 frags[c2s + 4], frags[c2s + 5], frags[c2s + 6], frags[c2s + 7]);
3843 if (draw_id) {
3844 curve = [frags[c2s], frags[c2s + 1], frags[c2s + 2], frags[c2s + 3],
3845 frags[c2s + 4], frags[c2s + 5], frags[c2s + 6], frags[c2s + 7]];
3846 id = idByCurve(test, curve, PATH_CUBIC);
3847 }
3848 break;
3849 }
3850 if (id >= 0) {
Cary Clarkff114282016-12-14 11:56:16 -05003851 drawVisibleID(curve, 0.5, id);
caryclarkdac1d172014-06-17 05:15:38 -07003852 }
3853 }
3854 if (collect_bounds) {
3855 break;
3856 }
caryclark54359292015-03-26 07:52:43 -07003857 if (draw_intersection != 3 || step_limit == 0 || tIndex >= lastSect) {
3858 for (var idx = 0; idx < f.length; idx += 4) {
caryclarkdac1d172014-06-17 05:15:38 -07003859 drawPoint(frags[f[idx]], frags[f[idx + 1]], true);
3860 }
3861 }
3862 if (!draw_intersectT) {
3863 break;
3864 }
3865 ctx.fillStyle = "red";
caryclark54359292015-03-26 07:52:43 -07003866 if (draw_intersection != 3 || step_limit == 0 || tIndex >= lastSect) {
3867 for (var idx = 0; idx < f.length; idx += 4) {
caryclarkdac1d172014-06-17 05:15:38 -07003868 drawTAtPointUp(frags[f[idx]], frags[f[idx + 1]], frags[f[idx + 2]]);
3869 drawTAtPointDown(frags[f[idx]], frags[f[idx + 1]], frags[f[idx + 3]]);
3870 }
3871 }
3872 break;
3873 case REC_TYPE_SORT:
3874 if (!draw_sort || (step_limit > 0 && tIndex < lastSort)) {
3875 continue;
3876 }
3877 ctx.lineWidth = 3;
3878 ctx.strokeStyle = "rgba(127,127,0, 0.5)";
3879 focus_enabled = true;
3880 switch (fragType) {
3881 case SORT_UNARY:
3882 case SORT_BINARY:
3883 var curve = curvePartialByID(test, frags[0], frags[6], frags[8]);
3884 drawCurve(curve);
3885 break;
3886 default:
3887 console.log("unknown REC_TYPE_SORT frag type: " + fragType);
3888 throw "stop execution";
3889 }
3890 break;
caryclark03b03ca2015-04-23 09:13:37 -07003891 case REC_TYPE_TOP:
3892 if (!draw_top || (step_limit > 0 && tIndex < lastTop)) {
3893 continue;
3894 }
3895 ctx.lineWidth = 3;
3896 ctx.strokeStyle = "rgba(127,127,0, 0.5)";
3897 focus_enabled = true;
3898 {
3899 var curve = curvePartialByID(test, frags[0], frags[1], frags[2]);
3900 drawCurve(curve);
3901 var type = PATH_LINE + (curve.length / 2 - 2);
3902 var mid = pointAtT(curve, type, 0.5);
3903 var d = dxy_at_t(curve, type, 0.5);
3904 drawArrow(mid.x, mid.y, d.x, d.y, 0.3);
3905 }
3906 break;
caryclarkdac1d172014-06-17 05:15:38 -07003907 case REC_TYPE_MARK:
3908 if (!draw_mark || (step_limit > 0 && tIndex < lastMark)) {
3909 continue;
3910 }
3911 ctx.lineWidth = 3;
3912 ctx.strokeStyle = fragType >= MARK_DONE_LINE ?
3913 "rgba(127,0,127, 0.5)" : "rgba(127,127,0, 0.5)";
3914 focus_enabled = true;
3915 switch (fragType) {
3916 case MARK_LINE:
3917 case MARK_DONE_LINE:
3918 case MARK_UNSORTABLE_LINE:
3919 case MARK_SIMPLE_LINE:
3920 case MARK_SIMPLE_DONE_LINE:
3921 case MARK_DONE_UNARY_LINE:
3922 drawLinePartial(frags[1], frags[2], frags[3], frags[4],
3923 frags[5], frags[9]);
3924 if (draw_id) {
3925 drawLinePartialID(frags[0], frags[1], frags[2], frags[3], frags[4],
3926 frags[5], frags[9]);
3927 }
3928 break;
3929 case MARK_QUAD:
3930 case MARK_DONE_QUAD:
3931 case MARK_UNSORTABLE_QUAD:
3932 case MARK_SIMPLE_QUAD:
3933 case MARK_SIMPLE_DONE_QUAD:
3934 case MARK_DONE_UNARY_QUAD:
3935 drawQuadPartial(frags[1], frags[2], frags[3], frags[4],
3936 frags[5], frags[6], frags[7], frags[11]);
3937 if (draw_id) {
3938 drawQuadPartialID(frags[0], frags[1], frags[2], frags[3], frags[4],
3939 frags[5], frags[6], frags[7], frags[11]);
3940 }
3941 break;
3942 case MARK_CUBIC:
3943 case MARK_DONE_CUBIC:
3944 case MARK_UNSORTABLE_CUBIC:
3945 case MARK_SIMPLE_CUBIC:
3946 case MARK_SIMPLE_DONE_CUBIC:
3947 case MARK_DONE_UNARY_CUBIC:
3948 drawCubicPartial(frags[1], frags[2], frags[3], frags[4],
3949 frags[5], frags[6], frags[7], frags[8], frags[9], frags[13]);
3950 if (draw_id) {
3951 drawCubicPartialID(frags[0], frags[1], frags[2], frags[3], frags[4],
3952 frags[5], frags[6], frags[7], frags[8], frags[9], frags[13]);
3953 }
3954 break;
3955 case MARK_ANGLE_LAST:
3956 // FIXME: ignored for now
3957 break;
3958 default:
3959 console.log("unknown REC_TYPE_MARK frag type: " + fragType);
3960 throw "stop execution";
3961 }
3962 break;
3963 default:
3964 continue;
3965 }
3966 }
3967 switch (recType) {
3968 case REC_TYPE_SORT:
3969 if (!draw_sort || (step_limit > 0 && tIndex < lastSort)) {
3970 break;
3971 }
3972 var angles = []; // use tangent lines to describe arcs
3973 var windFrom = [];
3974 var windTo = [];
3975 var opp = [];
3976 var minXY = Number.MAX_VALUE;
3977 var partial;
3978 focus_enabled = true;
3979 var someUnsortable = false;
3980 for (var recordIndex = 0; recordIndex < records.length; recordIndex += 2) {
3981 var fragType = records[recordIndex];
3982 var frags = records[recordIndex + 1];
3983 var unsortable = (fragType == SORT_UNARY && frags[14]) ||
3984 (fragType == SORT_BINARY && frags[16]);
3985 someUnsortable |= unsortable;
3986 switch (fragType) {
3987 case SORT_UNARY:
3988 case SORT_BINARY:
3989 partial = curvePartialByID(test, frags[0], frags[6], frags[8]);
3990 break;
3991 default:
3992 console.log("unknown REC_TYPE_SORT frag type: " + fragType);
3993 throw "stop execution";
3994 }
3995 var dx = boundsWidth(partial);
3996 var dy = boundsHeight(partial);
3997 minXY = Math.min(minXY, dx * dx + dy * dy);
3998 if (collect_bounds) {
3999 continue;
4000 }
4001 angles.push(tangent(partial));
4002 var from = frags[12];
4003 var to = frags[12];
4004 var sgn = frags[10];
4005 if (sgn < 0) {
4006 from -= frags[11];
4007 } else if (sgn > 0) {
4008 to -= frags[11];
4009 }
4010 windFrom.push(from + (unsortable ? "!" : ""));
4011 windTo.push(to + (unsortable ? "!" : ""));
4012 opp.push(fragType == SORT_BINARY);
4013 if (draw_sort == 1) {
Cary Clarkff114282016-12-14 11:56:16 -05004014 drawVisibleOrder(partial, frags[12]);
caryclarkdac1d172014-06-17 05:15:38 -07004015 } else {
Cary Clarkff114282016-12-14 11:56:16 -05004016 drawVisibleOrder(partial, (recordIndex / 2) + 1);
caryclarkdac1d172014-06-17 05:15:38 -07004017 }
4018 }
4019 var radius = Math.sqrt(minXY) / 2 * scale;
4020 radius = Math.min(50, radius);
4021 var scaledRadius = radius / scale;
4022 var centerX = partial[0];
4023 var centerY = partial[1];
4024 if (collect_bounds) {
4025 if (focus_enabled) {
4026 focusXmin = Math.min(focusXmin, centerX - scaledRadius);
4027 focusYmin = Math.min(focusYmin, centerY - scaledRadius);
4028 focusXmax = Math.max(focusXmax, centerX + scaledRadius);
4029 focusYmax = Math.max(focusYmax, centerY + scaledRadius);
4030 }
4031 break;
4032 }
4033 break;
4034 default:
4035 break;
4036 }
4037 }
4038 if (collect_bounds) {
4039 return;
4040 }
4041 if (draw_log && logStart >= 0) {
4042 ctx.font = "normal 10px Arial";
4043 ctx.textAlign = "left";
4044 ctx.beginPath();
4045 var top = screenHeight - 20 - (logRange + 2) * 10;
4046 ctx.rect(50, top, screenWidth - 100, (logRange + 2) * 10);
4047 ctx.fillStyle = "white";
4048 ctx.fill();
4049 ctx.fillStyle = "rgba(0,0,0, 0.5)";
4050 if (logStart > 0) {
4051 ctx.fillText(lines[logStart - 1], 50, top + 8);
4052 }
4053 ctx.fillStyle = "black";
4054 for (var idx = 0; idx < logRange; ++idx) {
4055 ctx.fillText(lines[logStart + idx], 50, top + 18 + 10 * idx);
4056 }
4057 ctx.fillStyle = "rgba(0,0,0, 0.5)";
4058 if (logStart + logRange < lines.length) {
4059 ctx.fillText(lines[logStart + logRange], 50, top + 18 + 10 * logRange);
4060 }
4061 }
4062 if (draw_legend) {
4063 var pos = 0;
caryclark624637c2015-05-11 07:21:27 -07004064 var drawSomething = draw_add | draw_active | draw_angle | draw_coincidence | draw_sort | draw_mark;
caryclarkdac1d172014-06-17 05:15:38 -07004065 // drawBox(pos++, "yellow", "black", opLetter, true, '');
4066 drawBox(pos++, "rgba(0,0,255, 0.3)", "black", draw_intersection > 1 ? sectCount : sectMax2, draw_intersection, intersectionKey);
4067 drawBox(pos++, "rgba(0,0,255, 0.3)", "black", draw_add ? addCount : addMax, draw_add, addKey);
4068 drawBox(pos++, "rgba(0,0,255, 0.3)", "black", draw_active ? activeCount : activeMax, draw_active, activeKey);
4069 drawBox(pos++, "rgba(127,127,0, 0.3)", "black", draw_angle ? angleCount : angleMax, draw_angle, angleKey);
caryclark624637c2015-05-11 07:21:27 -07004070 drawBox(pos++, "rgba(127,127,0, 0.3)", "black", draw_coincidence ? coinCount : coinMax, draw_coincidence, coincidenceKey);
caryclarkdac1d172014-06-17 05:15:38 -07004071 drawBox(pos++, "rgba(127,127,0, 0.3)", "black", draw_op ? opCount : opMax, draw_op, opKey);
4072 drawBox(pos++, "rgba(127,127,0, 0.3)", "black", draw_sort ? sortCount : sortMax, draw_sort, sortKey);
caryclark03b03ca2015-04-23 09:13:37 -07004073 drawBox(pos++, "rgba(127,127,0, 0.3)", "black", draw_top ? topCount : topMax, draw_top, topKey);
caryclarkdac1d172014-06-17 05:15:38 -07004074 drawBox(pos++, "rgba(127,0,127, 0.3)", "black", draw_mark ? markCount : markMax, draw_mark, markKey);
caryclark55888e42016-07-18 10:01:36 -07004075 drawBox(pos++, "black", "white",
caryclark26ad22a2015-10-16 09:03:38 -07004076 (new Array('P', 'P1', 'P2', 'P', 'p', 'p1', 'p2'))[draw_path], draw_path != 0, pathKey);
caryclarkdac1d172014-06-17 05:15:38 -07004077 drawBox(pos++, "rgba(0,63,0, 0.7)", "white",
4078 (new Array('Q', 'Q', 'C', 'QC', 'Qc', 'Cq'))[draw_computed],
4079 draw_computed != 0, computedKey);
4080 drawBox(pos++, "green", "black", step_limit, drawSomething, '');
4081 drawBox(pos++, "green", "black", stepMax, drawSomething, '');
4082 drawBox(pos++, "rgba(255,0,0, 0.6)", "black", lastIndex, drawSomething & draw_log, '');
4083 drawBox(pos++, "rgba(255,0,0, 0.6)", "black", test.length - 1, drawSomething & draw_log, '');
4084 if (curve_t) {
4085 drawCurveTControl();
4086 }
4087 ctx.font = "normal 20px Arial";
4088 ctx.fillStyle = "rgba(0,0,0, 0.3)";
4089 ctx.textAlign = "right";
4090 ctx.fillText(scale.toFixed(decimal_places) + 'x' , screenWidth - 10, screenHeight - 5);
4091 }
4092 if (draw_hints) {
4093 ctx.font = "normal 10px Arial";
4094 ctx.fillStyle = "rgba(0,0,0, 0.5)";
4095 ctx.textAlign = "right";
4096 var y = 4;
4097 ctx.fillText("control lines : " + controlLinesKey, ctx.screenWidthwidth - 10, pos * 50 + y++ * 10);
4098 ctx.fillText("curve t : " + curveTKey, screenWidth - 10, pos * 50 + y++ * 10);
4099 ctx.fillText("deriviatives : " + deriviativesKey, screenWidth - 10, pos * 50 + y++ * 10);
4100 ctx.fillText("intersect t : " + intersectTKey, screenWidth - 10, pos * 50 + y++ * 10);
caryclarkdac1d172014-06-17 05:15:38 -07004101 ctx.fillText("log : " + logKey, screenWidth - 10, pos * 50 + y++ * 10);
4102 ctx.fillText("log curve : " + logCurvesKey, screenWidth - 10, pos * 50 + y++ * 10);
4103 ctx.fillText("mid point : " + midpointKey, screenWidth - 10, pos * 50 + y++ * 10);
4104 ctx.fillText("points : " + ptsKey, screenWidth - 10, pos * 50 + y++ * 10);
4105 ctx.fillText("sequence : " + sequenceKey, screenWidth - 10, pos * 50 + y++ * 10);
4106 ctx.fillText("xy : " + xyKey, screenWidth - 10, pos * 50 + y++ * 10);
4107 }
4108}
4109
4110function drawBox(y, backC, foreC, str, enable, label) {
4111 ctx.beginPath();
4112 ctx.fillStyle = backC;
4113 ctx.rect(screenWidth - 40, y * 50 + 10, 40, 30);
4114 ctx.fill();
4115 ctx.font = "normal 16px Arial";
4116 ctx.fillStyle = foreC;
4117 ctx.textAlign = "center";
4118 ctx.fillText(str, screenWidth - 20, y * 50 + 32);
4119 if (!enable) {
4120 ctx.fillStyle = "rgba(255,255,255, 0.5)";
4121 ctx.fill();
4122 }
4123 if (label != '') {
4124 ctx.font = "normal 9px Arial";
4125 ctx.fillStyle = "black";
4126 ctx.fillText(label, screenWidth - 47, y * 50 + 40);
4127 }
4128}
4129
4130function drawCurveTControl() {
4131 ctx.lineWidth = 2;
4132 ctx.strokeStyle = "rgba(0,0,0, 0.3)";
4133 ctx.beginPath();
4134 ctx.rect(screenWidth - 80, 40, 28, screenHeight - 80);
4135 ctx.stroke();
4136 var ty = 40 + curveT * (screenHeight - 80);
4137 ctx.beginPath();
4138 ctx.moveTo(screenWidth - 80, ty);
4139 ctx.lineTo(screenWidth - 85, ty - 5);
4140 ctx.lineTo(screenWidth - 85, ty + 5);
4141 ctx.lineTo(screenWidth - 80, ty);
4142 ctx.fillStyle = "rgba(0,0,0, 0.6)";
4143 ctx.fill();
4144 var num = curveT.toFixed(decimal_places);
4145 ctx.font = "normal 10px Arial";
4146 ctx.textAlign = "left";
4147 ctx.fillText(num, screenWidth - 78, ty);
4148}
4149
4150function ptInTControl() {
4151 var e = window.event;
caryclark55888e42016-07-18 10:01:36 -07004152 var tgt = e.target || e.srcElement;
caryclarkdac1d172014-06-17 05:15:38 -07004153 var left = tgt.offsetLeft;
4154 var top = tgt.offsetTop;
4155 var x = (e.clientX - left);
4156 var y = (e.clientY - top);
4157 if (x < screenWidth - 80 || x > screenWidth - 50) {
4158 return false;
4159 }
4160 if (y < 40 || y > screenHeight - 80) {
4161 return false;
4162 }
4163 curveT = (y - 40) / (screenHeight - 120);
4164 if (curveT < 0 || curveT > 1) {
4165 throw "stop execution";
4166 }
4167 return true;
4168}
4169
4170function drawTop() {
4171 if (tests[testIndex] == null) {
4172 var str = testDivs[testIndex].textContent;
4173 parse_all(str);
4174 var title = testDivs[testIndex].id.toString();
4175 testTitles[testIndex] = title;
4176 }
4177 init(tests[testIndex]);
4178 redraw();
4179}
4180
4181function redraw() {
4182 if (focus_on_selection) {
4183 collect_bounds = true;
4184 draw(tests[testIndex], testLines[testIndex], testTitles[testIndex]);
4185 collect_bounds = false;
4186 if (focusXmin < focusXmax && focusYmin < focusYmax) {
4187 setScale(focusXmin, focusXmax, focusYmin, focusYmax);
4188 }
4189 }
4190 ctx.beginPath();
4191 ctx.fillStyle = "white";
4192 ctx.rect(0, 0, screenWidth, screenHeight);
4193 ctx.fill();
4194 draw(tests[testIndex], testLines[testIndex], testTitles[testIndex]);
4195}
4196
4197function dumpCurvePartial(test, id, t0, t1) {
4198 var curve = curveByID(test, id);
4199 var name = ["line", "quad", "cubic"][curve.length / 2 - 2];
4200 console.log("id=" + id + " " + name + "=" + curveToString(curve)
4201 + " t0=" + t0 + " t1=" + t1
4202 + " partial=" + curveToString(curvePartialByID(test, id, t0, t1)));
4203}
4204
4205function dumpAngleTest(test, id, t0, t1) {
4206 var curve = curveByID(test, id);
caryclark55888e42016-07-18 10:01:36 -07004207 console.log(" { {" + curveToString(curve) + "}, "
caryclarkdac1d172014-06-17 05:15:38 -07004208 + curve.length / 2 + ", " + t0 + ", " + t1 + ", {} }, //");
4209}
4210
4211function dumpLogToConsole() {
4212 if (logStart < 0) {
4213 return;
4214 }
4215 var test = tests[testIndex];
4216 var recType = REC_TYPE_UNKNOWN;
4217 var records;
4218 for (var index = 0; index < test.length; index += 3) {
4219 var lastLineNo = test[index + 1];
4220 if (lastLineNo >= logStart && lastLineNo < logStart + logRange) {
4221 recType = test[index];
4222 records = test[index + 2];
4223 break;
4224 }
4225 }
4226 if (recType == REC_TYPE_UNKNOWN) {
4227 return;
4228 }
4229 var lines = testLines[testIndex];
4230 for (var idx = 0; idx < logRange; ++idx) {
4231 var line = lines[logStart + idx];
4232 console.log(line);
4233 for (var recordIndex = 0; recordIndex < records.length; recordIndex += 2) {
4234 var fragType = records[recordIndex];
4235 var frags = records[recordIndex + 1];
4236 if (recType == REC_TYPE_ANGLE && fragType == ANGLE_AFTER) {
caryclarkdac1d172014-06-17 05:15:38 -07004237 dumpCurvePartial(test, frags[0], frags[4], frags[5]);
4238 dumpCurvePartial(test, frags[6], frags[10], frags[11]);
4239 dumpCurvePartial(test, frags[12], frags[16], frags[17]);
4240 console.log("\nstatic IntersectData intersectDataSet[] = { //");
4241 dumpAngleTest(test, frags[0], frags[4], frags[5]);
4242 dumpAngleTest(test, frags[6], frags[10], frags[11]);
4243 dumpAngleTest(test, frags[12], frags[16], frags[17]);
4244 console.log("}; //");
4245 }
4246 }
4247 }
4248}
4249
4250var activeKey = 'a';
4251var pathKey = 'b';
4252var pathBackKey = 'B';
4253var centerKey = 'c';
caryclark624637c2015-05-11 07:21:27 -07004254var coincidenceKey = 'C';
caryclarkdac1d172014-06-17 05:15:38 -07004255var addKey = 'd';
4256var deriviativesKey = 'f';
4257var angleKey = 'g';
4258var angleBackKey = 'G';
caryclarkdac1d172014-06-17 05:15:38 -07004259var intersectionKey = 'i';
4260var intersectionBackKey = 'I';
4261var sequenceKey = 'j';
4262var midpointKey = 'k';
4263var logKey = 'l';
4264var logToConsoleKey = 'L';
4265var markKey = 'm';
4266var sortKey = 'o';
4267var opKey = 'p';
4268var opBackKey = 'P';
4269var computedKey = 'q';
4270var computedBackKey = 'Q';
Cary Clarkff114282016-12-14 11:56:16 -05004271var directionKey = 'r';
caryclarkdac1d172014-06-17 05:15:38 -07004272var stepKey = 's';
4273var stepBackKey = 'S';
4274var intersectTKey = 't';
caryclark03b03ca2015-04-23 09:13:37 -07004275var topKey = 'T';
caryclarkdac1d172014-06-17 05:15:38 -07004276var curveTKey = 'u';
4277var controlLinesBackKey = 'V';
4278var controlLinesKey = 'v';
4279var ptsKey = 'x';
4280var xyKey = 'y';
4281var logCurvesKey = 'z';
4282var focusKey = '`';
4283var idKey = '.';
4284var retinaKey = '\\';
4285
4286function doKeyPress(evt) {
4287 var char = String.fromCharCode(evt.charCode);
4288 var focusWasOn = false;
4289 switch (char) {
4290 case '0':
4291 case '1':
4292 case '2':
4293 case '3':
4294 case '4':
4295 case '5':
4296 case '6':
4297 case '7':
4298 case '8':
4299 case '9':
4300 decimal_places = char - '0';
4301 redraw();
4302 break;
4303 case activeKey:
4304 draw_active ^= true;
caryclark55888e42016-07-18 10:01:36 -07004305 redraw();
caryclarkdac1d172014-06-17 05:15:38 -07004306 break;
4307 case addKey:
4308 draw_add ^= true;
caryclark55888e42016-07-18 10:01:36 -07004309 redraw();
caryclarkdac1d172014-06-17 05:15:38 -07004310 break;
4311 case angleKey:
caryclark54359292015-03-26 07:52:43 -07004312 draw_angle = (draw_angle + 1) % 4;
caryclarkdac1d172014-06-17 05:15:38 -07004313 redraw();
4314 break;
4315 case angleBackKey:
4316 draw_angle = (draw_angle + 2) % 3;
4317 redraw();
4318 break;
4319 case centerKey:
4320 setScale(xmin, xmax, ymin, ymax);
caryclark55888e42016-07-18 10:01:36 -07004321 redraw();
caryclarkdac1d172014-06-17 05:15:38 -07004322 break;
caryclark624637c2015-05-11 07:21:27 -07004323 case coincidenceKey:
4324 draw_coincidence ^= true;
4325 redraw();
4326 break;
caryclarkdac1d172014-06-17 05:15:38 -07004327 case controlLinesBackKey:
4328 control_lines = (control_lines + 3) % 4;
caryclark55888e42016-07-18 10:01:36 -07004329 redraw();
caryclarkdac1d172014-06-17 05:15:38 -07004330 break;
4331 case controlLinesKey:
4332 control_lines = (control_lines + 1) % 4;
caryclark55888e42016-07-18 10:01:36 -07004333 redraw();
caryclarkdac1d172014-06-17 05:15:38 -07004334 break;
4335 case computedBackKey:
4336 draw_computed = (draw_computed + 5) % 6;
caryclark55888e42016-07-18 10:01:36 -07004337 redraw();
caryclarkdac1d172014-06-17 05:15:38 -07004338 break;
4339 case computedKey:
4340 draw_computed = (draw_computed + 1) % 6;
caryclark55888e42016-07-18 10:01:36 -07004341 redraw();
caryclarkdac1d172014-06-17 05:15:38 -07004342 break;
4343 case curveTKey:
4344 curve_t ^= true;
4345 if (curve_t) {
4346 draw_legend = true;
4347 }
4348 redraw();
4349 break;
4350 case deriviativesKey:
4351 draw_deriviatives = (draw_deriviatives + 1) % 3;
4352 redraw();
4353 break;
Cary Clarkff114282016-12-14 11:56:16 -05004354 case directionKey:
4355 draw_direction ^= true;
4356 redraw();
4357 break;
caryclarkdac1d172014-06-17 05:15:38 -07004358 case focusKey:
4359 focus_on_selection ^= true;
4360 setScale(xmin, xmax, ymin, ymax);
4361 redraw();
4362 break;
caryclarkdac1d172014-06-17 05:15:38 -07004363 case idKey:
4364 draw_id ^= true;
4365 redraw();
4366 break;
4367 case intersectionBackKey:
4368 draw_intersection = (draw_intersection + 3) % 4;
caryclark55888e42016-07-18 10:01:36 -07004369 redraw();
caryclarkdac1d172014-06-17 05:15:38 -07004370 break;
4371 case intersectionKey:
4372 draw_intersection = (draw_intersection + 1) % 4;
caryclark55888e42016-07-18 10:01:36 -07004373 redraw();
caryclarkdac1d172014-06-17 05:15:38 -07004374 break;
4375 case intersectTKey:
4376 draw_intersectT ^= true;
4377 redraw();
4378 break;
4379 case logCurvesKey:
4380 logCurves(tests[testIndex]);
4381 break;
4382 case logKey:
4383 draw_log ^= true;
4384 redraw();
4385 break;
4386 case logToConsoleKey:
4387 if (draw_log) {
4388 dumpLogToConsole();
4389 }
4390 break;
4391 case markKey:
4392 draw_mark ^= true;
4393 redraw();
4394 break;
4395 case midpointKey:
4396 draw_midpoint ^= true;
4397 redraw();
4398 break;
4399 case opKey:
4400 draw_op = (draw_op + 1) % 3;
4401 redraw();
4402 break;
4403 case opBackKey:
4404 draw_op = (draw_op + 2) % 3;
4405 redraw();
4406 break;
4407 case pathKey:
caryclark26ad22a2015-10-16 09:03:38 -07004408 draw_path = (draw_path + 1) % (4 + (hasAlignedPath ? 3 : 0));
caryclark55888e42016-07-18 10:01:36 -07004409 redraw();
caryclarkdac1d172014-06-17 05:15:38 -07004410 break;
4411 case pathBackKey:
caryclark26ad22a2015-10-16 09:03:38 -07004412 draw_path = (draw_path + 3 + (hasAlignedPath ? 3 : 0)) % (4 + (hasAlignedPath ? 3 : 0));
caryclark55888e42016-07-18 10:01:36 -07004413 redraw();
caryclarkdac1d172014-06-17 05:15:38 -07004414 break;
4415 case ptsKey:
4416 pt_labels = (pt_labels + 1) % 3;
4417 redraw();
4418 break;
4419 case retinaKey:
4420 retina_scale ^= true;
4421 drawTop();
4422 break;
4423 case sequenceKey:
4424 draw_sequence ^= true;
4425 redraw();
4426 break;
4427 case sortKey:
4428 draw_sort = (draw_sort + 1) % 3;
4429 drawTop();
4430 break;
4431 case stepKey:
4432 step_limit++;
4433 if (step_limit > stepMax) {
4434 step_limit = stepMax;
4435 }
4436 redraw();
4437 break;
4438 case stepBackKey:
4439 step_limit--;
4440 if (step_limit < 0) {
4441 step_limit = 0;
4442 }
4443 redraw();
4444 break;
caryclark03b03ca2015-04-23 09:13:37 -07004445 case topKey:
4446 draw_top ^= true;
4447 redraw();
4448 break;
caryclarkdac1d172014-06-17 05:15:38 -07004449 case xyKey:
4450 debug_xy = (debug_xy + 1) % 3;
4451 redraw();
4452 break;
4453 case '-':
4454 focusWasOn = focus_on_selection;
4455 if (focusWasOn) {
4456 focus_on_selection = false;
4457 scale /= 1.2;
4458 } else {
4459 scale /= 2;
4460 calcLeftTop();
4461 }
4462 redraw();
4463 focus_on_selection = focusWasOn;
4464 break;
4465 case '=':
4466 case '+':
4467 focusWasOn = focus_on_selection;
4468 if (focusWasOn) {
4469 focus_on_selection = false;
4470 scale *= 1.2;
4471 } else {
4472 scale *= 2;
4473 calcLeftTop();
4474 }
4475 redraw();
4476 focus_on_selection = focusWasOn;
4477 break;
4478 case '?':
4479 draw_hints ^= true;
4480 if (draw_hints && !draw_legend) {
4481 draw_legend = true;
4482 }
4483 redraw();
4484 break;
4485 case '/':
4486 draw_legend ^= true;
4487 redraw();
4488 break;
4489 }
4490}
4491
4492function doKeyDown(evt) {
4493 var char = evt.keyCode;
4494 var preventDefault = false;
4495 switch (char) {
4496 case 37: // left arrow
4497 if (evt.shiftKey) {
4498 testIndex -= 9;
4499 }
4500 if (--testIndex < 0)
4501 testIndex = tests.length - 1;
4502 drawTop();
4503 preventDefault = true;
4504 break;
4505 case 39: // right arrow
4506 if (evt.shiftKey) {
4507 testIndex += 9;
4508 }
4509 if (++testIndex >= tests.length)
4510 testIndex = 0;
4511 drawTop();
4512 preventDefault = true;
4513 break;
4514 }
4515 if (preventDefault) {
4516 evt.preventDefault();
4517 return false;
4518 }
4519 return true;
4520}
4521
4522(function() {
4523 var hidden = "hidden";
4524
4525 // Standards:
4526 if (hidden in document)
4527 document.addEventListener("visibilitychange", onchange);
4528 else if ((hidden = "mozHidden") in document)
4529 document.addEventListener("mozvisibilitychange", onchange);
4530 else if ((hidden = "webkitHidden") in document)
4531 document.addEventListener("webkitvisibilitychange", onchange);
4532 else if ((hidden = "msHidden") in document)
4533 document.addEventListener("msvisibilitychange", onchange);
4534 // IE 9 and lower:
4535 else if ('onfocusin' in document)
4536 document.onfocusin = document.onfocusout = onchange;
4537 // All others:
4538 else
caryclark55888e42016-07-18 10:01:36 -07004539 window.onpageshow = window.onpagehide
caryclarkdac1d172014-06-17 05:15:38 -07004540 = window.onfocus = window.onblur = onchange;
4541
4542 function onchange (evt) {
4543 var v = 'visible', h = 'hidden',
caryclark55888e42016-07-18 10:01:36 -07004544 evtMap = {
4545 focus:v, focusin:v, pageshow:v, blur:h, focusout:h, pagehide:h
caryclarkdac1d172014-06-17 05:15:38 -07004546 };
4547
4548 evt = evt || window.event;
4549 if (evt.type in evtMap)
4550 document.body.className = evtMap[evt.type];
caryclark55888e42016-07-18 10:01:36 -07004551 else
caryclarkdac1d172014-06-17 05:15:38 -07004552 document.body.className = this[hidden] ? "hidden" : "visible";
4553 }
4554})();
4555
4556function calcXY() {
4557 var e = window.event;
caryclark55888e42016-07-18 10:01:36 -07004558 var tgt = e.target || e.srcElement;
caryclarkdac1d172014-06-17 05:15:38 -07004559 var left = tgt.offsetLeft;
4560 var top = tgt.offsetTop;
4561 mouseX = (e.clientX - left) / scale + srcLeft;
4562 mouseY = (e.clientY - top) / scale + srcTop;
4563}
4564
4565function calcLeftTop() {
4566 srcLeft = mouseX - screenWidth / 2 / scale;
4567 srcTop = mouseY - screenHeight / 2 / scale;
4568}
4569
4570var disableClick = false;
4571
4572function handleMouseClick() {
4573 if (disableClick) {
4574 return;
4575 }
4576 if (!curve_t || !ptInTControl()) {
4577 calcXY();
4578 calcLeftTop();
4579 }
4580 redraw();
4581// if (!curve_t || !ptInTControl()) {
4582// mouseX = screenWidth / 2 / scale + srcLeft;
4583// mouseY = screenHeight / 2 / scale + srcTop;
4584// }
4585}
4586
4587function handleMouseOver() {
4588 calcXY();
4589 if (debug_xy != 2) {
4590 return;
4591 }
4592 var num = mouseX.toFixed(decimal_places) + ", " + mouseY.toFixed(decimal_places);
4593 ctx.beginPath();
4594 ctx.rect(300,100,num.length * 6,10);
4595 ctx.fillStyle="white";
4596 ctx.fill();
4597 ctx.font = "normal 10px Arial";
4598 ctx.fillStyle="black";
4599 ctx.textAlign = "left";
4600 ctx.fillText(num, 300, 108);
4601}
4602
4603function start() {
4604 for (var i = 0; i < testDivs.length; ++i) {
4605 tests[i] = null;
4606 }
4607 testIndex = 0;
4608 drawTop();
4609 window.addEventListener('keypress', doKeyPress, true);
4610 window.addEventListener('keydown', doKeyDown, true);
4611 window.onresize = function() {
4612 drawTop();
4613 }
4614 /*
4615 window.onpagehide = function() {
4616 disableClick = true;
4617 }
4618 */
4619 window.onpageshow = function () {
4620 disableClick = false;
4621 }
4622}
4623
4624</script>
4625</head>
4626
4627<body onLoad="start();">
4628<canvas id="canvas" width="750" height="500"
4629 onmousemove="handleMouseOver()"
4630 onclick="handleMouseClick()"
4631 ></canvas >
4632</body>
4633</html>