blob: 5acbeb136e860b0af6a237c192e2f4f491a5286f [file] [log] [blame]
caryclarkdac1d172014-06-17 05:15:38 -07001<html>
2<head>
Cary Clarkd2eb5812017-01-18 11:00:57 -05003<div height="0" hidden="true">
Cary Clark7eb01e02016-12-08 14:36:32 -05004
Cary Clarkd2eb5812017-01-18 11:00:57 -05005Skia UnitTests: --match Simplify$ --resourcePath resources\ -v -V SK_DEBUG
6
Cary Clarkab2d73b2016-12-16 17:17:25 -05007<div id="joel_9">
8SkDCubic::ComplexBreak
9{{{135.9219970703125, 286.843994140625}, {137.0699920654296875, 287.218994140625}, {138.24200439453125, 287.08599853515625}, {139.24200439453125, 286.5780029296875}}},
10maxCurvature[0]=0.792934788 {{{135.4119318213115264, 287.8851344587143899}, {141.7889152443062528, 285.8031681979956034}}},
11SkDCubic::ComplexBreak
12{{{144.8590087890625, 285.1719970703125}, {143.49200439453125, 289.375}, {138.99200439453125, 291.656005859375}, {134.7970123291015625, 290.2969970703125}}},
13maxCurvature[0]=0.500369557 {{{151.8091004853574191, 284.2739657784525775}, {129.9598379993292951, 295.3706402825127384}}},
14SkDCubic::ComplexBreak
15{{{133.13299560546875, 281.36700439453125}, {132.75799560546875, 282.50799560546875}, {132.88299560546875, 283.68701171875}, {133.3909912109375, 284.67901611328125}}},
16maxCurvature[0]=0.890138394 {{{131.9702953334127074, 281.2544561239553218}, {134.504877661677142, 287.4367308089338735}}},
17SkDCubic::ComplexBreak
18{{{134.7969970703125, 290.2960205078125}, {130.60198974609375, 288.92901611328125}, {128.3130035400390625, 284.43701171875}, {129.67999267578125, 280.24102783203125}}},
19maxCurvature[0]=0.501284828 {{{135.6786690755316727, 297.2365018076872047}, {124.6125777463847015, 275.3942315809875936}}},
20SkDCubic::ComplexBreak
21{{{138.6089935302734375, 278.57000732421875}, {137.46099853515625, 278.2030029296875}, {136.2969970703125, 278.3280029296875}, {135.2969970703125, 278.83599853515625}}},
22maxCurvature[0]=0.752685444 {{{139.2766403970662736, 277.5953584796508267}, {132.8559815638245141, 279.4666826521223584}}},
23SkDCubic::ComplexBreak
24{{{129.67999267578125, 280.24200439453125}, {131.0469970703125, 276.03900146484375}, {135.5389862060546875, 273.75799560546875}, {139.7419891357421875, 275.11700439453125}}},
25maxCurvature[0]=0.497337863 {{{122.7256959778976722, 281.2074843176263244}, {144.5112303093615367, 270.009707570421881}}},
26SkDCubic::ComplexBreak
27{{{141.406005859375, 284.05499267578125}, {141.77301025390625, 282.906982421875}, {141.64801025390625, 281.7349853515625}, {141.14801025390625, 280.7349853515625}}},
28maxCurvature[0]=0.832410427 {{{142.480311641757794, 284.4077599725231948}, {140.2541820165808417, 278.0948877187078097}}},
29SkDCubic::ComplexBreak
30{{{139.74200439453125, 275.11798095703125}, {143.93701171875, 276.49298095703125}, {146.2190093994140625, 280.97698974609375}, {144.8590087890625, 285.1729736328125}}},
31maxCurvature[0]=0.502822735 {{{138.8970629124157199, 268.1903632194039346}, {149.9014014889614828, 290.0464803476303359}}},
32<empty>
33<empty>
34seg=1 {{{135.921997f, 286.843994f}, {137.069992f, 287.218994f}, {138.242004f, 287.085999f}, {139.242004f, 286.578003f}}}
35seg=2 {{{139.242004f, 286.578003f}, {140.234009f, 286.078003f}, {141.031006f, 285.203003f}, {141.406006f, 284.054993f}}}
36seg=3 {{{141.406006f, 284.054993f}, {144.859009f, 285.171997f}}}
37seg=4 {{{144.859009f, 285.171997f}, {143.492004f, 289.375f}, {138.992004f, 291.656006f}, {134.797012f, 290.296997f}}}
38seg=5 {{{134.797012f, 290.296997f}, {135.921997f, 286.843994f}}}
39<empty>
40seg=6 {{{133.132996f, 281.367004f}, {132.757996f, 282.507996f}, {132.882996f, 283.687012f}, {133.390991f, 284.679016f}}}
41seg=7 {{{133.390991f, 284.679016f}, {133.906998f, 285.679016f}, {134.773987f, 286.468018f}, {135.921997f, 286.843018f}}}
42seg=8 {{{135.921997f, 286.843018f}, {134.796997f, 290.296021f}}}
43seg=9 {{{134.796997f, 290.296021f}, {130.60199f, 288.929016f}, {128.313004f, 284.437012f}, {129.679993f, 280.241028f}}}
44seg=10 {{{129.679993f, 280.241028f}, {133.132996f, 281.367004f}}}
45<empty>
46seg=11 {{{138.608994f, 278.570007f}, {137.460999f, 278.203003f}, {136.296997f, 278.328003f}, {135.296997f, 278.835999f}}}
47seg=12 {{{135.296997f, 278.835999f}, {134.296997f, 279.343994f}, {133.507996f, 280.218994f}, {133.132996f, 281.367004f}}}
48seg=13 {{{133.132996f, 281.367004f}, {129.679993f, 280.242004f}}}
49seg=14 {{{129.679993f, 280.242004f}, {131.046997f, 276.039001f}, {135.538986f, 273.757996f}, {139.741989f, 275.117004f}}}
50seg=15 {{{139.741989f, 275.117004f}, {138.608994f, 278.570007f}}}
51seg=16 {{{141.406006f, 284.054993f}, {141.77301f, 282.906982f}, {141.64801f, 281.734985f}, {141.14801f, 280.734985f}}}
52seg=17 {{{141.14801f, 280.734985f}, {140.625015f, 279.734985f}, {139.757004f, 278.945984f}, {138.609009f, 278.570984f}}}
53seg=18 {{{138.609009f, 278.570984f}, {139.742004f, 275.117981f}}}
54seg=19 {{{139.742004f, 275.117981f}, {143.937012f, 276.492981f}, {146.219009f, 280.97699f}, {144.859009f, 285.172974f}}}
55seg=20 {{{144.859009f, 285.172974f}, {141.406006f, 284.054993f}}}
56debugShowCubicIntersection wtTs[0]=1 {{{138.608994,278.570007}, {137.460999,278.203003}, {136.296997,278.328003}, {135.296997,278.835999}}} {{135.296997,278.835999}} wnTs[0]=0 {{{135.296997,278.835999}, {134.296997,279.343994}, {133.507996,280.218994}, {133.132996,281.367004}}}
57debugShowCubicIntersection no intersect {{{138.608994,278.570007}, {137.460999,278.203003}, {136.296997,278.328003}, {135.296997,278.835999}}} {{{129.679993,280.242004}, {131.046997,276.039001}, {135.538986,273.757996}, {139.741989,275.117004}}}
58debugShowCubicLineIntersection wtTs[0]=0 {{{138.608994,278.570007}, {137.460999,278.203003}, {136.296997,278.328003}, {135.296997,278.835999}}} {{138.608994,278.570007}} wnTs[0]=1 {{{139.741989,275.117004}, {138.608994,278.570007}}}
59debugShowCubicLineIntersection wtTs[0]=1 {{{135.296997,278.835999}, {134.296997,279.343994}, {133.507996,280.218994}, {133.132996,281.367004}}} {{133.132996,281.367004}} wnTs[0]=0 {{{133.132996,281.367004}, {129.679993,280.242004}}}
60debugShowCubicIntersection no intersect {{{135.296997,278.835999}, {134.296997,279.343994}, {133.507996,280.218994}, {133.132996,281.367004}}} {{{129.679993,280.242004}, {131.046997,276.039001}, {135.538986,273.757996}, {139.741989,275.117004}}}
61debugShowCubicLineIntersection wtTs[0]=0 {{{129.679993,280.242004}, {131.046997,276.039001}, {135.538986,273.757996}, {139.741989,275.117004}}} {{129.679993,280.242004}} wnTs[0]=1 {{{133.132996,281.367004}, {129.679993,280.242004}}}
62debugShowCubicLineIntersection wtTs[0]=1 {{{129.679993,280.242004}, {131.046997,276.039001}, {135.538986,273.757996}, {139.741989,275.117004}}} {{139.741989,275.117004}} wnTs[0]=0 {{{139.741989,275.117004}, {138.608994,278.570007}}}
63debugShowCubicIntersection no intersect {{{138.608994,278.570007}, {137.460999,278.203003}, {136.296997,278.328003}, {135.296997,278.835999}}} {{{141.14801,280.734985}, {140.625015,279.734985}, {139.757004,278.945984}, {138.609009,278.570984}}}
64debugShowCubicLineIntersection wtTs[0]=0 {{{138.608994,278.570007}, {137.460999,278.203003}, {136.296997,278.328003}, {135.296997,278.835999}}} {{138.608994,278.570007}} wnTs[0]=0.000254017 {{{138.609009,278.570984}, {139.742004,275.117981}}}
65SkOpSegment::addT insert t=0.00025401744 segID=18 spanID=41
66debugShowCubicIntersection no intersect {{{129.679993,280.242004}, {131.046997,276.039001}, {135.538986,273.757996}, {139.741989,275.117004}}} {{{141.14801,280.734985}, {140.625015,279.734985}, {139.757004,278.945984}, {138.609009,278.570984}}}
67debugShowCubicLineIntersection no intersect {{{129.679993,280.242004}, {131.046997,276.039001}, {135.538986,273.757996}, {139.741989,275.117004}}} {{{138.609009,278.570984}, {139.742004,275.117981}}}
68debugShowCubicIntersection no intersect {{{129.679993,280.242004}, {131.046997,276.039001}, {135.538986,273.757996}, {139.741989,275.117004}}} {{{139.742004,275.117981}, {143.937012,276.492981}, {146.219009,280.97699}, {144.859009,285.172974}}}
69debugShowLineIntersection wtTs[0]=0.00025401744 {{{139.741989,275.117004}, {138.608994,278.570007}}} {{139.742004,275.117981}} wtTs[1]=1 {{138.608994,278.570007}} wnTs[0]=1 {{{138.609009,278.570984}, {139.742004,275.117981}}} wnTs[1]=0.00025401744
70SkOpSegment::addT insert t=0.00025401744 segID=15 spanID=42
71debugShowCubicLineIntersection wtTs[0]=0 {{{139.742004,275.117981}, {143.937012,276.492981}, {146.219009,280.97699}, {144.859009,285.172974}}} {{139.742004,275.117981}} wnTs[0]=0.000254017 {{{139.741989,275.117004}, {138.608994,278.570007}}}
72debugShowCubicIntersection wtTs[0]=1 {{{135.296997,278.835999}, {134.296997,279.343994}, {133.507996,280.218994}, {133.132996,281.367004}}} {{133.132996,281.367004}} wnTs[0]=0 {{{133.132996,281.367004}, {132.757996,282.507996}, {132.882996,283.687012}, {133.390991,284.679016}}}
73debugShowCubicIntersection no intersect {{{135.296997,278.835999}, {134.296997,279.343994}, {133.507996,280.218994}, {133.132996,281.367004}}} {{{134.796997,290.296021}, {130.60199,288.929016}, {128.313004,284.437012}, {129.679993,280.241028}}}
74debugShowCubicLineIntersection wtTs[0]=1 {{{135.296997,278.835999}, {134.296997,279.343994}, {133.507996,280.218994}, {133.132996,281.367004}}} {{133.132996,281.367004}} wnTs[0]=1 {{{129.679993,280.241028}, {133.132996,281.367004}}}
75debugShowCubicLineIntersection wtTs[0]=0 {{{133.132996,281.367004}, {132.757996,282.507996}, {132.882996,283.687012}, {133.390991,284.679016}}} {{133.132996,281.367004}} wnTs[0]=0 {{{133.132996,281.367004}, {129.679993,280.242004}}}
76debugShowCubicLineIntersection no intersect {{{134.796997,290.296021}, {130.60199,288.929016}, {128.313004,284.437012}, {129.679993,280.241028}}} {{{133.132996,281.367004}, {129.679993,280.242004}}}
77debugShowLineIntersection wtTs[0]=0 {{{133.132996,281.367004}, {129.679993,280.242004}}} {{133.132996,281.367004}} wnTs[0]=1 {{{129.679993,280.241028}, {133.132996,281.367004}}}
78debugShowCubicIntersection no intersect {{{129.679993,280.242004}, {131.046997,276.039001}, {135.538986,273.757996}, {139.741989,275.117004}}} {{{134.796997,290.296021}, {130.60199,288.929016}, {128.313004,284.437012}, {129.679993,280.241028}}}
79debugShowCubicLineIntersection wtTs[0]=7.00240426e-05 {{{129.679993,280.242004}, {131.046997,276.039001}, {135.538986,273.757996}, {139.741989,275.117004}}} {{129.680283,280.241119}} wnTs[0]=8.31785e-05 {{{129.679993,280.241028}, {133.132996,281.367004}}}
80SkOpSegment::addT insert t=7.00240426e-05 segID=14 spanID=43
81debugShowCubicIntersection wtTs[0]=1 {{{141.406006,284.054993}, {141.77301,282.906982}, {141.64801,281.734985}, {141.14801,280.734985}}} {{141.14801,280.734985}} wnTs[0]=0 {{{141.14801,280.734985}, {140.625015,279.734985}, {139.757004,278.945984}, {138.609009,278.570984}}}
82debugShowCubicIntersection no intersect {{{141.406006,284.054993}, {141.77301,282.906982}, {141.64801,281.734985}, {141.14801,280.734985}}} {{{139.742004,275.117981}, {143.937012,276.492981}, {146.219009,280.97699}, {144.859009,285.172974}}}
83debugShowCubicLineIntersection wtTs[0]=0 {{{141.406006,284.054993}, {141.77301,282.906982}, {141.64801,281.734985}, {141.14801,280.734985}}} {{141.406006,284.054993}} wnTs[0]=1 {{{144.859009,285.172974}, {141.406006,284.054993}}}
84debugShowCubicLineIntersection wtTs[0]=1 {{{141.14801,280.734985}, {140.625015,279.734985}, {139.757004,278.945984}, {138.609009,278.570984}}} {{138.609009,278.570984}} wnTs[0]=0 {{{138.609009,278.570984}, {139.742004,275.117981}}}
85debugShowCubicIntersection no intersect {{{141.14801,280.734985}, {140.625015,279.734985}, {139.757004,278.945984}, {138.609009,278.570984}}} {{{139.742004,275.117981}, {143.937012,276.492981}, {146.219009,280.97699}, {144.859009,285.172974}}}
86debugShowCubicLineIntersection wtTs[0]=0 {{{139.742004,275.117981}, {143.937012,276.492981}, {146.219009,280.97699}, {144.859009,285.172974}}} {{139.742004,275.117981}} wnTs[0]=1 {{{138.609009,278.570984}, {139.742004,275.117981}}}
87debugShowCubicLineIntersection wtTs[0]=1 {{{139.742004,275.117981}, {143.937012,276.492981}, {146.219009,280.97699}, {144.859009,285.172974}}} {{144.859009,285.172974}} wnTs[0]=0 {{{144.859009,285.172974}, {141.406006,284.054993}}}
88debugShowCubicIntersection wtTs[0]=0 {{{141.406006,284.054993}, {141.77301,282.906982}, {141.64801,281.734985}, {141.14801,280.734985}}} {{141.406006,284.054993}} wnTs[0]=1 {{{139.242004,286.578003}, {140.234009,286.078003}, {141.031006,285.203003}, {141.406006,284.054993}}}
89debugShowCubicLineIntersection wtTs[0]=0 {{{141.406006,284.054993}, {141.77301,282.906982}, {141.64801,281.734985}, {141.14801,280.734985}}} {{141.406006,284.054993}} wnTs[0]=0 {{{141.406006,284.054993}, {144.859009,285.171997}}}
90debugShowCubicIntersection no intersect {{{139.742004,275.117981}, {143.937012,276.492981}, {146.219009,280.97699}, {144.859009,285.172974}}} {{{139.242004,286.578003}, {140.234009,286.078003}, {141.031006,285.203003}, {141.406006,284.054993}}}
91debugShowCubicLineIntersection no intersect {{{139.742004,275.117981}, {143.937012,276.492981}, {146.219009,280.97699}, {144.859009,285.172974}}} {{{141.406006,284.054993}, {144.859009,285.171997}}}
92debugShowCubicIntersection no intersect {{{139.742004,275.117981}, {143.937012,276.492981}, {146.219009,280.97699}, {144.859009,285.172974}}} {{{144.859009,285.171997}, {143.492004,289.375}, {138.992004,291.656006}, {134.797012,290.296997}}}
93debugShowCubicLineIntersection wtTs[0]=1 {{{139.242004,286.578003}, {140.234009,286.078003}, {141.031006,285.203003}, {141.406006,284.054993}}} {{141.406006,284.054993}} wnTs[0]=1 {{{144.859009,285.172974}, {141.406006,284.054993}}}
94debugShowLineIntersection wtTs[0]=1 {{{144.859009,285.172974}, {141.406006,284.054993}}} {{141.406006,284.054993}} wnTs[0]=0 {{{141.406006,284.054993}, {144.859009,285.171997}}}
95debugShowCubicLineIntersection wtTs[0]=7.00717611e-05 {{{144.859009,285.171997}, {143.492004,289.375}, {138.992004,291.656006}, {134.797012,290.296997}}} {{144.858719,285.172882}} wnTs[0]=8.32352e-05 {{{144.859009,285.172974}, {141.406006,284.054993}}}
96SkOpSegment::addT insert t=7.00717611e-05 segID=4 spanID=44
97debugShowCubicIntersection wtTs[0]=1 {{{133.132996,281.367004}, {132.757996,282.507996}, {132.882996,283.687012}, {133.390991,284.679016}}} {{133.390991,284.679016}} wnTs[0]=0 {{{133.390991,284.679016}, {133.906998,285.679016}, {134.773987,286.468018}, {135.921997,286.843018}}}
98debugShowCubicIntersection no intersect {{{133.132996,281.367004}, {132.757996,282.507996}, {132.882996,283.687012}, {133.390991,284.679016}}} {{{134.796997,290.296021}, {130.60199,288.929016}, {128.313004,284.437012}, {129.679993,280.241028}}}
99debugShowCubicLineIntersection wtTs[0]=0 {{{133.132996,281.367004}, {132.757996,282.507996}, {132.882996,283.687012}, {133.390991,284.679016}}} {{133.132996,281.367004}} wnTs[0]=1 {{{129.679993,280.241028}, {133.132996,281.367004}}}
100debugShowCubicLineIntersection wtTs[0]=1 {{{133.390991,284.679016}, {133.906998,285.679016}, {134.773987,286.468018}, {135.921997,286.843018}}} {{135.921997,286.843018}} wnTs[0]=0 {{{135.921997,286.843018}, {134.796997,290.296021}}}
101debugShowCubicIntersection no intersect {{{133.390991,284.679016}, {133.906998,285.679016}, {134.773987,286.468018}, {135.921997,286.843018}}} {{{134.796997,290.296021}, {130.60199,288.929016}, {128.313004,284.437012}, {129.679993,280.241028}}}
102debugShowCubicLineIntersection wtTs[0]=0 {{{134.796997,290.296021}, {130.60199,288.929016}, {128.313004,284.437012}, {129.679993,280.241028}}} {{134.796997,290.296021}} wnTs[0]=1 {{{135.921997,286.843018}, {134.796997,290.296021}}}
103debugShowCubicLineIntersection wtTs[0]=1 {{{134.796997,290.296021}, {130.60199,288.929016}, {128.313004,284.437012}, {129.679993,280.241028}}} {{129.679993,280.241028}} wnTs[0]=0 {{{129.679993,280.241028}, {133.132996,281.367004}}}
104debugShowCubicIntersection no intersect {{{133.390991,284.679016}, {133.906998,285.679016}, {134.773987,286.468018}, {135.921997,286.843018}}} {{{135.921997,286.843994}, {137.069992,287.218994}, {138.242004,287.085999}, {139.242004,286.578003}}}
105debugShowCubicIntersection no intersect {{{133.390991,284.679016}, {133.906998,285.679016}, {134.773987,286.468018}, {135.921997,286.843018}}} {{{144.859009,285.171997}, {143.492004,289.375}, {138.992004,291.656006}, {134.797012,290.296997}}}
106debugShowCubicLineIntersection wtTs[0]=0 {{{135.921997,286.843994}, {137.069992,287.218994}, {138.242004,287.085999}, {139.242004,286.578003}}} {{135.921997,286.843994}} wnTs[0]=0.000255676 {{{135.921997,286.843018}, {134.796997,290.296021}}}
107SkOpSegment::addT insert t=0.000255675976 segID=8 spanID=45
108debugShowCubicLineIntersection no intersect {{{144.859009,285.171997}, {143.492004,289.375}, {138.992004,291.656006}, {134.797012,290.296997}}} {{{135.921997,286.843018}, {134.796997,290.296021}}}
109debugShowLineIntersection wtTs[0]=0.000255675976 {{{135.921997,286.843018}, {134.796997,290.296021}}} {{135.921997,286.843994}} wtTs[1]=1 {{134.796997,290.296021}} wnTs[0]=1 {{{134.797012,290.296997}, {135.921997,286.843994}}} wnTs[1]=0.000254375091
110SkOpSegment::addT insert t=0.000254375091 segID=5 spanID=46
111debugShowCubicIntersection no intersect {{{134.796997,290.296021}, {130.60199,288.929016}, {128.313004,284.437012}, {129.679993,280.241028}}} {{{144.859009,285.171997}, {143.492004,289.375}, {138.992004,291.656006}, {134.797012,290.296997}}}
112debugShowCubicLineIntersection wtTs[0]=0 {{{134.796997,290.296021}, {130.60199,288.929016}, {128.313004,284.437012}, {129.679993,280.241028}}} {{134.796997,290.296021}} wnTs[0]=0.000254375 {{{134.797012,290.296997}, {135.921997,286.843994}}}
113debugShowCubicIntersection wtTs[0]=1 {{{135.921997,286.843994}, {137.069992,287.218994}, {138.242004,287.085999}, {139.242004,286.578003}}} {{139.242004,286.578003}} wnTs[0]=0 {{{139.242004,286.578003}, {140.234009,286.078003}, {141.031006,285.203003}, {141.406006,284.054993}}}
114debugShowCubicIntersection no intersect {{{135.921997,286.843994}, {137.069992,287.218994}, {138.242004,287.085999}, {139.242004,286.578003}}} {{{144.859009,285.171997}, {143.492004,289.375}, {138.992004,291.656006}, {134.797012,290.296997}}}
115debugShowCubicLineIntersection wtTs[0]=0 {{{135.921997,286.843994}, {137.069992,287.218994}, {138.242004,287.085999}, {139.242004,286.578003}}} {{135.921997,286.843994}} wnTs[0]=1 {{{134.797012,290.296997}, {135.921997,286.843994}}}
116debugShowCubicLineIntersection wtTs[0]=1 {{{139.242004,286.578003}, {140.234009,286.078003}, {141.031006,285.203003}, {141.406006,284.054993}}} {{141.406006,284.054993}} wnTs[0]=0 {{{141.406006,284.054993}, {144.859009,285.171997}}}
117debugShowCubicIntersection no intersect {{{139.242004,286.578003}, {140.234009,286.078003}, {141.031006,285.203003}, {141.406006,284.054993}}} {{{144.859009,285.171997}, {143.492004,289.375}, {138.992004,291.656006}, {134.797012,290.296997}}}
118debugShowCubicLineIntersection wtTs[0]=0 {{{144.859009,285.171997}, {143.492004,289.375}, {138.992004,291.656006}, {134.797012,290.296997}}} {{144.859009,285.171997}} wnTs[0]=1 {{{141.406006,284.054993}, {144.859009,285.171997}}}
119debugShowCubicLineIntersection wtTs[0]=1 {{{144.859009,285.171997}, {143.492004,289.375}, {138.992004,291.656006}, {134.797012,290.296997}}} {{134.797012,290.296997}} wnTs[0]=0 {{{134.797012,290.296997}, {135.921997,286.843994}}}
120------------------x--x---------------- addExpanded
12100: seg/base=5/46 seg/base=8/45 MarkCoinStart
12201: seg/base=5/10 seg/base=8/16 MarkCoinEnd
12302: seg/base=18/41 seg/base=15/42 MarkCoinStart
12403: seg/base=18/36 seg/base=15/30 MarkCoinEnd
125SkOpSegment::debugShowActiveSpans id=11 (138.608994,278.570007 137.460999,278.203003 136.296997,278.328003 135.296997,278.835999) t=0 tEnd=1 windSum=? windValue=1
126SkOpSegment::debugShowActiveSpans id=12 (135.296997,278.835999 134.296997,279.343994 133.507996,280.218994 133.132996,281.367004) t=0 tEnd=1 windSum=? windValue=1
127SkOpSegment::debugShowActiveSpans id=13 (133.132996,281.367004 129.679993,280.242004) t=0 tEnd=1 windSum=? windValue=1
128SkOpSegment::debugShowActiveSpans id=14 (129.679993,280.242004 129.680088,280.24171 129.680187,280.241414 129.680283,280.241119) t=0 tEnd=7.00240426e-05 windSum=? windValue=1
129SkOpSegment::debugShowActiveSpans id=14 (129.680283,280.241119 131.047629,276.03868 135.539281,273.758091 139.741989,275.117004) t=7.00240426e-05 tEnd=1 windSum=? windValue=1
130SkOpSegment::debugShowActiveSpans id=15 (139.741989,275.117004 139.741699,275.117889) t=0 tEnd=0.00025401744 windSum=? windValue=1
131SkOpSegment::debugShowActiveSpans id=15 (139.741699,275.117889 138.608994,278.570007) t=0.00025401744 tEnd=1 windSum=? windValue=1
132SkOpSegment::debugShowActiveSpans id=16 (141.406006,284.054993 141.77301,282.906982 141.64801,281.734985 141.14801,280.734985) t=0 tEnd=1 windSum=? windValue=1
133SkOpSegment::debugShowActiveSpans id=17 (141.14801,280.734985 140.625015,279.734985 139.757004,278.945984 138.609009,278.570984) t=0 tEnd=1 windSum=? windValue=1
134SkOpSegment::debugShowActiveSpans id=18 (138.609009,278.570984 138.609299,278.570099) t=0 tEnd=0.00025401744 windSum=? windValue=1
135SkOpSegment::debugShowActiveSpans id=18 (138.609299,278.570099 139.742004,275.117981) t=0.00025401744 tEnd=1 windSum=? windValue=1
136SkOpSegment::debugShowActiveSpans id=19 (139.742004,275.117981 143.937012,276.492981 146.219009,280.97699 144.859009,285.172974) t=0 tEnd=1 windSum=? windValue=1
137SkOpSegment::debugShowActiveSpans id=20 (144.859009,285.172974 141.406006,284.054993) t=0 tEnd=1 windSum=? windValue=1
138SkOpSegment::debugShowActiveSpans id=6 (133.132996,281.367004 132.757996,282.507996 132.882996,283.687012 133.390991,284.679016) t=0 tEnd=1 windSum=? windValue=1
139SkOpSegment::debugShowActiveSpans id=7 (133.390991,284.679016 133.906998,285.679016 134.773987,286.468018 135.921997,286.843018) t=0 tEnd=1 windSum=? windValue=1
140SkOpSegment::debugShowActiveSpans id=8 (135.921997,286.843018 135.921707,286.843903) t=0 tEnd=0.000255675976 windSum=? windValue=1
141SkOpSegment::debugShowActiveSpans id=8 (135.921707,286.843903 134.796997,290.296021) t=0.000255675976 tEnd=1 windSum=? windValue=1
142SkOpSegment::debugShowActiveSpans id=9 (134.796997,290.296021 130.60199,288.929016 128.313004,284.437012 129.679993,280.241028) t=0 tEnd=1 windSum=? windValue=1
143SkOpSegment::debugShowActiveSpans id=10 (129.679993,280.241028 133.132996,281.367004) t=0 tEnd=1 windSum=? windValue=1
144SkOpSegment::debugShowActiveSpans id=1 (135.921997,286.843994 137.069992,287.218994 138.242004,287.085999 139.242004,286.578003) t=0 tEnd=1 windSum=? windValue=1
145SkOpSegment::debugShowActiveSpans id=2 (139.242004,286.578003 140.234009,286.078003 141.031006,285.203003 141.406006,284.054993) t=0 tEnd=1 windSum=? windValue=1
146SkOpSegment::debugShowActiveSpans id=3 (141.406006,284.054993 144.859009,285.171997) t=0 tEnd=1 windSum=? windValue=1
147SkOpSegment::debugShowActiveSpans id=4 (144.859009,285.171997 144.858913,285.172292 144.858815,285.172588 144.858719,285.172882) t=0 tEnd=7.00717611e-05 windSum=? windValue=1
148SkOpSegment::debugShowActiveSpans id=4 (144.858719,285.172882 143.491371,289.375321 138.99171,291.655911 134.797012,290.296997) t=7.00717611e-05 tEnd=1 windSum=? windValue=1
149SkOpSegment::debugShowActiveSpans id=5 (134.797012,290.296997 134.797302,290.296112) t=0 tEnd=0.000254375091 windSum=? windValue=1
150SkOpSegment::debugShowActiveSpans id=5 (134.797302,290.296112 135.921997,286.843994) t=0.000254375091 tEnd=1 windSum=? windValue=1
151------------------x--x---------------- move_multiples
15200: seg/base=5/46 seg/base=8/45 MarkCoinStart
15301: seg/base=5/10 seg/base=8/16 MarkCoinEnd
15402: seg/base=18/41 seg/base=15/42 MarkCoinStart
15503: seg/base=18/36 seg/base=15/30 MarkCoinEnd
156------------------x--x---------------- move_nearby
15700: seg/base=5/46 seg/base=8/45 MarkCoinStart
15801: seg/base=5/10 seg/base=8/16 MarkCoinEnd
15902: seg/base=18/41 seg/base=15/42 MarkCoinStart
16003: seg/base=18/36 seg/base=15/30 MarkCoinEnd
161------------------x--x---------------- correctEnds
16200: seg/base=5/46 seg/base=8/45 MarkCoinStart
16301: seg/base=5/10 seg/base=8/16 MarkCoinEnd
16402: seg/base=18/41 seg/base=15/42 MarkCoinStart
16503: seg/base=18/36 seg/base=15/30 MarkCoinEnd
166------------------x--x---------------- addEndMovedSpans
16700: seg/base=5/46 seg/base=8/45 MarkCoinStart
16801: seg/base=5/10 seg/base=8/16 MarkCoinEnd
16902: seg/base=18/41 seg/base=15/42 MarkCoinStart
17003: seg/base=18/36 seg/base=15/30 MarkCoinEnd
171------------------x--x---------------- expand
17200: seg/base=5/46 seg/base=8/45 MarkCoinStart
17301: seg/base=5/10 seg/base=8/16 MarkCoinEnd
17402: seg/base=18/41 seg/base=15/42 MarkCoinStart
17503: seg/base=18/36 seg/base=15/30 MarkCoinEnd
176------------------x--x---------------- addExpanded
17700: seg/base=5/46 seg/base=8/45 MarkCoinStart
17801: seg/base=5/10 seg/base=8/16 MarkCoinEnd
17902: seg/base=18/41 seg/base=15/42 MarkCoinStart
18003: seg/base=18/36 seg/base=15/30 MarkCoinEnd
181------------------x--x---------------- mark
18200: seg/base=5/46 seg/base=8/45 MarkCoinStart
18301: seg/base=5/10 seg/base=8/16 MarkCoinEnd
18402: seg/base=18/41 seg/base=15/42 MarkCoinStart
18503: seg/base=18/36 seg/base=15/30 MarkCoinEnd
186-------------------------------------- missing_coincidence
187-------------------------------------- expand
188-------------------------------------- expand
189-------------------------------------- apply
190SkOpSegment::markDone id=5 (134.797012,290.296997 135.921997,286.843994) t=0.000254375091 [46] (134.797302,290.296112) tEnd=1 newWindSum=? newOppSum=? oppSum=? windSum=? windValue=0 oppValue=0
191SkOpSegment::markDone id=8 (135.921997,286.843018 134.796997,290.296021) t=0.000255675976 [45] (135.921707,286.843903) tEnd=1 newWindSum=? newOppSum=? oppSum=? windSum=? windValue=0 oppValue=0
192SkOpSegment::markDone id=18 (138.609009,278.570984 139.742004,275.117981) t=0.00025401744 [41] (138.609299,278.570099) tEnd=1 newWindSum=? newOppSum=? oppSum=? windSum=? windValue=0 oppValue=0
193SkOpSegment::markDone id=15 (139.741989,275.117004 138.608994,278.570007) t=0.00025401744 [42] (139.741699,275.117889) tEnd=1 newWindSum=? newOppSum=? oppSum=? windSum=? windValue=0 oppValue=0
194-------------------------------------- findOverlaps
195SkOpSegment::debugShowActiveSpans id=11 (138.608994,278.570007 137.460999,278.203003 136.296997,278.328003 135.296997,278.835999) t=0 tEnd=1 windSum=? windValue=1
196SkOpSegment::debugShowActiveSpans id=12 (135.296997,278.835999 134.296997,279.343994 133.507996,280.218994 133.132996,281.367004) t=0 tEnd=1 windSum=? windValue=1
197SkOpSegment::debugShowActiveSpans id=13 (133.132996,281.367004 129.679993,280.242004) t=0 tEnd=1 windSum=? windValue=1
198SkOpSegment::debugShowActiveSpans id=14 (129.679993,280.242004 129.680088,280.24171 129.680187,280.241414 129.680283,280.241119) t=0 tEnd=7.00240426e-05 windSum=? windValue=1
199SkOpSegment::debugShowActiveSpans id=14 (129.680283,280.241119 131.047629,276.03868 135.539281,273.758091 139.741989,275.117004) t=7.00240426e-05 tEnd=1 windSum=? windValue=1
200SkOpSegment::debugShowActiveSpans id=15 (139.741989,275.117004 139.741699,275.117889) t=0 tEnd=0.00025401744 windSum=? windValue=1
201SkOpSegment::debugShowActiveSpans id=16 (141.406006,284.054993 141.77301,282.906982 141.64801,281.734985 141.14801,280.734985) t=0 tEnd=1 windSum=? windValue=1
202SkOpSegment::debugShowActiveSpans id=17 (141.14801,280.734985 140.625015,279.734985 139.757004,278.945984 138.609009,278.570984) t=0 tEnd=1 windSum=? windValue=1
203SkOpSegment::debugShowActiveSpans id=18 (138.609009,278.570984 138.609299,278.570099) t=0 tEnd=0.00025401744 windSum=? windValue=1
204SkOpSegment::debugShowActiveSpans id=19 (139.742004,275.117981 143.937012,276.492981 146.219009,280.97699 144.859009,285.172974) t=0 tEnd=1 windSum=? windValue=1
205SkOpSegment::debugShowActiveSpans id=20 (144.859009,285.172974 141.406006,284.054993) t=0 tEnd=1 windSum=? windValue=1
206SkOpSegment::debugShowActiveSpans id=6 (133.132996,281.367004 132.757996,282.507996 132.882996,283.687012 133.390991,284.679016) t=0 tEnd=1 windSum=? windValue=1
207SkOpSegment::debugShowActiveSpans id=7 (133.390991,284.679016 133.906998,285.679016 134.773987,286.468018 135.921997,286.843018) t=0 tEnd=1 windSum=? windValue=1
208SkOpSegment::debugShowActiveSpans id=8 (135.921997,286.843018 135.921707,286.843903) t=0 tEnd=0.000255675976 windSum=? windValue=1
209SkOpSegment::debugShowActiveSpans id=9 (134.796997,290.296021 130.60199,288.929016 128.313004,284.437012 129.679993,280.241028) t=0 tEnd=1 windSum=? windValue=1
210SkOpSegment::debugShowActiveSpans id=10 (129.679993,280.241028 133.132996,281.367004) t=0 tEnd=1 windSum=? windValue=1
211SkOpSegment::debugShowActiveSpans id=1 (135.921997,286.843994 137.069992,287.218994 138.242004,287.085999 139.242004,286.578003) t=0 tEnd=1 windSum=? windValue=1
212SkOpSegment::debugShowActiveSpans id=2 (139.242004,286.578003 140.234009,286.078003 141.031006,285.203003 141.406006,284.054993) t=0 tEnd=1 windSum=? windValue=1
213SkOpSegment::debugShowActiveSpans id=3 (141.406006,284.054993 144.859009,285.171997) t=0 tEnd=1 windSum=? windValue=1
214SkOpSegment::debugShowActiveSpans id=4 (144.859009,285.171997 144.858913,285.172292 144.858815,285.172588 144.858719,285.172882) t=0 tEnd=7.00717611e-05 windSum=? windValue=1
215SkOpSegment::debugShowActiveSpans id=4 (144.858719,285.172882 143.491371,289.375321 138.99171,291.655911 134.797012,290.296997) t=7.00717611e-05 tEnd=1 windSum=? windValue=1
216SkOpSegment::debugShowActiveSpans id=5 (134.797012,290.296997 134.797302,290.296112) t=0 tEnd=0.000254375091 windSum=? windValue=1
217-------------------------------------- calc_angles
218SkOpSegment::sortAngles [11] tStart=0 [21]
219SkOpSegment::sortAngles [12] tStart=1 [24]
Cary Clarkd2eb5812017-01-18 11:00:57 -0500220SkOpAngle::debugAfter [12/2] 5/5 tStart=1 tEnd=0 < [6/13] 21/25 tStart=0 tEnd=1 < [10/18] 13/13 tStart=1 tEnd=0 F 4
Cary Clarkab2d73b2016-12-16 17:17:25 -0500221SkOpAngle::afterPart {{{133.132996,281.367004}, {133.507996,280.218994}, {134.296997,279.343994}, {135.296997,278.835999}}} id=12
222SkOpAngle::afterPart {{{133.132996,281.367004}, {132.757996,282.507996}, {132.882996,283.687012}, {133.390991,284.679016}}} id=6
223SkOpAngle::afterPart {{{133.132996,281.367004}, {129.679993,280.241028}}} id=10
Cary Clarkd2eb5812017-01-18 11:00:57 -0500224SkOpAngle::debugAfter [12/2] 5/5 tStart=1 tEnd=0 < [13/3] 13/13 tStart=0 tEnd=1 < [10/18] 13/13 tStart=1 tEnd=0 F 9
Cary Clarkab2d73b2016-12-16 17:17:25 -0500225SkOpAngle::afterPart {{{133.132996,281.367004}, {133.507996,280.218994}, {134.296997,279.343994}, {135.296997,278.835999}}} id=12
226SkOpAngle::afterPart {{{133.132996,281.367004}, {129.679993,280.242004}}} id=13
227SkOpAngle::afterPart {{{133.132996,281.367004}, {129.679993,280.241028}}} id=10
Cary Clarkd2eb5812017-01-18 11:00:57 -0500228SkOpAngle::debugAfter [10/18] 13/13 tStart=1 tEnd=0 < [13/3] 13/13 tStart=0 tEnd=1 < [6/13] 21/25 tStart=0 tEnd=1 T 9
Cary Clarkab2d73b2016-12-16 17:17:25 -0500229SkOpAngle::afterPart {{{133.132996,281.367004}, {129.679993,280.241028}}} id=10
230SkOpAngle::afterPart {{{133.132996,281.367004}, {129.679993,280.242004}}} id=13
231SkOpAngle::afterPart {{{133.132996,281.367004}, {132.757996,282.507996}, {132.882996,283.687012}, {133.390991,284.679016}}} id=6
232SkOpSegment::sortAngles [13] tStart=0 [25]
233SkOpSegment::sortAngles [14] tStart=7.00240426e-05 [43]
Cary Clarkd2eb5812017-01-18 11:00:57 -0500234ccwOf {{{129.680283,280.241119}, {129.680187,280.241414}}} id=1
235ccwOf {{{129.679993,280.241028}, {128.313004,284.437012}}} id=2
236ccwOf {{{129.680283,280.241119}, {139.741989,275.117004}}} id=1
237ccwOf {{{129.679993,280.241028}, {134.796997,290.296021}}} id=2
238ccwOf {{{129.680283,280.241119}, {139.741989,275.117004}}} id=1
239ccwOf {{{129.680283,280.241119}, {129.680088,280.24171}}} id=2
240ccwOf {{{129.680283,280.241119}, {131.047629,276.03868}}} id=1
241ccwOf {{{129.680283,280.241119}, {129.680088,280.24171}}} id=2
242ccwOf {{{129.680283,280.241119}, {131.047629,276.03868}}} id=1
243ccwOf {{{129.679993,280.241028}, {128.313004,284.437012}}} id=2
244ccwOf {{{129.680283,280.241119}, {129.680088,280.24171}}} id=1
245ccwOf {{{129.679993,280.241028}, {134.796997,290.296021}}} id=2
246SkOpAngle::debugAfter [14/4] 21/21 tStart=7.00240426e-05 tEnd=0 < [9/16] 21/25 tStart=1 tEnd=0 < [14/5] 5/1 tStart=7.00240426e-05 tEnd=1 T 14
247SkOpAngle::afterPart {{{129.680283,280.241119}, {129.679993,280.242004}, {129.680088,280.24171}, {129.679993,280.242004}}} id=14
Cary Clarkab2d73b2016-12-16 17:17:25 -0500248SkOpAngle::afterPart {{{129.679993,280.241028}, {128.313004,284.437012}, {130.60199,288.929016}, {134.796997,290.296021}}} id=9
Cary Clarkd2eb5812017-01-18 11:00:57 -0500249SkOpAngle::afterPart {{{129.680283,280.241119}, {131.047629,276.03868}, {135.539281,273.758091}, {139.741989,275.117004}}} id=14
250ccwOf {{{129.680283,280.241119}, {129.680187,280.241414}}} id=1
251ccwOf {{{129.679993,280.241028}, {133.132996,281.367004}}} id=2
252ccwOf {{{129.679993,280.241028}, {128.313004,284.437012}}} id=1
253ccwOf {{{129.679993,280.241028}, {133.132996,281.367004}}} id=2
254ccwOf {{{129.679993,280.241028}, {128.313004,284.437012}}} id=1
255ccwOf {{{129.680283,280.241119}, {129.680088,280.24171}}} id=2
256ccwOf {{{129.679993,280.241028}, {134.796997,290.296021}}} id=1
257ccwOf {{{129.680283,280.241119}, {129.680088,280.24171}}} id=2
258ccwOf {{{129.679993,280.241028}, {134.796997,290.296021}}} id=1
259ccwOf {{{129.679993,280.241028}, {133.132996,281.367004}}} id=2
260SkOpAngle::debugAfter [14/4] 21/21 tStart=7.00240426e-05 tEnd=0 < [10/17] 29/29 tStart=0 tEnd=1 < [9/16] 21/25 tStart=1 tEnd=0 F 8
Cary Clarkab2d73b2016-12-16 17:17:25 -0500261SkOpAngle::afterPart {{{129.679993,280.241028}, {129.679703,280.241913}, {129.679798,280.241619}, {129.679703,280.241913}}} id=14
262SkOpAngle::afterPart {{{129.679993,280.241028}, {133.132996,281.367004}}} id=10
263SkOpAngle::afterPart {{{129.679993,280.241028}, {128.313004,284.437012}, {130.60199,288.929016}, {134.796997,290.296021}}} id=9
Cary Clarkd2eb5812017-01-18 11:00:57 -0500264SkOpAngle::debugAfter [9/16] 21/25 tStart=1 tEnd=0 < [10/17] 29/29 tStart=0 tEnd=1 < [14/5] 5/1 tStart=7.00240426e-05 tEnd=1 T 4
Cary Clarkab2d73b2016-12-16 17:17:25 -0500265SkOpAngle::afterPart {{{129.679993,280.241028}, {128.313004,284.437012}, {130.60199,288.929016}, {134.796997,290.296021}}} id=9
266SkOpAngle::afterPart {{{129.679993,280.241028}, {133.132996,281.367004}}} id=10
267SkOpAngle::afterPart {{{129.679993,280.241028}, {131.047339,276.038588}, {135.538991,273.757999}, {139.741699,275.116913}}} id=14
268SkOpSegment::sortAngles [15] tStart=0.00025401744 [42]
269SkOpSegment::sortAngles [16] tStart=0 [31]
Cary Clarkd2eb5812017-01-18 11:00:57 -0500270SkOpAngle::debugAfter [16/7] 5/9 tStart=0 tEnd=1 < [2/20] 21/21 tStart=1 tEnd=0 < [3/21] 29/29 tStart=0 tEnd=1 T 4
Cary Clarkab2d73b2016-12-16 17:17:25 -0500271SkOpAngle::afterPart {{{141.406006,284.054993}, {141.77301,282.906982}, {141.64801,281.734985}, {141.14801,280.734985}}} id=16
272SkOpAngle::afterPart {{{141.406006,284.054993}, {141.031006,285.203003}, {140.234009,286.078003}, {139.242004,286.578003}}} id=2
273SkOpAngle::afterPart {{{141.406006,284.054993}, {144.859009,285.171997}}} id=3
Cary Clarkd2eb5812017-01-18 11:00:57 -0500274SkOpAngle::debugAfter [16/7] 5/9 tStart=0 tEnd=1 < [20/12] 29/29 tStart=1 tEnd=0 < [2/20] 21/21 tStart=1 tEnd=0 F 4
Cary Clarkab2d73b2016-12-16 17:17:25 -0500275SkOpAngle::afterPart {{{141.406006,284.054993}, {141.77301,282.906982}, {141.64801,281.734985}, {141.14801,280.734985}}} id=16
276SkOpAngle::afterPart {{{141.406006,284.054993}, {144.859009,285.172974}}} id=20
277SkOpAngle::afterPart {{{141.406006,284.054993}, {141.031006,285.203003}, {140.234009,286.078003}, {139.242004,286.578003}}} id=2
Cary Clarkd2eb5812017-01-18 11:00:57 -0500278SkOpAngle::debugAfter [2/20] 21/21 tStart=1 tEnd=0 < [20/12] 29/29 tStart=1 tEnd=0 < [3/21] 29/29 tStart=0 tEnd=1 T 9
Cary Clarkab2d73b2016-12-16 17:17:25 -0500279SkOpAngle::afterPart {{{141.406006,284.054993}, {141.031006,285.203003}, {140.234009,286.078003}, {139.242004,286.578003}}} id=2
280SkOpAngle::afterPart {{{141.406006,284.054993}, {144.859009,285.172974}}} id=20
281SkOpAngle::afterPart {{{141.406006,284.054993}, {144.859009,285.171997}}} id=3
282SkOpSegment::sortAngles [18] tStart=0.00025401744 [41]
283SkOpSegment::sortAngles [19] tStart=0 [37]
284SkOpSegment::sortAngles [19] tStart=1 [38]
Cary Clarkd2eb5812017-01-18 11:00:57 -0500285ccwOf {{{144.859009,285.172974}, {139.742004,275.117981}}} id=1
286ccwOf {{{144.858719,285.172882}, {144.858913,285.172292}}} id=2
287ccwOf {{{144.859009,285.172974}, {141.406006,284.054993}}} id=1
288ccwOf {{{144.858719,285.172882}, {144.858815,285.172588}}} id=2
289ccwOf {{{144.859009,285.172974}, {141.406006,284.054993}}} id=1
290ccwOf {{{144.859009,285.172974}, {146.219009,280.97699}}} id=2
291ccwOf {{{144.859009,285.172974}, {141.406006,284.054993}}} id=1
292ccwOf {{{144.859009,285.172974}, {139.742004,275.117981}}} id=2
293ccwOf {{{144.859009,285.172974}, {146.219009,280.97699}}} id=1
294ccwOf {{{144.858719,285.172882}, {144.858815,285.172588}}} id=2
295SkOpAngle::debugAfter [19/10] 5/9 tStart=1 tEnd=0 < [4/22] 5/5 tStart=7.00717611e-05 tEnd=0 < [20/11] 13/13 tStart=0 tEnd=1 F 9
296SkOpAngle::afterPart {{{144.859009,285.172974}, {146.219009,280.97699}, {143.937012,276.492981}, {139.742004,275.117981}}} id=19
Cary Clarkab2d73b2016-12-16 17:17:25 -0500297SkOpAngle::afterPart {{{144.858719,285.172882}, {144.859009,285.171997}, {144.858913,285.172292}, {144.859009,285.171997}}} id=4
Cary Clarkd2eb5812017-01-18 11:00:57 -0500298SkOpAngle::afterPart {{{144.859009,285.172974}, {141.406006,284.054993}}} id=20
299ccwOf {{{144.859009,285.172974}, {139.742004,275.117981}}} id=1
300ccwOf {{{144.858719,285.172882}, {134.797012,290.296997}}} id=2
301ccwOf {{{144.859009,285.172974}, {141.406006,284.054993}}} id=1
302ccwOf {{{144.858719,285.172882}, {143.491371,289.375321}}} id=2
303ccwOf {{{144.859009,285.172974}, {141.406006,284.054993}}} id=1
304ccwOf {{{144.859009,285.172974}, {146.219009,280.97699}}} id=2
305ccwOf {{{144.859009,285.172974}, {141.406006,284.054993}}} id=1
306ccwOf {{{144.859009,285.172974}, {139.742004,275.117981}}} id=2
307ccwOf {{{144.859009,285.172974}, {141.406006,284.054993}}} id=1
308ccwOf {{{144.858719,285.172882}, {134.797012,290.296997}}} id=2
309ccwOf {{{144.859009,285.172974}, {146.219009,280.97699}}} id=1
310ccwOf {{{144.858719,285.172882}, {143.491371,289.375321}}} id=2
311SkOpAngle::debugAfter [19/10] 5/9 tStart=1 tEnd=0 < [4/23] 21/17 tStart=7.00717611e-05 tEnd=1 < [20/11] 13/13 tStart=0 tEnd=1 F 7
Cary Clarkab2d73b2016-12-16 17:17:25 -0500312SkOpAngle::afterPart {{{144.858719,285.172882}, {146.218719,280.976898}, {143.936722,276.492889}, {139.741714,275.117889}}} id=19
313SkOpAngle::afterPart {{{144.858719,285.172882}, {143.491371,289.375321}, {138.99171,291.655911}, {134.797012,290.296997}}} id=4
314SkOpAngle::afterPart {{{144.858719,285.172882}, {141.405716,284.054901}}} id=20
Cary Clarkd2eb5812017-01-18 11:00:57 -0500315SkOpAngle::debugAfter [20/11] 13/13 tStart=0 tEnd=1 < [4/23] 21/17 tStart=7.00717611e-05 tEnd=1 < [4/22] 5/5 tStart=7.00717611e-05 tEnd=0 T 4
316SkOpAngle::afterPart {{{144.859009,285.172974}, {141.406006,284.054993}}} id=20
Cary Clarkab2d73b2016-12-16 17:17:25 -0500317SkOpAngle::afterPart {{{144.858719,285.172882}, {143.491371,289.375321}, {138.99171,291.655911}, {134.797012,290.296997}}} id=4
318SkOpAngle::afterPart {{{144.858719,285.172882}, {144.859009,285.171997}, {144.858913,285.172292}, {144.859009,285.171997}}} id=4
319SkOpSegment::sortAngles [20] tStart=0 [39]
320SkOpSegment::sortAngles [20] tStart=1 [40]
321SkOpSegment::sortAngles [6] tStart=0 [11]
322SkOpSegment::sortAngles [8] tStart=0.000255675976 [45]
323SkOpSegment::sortAngles [9] tStart=0 [17]
324SkOpSegment::sortAngles [9] tStart=1 [18]
325SkOpSegment::sortAngles [10] tStart=0 [19]
326SkOpSegment::sortAngles [10] tStart=1 [20]
327SkOpSegment::sortAngles [1] tStart=0 [1]
328SkOpSegment::sortAngles [2] tStart=1 [4]
329SkOpSegment::sortAngles [3] tStart=0 [5]
330SkOpSegment::sortAngles [4] tStart=7.00717611e-05 [44]
331SkOpSegment::sortAngles [5] tStart=0.000254375091 [46]
332coinSpan - id=5 t=0.000254375091 tEnd=1
333coinSpan + id=8 t=1 tEnd=0.000255675976
334coinSpan - id=18 t=0.00025401744 tEnd=1
335coinSpan + id=15 t=1 tEnd=0.00025401744
336SkOpSpan::sortableTop dir=kTop seg=11 t=0.5 pt=(136.897491,278.374878)
337SkOpSpan::sortableTop [0] valid=1 operand=0 span=43 ccw=1 seg=14 {{{129.679993f, 280.242004f}, {131.046997f, 276.039001f}, {135.538986f, 273.757996f}, {139.741989f, 275.117004f}}} t=0.774802234 pt=(136.897491,274.733032) slope=(12.4800744,-0.579929823)
338SkOpSpan::sortableTop [1] valid=1 operand=0 span=21 ccw=0 seg=11 {{{138.608994f, 278.570007f}, {137.460999f, 278.203003f}, {136.296997f, 278.328003f}, {135.296997f, 278.835999f}}} t=0.5 pt=(136.897491,278.374878) slope=(-3.35699844,0.293243408)
339SkOpSegment::markWinding id=14 (129.679993,280.242004 131.046997,276.039001 135.538986,273.757996 139.741989,275.117004) t=7.00240426e-05 [43] (129.680283,280.241119) tEnd=1 newWindSum=-1 newOppSum=0 oppSum=0 windSum=-1 windValue=1 oppValue=0
340SkOpSegment::markWinding id=15 (139.741989,275.117004 138.608994,278.570007) t=0 [29] (139.741989,275.117004) tEnd=0.00025401744 newWindSum=-1 newOppSum=0 oppSum=? windSum=? windValue=1 oppValue=0
341SkOpSegment::nextChase mismatched signs
342SkOpSegment::markWinding id=19 (139.742004,275.117981 143.937012,276.492981 146.219009,280.97699 144.859009,285.172974) t=0 [37] (139.742004,275.117981) tEnd=1 newWindSum=-1 newOppSum=0 oppSum=? windSum=? windValue=1 oppValue=0
343SkOpSegment::markWinding id=14 (129.679993,280.242004 131.046997,276.039001 135.538986,273.757996 139.741989,275.117004) t=7.00240426e-05 [43] (129.680283,280.241119) tEnd=1 newWindSum=-1 newOppSum=0 oppSum=0 windSum=-1 windValue=1 oppValue=0
344SkOpSegment::markWinding id=11 (138.608994,278.570007 137.460999,278.203003 136.296997,278.328003 135.296997,278.835999) t=0 [21] (138.608994,278.570007) tEnd=1 newWindSum=-1 newOppSum=0 oppSum=0 windSum=-1 windValue=1 oppValue=0
345SkOpSegment::markWinding id=12 (135.296997,278.835999 134.296997,279.343994 133.507996,280.218994 133.132996,281.367004) t=0 [23] (135.296997,278.835999) tEnd=1 newWindSum=-1 newOppSum=0 oppSum=? windSum=? windValue=1 oppValue=0
346SkOpSegment::markWinding id=11 (138.608994,278.570007 137.460999,278.203003 136.296997,278.328003 135.296997,278.835999) t=0 [21] (138.608994,278.570007) tEnd=1 newWindSum=-1 newOppSum=0 oppSum=0 windSum=-1 windValue=1 oppValue=0
347SkOpSegment::nextChase mismatched signs
348SkOpSegment::markWinding id=18 (138.609009,278.570984 139.742004,275.117981) t=0 [35] (138.609009,278.570984) tEnd=0.00025401744 newWindSum=-1 newOppSum=0 oppSum=? windSum=? windValue=1 oppValue=0
349SkOpSegment::markWinding id=17 (141.14801,280.734985 140.625015,279.734985 139.757004,278.945984 138.609009,278.570984) t=0 [33] (141.14801,280.734985) tEnd=1 newWindSum=-1 newOppSum=0 oppSum=? windSum=? windValue=1 oppValue=0
350SkOpSegment::markWinding id=16 (141.406006,284.054993 141.77301,282.906982 141.64801,281.734985 141.14801,280.734985) t=0 [31] (141.406006,284.054993) tEnd=1 newWindSum=-1 newOppSum=0 oppSum=? windSum=? windValue=1 oppValue=0
351SkOpSegment::nextChase mismatched signs
352SkOpSegment::findNextWinding simple
353SkOpSegment::markDone id=11 (138.608994,278.570007 137.460999,278.203003 136.296997,278.328003 135.296997,278.835999) t=0 [21] (138.608994,278.570007) tEnd=1 newWindSum=-1 newOppSum=0 oppSum=0 windSum=-1 windValue=1 oppValue=0
354bridgeWinding current id=11 from=(135.296997,278.835999) to=(138.608994,278.570007)
355path.moveTo(135.296997,278.835999);
356path.cubicTo(136.296997,278.328003, 137.460999,278.203003, 138.608994,278.570007);
357SkOpSegment::findNextWinding simple
358SkOpSegment::markDone id=18 (138.609009,278.570984 139.742004,275.117981) t=0 [35] (138.609009,278.570984) tEnd=0.00025401744 newWindSum=-1 newOppSum=0 oppSum=0 windSum=-1 windValue=1 oppValue=0
359bridgeWinding current id=18 from=(138.609299,278.570099) to=(138.609009,278.570984)
360SkOpSegment::findNextWinding simple
361SkOpSegment::markDone id=17 (141.14801,280.734985 140.625015,279.734985 139.757004,278.945984 138.609009,278.570984) t=0 [33] (141.14801,280.734985) tEnd=1 newWindSum=-1 newOppSum=0 oppSum=0 windSum=-1 windValue=1 oppValue=0
362bridgeWinding current id=17 from=(138.609009,278.570984) to=(141.14801,280.734985)
363path.lineTo(138.609009,278.570984);
364path.cubicTo(139.757004,278.945984, 140.625015,279.734985, 141.14801,280.734985);
365SkOpSegment::markWinding id=2 (139.242004,286.578003 140.234009,286.078003 141.031006,285.203003 141.406006,284.054993) t=0 [3] (139.242004,286.578003) tEnd=1 newWindSum=-1 windSum=? windValue=1
366SkOpSegment::markWinding id=1 (135.921997,286.843994 137.069992,287.218994 138.242004,287.085999 139.242004,286.578003) t=0 [1] (135.921997,286.843994) tEnd=1 newWindSum=-1 windSum=? windValue=1
367SkOpSegment::nextChase mismatched signs
368SkOpSegment::markWinding id=8 (135.921997,286.843018 134.796997,290.296021) t=0 [15] (135.921997,286.843018) tEnd=0.000255675976 newWindSum=-1 windSum=? windValue=1
369SkOpSegment::markWinding id=7 (133.390991,284.679016 133.906998,285.679016 134.773987,286.468018 135.921997,286.843018) t=0 [13] (133.390991,284.679016) tEnd=1 newWindSum=-1 windSum=? windValue=1
370SkOpSegment::markWinding id=6 (133.132996,281.367004 132.757996,282.507996 132.882996,283.687012 133.390991,284.679016) t=0 [11] (133.132996,281.367004) tEnd=1 newWindSum=-1 windSum=? windValue=1
371SkOpSegment::markAngle last seg=6 span=11 windSum=-1
372SkOpSegment::markWinding id=20 (144.859009,285.172974 141.406006,284.054993) t=0 [39] (144.859009,285.172974) tEnd=1 newWindSum=-2 windSum=? windValue=1
373SkOpSegment::markAngle last seg=20 span=39 windSum=-2
374SkOpSegment::markWinding id=3 (141.406006,284.054993 144.859009,285.171997) t=0 [5] (141.406006,284.054993) tEnd=1 newWindSum=-2 windSum=? windValue=1
375SkOpSegment::markWinding id=4 (144.859009,285.171997 143.492004,289.375 138.992004,291.656006 134.797012,290.296997) t=0 [7] (144.859009,285.171997) tEnd=7.00717611e-05 newWindSum=-2 windSum=? windValue=1
376SkOpSegment::markAngle last seg=4 span=44 windSum=?
377SkOpSegment::findNextWinding
378SkOpAngle::dumpOne [16/7] next=2/20 sect=5/9 s=0 [31] e=1 [32] sgn=-1 windVal=1 windSum=-1 oppVal=0 oppSum=0
379SkOpAngle::dumpOne [2/20] next=20/12 sect=21/21 s=1 [4] e=0 [3] sgn=1 windVal=1 windSum=-1
380SkOpAngle::dumpOne [20/12] next=3/21 sect=29/29 s=1 [40] e=0 [39] sgn=1 windVal=1 windSum=-2
381SkOpAngle::dumpOne [3/21] next=16/7 sect=29/29 s=0 [5] e=1 [6] sgn=-1 windVal=1 windSum=-2
382SkOpSegment::findNextWinding chase.append segment=6 span=11 windSum=-1
383SkOpSegment::markDone id=20 (144.859009,285.172974 141.406006,284.054993) t=0 [39] (144.859009,285.172974) tEnd=1 newWindSum=-2 newOppSum=? oppSum=? windSum=-2 windValue=1 oppValue=0
384SkOpSegment::findNextWinding chase.append segment=20 span=39 windSum=-2
385SkOpSegment::markDone id=3 (141.406006,284.054993 144.859009,285.171997) t=0 [5] (141.406006,284.054993) tEnd=1 newWindSum=-2 newOppSum=? oppSum=? windSum=-2 windValue=1 oppValue=0
386SkOpSegment::markDone id=4 (144.859009,285.171997 143.492004,289.375 138.992004,291.656006 134.797012,290.296997) t=0 [7] (144.859009,285.171997) tEnd=7.00717611e-05 newWindSum=-2 newOppSum=? oppSum=? windSum=-2 windValue=1 oppValue=0
387SkOpSegment::findNextWinding chase.append segment=4 span=44 windSum=-2147483647
388SkOpSegment::markDone id=16 (141.406006,284.054993 141.77301,282.906982 141.64801,281.734985 141.14801,280.734985) t=0 [31] (141.406006,284.054993) tEnd=1 newWindSum=-1 newOppSum=0 oppSum=0 windSum=-1 windValue=1 oppValue=0
Cary Clarkd2eb5812017-01-18 11:00:57 -0500389SkOpSegment::findNextWinding from:[16] to:[2] start=4746648 end=4746504
Cary Clarkab2d73b2016-12-16 17:17:25 -0500390bridgeWinding current id=16 from=(141.14801,280.734985) to=(141.406006,284.054993)
391path.cubicTo(141.64801,281.734985, 141.77301,282.906982, 141.406006,284.054993);
392SkOpSegment::findNextWinding simple
393SkOpSegment::markDone id=2 (139.242004,286.578003 140.234009,286.078003 141.031006,285.203003 141.406006,284.054993) t=0 [3] (139.242004,286.578003) tEnd=1 newWindSum=-1 newOppSum=? oppSum=? windSum=-1 windValue=1 oppValue=0
394bridgeWinding current id=2 from=(141.406006,284.054993) to=(139.242004,286.578003)
395path.cubicTo(141.031006,285.203003, 140.234009,286.078003, 139.242004,286.578003);
396SkOpSegment::nextChase mismatched signs
397SkOpSegment::findNextWinding simple
398SkOpSegment::markDone id=1 (135.921997,286.843994 137.069992,287.218994 138.242004,287.085999 139.242004,286.578003) t=0 [1] (135.921997,286.843994) tEnd=1 newWindSum=-1 newOppSum=? oppSum=? windSum=-1 windValue=1 oppValue=0
399bridgeWinding current id=1 from=(139.242004,286.578003) to=(135.921997,286.843994)
400path.cubicTo(138.242004,287.085999, 137.069992,287.218994, 135.921997,286.843994);
401SkOpSegment::findNextWinding simple
402SkOpSegment::markDone id=8 (135.921997,286.843018 134.796997,290.296021) t=0 [15] (135.921997,286.843018) tEnd=0.000255675976 newWindSum=-1 newOppSum=? oppSum=? windSum=-1 windValue=1 oppValue=0
403bridgeWinding current id=8 from=(135.921707,286.843903) to=(135.921997,286.843018)
404SkOpSegment::findNextWinding simple
405SkOpSegment::markDone id=7 (133.390991,284.679016 133.906998,285.679016 134.773987,286.468018 135.921997,286.843018) t=0 [13] (133.390991,284.679016) tEnd=1 newWindSum=-1 newOppSum=? oppSum=? windSum=-1 windValue=1 oppValue=0
406bridgeWinding current id=7 from=(135.921997,286.843018) to=(133.390991,284.679016)
407path.lineTo(135.921997,286.843018);
408path.cubicTo(134.773987,286.468018, 133.906998,285.679016, 133.390991,284.679016);
409SkOpSegment::markWinding id=10 (129.679993,280.241028 133.132996,281.367004) t=0 [19] (129.679993,280.241028) tEnd=1 newWindSum=-2 windSum=? windValue=1
410SkOpSegment::markAngle last seg=10 span=19 windSum=-2
411SkOpSegment::markWinding id=13 (133.132996,281.367004 129.679993,280.242004) t=0 [25] (133.132996,281.367004) tEnd=1 newWindSum=-2 windSum=? windValue=1
412SkOpSegment::markWinding id=14 (129.679993,280.242004 131.046997,276.039001 135.538986,273.757996 139.741989,275.117004) t=0 [27] (129.679993,280.242004) tEnd=7.00240426e-05 newWindSum=-2 windSum=? windValue=1
413SkOpSegment::markAngle last seg=14 span=43 windSum=-1
414SkOpSegment::findNextWinding
415SkOpAngle::dumpOne [6/13] next=12/2 sect=21/25 s=0 [11] e=1 [12] sgn=-1 windVal=1 windSum=-1
416SkOpAngle::dumpOne [12/2] next=10/18 sect=5/5 s=1 [24] e=0 [23] sgn=1 windVal=1 windSum=-1 oppVal=0 oppSum=0
417SkOpAngle::dumpOne [10/18] next=13/3 sect=13/13 s=1 [20] e=0 [19] sgn=1 windVal=1 windSum=-2
418SkOpAngle::dumpOne [13/3] next=6/13 sect=13/13 s=0 [25] e=1 [26] sgn=-1 windVal=1 windSum=-2
419SkOpSegment::markDone id=10 (129.679993,280.241028 133.132996,281.367004) t=0 [19] (129.679993,280.241028) tEnd=1 newWindSum=-2 newOppSum=? oppSum=? windSum=-2 windValue=1 oppValue=0
420SkOpSegment::findNextWinding chase.append segment=10 span=19 windSum=-2
421SkOpSegment::markDone id=13 (133.132996,281.367004 129.679993,280.242004) t=0 [25] (133.132996,281.367004) tEnd=1 newWindSum=-2 newOppSum=? oppSum=? windSum=-2 windValue=1 oppValue=0
422SkOpSegment::markDone id=14 (129.679993,280.242004 131.046997,276.039001 135.538986,273.757996 139.741989,275.117004) t=0 [27] (129.679993,280.242004) tEnd=7.00240426e-05 newWindSum=-2 newOppSum=? oppSum=? windSum=-2 windValue=1 oppValue=0
423SkOpSegment::findNextWinding chase.append segment=14 span=43 windSum=-1
424SkOpSegment::markDone id=6 (133.132996,281.367004 132.757996,282.507996 132.882996,283.687012 133.390991,284.679016) t=0 [11] (133.132996,281.367004) tEnd=1 newWindSum=-1 newOppSum=? oppSum=? windSum=-1 windValue=1 oppValue=0
Cary Clarkd2eb5812017-01-18 11:00:57 -0500425SkOpSegment::findNextWinding from:[6] to:[12] start=4750776 end=4750632
Cary Clarkab2d73b2016-12-16 17:17:25 -0500426bridgeWinding current id=6 from=(133.390991,284.679016) to=(133.132996,281.367004)
427path.cubicTo(132.882996,283.687012, 132.757996,282.507996, 133.132996,281.367004);
428SkOpSegment::findNextWinding simple
429SkOpSegment::markDone id=12 (135.296997,278.835999 134.296997,279.343994 133.507996,280.218994 133.132996,281.367004) t=0 [23] (135.296997,278.835999) tEnd=1 newWindSum=-1 newOppSum=0 oppSum=0 windSum=-1 windValue=1 oppValue=0
430bridgeWinding current id=12 from=(133.132996,281.367004) to=(135.296997,278.835999)
431path.cubicTo(133.507996,280.218994, 134.296997,279.343994, 135.296997,278.835999);
432path.close();
433SkOpSegment::markWinding id=14 (129.679993,280.242004 131.046997,276.039001 135.538986,273.757996 139.741989,275.117004) t=7.00240426e-05 [43] (129.680283,280.241119) tEnd=1 newWindSum=-1 windSum=-1 windValue=1
434SkOpSegment::markWinding id=9 (134.796997,290.296021 130.60199,288.929016 128.313004,284.437012 129.679993,280.241028) t=0 [17] (134.796997,290.296021) tEnd=1 newWindSum=-2 windSum=? windValue=1
435SkOpSegment::nextChase mismatched signs
436SkOpSegment::markWinding id=5 (134.797012,290.296997 135.921997,286.843994) t=0 [9] (134.797012,290.296997) tEnd=0.000254375091 newWindSum=-2 windSum=? windValue=1
437SkOpSegment::markWinding id=4 (144.859009,285.171997 143.492004,289.375 138.992004,291.656006 134.797012,290.296997) t=7.00717611e-05 [44] (144.858719,285.172882) tEnd=1 newWindSum=-2 windSum=? windValue=1
438SkOpSegment::markAngle last seg=4 span=44 windSum=-2
439SkOpSegment::debugShowActiveSpans id=14 (129.680283,280.241119 131.047629,276.03868 135.539281,273.758091 139.741989,275.117004) t=7.00240426e-05 tEnd=1 windSum=-1 oppSum=0 windValue=1 oppValue=0
440SkOpSegment::debugShowActiveSpans id=15 (139.741989,275.117004 139.741699,275.117889) t=0 tEnd=0.00025401744 windSum=-1 oppSum=0 windValue=1 oppValue=0
441SkOpSegment::debugShowActiveSpans id=19 (139.742004,275.117981 143.937012,276.492981 146.219009,280.97699 144.859009,285.172974) t=0 tEnd=1 windSum=-1 oppSum=0 windValue=1 oppValue=0
442SkOpSegment::debugShowActiveSpans id=9 (134.796997,290.296021 130.60199,288.929016 128.313004,284.437012 129.679993,280.241028) t=0 tEnd=1 windSum=-2 windValue=1
443SkOpSegment::debugShowActiveSpans id=4 (144.858719,285.172882 143.491371,289.375321 138.99171,291.655911 134.797012,290.296997) t=7.00717611e-05 tEnd=1 windSum=-2 windValue=1
444SkOpSegment::debugShowActiveSpans id=5 (134.797012,290.296997 134.797302,290.296112) t=0 tEnd=0.000254375091 windSum=-2 windValue=1
445SkOpSegment::findNextWinding simple
446SkOpSegment::markDone id=14 (129.679993,280.242004 131.046997,276.039001 135.538986,273.757996 139.741989,275.117004) t=7.00240426e-05 [43] (129.680283,280.241119) tEnd=1 newWindSum=-1 newOppSum=0 oppSum=0 windSum=-1 windValue=1 oppValue=0
447bridgeWinding current id=14 from=(129.680283,280.241119) to=(139.741989,275.117004)
448path.moveTo(129.680283,280.241119);
449path.cubicTo(131.047623,276.038666, 135.539276,273.758087, 139.741989,275.117004);
450SkOpSegment::nextChase mismatched signs
451SkOpSegment::findNextWinding simple
452SkOpSegment::markDone id=15 (139.741989,275.117004 138.608994,278.570007) t=0 [29] (139.741989,275.117004) tEnd=0.00025401744 newWindSum=-1 newOppSum=0 oppSum=0 windSum=-1 windValue=1 oppValue=0
453bridgeWinding current id=15 from=(139.741989,275.117004) to=(139.741699,275.117889)
454SkOpSegment::findNextWinding
455SkOpAngle::dumpOne [19/10] next=20/11 sect=5/9 s=1 [38] e=0 [37] sgn=1 windVal=1 windSum=-1 oppVal=0 oppSum=0
456SkOpAngle::dumpOne [20/11] next=4/23 sect=13/13 s=0 [39] e=1 [40] sgn=-1 windVal=1 windSum=-2 done
457SkOpAngle::dumpOne [4/23] next=4/22 sect=21/17 s=7.00717611e-05 [44] e=1 [8] sgn=-1 windVal=1 windSum=-2
458SkOpAngle::dumpOne [4/22] next=19/10 sect=5/5 s=7.00717611e-05 [44] e=0 [7] sgn=1 windVal=1 windSum=-2 done
459SkOpSegment::markDone id=19 (139.742004,275.117981 143.937012,276.492981 146.219009,280.97699 144.859009,285.172974) t=0 [37] (139.742004,275.117981) tEnd=1 newWindSum=-1 newOppSum=0 oppSum=0 windSum=-1 windValue=1 oppValue=0
Cary Clarkd2eb5812017-01-18 11:00:57 -0500460SkOpSegment::findNextWinding from:[19] to:[4] start=4754056 end=4747144
Cary Clarkab2d73b2016-12-16 17:17:25 -0500461bridgeWinding current id=19 from=(139.742004,275.117981) to=(144.859009,285.172974)
462path.lineTo(139.741699,275.117889);
463path.cubicTo(143.937012,276.492981, 146.219009,280.97699, 144.859009,285.172974);
464SkOpSegment::findNextWinding simple
465SkOpSegment::debugShowActiveSpans id=9 (134.796997,290.296021 130.60199,288.929016 128.313004,284.437012 129.679993,280.241028) t=0 tEnd=1 windSum=-2 windValue=1
466SkOpSegment::debugShowActiveSpans id=4 (144.858719,285.172882 143.491371,289.375321 138.99171,291.655911 134.797012,290.296997) t=7.00717611e-05 tEnd=1 windSum=-2 windValue=1
467SkOpSegment::debugShowActiveSpans id=5 (134.797012,290.296997 134.797302,290.296112) t=0 tEnd=0.000254375091 windSum=-2 windValue=1
468SkOpSegment::markDone id=9 (134.796997,290.296021 130.60199,288.929016 128.313004,284.437012 129.679993,280.241028) t=0 [17] (134.796997,290.296021) tEnd=1 newWindSum=-2 newOppSum=? oppSum=? windSum=-2 windValue=1 oppValue=0
469SkOpSegment::nextChase mismatched signs
470SkOpSegment::markDone id=5 (134.797012,290.296997 135.921997,286.843994) t=0 [9] (134.797012,290.296997) tEnd=0.000254375091 newWindSum=-2 newOppSum=? oppSum=? windSum=-2 windValue=1 oppValue=0
471SkOpSegment::markDone id=4 (144.859009,285.171997 143.492004,289.375 138.992004,291.656006 134.797012,290.296997) t=7.00717611e-05 [44] (144.858719,285.172882) tEnd=1 newWindSum=-2 newOppSum=? oppSum=? windSum=-2 windValue=1 oppValue=0
472</div>
473
caryclarkdac1d172014-06-17 05:15:38 -0700474</div>
475
476<script type="text/javascript">
477
caryclark55888e42016-07-18 10:01:36 -0700478 var testDivs = [
Cary Clarkab2d73b2016-12-16 17:17:25 -0500479 joel_9,
caryclark30b9fdd2016-08-31 14:36:29 -0700480 ];
caryclarkdac1d172014-06-17 05:15:38 -0700481
482var decimal_places = 3; // make this 3 to show more precision
483
484var tests = [];
485var testLines = [];
486var testTitles = [];
487var testIndex = 0;
488var ctx;
489
490var xmin, xmax, focusXmin, focusXmax;
491var ymin, ymax, focusYmin, focusYmax;
492var scale;
493var mouseX, mouseY;
494var srcLeft, srcTop;
495var screenWidth, screenHeight;
caryclark1049f122015-04-20 08:31:59 -0700496var drawnPts, drawnLines, drawnQuads, drawnConics, drawnCubics;
caryclarkdac1d172014-06-17 05:15:38 -0700497var curveT = 0;
498
499var pt_labels = 2;
500var collect_bounds = false;
501var control_lines = 0;
502var curve_t = false;
503var debug_xy = 1;
504var focus_enabled = false;
505var focus_on_selection = false;
506var step_limit = 0;
507var draw_active = false;
508var draw_add = false;
509var draw_angle = 0;
caryclark624637c2015-05-11 07:21:27 -0700510var draw_coincidence = false;
caryclarkdac1d172014-06-17 05:15:38 -0700511var draw_deriviatives = 0;
Cary Clarkff114282016-12-14 11:56:16 -0500512var draw_direction = false;
caryclarkdac1d172014-06-17 05:15:38 -0700513var draw_hints = false;
caryclarkdac1d172014-06-17 05:15:38 -0700514var draw_id = false;
515var draw_intersection = 0;
516var draw_intersectT = false;
517var draw_legend = true;
518var draw_log = false;
519var draw_mark = false;
520var draw_midpoint = false;
521var draw_op = 0;
522var draw_sequence = false;
523var draw_sort = 0;
caryclark03b03ca2015-04-23 09:13:37 -0700524var draw_top = false;
caryclarkdac1d172014-06-17 05:15:38 -0700525var draw_path = 3;
526var draw_computed = 0;
527var retina_scale = !!window.devicePixelRatio;
528
529var activeCount = 0;
530var addCount = 0;
531var angleCount = 0;
caryclark624637c2015-05-11 07:21:27 -0700532var coinCount = 0;
caryclarkdac1d172014-06-17 05:15:38 -0700533var opCount = 0;
534var sectCount = 0;
535var sortCount = 0;
caryclark03b03ca2015-04-23 09:13:37 -0700536var topCount = 0;
caryclarkdac1d172014-06-17 05:15:38 -0700537var markCount = 0;
538var activeMax = 0;
539var addMax = 0;
540var angleMax = 0;
caryclark624637c2015-05-11 07:21:27 -0700541var coinMax = 0;
caryclarkdac1d172014-06-17 05:15:38 -0700542var sectMax = 0;
543var sectMax2 = 0;
544var sortMax = 0;
caryclark03b03ca2015-04-23 09:13:37 -0700545var topMax = 0;
caryclarkdac1d172014-06-17 05:15:38 -0700546var markMax = 0;
547var opMax = 0;
548var stepMax = 0;
549var lastIndex = 0;
550var hasPath = false;
caryclark26ad22a2015-10-16 09:03:38 -0700551var hasAlignedPath = false;
caryclarkdac1d172014-06-17 05:15:38 -0700552var hasComputedPath = false;
caryclark54359292015-03-26 07:52:43 -0700553var angleBetween = false;
554var afterIndex = 0;
caryclarkdac1d172014-06-17 05:15:38 -0700555
556var firstActiveSpan = -1;
557var logStart = -1;
558var logRange = 0;
559
560var SPAN_ID = 0;
561var SPAN_X1 = SPAN_ID + 1;
562var SPAN_Y1 = SPAN_X1 + 1;
563var SPAN_X2 = SPAN_Y1 + 1;
564var SPAN_Y2 = SPAN_X2 + 1;
caryclark1049f122015-04-20 08:31:59 -0700565
caryclark55888e42016-07-18 10:01:36 -0700566var SPAN_L_TX = SPAN_Y2 + 1;
caryclarkdac1d172014-06-17 05:15:38 -0700567var SPAN_L_TY = SPAN_L_TX + 1;
caryclark55888e42016-07-18 10:01:36 -0700568var SPAN_L_OTHER = SPAN_L_TY + 1;
caryclarkdac1d172014-06-17 05:15:38 -0700569var SPAN_L_OTHERT = SPAN_L_OTHER + 1;
570var SPAN_L_OTHERI = SPAN_L_OTHERT + 1;
571var SPAN_L_SUM = SPAN_L_OTHERI + 1;
572var SPAN_L_VAL = SPAN_L_SUM + 1;
573var SPAN_L_OPP = SPAN_L_VAL + 1;
574
575var SPAN_X3 = SPAN_Y2 + 1;
576var SPAN_Y3 = SPAN_X3 + 1;
caryclark1049f122015-04-20 08:31:59 -0700577
caryclark55888e42016-07-18 10:01:36 -0700578var SPAN_Q_TX = SPAN_Y3 + 1;
caryclarkdac1d172014-06-17 05:15:38 -0700579var SPAN_Q_TY = SPAN_Q_TX + 1;
caryclark55888e42016-07-18 10:01:36 -0700580var SPAN_Q_OTHER = SPAN_Q_TY + 1;
caryclarkdac1d172014-06-17 05:15:38 -0700581var SPAN_Q_OTHERT = SPAN_Q_OTHER + 1;
582var SPAN_Q_OTHERI = SPAN_Q_OTHERT + 1;
583var SPAN_Q_SUM = SPAN_Q_OTHERI + 1;
584var SPAN_Q_VAL = SPAN_Q_SUM + 1;
585var SPAN_Q_OPP = SPAN_Q_VAL + 1;
586
caryclark1049f122015-04-20 08:31:59 -0700587var SPAN_K_W = SPAN_Y3 + 1;
caryclark55888e42016-07-18 10:01:36 -0700588var SPAN_K_TX = SPAN_K_W + 1;
caryclark1049f122015-04-20 08:31:59 -0700589var SPAN_K_TY = SPAN_K_TX + 1;
caryclark55888e42016-07-18 10:01:36 -0700590var SPAN_K_OTHER = SPAN_K_TY + 1;
caryclark1049f122015-04-20 08:31:59 -0700591var SPAN_K_OTHERT = SPAN_K_OTHER + 1;
592var SPAN_K_OTHERI = SPAN_K_OTHERT + 1;
593var SPAN_K_SUM = SPAN_K_OTHERI + 1;
594var SPAN_K_VAL = SPAN_K_SUM + 1;
595var SPAN_K_OPP = SPAN_K_VAL + 1;
596
caryclarkdac1d172014-06-17 05:15:38 -0700597var SPAN_X4 = SPAN_Y3 + 1;
598var SPAN_Y4 = SPAN_X4 + 1;
caryclark1049f122015-04-20 08:31:59 -0700599
caryclark55888e42016-07-18 10:01:36 -0700600var SPAN_C_TX = SPAN_Y4 + 1;
caryclarkdac1d172014-06-17 05:15:38 -0700601var SPAN_C_TY = SPAN_C_TX + 1;
caryclark55888e42016-07-18 10:01:36 -0700602var SPAN_C_OTHER = SPAN_C_TY + 1;
caryclarkdac1d172014-06-17 05:15:38 -0700603var SPAN_C_OTHERT = SPAN_C_OTHER + 1;
604var SPAN_C_OTHERI = SPAN_C_OTHERT + 1;
605var SPAN_C_SUM = SPAN_C_OTHERI + 1;
606var SPAN_C_VAL = SPAN_C_SUM + 1;
607var SPAN_C_OPP = SPAN_C_VAL + 1;
608
609var ACTIVE_LINE_SPAN = 1;
610var ACTIVE_QUAD_SPAN = ACTIVE_LINE_SPAN + 1;
caryclark1049f122015-04-20 08:31:59 -0700611var ACTIVE_CONIC_SPAN = ACTIVE_QUAD_SPAN + 1;
612var ACTIVE_CUBIC_SPAN = ACTIVE_CONIC_SPAN + 1;
caryclarkdac1d172014-06-17 05:15:38 -0700613
614var ADD_MOVETO = ACTIVE_CUBIC_SPAN + 1;
615var ADD_LINETO = ADD_MOVETO + 1;
616var ADD_QUADTO = ADD_LINETO + 1;
caryclark1049f122015-04-20 08:31:59 -0700617var ADD_CONICTO = ADD_QUADTO + 1;
618var ADD_CUBICTO = ADD_CONICTO + 1;
caryclarkdac1d172014-06-17 05:15:38 -0700619var ADD_CLOSE = ADD_CUBICTO + 1;
620var ADD_FILL = ADD_CLOSE + 1;
621
622var PATH_LINE = ADD_FILL + 1;
623var PATH_QUAD = PATH_LINE + 1;
caryclark1049f122015-04-20 08:31:59 -0700624var PATH_CONIC = PATH_QUAD + 1;
625var PATH_CUBIC = PATH_CONIC + 1;
caryclarkdac1d172014-06-17 05:15:38 -0700626
627var INTERSECT_LINE = PATH_CUBIC + 1;
628var INTERSECT_LINE_2 = INTERSECT_LINE + 1;
629var INTERSECT_LINE_NO = INTERSECT_LINE_2 + 1;
630var INTERSECT_QUAD_LINE = INTERSECT_LINE_NO + 1;
631var INTERSECT_QUAD_LINE_2 = INTERSECT_QUAD_LINE + 1;
632var INTERSECT_QUAD_LINE_NO = INTERSECT_QUAD_LINE_2 + 1;
633var INTERSECT_QUAD = INTERSECT_QUAD_LINE_NO + 1;
634var INTERSECT_QUAD_2 = INTERSECT_QUAD + 1;
635var INTERSECT_QUAD_NO = INTERSECT_QUAD_2 + 1;
caryclark1049f122015-04-20 08:31:59 -0700636var INTERSECT_CONIC_LINE = INTERSECT_QUAD_NO + 1;
637var INTERSECT_CONIC_LINE_2 = INTERSECT_CONIC_LINE + 1;
638var INTERSECT_CONIC_LINE_NO = INTERSECT_CONIC_LINE_2 + 1;
caryclark55888e42016-07-18 10:01:36 -0700639var INTERSECT_CONIC_QUAD = INTERSECT_CONIC_LINE_NO + 1;
640var INTERSECT_CONIC_QUAD_2 = INTERSECT_CONIC_QUAD + 1;
caryclark6c3b9cd2016-09-26 05:36:58 -0700641var INTERSECT_CONIC_QUAD_3 = INTERSECT_CONIC_QUAD_2 + 1;
642var INTERSECT_CONIC_QUAD_4 = INTERSECT_CONIC_QUAD_3 + 1;
643var INTERSECT_CONIC_QUAD_NO = INTERSECT_CONIC_QUAD_4 + 1;
caryclark55888e42016-07-18 10:01:36 -0700644var INTERSECT_CONIC = INTERSECT_CONIC_QUAD_NO + 1;
caryclark1049f122015-04-20 08:31:59 -0700645var INTERSECT_CONIC_2 = INTERSECT_CONIC + 1;
646var INTERSECT_CONIC_NO = INTERSECT_CONIC_2 + 1;
647var INTERSECT_SELF_CUBIC = INTERSECT_CONIC_NO + 1;
caryclarkdac1d172014-06-17 05:15:38 -0700648var INTERSECT_SELF_CUBIC_NO = INTERSECT_SELF_CUBIC + 1;
649var INTERSECT_CUBIC_LINE = INTERSECT_SELF_CUBIC_NO + 1;
650var INTERSECT_CUBIC_LINE_2 = INTERSECT_CUBIC_LINE + 1;
651var INTERSECT_CUBIC_LINE_3 = INTERSECT_CUBIC_LINE_2 + 1;
652var INTERSECT_CUBIC_LINE_NO = INTERSECT_CUBIC_LINE_3 + 1;
653var INTERSECT_CUBIC_QUAD = INTERSECT_CUBIC_LINE_NO + 1;
654var INTERSECT_CUBIC_QUAD_2 = INTERSECT_CUBIC_QUAD + 1;
655var INTERSECT_CUBIC_QUAD_3 = INTERSECT_CUBIC_QUAD_2 + 1;
656var INTERSECT_CUBIC_QUAD_4 = INTERSECT_CUBIC_QUAD_3 + 1;
657var INTERSECT_CUBIC_QUAD_NO = INTERSECT_CUBIC_QUAD_4 + 1;
658var INTERSECT_CUBIC = INTERSECT_CUBIC_QUAD_NO + 1;
659var INTERSECT_CUBIC_2 = INTERSECT_CUBIC + 1;
660var INTERSECT_CUBIC_3 = INTERSECT_CUBIC_2 + 1;
661var INTERSECT_CUBIC_4 = INTERSECT_CUBIC_3 + 1;
662// FIXME: add cubic 5- 9
663var INTERSECT_CUBIC_NO = INTERSECT_CUBIC_4 + 1;
664
665var SORT_UNARY = INTERSECT_CUBIC_NO + 1;
666var SORT_BINARY = SORT_UNARY + 1;
667
668var OP_DIFFERENCE = SORT_BINARY + 1;
669var OP_INTERSECT = OP_DIFFERENCE + 1;
670var OP_UNION = OP_INTERSECT + 1;
671var OP_XOR = OP_UNION + 1;
672
673var MARK_LINE = OP_XOR + 1;
674var MARK_QUAD = MARK_LINE + 1;
caryclark1049f122015-04-20 08:31:59 -0700675var MARK_CONIC = MARK_QUAD + 1;
676var MARK_CUBIC = MARK_CONIC + 1;
caryclarkdac1d172014-06-17 05:15:38 -0700677var MARK_DONE_LINE = MARK_CUBIC + 1;
678var MARK_DONE_QUAD = MARK_DONE_LINE + 1;
caryclark1049f122015-04-20 08:31:59 -0700679var MARK_DONE_CONIC = MARK_DONE_QUAD + 1;
680var MARK_DONE_CUBIC = MARK_DONE_CONIC + 1;
caryclarkdac1d172014-06-17 05:15:38 -0700681var MARK_UNSORTABLE_LINE = MARK_DONE_CUBIC + 1;
682var MARK_UNSORTABLE_QUAD = MARK_UNSORTABLE_LINE + 1;
caryclark1049f122015-04-20 08:31:59 -0700683var MARK_UNSORTABLE_CONIC = MARK_UNSORTABLE_QUAD + 1;
684var MARK_UNSORTABLE_CUBIC = MARK_UNSORTABLE_CONIC + 1;
caryclarkdac1d172014-06-17 05:15:38 -0700685var MARK_SIMPLE_LINE = MARK_UNSORTABLE_CUBIC + 1;
686var MARK_SIMPLE_QUAD = MARK_SIMPLE_LINE + 1;
caryclark1049f122015-04-20 08:31:59 -0700687var MARK_SIMPLE_CONIC = MARK_SIMPLE_QUAD + 1;
688var MARK_SIMPLE_CUBIC = MARK_SIMPLE_CONIC + 1;
caryclarkdac1d172014-06-17 05:15:38 -0700689var MARK_SIMPLE_DONE_LINE = MARK_SIMPLE_CUBIC + 1;
690var MARK_SIMPLE_DONE_QUAD = MARK_SIMPLE_DONE_LINE + 1;
caryclark1049f122015-04-20 08:31:59 -0700691var MARK_SIMPLE_DONE_CONIC = MARK_SIMPLE_DONE_QUAD + 1;
692var MARK_SIMPLE_DONE_CUBIC = MARK_SIMPLE_DONE_CONIC + 1;
caryclarkdac1d172014-06-17 05:15:38 -0700693var MARK_DONE_UNARY_LINE = MARK_SIMPLE_DONE_CUBIC + 1;
694var MARK_DONE_UNARY_QUAD = MARK_DONE_UNARY_LINE + 1;
caryclark1049f122015-04-20 08:31:59 -0700695var MARK_DONE_UNARY_CONIC = MARK_DONE_UNARY_QUAD + 1;
696var MARK_DONE_UNARY_CUBIC = MARK_DONE_UNARY_CONIC + 1;
caryclarkdac1d172014-06-17 05:15:38 -0700697var MARK_ANGLE_LAST = MARK_DONE_UNARY_CUBIC + 1;
698
699var COMPUTED_SET_1 = MARK_ANGLE_LAST + 1;
700var COMPUTED_SET_2 = COMPUTED_SET_1 + 1;
701
caryclark624637c2015-05-11 07:21:27 -0700702var ANGLE_AFTER = COMPUTED_SET_2 + 1;
caryclark54359292015-03-26 07:52:43 -0700703var ANGLE_AFTERPART = ANGLE_AFTER + 1;
caryclarkdac1d172014-06-17 05:15:38 -0700704
caryclark54359292015-03-26 07:52:43 -0700705var ACTIVE_OP = ANGLE_AFTERPART + 1;
caryclarkdac1d172014-06-17 05:15:38 -0700706
caryclark624637c2015-05-11 07:21:27 -0700707var COIN_MAIN_SPAN = ACTIVE_OP + 1;
708var COIN_OPP_SPAN = COIN_MAIN_SPAN + 1;
709
710var FRAG_TYPE_LAST = COIN_OPP_SPAN;
caryclarkdac1d172014-06-17 05:15:38 -0700711
712var REC_TYPE_UNKNOWN = -1;
713var REC_TYPE_PATH = 0;
caryclark54359292015-03-26 07:52:43 -0700714var REC_TYPE_PATH2 = 1;
715var REC_TYPE_SECT = 2;
716var REC_TYPE_ACTIVE = 3;
717var REC_TYPE_ADD = 4;
718var REC_TYPE_SORT = 5;
719var REC_TYPE_OP = 6;
720var REC_TYPE_MARK = 7;
721var REC_TYPE_COMPUTED = 8;
722var REC_TYPE_COIN = 9;
723var REC_TYPE_ANGLE = 10;
724var REC_TYPE_ACTIVE_OP = 11;
725var REC_TYPE_AFTERPART = 12;
caryclark03b03ca2015-04-23 09:13:37 -0700726var REC_TYPE_TOP = 13;
caryclark624637c2015-05-11 07:21:27 -0700727var REC_TYPE_COINCIDENCE = 14;
caryclark26ad22a2015-10-16 09:03:38 -0700728var REC_TYPE_ALIGNED = 15;
729var REC_TYPE_LAST = REC_TYPE_ALIGNED;
caryclarkdac1d172014-06-17 05:15:38 -0700730
731function strs_to_nums(strs) {
732 var result = [];
733 for (var idx = 1; idx < strs.length; ++idx) {
734 var str = strs[idx];
735 var num = parseFloat(str);
736 if (isNaN(num)) {
737 result.push(str);
738 } else {
739 result.push(num);
740 }
741 }
742 return result;
743}
744
745function filter_str_by(id, str, regex, array) {
746 if (regex.test(str)) {
747 var strs = regex.exec(str);
748 var result = strs_to_nums(strs);
749 array.push(id);
750 array.push(result);
751 return true;
752 }
753 return false;
754}
755
756function construct_regexp2(pattern) {
757 var escape = pattern.replace(/[-/\\^$*+?.()|[\]{}]/g, '\\$&');
758 escape = escape.replace(/UNSORTABLE/g, "\\*\\*\\* UNSORTABLE \\*\\*\\*");
759 escape = escape.replace(/CUBIC_VAL/g, "\\(P_VAL P_VAL P_VAL P_VAL\\)");
caryclark1049f122015-04-20 08:31:59 -0700760 escape = escape.replace(/CONIC_VAL/g, "\\(P_VAL P_VAL P_VAL W_VAL\\)");
caryclarkdac1d172014-06-17 05:15:38 -0700761 escape = escape.replace(/QUAD_VAL/g, "\\(P_VAL P_VAL P_VAL\\)");
762 escape = escape.replace(/LINE_VAL/g, "\\(P_VAL P_VAL\\)");
763 escape = escape.replace(/FILL_TYPE/g, "SkPath::k[a-zA-Z]+_FillType");
caryclark54359292015-03-26 07:52:43 -0700764 escape = escape.replace(/PTR_VAL/g, "0x[0-9A-F]+");
caryclarkdac1d172014-06-17 05:15:38 -0700765 escape = escape.replace(/PT_VAL/g, "\\(P_VAL\\)");
766 escape = escape.replace(/P_VAL/g, "(-?\\d+\\.?\\d*(?:e-?\\d+)?)[Ff]?, ?(-?\\d+\\.?\\d*(?:e-?\\d+)?)[Ff]?");
767 escape = escape.replace(/T_VAL/g, "(-?\\d+\\.?\\d*(?:e-?\\d+)?)");
caryclark1049f122015-04-20 08:31:59 -0700768 escape = escape.replace(/W_VAL/g, "(-?\\d+\\.?\\d*(?:e-?\\d+)?)[Ff]?");
caryclarkdac1d172014-06-17 05:15:38 -0700769 escape = escape.replace(/PATH/g, "pathB?");
caryclark1049f122015-04-20 08:31:59 -0700770 escape = escape.replace(/IDX/g, "(-?\\d+)");
caryclarkdac1d172014-06-17 05:15:38 -0700771 escape = escape.replace(/NUM/g, "(-?\\d+)");
772 escape = escape.replace(/OPT/g, "(\\?|-?\\d+)");
773 return new RegExp(escape, 'i');
774}
775
776function construct_regexp2c(pattern) {
777 var escape = pattern.replace(/[-/\\^$*+?.()|[\]{}]/g, '\\$&');
778 escape = escape.replace(/UNSORTABLE/g, "\\*\\*\\* UNSORTABLE \\*\\*\\*");
caryclark54359292015-03-26 07:52:43 -0700779 escape = escape.replace(/CUBIC_VAL/g, "(?:\\$\\d = )?\\{\\{\\{P_VAL\\}, \\{P_VAL\\}, \\{P_VAL\\}, \\{P_VAL\\}\\}\\}");
caryclark1049f122015-04-20 08:31:59 -0700780 escape = escape.replace(/CONIC_VAL/g, "(?:\\$\\d = )?\\{\\{\\{\\{P_VAL\\}, \\{P_VAL\\}, \\{P_VAL\\}\\}\\}, W_VAL\\}");
caryclark54359292015-03-26 07:52:43 -0700781 escape = escape.replace(/QUAD_VAL/g, "(?:\\$\\d = )?\\{\\{\\{P_VAL\\}, \\{P_VAL\\}, \\{P_VAL\\}\\}\\}");
782 escape = escape.replace(/LINE_VAL/g, "(?:\\$\\d = )?\\{\\{\\{P_VAL\\}, \\{P_VAL\\}\\}\\}");
caryclarkdac1d172014-06-17 05:15:38 -0700783 escape = escape.replace(/FILL_TYPE/g, "SkPath::k[a-zA-Z]+_FillType");
caryclark54359292015-03-26 07:52:43 -0700784 escape = escape.replace(/PTR_VAL/g, "0x[0-9A-F]+");
caryclarkdac1d172014-06-17 05:15:38 -0700785 escape = escape.replace(/PT_VAL/g, "\\{\\{P_VAL\\}\\}");
caryclark54359292015-03-26 07:52:43 -0700786 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 -0700787 escape = escape.replace(/T_VAL/g, "(-?\\d+\\.?\\d*(?:e-?\\d+)?)");
caryclark1049f122015-04-20 08:31:59 -0700788 escape = escape.replace(/W_VAL/g, "(-?\\d+\\.?\\d*(?:e-?\\d+)?)[Ff]?");
caryclarkdac1d172014-06-17 05:15:38 -0700789 escape = escape.replace(/OPER/g, "[a-z]+");
790 escape = escape.replace(/PATH/g, "pathB?");
791 escape = escape.replace(/T_F/g, "([TF])");
caryclark1049f122015-04-20 08:31:59 -0700792 escape = escape.replace(/IDX/g, "(-?\\d+)");
caryclarkdac1d172014-06-17 05:15:38 -0700793 escape = escape.replace(/NUM/g, "(-?\\d+)");
794 escape = escape.replace(/OPT/g, "(\\?|-?\\d+)");
795 return new RegExp(escape, 'i');
796}
797
798function match_regexp(str, lineNo, array, id, pattern) {
799 var regex = construct_regexp2(pattern);
800 if (filter_str_by(id, str, regex, array)) {
801 return true;
802 }
803 regex = construct_regexp2c(pattern);
804 return filter_str_by(id, str, regex, array);
805}
806
807function endsWith(str, suffix) {
808 return str.indexOf(suffix, str.length - suffix.length) !== -1;
809}
810
811function parse_all(test) {
812 var lines = test.match(/[^\r\n]+/g);
813 var records = []; // a rec can be the original paths, a set of intersections, a set of active spans, a sort, or a path add
814 var record = [];
815 var recType = REC_TYPE_UNKNOWN;
816 var lastLineNo;
817 var moveX, moveY;
818 for (var lineNo = 0; lineNo < lines.length; ++lineNo) {
819 var line = lines[lineNo];
820 if (line.length == 0) {
821 continue;
822 }
823 var opStart = "SkOpSegment::";
824 if (line.lastIndexOf(opStart, 0) === 0) {
825 line = line.substr(opStart.length);
826 }
827 var angleStart = "SkOpAngle::";
828 if (line.lastIndexOf(angleStart, 0) === 0) {
829 line = line.substr(angleStart.length);
830 }
caryclark624637c2015-05-11 07:21:27 -0700831 var coinStart = "SkOpCoincidence::";
832 if (line.lastIndexOf(coinStart, 0) === 0) {
833 line = line.substr(coinStart.length);
834 }
caryclark54359292015-03-26 07:52:43 -0700835 var type = line.lastIndexOf("debugShowActiveSpans", 0) === 0 ? REC_TYPE_ACTIVE
caryclark624637c2015-05-11 07:21:27 -0700836 : line.lastIndexOf("debugShowCoincidence", 0) === 0 ? REC_TYPE_COINCIDENCE
caryclark54359292015-03-26 07:52:43 -0700837 : line.lastIndexOf("((SkOpSegment*)", 0) === 0 ? REC_TYPE_PATH2
caryclark55888e42016-07-18 10:01:36 -0700838 : line.lastIndexOf("debugShowTs", 0) === 0 ? REC_TYPE_COIN
Cary Clarkd2eb5812017-01-18 11:00:57 -0500839 : line.lastIndexOf("debugAfter", 0) === 0 ? REC_TYPE_ANGLE
caryclark54359292015-03-26 07:52:43 -0700840 : line.lastIndexOf("afterPart", 0) === 0 ? REC_TYPE_AFTERPART
caryclarkdac1d172014-06-17 05:15:38 -0700841 : line.lastIndexOf("debugShow", 0) === 0 ? REC_TYPE_SECT
842 : line.lastIndexOf("activeOp", 0) === 0 ? REC_TYPE_ACTIVE_OP
843 : line.lastIndexOf("computed", 0) === 0 ? REC_TYPE_COMPUTED
844 : line.lastIndexOf("debugOne", 0) === 0 ? REC_TYPE_SORT
caryclark26ad22a2015-10-16 09:03:38 -0700845 : line.lastIndexOf("aligned=", 0) === 0 ? REC_TYPE_ALIGNED
caryclarkdac1d172014-06-17 05:15:38 -0700846 : line.lastIndexOf("dumpOne", 0) === 0 ? REC_TYPE_SORT
caryclark03b03ca2015-04-23 09:13:37 -0700847 : line.lastIndexOf("findTop", 0) === 0 ? REC_TYPE_TOP
caryclarkdac1d172014-06-17 05:15:38 -0700848 : line.lastIndexOf("pathB.", 0) === 0 ? REC_TYPE_ADD
849 : line.lastIndexOf("path.", 0) === 0 ? REC_TYPE_ADD
caryclarkdac1d172014-06-17 05:15:38 -0700850 : line.lastIndexOf("mark", 0) === 0 ? REC_TYPE_MARK
851 : line.lastIndexOf(" {{", 0) === 0 ? REC_TYPE_COMPUTED
caryclark54359292015-03-26 07:52:43 -0700852 : line.lastIndexOf("seg=", 0) === 0 ? REC_TYPE_PATH
caryclarkdac1d172014-06-17 05:15:38 -0700853 : line.lastIndexOf("op", 0) === 0 ? REC_TYPE_OP
854 : line.lastIndexOf("$", 0) === 0 ? REC_TYPE_PATH
855 : REC_TYPE_UNKNOWN;
856 if (recType != type || recType == REC_TYPE_ADD || recType == REC_TYPE_SECT
857 || recType == REC_TYPE_ACTIVE_OP || recType == REC_TYPE_ANGLE) {
858 if (recType != REC_TYPE_UNKNOWN) {
859 records.push(recType);
860 records.push(lastLineNo);
861 records.push(record);
862 }
863 record = [];
864 recType = type;
865 lastLineNo = lineNo;
866 }
867 var found = false;
868 switch (recType) {
869 case REC_TYPE_ACTIVE:
870 found = match_regexp(line, lineNo, record, ACTIVE_LINE_SPAN, "debugShowActiveSpans" +
caryclark55888e42016-07-18 10:01:36 -0700871" id=IDX LINE_VAL t=T_VAL tEnd=T_VAL windSum=OPT windValue=IDX"
caryclarkdac1d172014-06-17 05:15:38 -0700872 ) || match_regexp(line, lineNo, record, ACTIVE_QUAD_SPAN, "debugShowActiveSpans" +
caryclark55888e42016-07-18 10:01:36 -0700873" id=IDX QUAD_VAL t=T_VAL tEnd=T_VAL windSum=OPT windValue=IDX"
caryclark1049f122015-04-20 08:31:59 -0700874 ) || match_regexp(line, lineNo, record, ACTIVE_CONIC_SPAN, "debugShowActiveSpans" +
caryclark55888e42016-07-18 10:01:36 -0700875" id=IDX CONIC_VAL t=T_VAL tEnd=T_VAL windSum=OPT windValue=IDX"
caryclarkdac1d172014-06-17 05:15:38 -0700876 ) || match_regexp(line, lineNo, record, ACTIVE_CUBIC_SPAN, "debugShowActiveSpans" +
caryclark55888e42016-07-18 10:01:36 -0700877" id=IDX CUBIC_VAL t=T_VAL tEnd=T_VAL windSum=OPT windValue=IDX"
caryclark624637c2015-05-11 07:21:27 -0700878 ) || match_regexp(line, lineNo, record, ACTIVE_LINE_SPAN, "debugShowActiveSpans" +
caryclark55888e42016-07-18 10:01:36 -0700879" id=IDX LINE_VAL t=T_VAL tEnd=T_VAL windSum=OPT oppSum=OPT windValue=IDX oppValue=NUM"
caryclark624637c2015-05-11 07:21:27 -0700880 ) || match_regexp(line, lineNo, record, ACTIVE_QUAD_SPAN, "debugShowActiveSpans" +
caryclark55888e42016-07-18 10:01:36 -0700881" id=IDX QUAD_VAL t=T_VAL tEnd=T_VAL windSum=OPT oppSum=OPT windValue=IDX oppValue=NUM"
caryclark624637c2015-05-11 07:21:27 -0700882 ) || match_regexp(line, lineNo, record, ACTIVE_CONIC_SPAN, "debugShowActiveSpans" +
caryclark55888e42016-07-18 10:01:36 -0700883" id=IDX CONIC_VAL t=T_VAL tEnd=T_VAL windSum=OPT oppSum=OPT windValue=IDX oppValue=NUM"
caryclark624637c2015-05-11 07:21:27 -0700884 ) || match_regexp(line, lineNo, record, ACTIVE_CUBIC_SPAN, "debugShowActiveSpans" +
caryclark55888e42016-07-18 10:01:36 -0700885" id=IDX CUBIC_VAL t=T_VAL tEnd=T_VAL windSum=OPT oppSum=OPT windValue=IDX oppValue=NUM"
caryclarkdac1d172014-06-17 05:15:38 -0700886 );
887 break;
888 case REC_TYPE_ACTIVE_OP:
889 found = match_regexp(line, lineNo, record, ACTIVE_OP, "activeOp" +
890" id=IDX t=T_VAL tEnd=T_VAL op=OPER miFrom=NUM miTo=NUM suFrom=NUM suTo=NUM result=IDX"
891 );
892 break;
893 case REC_TYPE_ADD:
894 if (match_regexp(line, lineNo, record, ADD_MOVETO, "PATH.moveTo(P_VAL);")) {
895 moveX = record[1][0];
896 moveY = record[1][1];
897 found = true;
898 } else if (match_regexp(line, lineNo, record, ADD_LINETO, "PATH.lineTo(P_VAL);")) {
899 record[1].unshift(moveY);
900 record[1].unshift(moveX);
901 moveX = record[1][2];
902 moveY = record[1][3];
903 found = true;
904 } else if (match_regexp(line, lineNo, record, ADD_QUADTO, "PATH.quadTo(P_VAL, P_VAL);")) {
905 record[1].unshift(moveY);
906 record[1].unshift(moveX);
907 moveX = record[1][4];
908 moveY = record[1][5];
909 found = true;
caryclark1049f122015-04-20 08:31:59 -0700910 } else if (match_regexp(line, lineNo, record, ADD_CONICTO, "PATH.conicTo(P_VAL, P_VAL, T_VAL);")) {
911 record[1].unshift(moveY);
912 record[1].unshift(moveX);
913 moveX = record[1][4];
914 moveY = record[1][5];
915 found = true;
caryclarkdac1d172014-06-17 05:15:38 -0700916 } else if (match_regexp(line, lineNo, record, ADD_CUBICTO, "PATH.cubicTo(P_VAL, P_VAL, P_VAL);")) {
917 record[1].unshift(moveY);
918 record[1].unshift(moveX);
919 moveX = record[1][6];
920 moveY = record[1][7];
921 found = true;
922 } else if (match_regexp(line, lineNo, record, ADD_FILL, "PATH.setFillType(FILL_TYPE);")) {
923 found = true;
924 } else {
925 found = match_regexp(line, lineNo, record, ADD_CLOSE, "PATH.close();");
926 }
927 break;
caryclark54359292015-03-26 07:52:43 -0700928 case REC_TYPE_AFTERPART:
Cary Clarkff114282016-12-14 11:56:16 -0500929 found = match_regexp(line, lineNo, record, PATH_LINE, "afterPart LINE_VAL id=IDX")
930 || match_regexp(line, lineNo, record, PATH_QUAD, "afterPart QUAD_VAL id=IDX")
931 || match_regexp(line, lineNo, record, PATH_CONIC, "afterPart CONIC_VAL id=IDX")
932 || match_regexp(line, lineNo, record, PATH_CUBIC, "afterPart CUBIC_VAL id=IDX")
caryclark54359292015-03-26 07:52:43 -0700933 break;
caryclark26ad22a2015-10-16 09:03:38 -0700934 case REC_TYPE_ALIGNED:
935 found = match_regexp(line, lineNo, record, PATH_LINE, "aligned=IDX LINE_VAL"
936 ) || match_regexp(line, lineNo, record, PATH_QUAD, "aligned=IDX QUAD_VAL"
937 ) || match_regexp(line, lineNo, record, PATH_CONIC, "aligned=IDX CONIC_VAL"
938 ) || match_regexp(line, lineNo, record, PATH_CUBIC, "aligned=IDX CUBIC_VAL"
939 );
940 break;
caryclarkdac1d172014-06-17 05:15:38 -0700941 case REC_TYPE_ANGLE:
Cary Clarkd2eb5812017-01-18 11:00:57 -0500942 found = match_regexp(line, lineNo, record, ANGLE_AFTER, "debugAfter " +
caryclarkdac1d172014-06-17 05:15:38 -0700943"[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");
944 break;
945 case REC_TYPE_COIN:
946 found = true;
947 break;
caryclark624637c2015-05-11 07:21:27 -0700948 case REC_TYPE_COINCIDENCE:
949 found = match_regexp(line, lineNo, record, COIN_MAIN_SPAN, "debugShowCoincidence" +
950" + id=IDX t=T_VAL tEnd=T_VAL"
951 ) || match_regexp(line, lineNo, record, COIN_OPP_SPAN, "debugShowCoincidence" +
952" - id=IDX t=T_VAL tEnd=T_VAL"
953 );
954 break;
caryclarkdac1d172014-06-17 05:15:38 -0700955 case REC_TYPE_COMPUTED:
956 found = line == "computed quadratics given"
957 || match_regexp(line, lineNo, record, COMPUTED_SET_1, "computed quadratics set 1"
958 ) || match_regexp(line, lineNo, record, COMPUTED_SET_2, "computed quadratics set 2"
959 ) || match_regexp(line, lineNo, record, PATH_QUAD, " QUAD_VAL,"
caryclark1049f122015-04-20 08:31:59 -0700960 ) || match_regexp(line, lineNo, record, PATH_CONIC, " CONIC_VAL,"
caryclarkdac1d172014-06-17 05:15:38 -0700961 ) || match_regexp(line, lineNo, record, PATH_CUBIC, " CUBIC_VAL,"
962 );
963 break;
964 case REC_TYPE_PATH:
caryclark54359292015-03-26 07:52:43 -0700965 found = match_regexp(line, lineNo, record, PATH_LINE, "seg=IDX LINE_VAL"
966 ) || match_regexp(line, lineNo, record, PATH_QUAD, "seg=IDX QUAD_VAL"
caryclark1049f122015-04-20 08:31:59 -0700967 ) || match_regexp(line, lineNo, record, PATH_CONIC, "seg=IDX CONIC_VAL"
caryclark54359292015-03-26 07:52:43 -0700968 ) || match_regexp(line, lineNo, record, PATH_CUBIC, "seg=IDX CUBIC_VAL"
969 );
970 break;
971 case REC_TYPE_PATH2:
972 found = match_regexp(line, lineNo, record, PATH_LINE, "((SkOpSegment*) PTR_VAL) [IDX] {LINE_VAL}"
973 ) || match_regexp(line, lineNo, record, PATH_QUAD, "((SkOpSegment*) PTR_VAL) [IDX] {QUAD_VAL}"
caryclark1049f122015-04-20 08:31:59 -0700974 ) || match_regexp(line, lineNo, record, PATH_CONIC, "((SkOpSegment*) PTR_VAL) [IDX] {CONIC_VAL}"
caryclark54359292015-03-26 07:52:43 -0700975 ) || match_regexp(line, lineNo, record, PATH_CUBIC, "((SkOpSegment*) PTR_VAL) [IDX] {CUBIC_VAL}"
caryclarkdac1d172014-06-17 05:15:38 -0700976 );
977 break;
978 case REC_TYPE_SECT:
979 found = match_regexp(line, lineNo, record, INTERSECT_LINE, "debugShowLineIntersection" +
980" wtTs[0]=T_VAL LINE_VAL PT_VAL wnTs[0]=T_VAL LINE_VAL"
981 ) || match_regexp(line, lineNo, record, INTERSECT_LINE_2, "debugShowLineIntersection" +
982" wtTs[0]=T_VAL LINE_VAL PT_VAL wtTs[1]=T_VAL PT_VAL wnTs[0]=T_VAL LINE_VAL wnTs[1]=T_VAL"
983 ) || match_regexp(line, lineNo, record, INTERSECT_LINE_NO, "debugShowLineIntersection" +
984" no intersect LINE_VAL LINE_VAL"
985 ) || match_regexp(line, lineNo, record, INTERSECT_QUAD_LINE, "debugShowQuadLineIntersection" +
986" wtTs[0]=T_VAL QUAD_VAL PT_VAL wnTs[0]=T_VAL LINE_VAL"
987 ) || match_regexp(line, lineNo, record, INTERSECT_QUAD_LINE_2, "debugShowQuadLineIntersection" +
988" wtTs[0]=T_VAL QUAD_VAL PT_VAL wtTs[1]=T_VAL PT_VAL wnTs[0]=T_VAL LINE_VAL wnTs[1]=T_VAL"
989 ) || match_regexp(line, lineNo, record, INTERSECT_QUAD_LINE_NO, "debugShowQuadLineIntersection" +
990" no intersect QUAD_VAL LINE_VAL"
991 ) || match_regexp(line, lineNo, record, INTERSECT_QUAD, "debugShowQuadIntersection" +
992" wtTs[0]=T_VAL QUAD_VAL PT_VAL wnTs[0]=T_VAL QUAD_VAL"
993 ) || match_regexp(line, lineNo, record, INTERSECT_QUAD_2, "debugShowQuadIntersection" +
994" wtTs[0]=T_VAL QUAD_VAL PT_VAL wtTs[1]=T_VAL PT_VAL wnTs[0]=T_VAL QUAD_VAL wnTs[1]=T_VAL"
995 ) || match_regexp(line, lineNo, record, INTERSECT_QUAD_NO, "debugShowQuadIntersection" +
996" no intersect QUAD_VAL QUAD_VAL"
caryclark55888e42016-07-18 10:01:36 -0700997
caryclark1049f122015-04-20 08:31:59 -0700998 ) || match_regexp(line, lineNo, record, INTERSECT_CONIC_LINE, "debugShowConicLineIntersection" +
999" wtTs[0]=T_VAL CONIC_VAL PT_VAL wnTs[0]=T_VAL LINE_VAL"
1000 ) || match_regexp(line, lineNo, record, INTERSECT_CONIC_LINE_2, "debugShowConicLineIntersection" +
1001" wtTs[0]=T_VAL CONIC_VAL PT_VAL wtTs[1]=T_VAL PT_VAL wnTs[0]=T_VAL LINE_VAL wnTs[1]=T_VAL"
1002 ) || match_regexp(line, lineNo, record, INTERSECT_CONIC_LINE_NO, "debugShowConicLineIntersection" +
1003" no intersect CONIC_VAL LINE_VAL"
caryclark55888e42016-07-18 10:01:36 -07001004
1005 ) || match_regexp(line, lineNo, record, INTERSECT_CONIC_QUAD, "debugShowConicQuadIntersection" +
1006" wtTs[0]=T_VAL CONIC_VAL PT_VAL wnTs[0]=T_VAL QUAD_VAL"
1007 ) || match_regexp(line, lineNo, record, INTERSECT_CONIC_QUAD_2, "debugShowConicQuadIntersection" +
1008" 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 -07001009 ) || match_regexp(line, lineNo, record, INTERSECT_CONIC_QUAD_3, "debugShowConicQuadIntersection" +
1010" 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"
1011 ) || match_regexp(line, lineNo, record, INTERSECT_CONIC_QUAD_4, "debugShowConicQuadIntersection" +
1012" 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 -07001013 ) || match_regexp(line, lineNo, record, INTERSECT_CONIC_QUAD_NO, "debugShowConicQuadIntersection" +
1014" no intersect CONIC_VAL QUAD_VAL"
1015
caryclark1049f122015-04-20 08:31:59 -07001016 ) || match_regexp(line, lineNo, record, INTERSECT_CONIC, "debugShowConicIntersection" +
1017" wtTs[0]=T_VAL CONIC_VAL PT_VAL wnTs[0]=T_VAL CONIC_VAL"
1018 ) || match_regexp(line, lineNo, record, INTERSECT_CONIC_2, "debugShowConicIntersection" +
1019" wtTs[0]=T_VAL CONIC_VAL PT_VAL wtTs[1]=T_VAL PT_VAL wnTs[0]=T_VAL CONIC_VAL wnTs[1]=T_VAL"
1020 ) || match_regexp(line, lineNo, record, INTERSECT_CONIC_NO, "debugShowConicIntersection" +
1021" no intersect CONIC_VAL CONIC_VAL"
caryclarkdac1d172014-06-17 05:15:38 -07001022 ) || match_regexp(line, lineNo, record, INTERSECT_CUBIC_LINE, "debugShowCubicLineIntersection" +
1023" wtTs[0]=T_VAL CUBIC_VAL PT_VAL wnTs[0]=T_VAL LINE_VAL"
1024 ) || match_regexp(line, lineNo, record, INTERSECT_CUBIC_LINE_2, "debugShowCubicLineIntersection" +
1025" wtTs[0]=T_VAL CUBIC_VAL PT_VAL wtTs[1]=T_VAL PT_VAL wnTs[0]=T_VAL LINE_VAL wnTs[1]=T_VAL"
1026 ) || match_regexp(line, lineNo, record, INTERSECT_CUBIC_LINE_3, "debugShowCubicLineIntersection" +
1027" 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"
1028 ) || match_regexp(line, lineNo, record, INTERSECT_CUBIC_LINE_NO, "debugShowCubicLineIntersection" +
1029" no intersect CUBIC_VAL LINE_VAL"
1030 ) || match_regexp(line, lineNo, record, INTERSECT_CUBIC_QUAD, "debugShowCubicQuadIntersection" +
1031" wtTs[0]=T_VAL CUBIC_VAL PT_VAL wnTs[0]=T_VAL QUAD_VAL"
1032 ) || match_regexp(line, lineNo, record, INTERSECT_CUBIC_QUAD_2, "debugShowCubicQuadIntersection" +
1033" wtTs[0]=T_VAL CUBIC_VAL PT_VAL wtTs[1]=T_VAL PT_VAL wnTs[0]=T_VAL QUAD_VAL wnTs[1]=T_VAL"
1034 ) || match_regexp(line, lineNo, record, INTERSECT_CUBIC_QUAD_3, "debugShowCubicQuadIntersection" +
1035" 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"
1036 ) || match_regexp(line, lineNo, record, INTERSECT_CUBIC_QUAD_4, "debugShowCubicQuadIntersection" +
1037" 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"
1038 ) || match_regexp(line, lineNo, record, INTERSECT_CUBIC_QUAD_NO, "debugShowCubicQuadIntersection" +
1039" no intersect CUBIC_VAL QUAD_VAL"
1040 ) || match_regexp(line, lineNo, record, INTERSECT_CUBIC, "debugShowCubicIntersection" +
1041" wtTs[0]=T_VAL CUBIC_VAL PT_VAL wnTs[0]=T_VAL CUBIC_VAL"
1042 ) || match_regexp(line, lineNo, record, INTERSECT_CUBIC_2, "debugShowCubicIntersection" +
1043" wtTs[0]=T_VAL CUBIC_VAL PT_VAL wtTs[1]=T_VAL PT_VAL wnTs[0]=T_VAL CUBIC_VAL wnTs[1]=T_VAL"
1044 ) || match_regexp(line, lineNo, record, INTERSECT_CUBIC_3, "debugShowCubicIntersection" +
1045" 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"
1046 ) || match_regexp(line, lineNo, record, INTERSECT_CUBIC_4, "debugShowCubicIntersection" +
1047" 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"
1048 ) || match_regexp(line, lineNo, record, INTERSECT_CUBIC_NO, "debugShowCubicIntersection" +
1049" no intersect CUBIC_VAL CUBIC_VAL"
1050 ) || match_regexp(line, lineNo, record, INTERSECT_SELF_CUBIC, "debugShowCubicIntersection" +
1051" wtTs[0]=T_VAL CUBIC_VAL PT_VAL wtTs[1]=T_VAL"
1052 ) || match_regexp(line, lineNo, record, INTERSECT_SELF_CUBIC_NO, "debugShowCubicIntersection" +
1053" no self intersect CUBIC_VAL"
1054 );
1055 break;
1056 case REC_TYPE_SORT:
1057 var hasDone = / done/.test(line);
1058 var hasUnorderable = / unorderable/.test(line);
1059 var hasSmall = / small/.test(line);
1060 var hasTiny = / tiny/.test(line);
1061 var hasOperand = / operand/.test(line);
1062 var hasStop = / stop/.test(line);
1063 line.replace(/[ a-z]+$/, "");
1064 found = match_regexp(line, lineNo, record, SORT_UNARY, "debugOne" +
1065" [IDX/IDX] next=IDX/IDX sect=IDX/IDX s=T_VAL [IDX] e=T_VAL [IDX] sgn=NUM windVal=IDX windSum=OPT"
1066 ) || match_regexp(line, lineNo, record, SORT_BINARY, "debugOne" +
1067" [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"
1068 ) || match_regexp(line, lineNo, record, SORT_UNARY, "dumpOne" +
1069" [IDX/IDX] next=IDX/IDX sect=NUM/NUM s=T_VAL [IDX] e=T_VAL [IDX] sgn=NUM windVal=IDX windSum=OPT"
1070 ) || match_regexp(line, lineNo, record, SORT_BINARY, "dumpOne" +
1071" [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"
1072 );
1073 if (found) {
1074 record[1].push(hasDone);
1075 record[1].push(hasUnorderable);
1076 record[1].push(hasSmall);
1077 record[1].push(hasTiny);
1078 record[1].push(hasOperand);
1079 record[1].push(hasStop);
1080 }
1081 break;
caryclark03b03ca2015-04-23 09:13:37 -07001082 case REC_TYPE_TOP:
1083 found = match_regexp(line, lineNo, record, ACTIVE_OP, "findTop" +
1084" id=IDX s=T_VAL e=T_VAL cw=NUM swap=NUM inflections=NUM monotonic=NUM"
1085 ) || match_regexp(line, lineNo, record, ACTIVE_OP, "findTop" +
1086" id=IDX s=T_VAL e=T_VAL (-) cw=NUM swap=NUM inflections=NUM monotonic=NUM"
1087 ) || match_regexp(line, lineNo, record, ACTIVE_OP, "findTop" +
1088" id=IDX s=T_VAL e=T_VAL (+) cw=NUM swap=NUM inflections=NUM monotonic=NUM"
1089 );
1090 break;
caryclarkdac1d172014-06-17 05:15:38 -07001091 case REC_TYPE_MARK:
1092 found = match_regexp(line, lineNo, record, MARK_LINE, "markWinding" +
caryclark54359292015-03-26 07:52:43 -07001093" 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 -07001094 ) || match_regexp(line, lineNo, record, MARK_QUAD, "markWinding" +
caryclark54359292015-03-26 07:52:43 -07001095" 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 -07001096 ) || match_regexp(line, lineNo, record, MARK_CONIC, "markWinding" +
1097" 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 -07001098 ) || match_regexp(line, lineNo, record, MARK_CUBIC, "markWinding" +
caryclark54359292015-03-26 07:52:43 -07001099" id=IDX CUBIC_VAL t=T_VAL [IDX] PT_VAL tEnd=T_VAL newWindSum=NUM newOppSum=OPT oppSum=OPT windSum=OPT windValue=IDX"
1100 ) || match_regexp(line, lineNo, record, MARK_DONE_LINE, "markDone" +
1101" 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"
1102 ) || match_regexp(line, lineNo, record, MARK_DONE_QUAD, "markDone" +
1103" 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 -07001104 ) || match_regexp(line, lineNo, record, MARK_DONE_CONIC, "markDone" +
1105" 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 -07001106 ) || match_regexp(line, lineNo, record, MARK_DONE_CUBIC, "markDone" +
1107" 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 -07001108 ) || match_regexp(line, lineNo, record, MARK_SIMPLE_LINE, "markWinding" +
1109" id=IDX LINE_VAL t=T_VAL [IDX] PT_VAL tEnd=T_VAL newWindSum=NUM windSum=OPT windValue=IDX"
1110 ) || match_regexp(line, lineNo, record, MARK_SIMPLE_QUAD, "markWinding" +
1111" 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 -07001112 ) || match_regexp(line, lineNo, record, MARK_SIMPLE_CONIC, "markWinding" +
1113" 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 -07001114 ) || match_regexp(line, lineNo, record, MARK_SIMPLE_CUBIC, "markWinding" +
1115" 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 -07001116 ) || match_regexp(line, lineNo, record, MARK_ANGLE_LAST, "markAngle" +
caryclark1049f122015-04-20 08:31:59 -07001117" last segment=IDX span=IDX"
caryclark54359292015-03-26 07:52:43 -07001118 ) || match_regexp(line, lineNo, record, MARK_ANGLE_LAST, "markAngle" +
caryclark55888e42016-07-18 10:01:36 -07001119" last seg=IDX span=IDX"
1120 ) || match_regexp(line, lineNo, record, MARK_ANGLE_LAST, "markAngle" +
1121" last segment=IDX span=IDX windSum=OPT"
1122 ) || match_regexp(line, lineNo, record, MARK_ANGLE_LAST, "markAngle" +
1123" last seg=IDX span=IDX windSum=OPT"
1124 );
caryclarkdac1d172014-06-17 05:15:38 -07001125 break;
1126 case REC_TYPE_OP:
1127 if (line.lastIndexOf("oppSign oppSign=", 0) === 0
1128 || line.lastIndexOf("operator<", 0) === 0) {
1129 found = true;
1130 break;
1131 }
caryclark54359292015-03-26 07:52:43 -07001132 found = match_regexp(line, lineNo, record, OP_DIFFERENCE, "op diff"
caryclarkdac1d172014-06-17 05:15:38 -07001133 ) || match_regexp(line, lineNo, record, OP_INTERSECT, "op intersect"
caryclark54359292015-03-26 07:52:43 -07001134 ) || match_regexp(line, lineNo, record, OP_INTERSECT, "op sect"
caryclarkdac1d172014-06-17 05:15:38 -07001135 ) || match_regexp(line, lineNo, record, OP_UNION, "op union"
1136 ) || match_regexp(line, lineNo, record, OP_XOR, "op xor"
1137 );
1138 break;
1139 case REC_TYPE_UNKNOWN:
1140 found = true;
1141 break;
1142 }
1143 if (!found) {
1144 console.log(line + " [" + lineNo + "] of type " + type + " not found");
1145 }
1146 }
1147 if (recType != REC_TYPE_UNKNOWN) {
1148 records.push(recType);
1149 records.push(lastLineNo);
1150 records.push(record);
1151 }
1152 if (records.length >= 1) {
1153 tests[testIndex] = records;
1154 testLines[testIndex] = lines;
1155 }
1156}
1157
1158function init(test) {
1159 var canvas = document.getElementById('canvas');
1160 if (!canvas.getContext) return;
1161 ctx = canvas.getContext('2d');
1162 var resScale = retina_scale && window.devicePixelRatio ? window.devicePixelRatio : 1;
1163 var unscaledWidth = window.innerWidth - 20;
1164 var unscaledHeight = window.innerHeight - 20;
1165 screenWidth = unscaledWidth;
1166 screenHeight = unscaledHeight;
1167 canvas.width = unscaledWidth * resScale;
1168 canvas.height = unscaledHeight * resScale;
1169 canvas.style.width = unscaledWidth + 'px';
1170 canvas.style.height = unscaledHeight + 'px';
1171 if (resScale != 1) {
1172 ctx.scale(resScale, resScale);
1173 }
1174 xmin = Infinity;
1175 xmax = -Infinity;
1176 ymin = Infinity;
1177 ymax = -Infinity;
caryclark26ad22a2015-10-16 09:03:38 -07001178 hasPath = hasAlignedPath = hasComputedPath = false;
caryclarkdac1d172014-06-17 05:15:38 -07001179 firstActiveSpan = -1;
1180 for (var tIndex = 0; tIndex < test.length; tIndex += 3) {
1181 var recType = test[tIndex];
1182 if (!typeof recType == 'number' || recType < REC_TYPE_UNKNOWN || recType > REC_TYPE_LAST) {
1183 console.log("unknown rec type: " + recType);
1184 throw "stop execution";
1185 }
1186 var records = test[tIndex + 2];
1187 for (var recordIndex = 0; recordIndex < records.length; recordIndex += 2) {
1188 var fragType = records[recordIndex];
1189 if (!typeof fragType == 'number' || fragType < 1 || fragType > FRAG_TYPE_LAST) {
1190 console.log("unknown in range frag type: " + fragType);
1191 throw "stop execution";
1192 }
1193 var frags = records[recordIndex + 1];
1194 var first = 0;
1195 var last = -1;
1196 var first2 = 0;
1197 var last2 = 0;
1198 switch (recType) {
caryclark26ad22a2015-10-16 09:03:38 -07001199 case REC_TYPE_ALIGNED:
1200 hasAlignedPath = true;
caryclarkdac1d172014-06-17 05:15:38 -07001201 case REC_TYPE_COMPUTED:
1202 if (fragType == COMPUTED_SET_1 || fragType == COMPUTED_SET_2) {
1203 break;
1204 }
caryclark26ad22a2015-10-16 09:03:38 -07001205 if (REC_TYPE_COMPUTED == recType) {
1206 hasComputedPath = true;
1207 }
caryclarkdac1d172014-06-17 05:15:38 -07001208 case REC_TYPE_PATH:
caryclark54359292015-03-26 07:52:43 -07001209 first = 1;
caryclarkdac1d172014-06-17 05:15:38 -07001210 switch (fragType) {
1211 case PATH_LINE:
caryclark54359292015-03-26 07:52:43 -07001212 last = 5;
caryclarkdac1d172014-06-17 05:15:38 -07001213 break;
caryclark1049f122015-04-20 08:31:59 -07001214 case PATH_CONIC:
caryclarkdac1d172014-06-17 05:15:38 -07001215 case PATH_QUAD:
caryclark54359292015-03-26 07:52:43 -07001216 last = 7;
caryclarkdac1d172014-06-17 05:15:38 -07001217 break;
1218 case PATH_CUBIC:
caryclark54359292015-03-26 07:52:43 -07001219 last = 9;
caryclarkdac1d172014-06-17 05:15:38 -07001220 break;
1221 default:
caryclark55888e42016-07-18 10:01:36 -07001222 console.log("unknown " + (recType == REC_TYPE_PATH ? "REC_TYPE_PATH"
caryclarkdac1d172014-06-17 05:15:38 -07001223 : "REC_TYPE_COMPUTED") + " frag type:" + fragType);
1224 throw "stop execution";
1225 }
1226 if (recType == REC_TYPE_PATH) {
1227 hasPath = true;
1228 }
1229 break;
caryclark54359292015-03-26 07:52:43 -07001230 case REC_TYPE_PATH2:
1231 first = 1;
1232 switch (fragType) {
1233 case PATH_LINE:
1234 last = 5;
1235 break;
caryclark1049f122015-04-20 08:31:59 -07001236 case PATH_CONIC:
caryclark54359292015-03-26 07:52:43 -07001237 case PATH_QUAD:
1238 last = 7;
1239 break;
1240 case PATH_CUBIC:
1241 last = 9;
1242 break;
1243 default:
caryclark55888e42016-07-18 10:01:36 -07001244 console.log("unknown " + (recType == REC_TYPE_PATH2 ? "REC_TYPE_PATH2"
caryclark54359292015-03-26 07:52:43 -07001245 : "REC_TYPE_COMPUTED") + " frag type:" + fragType);
1246 throw "stop execution";
1247 }
1248 if (recType == REC_TYPE_PATH2) {
1249 hasPath = true;
1250 }
1251 break;
caryclarkdac1d172014-06-17 05:15:38 -07001252 case REC_TYPE_ACTIVE:
1253 if (firstActiveSpan < 0) {
1254 firstActiveSpan = tIndex;
1255 }
1256 first = 1;
1257 switch (fragType) {
1258 case ACTIVE_LINE_SPAN:
1259 last = 5;
1260 break;
caryclark1049f122015-04-20 08:31:59 -07001261 case ACTIVE_CONIC_SPAN:
caryclarkdac1d172014-06-17 05:15:38 -07001262 case ACTIVE_QUAD_SPAN:
1263 last = 7;
1264 break;
1265 case ACTIVE_CUBIC_SPAN:
1266 last = 9;
1267 break;
1268 default:
1269 console.log("unknown REC_TYPE_ACTIVE frag type: " + fragType);
1270 throw "stop execution";
1271 }
1272 break;
1273 case REC_TYPE_ADD:
1274 switch (fragType) {
1275 case ADD_MOVETO:
1276 break;
1277 case ADD_LINETO:
1278 last = 4;
1279 break;
caryclark1049f122015-04-20 08:31:59 -07001280 case ADD_CONICTO:
caryclarkdac1d172014-06-17 05:15:38 -07001281 case ADD_QUADTO:
1282 last = 6;
1283 break;
1284 case ADD_CUBICTO:
1285 last = 8;
1286 break;
1287 case ADD_CLOSE:
1288 case ADD_FILL:
1289 break;
1290 default:
1291 console.log("unknown REC_TYPE_ADD frag type: " + fragType);
1292 throw "stop execution";
1293 }
1294 break;
caryclark54359292015-03-26 07:52:43 -07001295 case REC_TYPE_AFTERPART:
1296 switch (fragType) {
1297 case PATH_LINE:
1298 last = 4;
1299 break;
caryclark1049f122015-04-20 08:31:59 -07001300 case PATH_CONIC:
caryclark54359292015-03-26 07:52:43 -07001301 case PATH_QUAD:
1302 last = 6;
1303 break;
1304 case PATH_CUBIC:
1305 last = 8;
1306 break;
1307 default:
1308 console.log("unknown REC_TYPE_ACTIVEPART frag type: " + fragType);
1309 throw "stop execution";
1310 }
1311 break;
caryclarkdac1d172014-06-17 05:15:38 -07001312 case REC_TYPE_SECT:
1313 switch (fragType) {
1314 case INTERSECT_LINE:
1315 first = 1; last = 5; first2 = 8; last2 = 12;
1316 break;
1317 case INTERSECT_LINE_2:
1318 first = 1; last = 5; first2 = 11; last2 = 15;
1319 break;
1320 case INTERSECT_LINE_NO:
1321 first = 0; last = 4; first2 = 4; last2 = 8;
1322 break;
caryclark1049f122015-04-20 08:31:59 -07001323 case INTERSECT_CONIC_LINE:
1324 first = 1; last = 7; first2 = 11; last2 = 15;
1325 break;
caryclarkdac1d172014-06-17 05:15:38 -07001326 case INTERSECT_QUAD_LINE:
1327 first = 1; last = 7; first2 = 10; last2 = 14;
1328 break;
caryclark1049f122015-04-20 08:31:59 -07001329 case INTERSECT_CONIC_LINE_2:
1330 first = 1; last = 7; first2 = 14; last2 = 18;
1331 break;
caryclarkdac1d172014-06-17 05:15:38 -07001332 case INTERSECT_QUAD_LINE_2:
1333 first = 1; last = 7; first2 = 13; last2 = 17;
1334 break;
caryclark1049f122015-04-20 08:31:59 -07001335 case INTERSECT_CONIC_LINE_NO:
1336 first = 0; last = 6; first2 = 7; last2 = 11;
1337 break;
caryclarkdac1d172014-06-17 05:15:38 -07001338 case INTERSECT_QUAD_LINE_NO:
1339 first = 0; last = 6; first2 = 6; last2 = 10;
1340 break;
caryclark1049f122015-04-20 08:31:59 -07001341 case INTERSECT_CONIC:
1342 first = 1; last = 7; first2 = 11; last2 = 17;
1343 break;
caryclarkdac1d172014-06-17 05:15:38 -07001344 case INTERSECT_QUAD:
1345 first = 1; last = 7; first2 = 10; last2 = 16;
1346 break;
caryclark1049f122015-04-20 08:31:59 -07001347 case INTERSECT_CONIC_2:
1348 first = 1; last = 7; first2 = 14; last2 = 20;
1349 break;
caryclarkdac1d172014-06-17 05:15:38 -07001350 case INTERSECT_QUAD_2:
1351 first = 1; last = 7; first2 = 13; last2 = 19;
1352 break;
caryclark1049f122015-04-20 08:31:59 -07001353 case INTERSECT_CONIC_NO:
1354 first = 0; last = 6; first2 = 7; last2 = 13;
1355 break;
caryclarkdac1d172014-06-17 05:15:38 -07001356 case INTERSECT_QUAD_NO:
1357 first = 0; last = 6; first2 = 6; last2 = 12;
1358 break;
1359 case INTERSECT_SELF_CUBIC:
1360 first = 1; last = 9;
1361 break;
1362 case INTERSECT_SELF_CUBIC_NO:
1363 first = 0; last = 8;
1364 break;
1365 case INTERSECT_CUBIC_LINE:
1366 first = 1; last = 9; first2 = 12; last2 = 16;
1367 break;
1368 case INTERSECT_CUBIC_LINE_2:
1369 first = 1; last = 9; first2 = 15; last2 = 19;
1370 break;
1371 case INTERSECT_CUBIC_LINE_3:
1372 first = 1; last = 9; first2 = 18; last2 = 22;
1373 break;
1374 case INTERSECT_CUBIC_LINE_NO:
1375 first = 0; last = 8; first2 = 8; last2 = 12;
1376 break;
caryclark55888e42016-07-18 10:01:36 -07001377 case INTERSECT_CONIC_QUAD:
1378 first = 1; last = 7; first2 = 11; last2 = 17;
1379 break;
1380 case INTERSECT_CONIC_QUAD_2:
1381 first = 1; last = 7; first2 = 14; last2 = 20;
1382 break;
caryclark6c3b9cd2016-09-26 05:36:58 -07001383 case INTERSECT_CONIC_QUAD_3:
1384 first = 1; last = 7; first2 = 17; last2 = 23;
1385 break;
1386 case INTERSECT_CONIC_QUAD_4:
1387 first = 1; last = 7; first2 = 20; last2 = 26;
1388 break;
caryclark55888e42016-07-18 10:01:36 -07001389 case INTERSECT_CONIC_QUAD_NO:
1390 first = 0; last = 6; first2 = 7; last2 = 13;
1391 break;
caryclarkdac1d172014-06-17 05:15:38 -07001392 case INTERSECT_CUBIC_QUAD:
1393 first = 1; last = 9; first2 = 12; last2 = 18;
1394 break;
1395 case INTERSECT_CUBIC_QUAD_2:
1396 first = 1; last = 9; first2 = 15; last2 = 21;
1397 break;
1398 case INTERSECT_CUBIC_QUAD_3:
1399 first = 1; last = 9; first2 = 18; last2 = 24;
1400 break;
1401 case INTERSECT_CUBIC_QUAD_4:
1402 first = 1; last = 9; first2 = 21; last2 = 27;
1403 break;
1404 case INTERSECT_CUBIC_QUAD_NO:
1405 first = 0; last = 8; first2 = 8; last2 = 14;
1406 break;
1407 case INTERSECT_CUBIC:
1408 first = 1; last = 9; first2 = 12; last2 = 20;
1409 break;
1410 case INTERSECT_CUBIC_2:
1411 first = 1; last = 9; first2 = 15; last2 = 23;
1412 break;
1413 case INTERSECT_CUBIC_3:
1414 first = 1; last = 9; first2 = 18; last2 = 26;
1415 break;
1416 case INTERSECT_CUBIC_4:
1417 first = 1; last = 9; first2 = 21; last2 = 29;
1418 break;
1419 case INTERSECT_CUBIC_NO:
1420 first = 0; last = 8; first2 = 8; last2 = 16;
1421 break;
1422 default:
1423 console.log("unknown REC_TYPE_SECT frag type: " + fragType);
1424 throw "stop execution";
1425 }
1426 break;
1427 default:
1428 continue;
1429 }
1430 for (var idx = first; idx < last; idx += 2) {
1431 xmin = Math.min(xmin, frags[idx]);
1432 xmax = Math.max(xmax, frags[idx]);
1433 ymin = Math.min(ymin, frags[idx + 1]);
1434 ymax = Math.max(ymax, frags[idx + 1]);
1435 }
1436 for (var idx = first2; idx < last2; idx += 2) {
1437 xmin = Math.min(xmin, frags[idx]);
1438 xmax = Math.max(xmax, frags[idx]);
1439 ymin = Math.min(ymin, frags[idx + 1]);
1440 ymax = Math.max(ymax, frags[idx + 1]);
1441 }
1442 }
1443 }
1444 var angleBounds = [Infinity, Infinity, -Infinity, -Infinity];
1445 for (var tIndex = 0; tIndex < test.length; tIndex += 3) {
1446 var recType = test[tIndex];
1447 var records = test[tIndex + 2];
1448 for (var recordIndex = 0; recordIndex < records.length; recordIndex += 2) {
1449 var fragType = records[recordIndex];
1450 var frags = records[recordIndex + 1];
1451 switch (recType) {
1452 case REC_TYPE_ACTIVE_OP:
1453 if (!draw_op) {
1454 break;
1455 }
1456 {
1457 var curve = curvePartialByID(test, frags[0], frags[1], frags[2]);
1458 curve_extremes(curve, angleBounds);
1459 }
1460 break;
1461 case REC_TYPE_ANGLE:
1462 if (!draw_angle) {
1463 break;
1464 }
caryclark54359292015-03-26 07:52:43 -07001465 {
caryclarkdac1d172014-06-17 05:15:38 -07001466 var curve = curvePartialByID(test, frags[0], frags[4], frags[5]);
1467 curve_extremes(curve, angleBounds);
1468 curve = curvePartialByID(test, frags[6], frags[10], frags[11]);
1469 curve_extremes(curve, angleBounds);
1470 curve = curvePartialByID(test, frags[12], frags[16], frags[17]);
1471 }
1472 break;
caryclark624637c2015-05-11 07:21:27 -07001473 case REC_TYPE_COINCIDENCE:
1474 if (!draw_coincidence) {
1475 break;
1476 }
1477 {
1478 var curve = curvePartialByID(test, frags[0], frags[1], frags[2]);
1479 curve_extremes(curve, angleBounds);
1480 }
1481 break;
caryclarkdac1d172014-06-17 05:15:38 -07001482 case REC_TYPE_SORT:
1483 if (!draw_sort) {
1484 break;
1485 }
1486 if (fragType == SORT_UNARY || fragType == SORT_BINARY) {
1487 var curve = curvePartialByID(test, frags[0], frags[6], frags[8]);
1488 curve_extremes(curve, angleBounds);
1489 }
1490 break;
caryclark03b03ca2015-04-23 09:13:37 -07001491 case REC_TYPE_TOP:
1492 if (!draw_top) {
1493 break;
1494 }
1495 {
1496 var curve = curvePartialByID(test, frags[0], frags[1], frags[2]);
1497 curve_extremes(curve, angleBounds);
1498 }
1499 break;
caryclarkdac1d172014-06-17 05:15:38 -07001500 }
1501 }
1502 }
1503 xmin = Math.min(xmin, angleBounds[0]);
1504 ymin = Math.min(ymin, angleBounds[1]);
1505 xmax = Math.max(xmax, angleBounds[2]);
1506 ymax = Math.max(ymax, angleBounds[3]);
1507 setScale(xmin, xmax, ymin, ymax);
1508 if (hasPath == false && hasComputedPath == true && !draw_computed) {
caryclark1049f122015-04-20 08:31:59 -07001509 draw_computed = 7; // show quadratics, conics, and cubics
caryclarkdac1d172014-06-17 05:15:38 -07001510 }
1511 if (hasPath == true && hasComputedPath == false && draw_computed) {
1512 draw_computed = 0;
1513 }
1514}
1515
caryclark26ad22a2015-10-16 09:03:38 -07001516function curveByIDMatch(test, id, recMatch) {
caryclark54359292015-03-26 07:52:43 -07001517 var tIndex = -3;
1518 while ((tIndex += 3) < test.length) {
caryclarkdac1d172014-06-17 05:15:38 -07001519 var recType = test[tIndex];
caryclark54359292015-03-26 07:52:43 -07001520 if (recType == REC_TYPE_OP) {
1521 continue;
1522 }
caryclark26ad22a2015-10-16 09:03:38 -07001523 if (recType != recMatch) {
caryclarkdac1d172014-06-17 05:15:38 -07001524 return [];
1525 }
1526 var records = test[tIndex + 2];
1527 for (var recordIndex = 0; recordIndex < records.length; recordIndex += 2) {
1528 var fragType = records[recordIndex];
1529 var frags = records[recordIndex + 1];
1530 if (frags[0] == id) {
1531 switch (fragType) {
caryclark54359292015-03-26 07:52:43 -07001532 case PATH_LINE:
caryclarkdac1d172014-06-17 05:15:38 -07001533 return [frags[1], frags[2], frags[3], frags[4]];
caryclark54359292015-03-26 07:52:43 -07001534 case PATH_QUAD:
caryclarkdac1d172014-06-17 05:15:38 -07001535 return [frags[1], frags[2], frags[3], frags[4],
1536 frags[5], frags[6]];
caryclark1049f122015-04-20 08:31:59 -07001537 case PATH_CONIC:
1538 return [frags[1], frags[2], frags[3], frags[4],
1539 frags[5], frags[6], frags[7]];
caryclark54359292015-03-26 07:52:43 -07001540 case PATH_CUBIC:
caryclarkdac1d172014-06-17 05:15:38 -07001541 return [frags[1], frags[2], frags[3], frags[4],
1542 frags[5], frags[6], frags[7], frags[8]];
1543 }
1544 }
1545 }
caryclarkdac1d172014-06-17 05:15:38 -07001546 }
1547 return [];
1548}
1549
caryclark26ad22a2015-10-16 09:03:38 -07001550function curveByID(test, id) {
1551 var result = draw_path >= 4 ? curveByIDMatch(test, id, REC_TYPE_ALIGNED) : [];
1552 if (!result.length) {
1553 result = curveByIDMatch(test, id, REC_TYPE_PATH);
1554 }
1555 return result;
1556}
1557
1558function curvePartialByIDMatch(test, id, t0, t1, recMatch) {
caryclark54359292015-03-26 07:52:43 -07001559 var tIndex = -3;
1560 while ((tIndex += 3) < test.length) {
caryclarkdac1d172014-06-17 05:15:38 -07001561 var recType = test[tIndex];
caryclark54359292015-03-26 07:52:43 -07001562 if (recType == REC_TYPE_OP) {
1563 continue;
1564 }
caryclark26ad22a2015-10-16 09:03:38 -07001565 if (recType != recMatch) {
caryclarkdac1d172014-06-17 05:15:38 -07001566 return [];
1567 }
1568 var records = test[tIndex + 2];
1569 for (var recordIndex = 0; recordIndex < records.length; recordIndex += 2) {
1570 var fragType = records[recordIndex];
1571 var frags = records[recordIndex + 1];
1572 if (frags[0] == id) {
1573 switch (fragType) {
caryclark54359292015-03-26 07:52:43 -07001574 case PATH_LINE:
caryclarkdac1d172014-06-17 05:15:38 -07001575 return linePartial(frags[1], frags[2], frags[3], frags[4], t0, t1);
caryclark54359292015-03-26 07:52:43 -07001576 case PATH_QUAD:
caryclarkdac1d172014-06-17 05:15:38 -07001577 return quadPartial(frags[1], frags[2], frags[3], frags[4],
1578 frags[5], frags[6], t0, t1);
caryclark1049f122015-04-20 08:31:59 -07001579 case PATH_CONIC:
1580 return conicPartial(frags[1], frags[2], frags[3], frags[4],
1581 frags[5], frags[6], frags[7], t0, t1);
caryclark54359292015-03-26 07:52:43 -07001582 case PATH_CUBIC:
caryclarkdac1d172014-06-17 05:15:38 -07001583 return cubicPartial(frags[1], frags[2], frags[3], frags[4],
1584 frags[5], frags[6], frags[7], frags[8], t0, t1);
1585 }
1586 }
1587 }
caryclarkdac1d172014-06-17 05:15:38 -07001588 }
1589 return [];
1590}
1591
caryclark26ad22a2015-10-16 09:03:38 -07001592function curvePartialByID(test, id, t0, t1) {
1593 var result = draw_path >= 4 ? curvePartialByIDMatch(test, id, t0, t1, REC_TYPE_ALIGNED) : [];
1594 if (!result.length) {
1595 result = curvePartialByIDMatch(test, id, t0, t1, REC_TYPE_PATH);
1596 }
1597 return result;
1598}
1599
1600function idByCurveIDMatch(test, frag, type, recMatch) {
caryclark54359292015-03-26 07:52:43 -07001601 var tIndex = 0;
caryclarkdac1d172014-06-17 05:15:38 -07001602 while (tIndex < test.length) {
1603 var recType = test[tIndex];
caryclark26ad22a2015-10-16 09:03:38 -07001604 if (recType != recMatch) {
caryclark54359292015-03-26 07:52:43 -07001605 ++tIndex;
1606 continue;
caryclarkdac1d172014-06-17 05:15:38 -07001607 }
1608 var records = test[tIndex + 2];
1609 for (var recordIndex = 0; recordIndex < records.length; recordIndex += 2) {
1610 var fragType = records[recordIndex];
1611 var frags = records[recordIndex + 1];
caryclark54359292015-03-26 07:52:43 -07001612 if (frag.length != frags.length - 1) {
1613 continue;
1614 }
caryclarkdac1d172014-06-17 05:15:38 -07001615 switch (fragType) {
caryclark54359292015-03-26 07:52:43 -07001616 case PATH_LINE:
caryclarkdac1d172014-06-17 05:15:38 -07001617 if (frag[0] != frags[1] || frag[1] != frags[2]
1618 || frag[2] != frags[3] || frag[3] != frags[4]) {
1619 continue;
1620 }
1621 return frags[0];
caryclark54359292015-03-26 07:52:43 -07001622 case PATH_QUAD:
caryclarkdac1d172014-06-17 05:15:38 -07001623 if (frag[0] != frags[1] || frag[1] != frags[2]
1624 || frag[2] != frags[3] || frag[3] != frags[4]
1625 || frag[4] != frags[5] || frag[5] != frags[6]) {
1626 continue;
1627 }
1628 return frags[0];
caryclark1049f122015-04-20 08:31:59 -07001629 case PATH_CONIC:
1630 if (frag[0] != frags[1] || frag[1] != frags[2]
1631 || frag[2] != frags[3] || frag[3] != frags[4]
1632 || frag[4] != frags[5] || frag[5] != frags[6]
1633 || frag[6] != frags[7]) {
1634 continue;
1635 }
1636 return frags[0];
caryclark54359292015-03-26 07:52:43 -07001637 case PATH_CUBIC:
caryclarkdac1d172014-06-17 05:15:38 -07001638 if (frag[0] != frags[1] || frag[1] != frags[2]
1639 || frag[2] != frags[3] || frag[3] != frags[4]
1640 || frag[4] != frags[5] || frag[5] != frags[6]
1641 || frag[6] != frags[7] || frag[7] != frags[8]) {
1642 continue;
1643 }
1644 return frags[0];
1645 }
1646 }
1647 ++tIndex;
1648 }
1649 return -1;
1650}
1651
caryclark26ad22a2015-10-16 09:03:38 -07001652function idByCurve(test, frag, type) {
1653 var result = draw_path >= 4 ? idByCurveIDMatch(test, frag, type, REC_TYPE_ALIGNED) : [];
1654 if (!result.length) {
1655 result = idByCurveIDMatch(test, frag, type, REC_TYPE_PATH);
1656 }
1657 return result;
1658}
1659
caryclarkdac1d172014-06-17 05:15:38 -07001660function curve_extremes(curve, bounds) {
caryclark1049f122015-04-20 08:31:59 -07001661 var length = curve.length == 7 ? 6 : curve.length;
caryclarked0935a2015-10-22 07:23:52 -07001662 for (var index = 0; index < length; index += 2) {
caryclarkdac1d172014-06-17 05:15:38 -07001663 var x = curve[index];
1664 var y = curve[index + 1];
1665 bounds[0] = Math.min(bounds[0], x);
1666 bounds[1] = Math.min(bounds[1], y);
1667 bounds[2] = Math.max(bounds[2], x);
1668 bounds[3] = Math.max(bounds[3], y);
1669 }
1670}
1671
1672function setScale(x0, x1, y0, y1) {
1673 var srcWidth = x1 - x0;
1674 var srcHeight = y1 - y0;
1675 var usableWidth = screenWidth;
1676 var xDigits = Math.ceil(Math.log(Math.abs(xmax)) / Math.log(10));
1677 var yDigits = Math.ceil(Math.log(Math.abs(ymax)) / Math.log(10));
1678 usableWidth -= (xDigits + yDigits) * 10;
1679 usableWidth -= decimal_places * 10;
1680 if (draw_legend) {
1681 usableWidth -= 40;
1682 }
1683 var hscale = usableWidth / srcWidth;
1684 var vscale = screenHeight / srcHeight;
1685 scale = Math.min(hscale, vscale);
1686 var invScale = 1 / scale;
1687 var sxmin = x0 - invScale * 5;
1688 var symin = y0 - invScale * 10;
1689 var sxmax = x1 + invScale * (6 * decimal_places + 10);
1690 var symax = y1 + invScale * 10;
1691 srcWidth = sxmax - sxmin;
1692 srcHeight = symax - symin;
1693 hscale = usableWidth / srcWidth;
1694 vscale = screenHeight / srcHeight;
1695 scale = Math.min(hscale, vscale);
1696 srcLeft = sxmin;
1697 srcTop = symin;
1698}
1699
1700function drawArc(curve, op, from, to) {
1701 var type = PATH_LINE + (curve.length / 2 - 2);
1702 var pt = pointAtT(curve, type, op ? 0.4 : 0.6);
1703 var dy = pt.y - curve[1];
1704 var dx = pt.x - curve[0];
1705 var dist = Math.sqrt(dy * dy + dx * dx);
1706 var _dist = dist * scale;
1707 var angle = Math.atan2(dy, dx);
1708 var _px = (curve[0] - srcLeft) * scale;
1709 var _py = (curve[1] - srcTop) * scale;
1710 var divisor = 4;
1711 var endDist;
1712 do {
1713 var ends = [];
1714 for (var index = -1; index <= 1; index += 2) {
1715 var px = Math.cos(index * Math.PI / divisor);
1716 var py = Math.sin(index * Math.PI / divisor);
1717 ends.push(px);
1718 ends.push(py);
1719 }
1720 var endDx = (ends[2] - ends[0]) * scale * dist;
1721 var endDy = (ends[3] - ends[1]) * scale * dist;
1722 endDist = Math.sqrt(endDx * endDx + endDy * endDy);
1723 if (endDist < 100) {
1724 break;
1725 }
1726 divisor *= 2;
1727 } while (true);
1728 if (endDist < 30) {
1729 return;
1730 }
1731 if (op) {
1732 divisor *= 2;
1733 }
1734 ctx.strokeStyle = op ? "rgba(210,0,45, 0.4)" : "rgba(90,90,90, 0.5)";
1735 ctx.beginPath();
1736 ctx.arc(_px, _py, _dist, angle - Math.PI / divisor, angle + Math.PI / divisor, false);
1737 ctx.stroke();
1738 var saveAlign = ctx.textAlign;
1739 var saveStyle = ctx.fillStyle;
1740 var saveFont = ctx.font;
1741 ctx.textAlign = "center";
1742 ctx.fillStyle = "black";
1743 ctx.font = "normal 24px Arial";
1744 divisor *= 0.8;
1745 for (var index = -1; index <= 1; index += 2) {
1746 var px = curve[0] + Math.cos(angle + index * Math.PI / divisor) * dist;
1747 var py = curve[1] + Math.sin(angle + index * Math.PI / divisor) * dist;
1748 var _px = (px - srcLeft) * scale;
1749 var _py = (py - srcTop) * scale;
1750 ctx.fillText(index < 0 ? to.toString() : from.toString(), _px, _py + 8);
1751 }
1752 ctx.textAlign = saveAlign;
1753 ctx.fillStyle = saveStyle;
1754 ctx.font = saveFont;
1755}
1756
1757function drawPoint(px, py, end) {
caryclark1049f122015-04-20 08:31:59 -07001758 var length = drawnPts.length == 7 ? 6 : drawnPts.length;
1759 for (var pts = 0; pts < length; pts += 2) {
caryclarkdac1d172014-06-17 05:15:38 -07001760 var x = drawnPts[pts];
1761 var y = drawnPts[pts + 1];
1762 if (px == x && py == y) {
1763 return;
1764 }
1765 }
1766 drawnPts.push(px);
1767 drawnPts.push(py);
1768 var label = px.toFixed(decimal_places) + ", " + py.toFixed(decimal_places);
1769 var _px = (px - srcLeft) * scale;
1770 var _py = (py - srcTop) * scale;
1771 ctx.beginPath();
1772 ctx.arc(_px, _py, 3, 0, Math.PI*2, true);
1773 ctx.closePath();
1774 if (end) {
1775 ctx.fill();
1776 } else {
1777 ctx.stroke();
1778 }
1779 if (debug_xy) {
1780 ctx.textAlign = "left";
1781 ctx.fillText(label, _px + 5, _py);
1782 }
1783}
1784
caryclark1049f122015-04-20 08:31:59 -07001785function coordCount(curveType) {
1786 switch (curveType) {
1787 case PATH_LINE:
1788 return 4;
1789 case PATH_QUAD:
1790 return 6;
1791 case PATH_CONIC:
1792 return 6;
1793 case PATH_CUBIC:
1794 return 8;
1795 }
1796 return -1;
1797}
1798
caryclarkdac1d172014-06-17 05:15:38 -07001799function drawPoints(ptArray, curveType, drawControls) {
caryclark1049f122015-04-20 08:31:59 -07001800 var count = coordCount(curveType);
caryclarkdac1d172014-06-17 05:15:38 -07001801 for (var idx = 0; idx < count; idx += 2) {
1802 if (!drawControls && idx != 0 && idx != count - 2) {
1803 continue;
1804 }
1805 drawPoint(ptArray[idx], ptArray[idx + 1], idx == 0 || idx == count - 2);
1806 }
1807}
1808
1809function drawControlLines(curve, curveType, drawEnd) {
1810 if (curveType == PATH_LINE) {
1811 return;
1812 }
1813 ctx.strokeStyle = "rgba(0,0,0, 0.3)";
1814 drawLine(curve[0], curve[1], curve[2], curve[3]);
1815 drawLine(curve[2], curve[3], curve[4], curve[5]);
1816 if (curveType == PATH_CUBIC) {
1817 drawLine(curve[4], curve[5], curve[6], curve[7]);
1818 if (drawEnd > 1) {
1819 drawLine(curve[6], curve[7], curve[0], curve[1]);
1820 if (drawEnd > 2) {
1821 drawLine(curve[0], curve[1], curve[4], curve[5]);
1822 drawLine(curve[6], curve[7], curve[2], curve[3]);
1823 }
1824 }
1825 } else if (drawEnd > 1) {
1826 drawLine(curve[4], curve[5], curve[0], curve[1]);
1827 }
1828}
1829
1830function pointAtT(curve, curveType, t) {
1831 var xy = {};
1832 switch (curveType) {
1833 case PATH_LINE:
1834 var a = 1 - t;
1835 var b = t;
1836 xy.x = a * curve[0] + b * curve[2];
1837 xy.y = a * curve[1] + b * curve[3];
1838 break;
1839 case PATH_QUAD:
1840 var one_t = 1 - t;
1841 var a = one_t * one_t;
1842 var b = 2 * one_t * t;
1843 var c = t * t;
1844 xy.x = a * curve[0] + b * curve[2] + c * curve[4];
1845 xy.y = a * curve[1] + b * curve[3] + c * curve[5];
1846 break;
caryclark1049f122015-04-20 08:31:59 -07001847 case PATH_CONIC:
1848 var one_t = 1 - t;
1849 var a = one_t * one_t;
1850 var b = 2 * one_t * t;
1851 var c = t * t;
1852 xy.x = a * curve[0] + b * curve[2] * curve[6] + c * curve[4];
1853 xy.y = a * curve[1] + b * curve[3] * curve[6] + c * curve[5];
1854 var d = a + b * curve[6] + c;
1855 xy.x /= d;
1856 xy.y /= d;
1857 break;
caryclarkdac1d172014-06-17 05:15:38 -07001858 case PATH_CUBIC:
1859 var one_t = 1 - t;
1860 var one_t2 = one_t * one_t;
1861 var a = one_t2 * one_t;
1862 var b = 3 * one_t2 * t;
1863 var t2 = t * t;
1864 var c = 3 * one_t * t2;
1865 var d = t2 * t;
1866 xy.x = a * curve[0] + b * curve[2] + c * curve[4] + d * curve[6];
1867 xy.y = a * curve[1] + b * curve[3] + c * curve[5] + d * curve[7];
1868 break;
1869 }
1870 return xy;
1871}
caryclark55888e42016-07-18 10:01:36 -07001872
caryclarkdac1d172014-06-17 05:15:38 -07001873function drawPointAtT(curve, curveType) {
1874 var x, y;
1875 var xy = pointAtT(curve, curveType, curveT);
1876 drawPoint(xy.x, xy.y, true);
1877 if (!draw_intersectT) {
1878 return;
1879 }
1880 ctx.fillStyle = "red";
1881 drawTAtPointUp(xy.x, xy.y, curveT);
1882}
1883
1884function drawTAtPointUp(px, py, t) {
1885 var label = t.toFixed(decimal_places);
1886 var _px = (px - srcLeft)* scale;
1887 var _py = (py - srcTop) * scale;
1888 ctx.fillText(label, _px + 5, _py - 10);
1889}
1890
1891function drawTAtPointDown(px, py, t) {
1892 var label = t.toFixed(decimal_places);
1893 var _px = (px - srcLeft)* scale;
1894 var _py = (py - srcTop) * scale;
1895 ctx.fillText(label, _px + 5, _py + 10);
1896}
1897
1898function alreadyDrawnLine(x1, y1, x2, y2) {
1899 if (collect_bounds) {
1900 if (focus_enabled) {
1901 focusXmin = Math.min(focusXmin, x1, x2);
1902 focusYmin = Math.min(focusYmin, y1, y2);
1903 focusXmax = Math.max(focusXmax, x1, x2);
1904 focusYmax = Math.max(focusYmax, y1, y2);
1905 }
1906 return true;
1907 }
1908 for (var pts = 0; pts < drawnLines.length; pts += 4) {
1909 if (x1 == drawnLines[pts] && y1 == drawnLines[pts + 1]
1910 && x2 == drawnLines[pts + 2] && y2 == drawnLines[pts + 3]) {
1911 return true;
1912 }
1913 }
1914 drawnLines.push(x1);
1915 drawnLines.push(y1);
1916 drawnLines.push(x2);
1917 drawnLines.push(y2);
1918 return false;
1919}
1920
1921function drawLine(x1, y1, x2, y2) {
1922 if (alreadyDrawnLine(x1, y1, x2, y2)) {
1923 return;
1924 }
1925 ctx.beginPath();
1926 ctx.moveTo((x1 - srcLeft) * scale,
1927 (y1 - srcTop) * scale);
1928 ctx.lineTo((x2 - srcLeft) * scale,
1929 (y2 - srcTop) * scale);
1930 ctx.stroke();
1931}
1932
1933function linePartial(x1, y1, x2, y2, t1, t2) {
1934 var dx = x1 - x2;
1935 var dy = y1 - y2;
1936 var array = [
1937 x1 - t1 * dx,
1938 y1 - t1 * dy,
1939 x1 - t2 * dx,
1940 y1 - t2 * dy
1941 ];
1942 return array;
1943}
1944
1945function drawLinePartial(x1, y1, x2, y2, t1, t2) {
1946 var a = linePartial(x1, y1, x2, y2, t1, t2);
1947 var ax = a[0];
1948 var ay = a[1];
1949 var bx = a[2];
1950 var by = a[3];
1951 if (alreadyDrawnLine(ax, ay, bx, by)) {
1952 return;
1953 }
1954 ctx.beginPath();
1955 ctx.moveTo((ax - srcLeft) * scale,
1956 (ay - srcTop) * scale);
1957 ctx.lineTo((bx - srcLeft) * scale,
1958 (by - srcTop) * scale);
1959 ctx.stroke();
1960}
1961
1962function alreadyDrawnQuad(x1, y1, x2, y2, x3, y3) {
1963 if (collect_bounds) {
1964 if (focus_enabled) {
1965 focusXmin = Math.min(focusXmin, x1, x2, x3);
1966 focusYmin = Math.min(focusYmin, y1, y2, y3);
1967 focusXmax = Math.max(focusXmax, x1, x2, x3);
1968 focusYmax = Math.max(focusYmax, y1, y2, y3);
1969 }
1970 return true;
1971 }
1972 for (var pts = 0; pts < drawnQuads.length; pts += 6) {
1973 if (x1 == drawnQuads[pts] && y1 == drawnQuads[pts + 1]
1974 && x2 == drawnQuads[pts + 2] && y2 == drawnQuads[pts + 3]
1975 && x3 == drawnQuads[pts + 4] && y3 == drawnQuads[pts + 5]) {
1976 return true;
1977 }
1978 }
1979 drawnQuads.push(x1);
1980 drawnQuads.push(y1);
1981 drawnQuads.push(x2);
1982 drawnQuads.push(y2);
1983 drawnQuads.push(x3);
1984 drawnQuads.push(y3);
1985 return false;
1986}
1987
1988function drawQuad(x1, y1, x2, y2, x3, y3) {
1989 if (alreadyDrawnQuad(x1, y1, x2, y2, x3, y3)) {
1990 return;
1991 }
1992 ctx.beginPath();
1993 ctx.moveTo((x1 - srcLeft) * scale,
1994 (y1 - srcTop) * scale);
1995 ctx.quadraticCurveTo((x2 - srcLeft) * scale,
1996 (y2 - srcTop) * scale,
1997 (x3 - srcLeft) * scale,
1998 (y3 - srcTop) * scale);
1999 ctx.stroke();
2000}
2001
2002function interp(A, B, t) {
2003 return A + (B - A) * t;
2004}
2005
2006function interp_quad_coords(x1, x2, x3, t)
2007{
2008 var ab = interp(x1, x2, t);
2009 var bc = interp(x2, x3, t);
2010 var abc = interp(ab, bc, t);
2011 return abc;
2012}
2013
2014function quadPartial(x1, y1, x2, y2, x3, y3, t1, t2) {
2015 var ax = interp_quad_coords(x1, x2, x3, t1);
2016 var ay = interp_quad_coords(y1, y2, y3, t1);
2017 var dx = interp_quad_coords(x1, x2, x3, (t1 + t2) / 2);
2018 var dy = interp_quad_coords(y1, y2, y3, (t1 + t2) / 2);
2019 var cx = interp_quad_coords(x1, x2, x3, t2);
2020 var cy = interp_quad_coords(y1, y2, y3, t2);
2021 var bx = 2*dx - (ax + cx)/2;
2022 var by = 2*dy - (ay + cy)/2;
2023 var array = [
2024 ax, ay, bx, by, cx, cy
2025 ];
2026 return array;
2027}
2028
2029function drawQuadPartial(x1, y1, x2, y2, x3, y3, t1, t2) {
2030 var a = quadPartial(x1, y1, x2, y2, x3, y3, t1, t2);
2031 var ax = a[0];
2032 var ay = a[1];
2033 var bx = a[2];
2034 var by = a[3];
2035 var cx = a[4];
2036 var cy = a[5];
2037 if (alreadyDrawnQuad(ax, ay, bx, by, cx, cy)) {
2038 return;
2039 }
2040 ctx.beginPath();
2041 ctx.moveTo((ax - srcLeft) * scale,
2042 (ay - srcTop) * scale);
2043 ctx.quadraticCurveTo((bx - srcLeft) * scale,
2044 (by - srcTop) * scale,
2045 (cx - srcLeft) * scale,
2046 (cy - srcTop) * scale);
2047 ctx.stroke();
2048}
2049
caryclark1049f122015-04-20 08:31:59 -07002050function alreadyDrawnConic(x1, y1, x2, y2, x3, y3, w) {
2051 if (collect_bounds) {
2052 if (focus_enabled) {
2053 focusXmin = Math.min(focusXmin, x1, x2, x3);
2054 focusYmin = Math.min(focusYmin, y1, y2, y3);
2055 focusXmax = Math.max(focusXmax, x1, x2, x3);
2056 focusYmax = Math.max(focusYmax, y1, y2, y3);
2057 }
2058 return true;
2059 }
2060 for (var pts = 0; pts < drawnConics.length; pts += 8) {
2061 if (x1 == drawnConics[pts] && y1 == drawnCubics[pts + 1]
caryclark55888e42016-07-18 10:01:36 -07002062 && x2 == drawnCubics[pts + 2] && y2 == drawnCubics[pts + 3]
2063 && x3 == drawnCubics[pts + 4] && y3 == drawnCubics[pts + 5]
caryclark1049f122015-04-20 08:31:59 -07002064 && w == drawnCubics[pts + 6]) {
2065 return true;
2066 }
2067 }
2068 drawnConics.push(x1);
2069 drawnConics.push(y1);
2070 drawnConics.push(x2);
2071 drawnConics.push(y2);
2072 drawnConics.push(x3);
2073 drawnConics.push(y3);
2074 drawnCubics.push(w);
2075 return false;
2076}
2077
2078var kMaxConicToQuadPOW2 = 5;
2079
2080function computeQuadPOW2(curve, tol) {
2081 var a = curve[6] - 1;
2082 var k = a / (4 * (2 + a));
2083 var x = k * (curve[0] - 2 * curve[2] + curve[4]);
2084 var y = k * (curve[1] - 2 * curve[3] + curve[5]);
2085
2086 var error = Math.sqrt(x * x + y * y);
2087 var pow2;
2088 for (pow2 = 0; pow2 < kMaxConicToQuadPOW2; ++pow2) {
2089 if (error <= tol) {
2090 break;
2091 }
2092 error *= 0.25;
2093 }
2094 return pow2;
2095}
2096
2097function subdivide_w_value(w) {
2098 return Math.sqrt(0.5 + w * 0.5);
2099}
2100
2101function chop(curve, part1, part2) {
2102 var w = curve[6];
2103 var scale = 1 / (1 + w);
2104 part1[0] = curve[0];
2105 part1[1] = curve[1];
2106 part1[2] = (curve[0] + curve[2] * w) * scale;
2107 part1[3] = (curve[1] + curve[3] * w) * scale;
2108 part1[4] = part2[0] = (curve[0] + (curve[2] * w) * 2 + curve[4]) * scale * 0.5;
2109 part1[5] = part2[1] = (curve[1] + (curve[3] * w) * 2 + curve[5]) * scale * 0.5;
2110 part2[2] = (curve[2] * w + curve[4]) * scale;
2111 part2[3] = (curve[3] * w + curve[5]) * scale;
2112 part2[4] = curve[4];
2113 part2[5] = curve[5];
2114 part1[6] = part2[6] = subdivide_w_value(w);
2115}
2116
2117function subdivide(curve, level, pts) {
2118 if (0 == level) {
2119 pts.push(curve[2]);
2120 pts.push(curve[3]);
2121 pts.push(curve[4]);
2122 pts.push(curve[5]);
2123 } else {
2124 var part1 = [], part2 = [];
2125 chop(curve, part1, part2);
2126 --level;
2127 subdivide(part1, level, pts);
2128 subdivide(part2, level, pts);
2129 }
2130}
2131
2132function chopIntoQuadsPOW2(curve, pow2, pts) {
2133 subdivide(curve, pow2, pts);
2134 return 1 << pow2;
2135}
2136
2137function drawConicWithQuads(x1, y1, x2, y2, x3, y3, w) {
2138 if (alreadyDrawnConic(x1, y1, x2, y2, x3, y3, w)) {
2139 return;
2140 }
2141 ctx.beginPath();
2142 ctx.moveTo((x1 - srcLeft) * scale,
2143 (y1 - srcTop) * scale);
2144 var tol = 1 / scale;
2145 var curve = [x1, y1, x2, y2, x3, y3, w];
2146 var pow2 = computeQuadPOW2(curve, tol);
2147 var pts = [];
2148 chopIntoQuadsPOW2(curve, pow2, pts);
2149 for (var i = 0; i < pts.length; i += 4) {
2150 ctx.quadraticCurveTo(
2151 (pts[i + 0] - srcLeft) * scale, (pts[i + 1] - srcTop) * scale,
2152 (pts[i + 2] - srcLeft) * scale, (pts[i + 3] - srcTop) * scale);
2153 }
2154 ctx.stroke();
2155}
2156
2157function conic_eval_numerator(x1, x2, x3, w, t) {
2158 var src2w = x2 * w;
2159 var C = x1;
2160 var A = x3 - 2 * src2w + C;
2161 var B = 2 * (src2w - C);
2162 return (A * t + B) * t + C;
2163}
2164
2165
2166function conic_eval_denominator(w, t) {
2167 var B = 2 * (w - 1);
2168 var C = 1;
2169 var A = -B;
2170 return (A * t + B) * t + C;
2171}
2172
2173function conicPartial(x1, y1, x2, y2, x3, y3, w, t1, t2) {
2174 var ax = conic_eval_numerator(x1, x2, x3, w, t1);
2175 var ay = conic_eval_numerator(y1, y2, y3, w, t1);
2176 var az = conic_eval_denominator(w, t1);
2177 var midT = (t1 + t2) / 2;
2178 var dx = conic_eval_numerator(x1, x2, x3, w, midT);
2179 var dy = conic_eval_numerator(y1, y2, y3, w, midT);
2180 var dz = conic_eval_denominator(w, midT);
2181 var cx = conic_eval_numerator(x1, x2, x3, w, t2);
2182 var cy = conic_eval_numerator(y1, y2, y3, w, t2);
2183 var cz = conic_eval_denominator(w, t2);
2184 var bx = 2 * dx - (ax + cx) / 2;
2185 var by = 2 * dy - (ay + cy) / 2;
2186 var bz = 2 * dz - (az + cz) / 2;
2187 var dt = t2 - t1;
2188 var dt_1 = 1 - dt;
caryclark1049f122015-04-20 08:31:59 -07002189 var array = [
caryclarked0935a2015-10-22 07:23:52 -07002190 ax / az, ay / az, bx / bz, by / bz, cx / cz, cy / cz, 0
caryclark1049f122015-04-20 08:31:59 -07002191 ];
caryclarked0935a2015-10-22 07:23:52 -07002192 var dMidAC = { x:(array[0] + array[4]) / 2, y:(array[1] + array[5]) / 2 };
2193 var dMid = { x:dx / dz, y:dy / dz };
2194 var dWNumer = { x:dMidAC.x - dMid.x, y:dMidAC.y - dMid.y };
2195 var dWDenom = { x:dMid.x - array[2], y:dMid.y - array[3] };
2196 var partW = Math.sqrt(dWNumer.x * dWNumer.x + dWNumer.y * dWNumer.y)
2197 / Math.sqrt(dWDenom.x * dWDenom.x + dWDenom.y * dWDenom.y);
2198 array[6] = partW;
caryclark1049f122015-04-20 08:31:59 -07002199 return array;
2200}
caryclark55888e42016-07-18 10:01:36 -07002201
caryclark1049f122015-04-20 08:31:59 -07002202function drawConicPartial(x1, y1, x2, y2, x3, y3, w, t1, t2) {
2203 var a = conicPartial(x1, y1, x2, y2, x3, y3, w, t1, t2);
2204 var ax = a[0];
2205 var ay = a[1];
2206 var bx = a[2];
2207 var by = a[3];
2208 var cx = a[4];
2209 var cy = a[5];
2210 var w_ = a[6];
2211 drawConicWithQuads(ax, ay, bx, by, cx, cy, w_);
2212}
2213
caryclarkdac1d172014-06-17 05:15:38 -07002214function alreadyDrawnCubic(x1, y1, x2, y2, x3, y3, x4, y4) {
2215 if (collect_bounds) {
2216 if (focus_enabled) {
2217 focusXmin = Math.min(focusXmin, x1, x2, x3, x4);
2218 focusYmin = Math.min(focusYmin, y1, y2, y3, y4);
2219 focusXmax = Math.max(focusXmax, x1, x2, x3, x4);
2220 focusYmax = Math.max(focusYmax, y1, y2, y3, y4);
2221 }
2222 return true;
2223 }
2224 for (var pts = 0; pts < drawnCubics.length; pts += 8) {
2225 if (x1 == drawnCubics[pts] && y1 == drawnCubics[pts + 1]
caryclark55888e42016-07-18 10:01:36 -07002226 && x2 == drawnCubics[pts + 2] && y2 == drawnCubics[pts + 3]
2227 && x3 == drawnCubics[pts + 4] && y3 == drawnCubics[pts + 5]
caryclarkdac1d172014-06-17 05:15:38 -07002228 && x4 == drawnCubics[pts + 6] && y4 == drawnCubics[pts + 7]) {
2229 return true;
2230 }
2231 }
2232 drawnCubics.push(x1);
2233 drawnCubics.push(y1);
2234 drawnCubics.push(x2);
2235 drawnCubics.push(y2);
2236 drawnCubics.push(x3);
2237 drawnCubics.push(y3);
2238 drawnCubics.push(x4);
2239 drawnCubics.push(y4);
2240 return false;
2241}
2242
2243function drawCubic(x1, y1, x2, y2, x3, y3, x4, y4) {
2244 if (alreadyDrawnCubic(x1, y1, x2, y2, x3, y3, x4, y4)) {
2245 return;
2246 }
2247 ctx.beginPath();
2248 ctx.moveTo((x1 - srcLeft) * scale,
2249 (y1 - srcTop) * scale);
2250 ctx.bezierCurveTo((x2 - srcLeft) * scale,
2251 (y2 - srcTop) * scale,
2252 (x3 - srcLeft) * scale,
2253 (y3 - srcTop) * scale,
2254 (x4 - srcLeft) * scale,
2255 (y4 - srcTop) * scale);
2256 ctx.stroke();
2257}
2258
2259function interp_cubic_coords(x1, x2, x3, x4, t)
2260{
2261 var ab = interp(x1, x2, t);
2262 var bc = interp(x2, x3, t);
2263 var cd = interp(x3, x4, t);
2264 var abc = interp(ab, bc, t);
2265 var bcd = interp(bc, cd, t);
2266 var abcd = interp(abc, bcd, t);
2267 return abcd;
2268}
2269
2270function cubicPartial(x1, y1, x2, y2, x3, y3, x4, y4, t1, t2) {
2271 var ax = interp_cubic_coords(x1, x2, x3, x4, t1);
2272 var ay = interp_cubic_coords(y1, y2, y3, y4, t1);
2273 var ex = interp_cubic_coords(x1, x2, x3, x4, (t1*2+t2)/3);
2274 var ey = interp_cubic_coords(y1, y2, y3, y4, (t1*2+t2)/3);
2275 var fx = interp_cubic_coords(x1, x2, x3, x4, (t1+t2*2)/3);
2276 var fy = interp_cubic_coords(y1, y2, y3, y4, (t1+t2*2)/3);
2277 var dx = interp_cubic_coords(x1, x2, x3, x4, t2);
2278 var dy = interp_cubic_coords(y1, y2, y3, y4, t2);
2279 var mx = ex * 27 - ax * 8 - dx;
2280 var my = ey * 27 - ay * 8 - dy;
2281 var nx = fx * 27 - ax - dx * 8;
2282 var ny = fy * 27 - ay - dy * 8;
2283 var bx = (mx * 2 - nx) / 18;
2284 var by = (my * 2 - ny) / 18;
2285 var cx = (nx * 2 - mx) / 18;
2286 var cy = (ny * 2 - my) / 18;
2287 var array = [
2288 ax, ay, bx, by, cx, cy, dx, dy
2289 ];
2290 return array;
2291}
caryclark55888e42016-07-18 10:01:36 -07002292
caryclarkdac1d172014-06-17 05:15:38 -07002293function drawCubicPartial(x1, y1, x2, y2, x3, y3, x4, y4, t1, t2) {
2294 var a = cubicPartial(x1, y1, x2, y2, x3, y3, x4, y4, t1, t2);
2295 var ax = a[0];
2296 var ay = a[1];
2297 var bx = a[2];
2298 var by = a[3];
2299 var cx = a[4];
2300 var cy = a[5];
2301 var dx = a[6];
2302 var dy = a[7];
2303 if (alreadyDrawnCubic(ax, ay, bx, by, cx, cy, dx, dy)) {
2304 return;
2305 }
2306 ctx.beginPath();
2307 ctx.moveTo((ax - srcLeft) * scale,
2308 (ay - srcTop) * scale);
2309 ctx.bezierCurveTo((bx - srcLeft) * scale,
2310 (by - srcTop) * scale,
2311 (cx - srcLeft) * scale,
2312 (cy - srcTop) * scale,
2313 (dx - srcLeft) * scale,
2314 (dy - srcTop) * scale);
2315 ctx.stroke();
2316}
2317
2318function drawCurve(c) {
2319 switch (c.length) {
2320 case 4:
2321 drawLine(c[0], c[1], c[2], c[3]);
2322 break;
2323 case 6:
2324 drawQuad(c[0], c[1], c[2], c[3], c[4], c[5]);
2325 break;
caryclark1049f122015-04-20 08:31:59 -07002326 case 7:
2327 drawConicWithQuads(c[0], c[1], c[2], c[3], c[4], c[5], c[6]);
2328 break;
caryclarkdac1d172014-06-17 05:15:38 -07002329 case 8:
2330 drawCubic(c[0], c[1], c[2], c[3], c[4], c[5], c[6], c[7]);
2331 break;
2332 }
2333}
2334
2335function boundsWidth(pts) {
2336 var min = pts[0];
2337 var max = pts[0];
caryclark1049f122015-04-20 08:31:59 -07002338 var length = pts.length == 7 ? 6 : pts.length;
2339 for (var idx = 2; idx < length; idx += 2) {
caryclarkdac1d172014-06-17 05:15:38 -07002340 min = Math.min(min, pts[idx]);
2341 max = Math.max(max, pts[idx]);
2342 }
2343 return max - min;
2344}
2345
2346function boundsHeight(pts) {
2347 var min = pts[1];
2348 var max = pts[1];
caryclark1049f122015-04-20 08:31:59 -07002349 var length = pts.length == 7 ? 6 : pts.length;
2350 for (var idx = 3; idx < length; idx += 2) {
caryclarkdac1d172014-06-17 05:15:38 -07002351 min = Math.min(min, pts[idx]);
2352 max = Math.max(max, pts[idx]);
2353 }
2354 return max - min;
2355}
2356
2357function tangent(pts) {
2358 var dx = pts[2] - pts[0];
2359 var dy = pts[3] - pts[1];
2360 if (dx == 0 && dy == 0 && pts.length > 4) {
2361 dx = pts[4] - pts[0];
2362 dy = pts[5] - pts[1];
caryclark1049f122015-04-20 08:31:59 -07002363 if (dx == 0 && dy == 0 && pts.length == 8) {
caryclarkdac1d172014-06-17 05:15:38 -07002364 dx = pts[6] - pts[0];
2365 dy = pts[7] - pts[1];
2366 }
2367 }
2368 return Math.atan2(-dy, dx);
2369}
2370
2371function hodograph(cubic) {
2372 var hodo = [];
2373 hodo[0] = 3 * (cubic[2] - cubic[0]);
2374 hodo[1] = 3 * (cubic[3] - cubic[1]);
2375 hodo[2] = 3 * (cubic[4] - cubic[2]);
2376 hodo[3] = 3 * (cubic[5] - cubic[3]);
2377 hodo[4] = 3 * (cubic[6] - cubic[4]);
2378 hodo[5] = 3 * (cubic[7] - cubic[5]);
2379 return hodo;
2380}
2381
2382function hodograph2(cubic) {
2383 var quad = hodograph(cubic);
2384 var hodo = [];
2385 hodo[0] = 2 * (quad[2] - quad[0]);
2386 hodo[1] = 2 * (quad[3] - quad[1]);
2387 hodo[2] = 2 * (quad[4] - quad[2]);
2388 hodo[3] = 2 * (quad[5] - quad[3]);
2389 return hodo;
2390}
2391
2392function quadraticRootsReal(A, B, C, s) {
2393 if (A == 0) {
2394 if (B == 0) {
2395 s[0] = 0;
2396 return C == 0;
2397 }
2398 s[0] = -C / B;
2399 return 1;
2400 }
2401 /* normal form: x^2 + px + q = 0 */
2402 var p = B / (2 * A);
2403 var q = C / A;
2404 var p2 = p * p;
2405 if (p2 < q) {
2406 return 0;
2407 }
2408 var sqrt_D = 0;
2409 if (p2 > q) {
2410 sqrt_D = sqrt(p2 - q);
2411 }
2412 s[0] = sqrt_D - p;
2413 s[1] = -sqrt_D - p;
2414 return 1 + s[0] != s[1];
2415}
2416
2417function add_valid_ts(s, realRoots, t) {
2418 var foundRoots = 0;
2419 for (var index = 0; index < realRoots; ++index) {
2420 var tValue = s[index];
2421 if (tValue >= 0 && tValue <= 1) {
2422 for (var idx2 = 0; idx2 < foundRoots; ++idx2) {
2423 if (t[idx2] != tValue) {
2424 t[foundRoots++] = tValue;
2425 }
2426 }
2427 }
2428 }
2429 return foundRoots;
2430}
2431
2432function quadraticRootsValidT(a, b, c, t) {
2433 var s = [];
2434 var realRoots = quadraticRootsReal(A, B, C, s);
2435 var foundRoots = add_valid_ts(s, realRoots, t);
2436 return foundRoots != 0;
2437}
2438
2439function find_cubic_inflections(cubic, tValues) {
2440 var Ax = src[2] - src[0];
2441 var Ay = src[3] - src[1];
2442 var Bx = src[4] - 2 * src[2] + src[0];
2443 var By = src[5] - 2 * src[3] + src[1];
2444 var Cx = src[6] + 3 * (src[2] - src[4]) - src[0];
2445 var Cy = src[7] + 3 * (src[3] - src[5]) - src[1];
2446 return quadraticRootsValidT(Bx * Cy - By * Cx, (Ax * Cy - Ay * Cx),
2447 Ax * By - Ay * Bx, tValues);
2448}
2449
2450function dxy_at_t(curve, type, t) {
2451 var dxy = {};
Cary Clarkff114282016-12-14 11:56:16 -05002452 if (type == PATH_LINE) {
2453 dxy.x = curve[2] - curve[0];
2454 dxy.y = curve[3] - curve[1];
2455 } else if (type == PATH_QUAD) {
caryclarkdac1d172014-06-17 05:15:38 -07002456 var a = t - 1;
2457 var b = 1 - 2 * t;
2458 var c = t;
2459 dxy.x = a * curve[0] + b * curve[2] + c * curve[4];
2460 dxy.y = a * curve[1] + b * curve[3] + c * curve[5];
caryclark1049f122015-04-20 08:31:59 -07002461 } else if (type == PATH_CONIC) {
2462 var p20x = curve[4] - curve[0];
2463 var p20y = curve[5] - curve[1];
2464 var p10xw = (curve[2] - curve[0]) * curve[6];
2465 var p10yw = (curve[3] - curve[1]) * curve[6];
2466 var coeff0x = curve[6] * p20x - p20x;
2467 var coeff0y = curve[6] * p20y - p20y;
2468 var coeff1x = p20x - 2 * p10xw;
2469 var coeff1y = p20y - 2 * p10yw;
2470 dxy.x = t * (t * coeff0x + coeff1x) + p10xw;
2471 dxy.y = t * (t * coeff0y + coeff1y) + p10yw;
caryclarkdac1d172014-06-17 05:15:38 -07002472 } else if (type == PATH_CUBIC) {
2473 var one_t = 1 - t;
2474 var a = curve[0];
2475 var b = curve[2];
2476 var c = curve[4];
2477 var d = curve[6];
2478 dxy.x = 3 * ((b - a) * one_t * one_t + 2 * (c - b) * t * one_t + (d - c) * t * t);
2479 a = curve[1];
2480 b = curve[3];
2481 c = curve[5];
2482 d = curve[7];
2483 dxy.y = 3 * ((b - a) * one_t * one_t + 2 * (c - b) * t * one_t + (d - c) * t * t);
2484 }
2485 return dxy;
2486}
2487
Cary Clarkd2eb5812017-01-18 11:00:57 -05002488function dpt_at_t(curve, t) {
Cary Clarkff114282016-12-14 11:56:16 -05002489 var type = PATH_LINE + (curve.length / 2 - 2);
Cary Clarkd2eb5812017-01-18 11:00:57 -05002490 return dxy_at_t(curve, type, t);
Cary Clarkff114282016-12-14 11:56:16 -05002491}
2492
caryclarkdac1d172014-06-17 05:15:38 -07002493function drawLabel(num, px, py) {
2494 ctx.beginPath();
2495 ctx.arc(px, py, 8, 0, Math.PI*2, true);
2496 ctx.closePath();
2497 ctx.strokeStyle = "rgba(0,0,0, 0.4)";
2498 ctx.lineWidth = num == 0 || num == 3 ? 2 : 1;
2499 ctx.stroke();
2500 ctx.fillStyle = "black";
2501 ctx.font = "normal 10px Arial";
2502 // ctx.rotate(0.001);
2503 ctx.fillText(num, px - 2, py + 3);
2504 // ctx.rotate(-0.001);
2505}
2506
2507function drawLabelX(ymin, num, loc) {
2508 var px = (loc - srcLeft) * scale;
2509 var py = (ymin - srcTop) * scale - 20;
2510 drawLabel(num, px, py);
2511}
2512
2513function drawLabelY(xmin, num, loc) {
2514 var px = (xmin - srcLeft) * scale - 20;
2515 var py = (loc - srcTop) * scale;
2516 drawLabel(num, px, py);
2517}
2518
2519function drawHodoOrigin(hx, hy, hMinX, hMinY, hMaxX, hMaxY) {
2520 ctx.beginPath();
2521 ctx.moveTo(hx, hy - 100);
2522 ctx.lineTo(hx, hy);
2523 ctx.strokeStyle = hMinY < 0 ? "green" : "blue";
2524 ctx.stroke();
2525 ctx.beginPath();
2526 ctx.moveTo(hx, hy);
2527 ctx.lineTo(hx, hy + 100);
2528 ctx.strokeStyle = hMaxY > 0 ? "green" : "blue";
2529 ctx.stroke();
2530 ctx.beginPath();
2531 ctx.moveTo(hx - 100, hy);
2532 ctx.lineTo(hx, hy);
2533 ctx.strokeStyle = hMinX < 0 ? "green" : "blue";
2534 ctx.stroke();
2535 ctx.beginPath();
2536 ctx.moveTo(hx, hy);
2537 ctx.lineTo(hx + 100, hy);
2538 ctx.strokeStyle = hMaxX > 0 ? "green" : "blue";
2539 ctx.stroke();
2540}
2541
2542function scalexy(x, y, mag) {
2543 var length = Math.sqrt(x * x + y * y);
2544 return mag / length;
2545}
2546
caryclark03b03ca2015-04-23 09:13:37 -07002547function drawArrow(x, y, dx, dy, s) {
2548 var dscale = scalexy(dx, dy, 1 / scale * 100 * s);
caryclarkdac1d172014-06-17 05:15:38 -07002549 dx *= dscale;
2550 dy *= dscale;
2551 ctx.beginPath();
2552 ctx.moveTo((x - srcLeft) * scale, (y - srcTop) * scale);
2553 x += dx;
2554 y += dy;
2555 ctx.lineTo((x - srcLeft) * scale, (y - srcTop) * scale);
2556 dx /= 10;
2557 dy /= 10;
2558 ctx.lineTo((x - dy - srcLeft) * scale, (y + dx - srcTop) * scale);
2559 ctx.lineTo((x + dx * 2 - srcLeft) * scale, (y + dy * 2 - srcTop) * scale);
2560 ctx.lineTo((x + dy - srcLeft) * scale, (y - dx - srcTop) * scale);
2561 ctx.lineTo((x - srcLeft) * scale, (y - srcTop) * scale);
2562 ctx.strokeStyle = "rgba(0,75,0, 0.4)";
2563 ctx.stroke();
2564}
2565
2566function x_at_t(curve, t) {
2567 var one_t = 1 - t;
2568 if (curve.length == 4) {
2569 return one_t * curve[0] + t * curve[2];
2570 }
2571 var one_t2 = one_t * one_t;
2572 var t2 = t * t;
2573 if (curve.length == 6) {
2574 return one_t2 * curve[0] + 2 * one_t * t * curve[2] + t2 * curve[4];
2575 }
caryclark1049f122015-04-20 08:31:59 -07002576 if (curve.length == 7) {
2577 return (one_t2 * curve[0] + 2 * one_t * t * curve[2] * curve[6] + t2 * curve[4])
2578 / (one_t2 +2 * one_t * t * curve[6] + t2);
2579 }
caryclarkdac1d172014-06-17 05:15:38 -07002580 var a = one_t2 * one_t;
2581 var b = 3 * one_t2 * t;
2582 var c = 3 * one_t * t2;
2583 var d = t2 * t;
2584 return a * curve[0] + b * curve[2] + c * curve[4] + d * curve[6];
2585}
2586
2587function y_at_t(curve, t) {
2588 var one_t = 1 - t;
2589 if (curve.length == 4) {
2590 return one_t * curve[1] + t * curve[3];
2591 }
2592 var one_t2 = one_t * one_t;
2593 var t2 = t * t;
2594 if (curve.length == 6) {
2595 return one_t2 * curve[1] + 2 * one_t * t * curve[3] + t2 * curve[5];
2596 }
caryclark1049f122015-04-20 08:31:59 -07002597 if (curve.length == 7) {
2598 return (one_t2 * curve[1] + 2 * one_t * t * curve[3] * curve[6] + t2 * curve[5])
2599 / (one_t2 +2 * one_t * t * curve[6] + t2);
2600 }
caryclarkdac1d172014-06-17 05:15:38 -07002601 var a = one_t2 * one_t;
2602 var b = 3 * one_t2 * t;
2603 var c = 3 * one_t * t2;
2604 var d = t2 * t;
2605 return a * curve[1] + b * curve[3] + c * curve[5] + d * curve[7];
2606}
2607
Cary Clarkd2eb5812017-01-18 11:00:57 -05002608function pt_at_t(curve, t) {
2609 var pt = {};
2610 pt.x = x_at_t(curve, t);
2611 pt.y = y_at_t(curve, t);
2612 return pt;
Cary Clarkff114282016-12-14 11:56:16 -05002613}
2614
2615function drawOrder(curve, t, label) {
2616 var px = x_at_t(curve, t);
2617 var py = y_at_t(curve, t);
caryclarkdac1d172014-06-17 05:15:38 -07002618 var _px = (px - srcLeft) * scale;
2619 var _py = (py - srcTop) * scale;
2620 ctx.beginPath();
2621 ctx.arc(_px, _py, 15, 0, Math.PI * 2, true);
2622 ctx.closePath();
2623 ctx.fillStyle = "white";
2624 ctx.fill();
2625 if (label == 'L') {
2626 ctx.strokeStyle = "rgba(255,0,0, 1)";
2627 ctx.fillStyle = "rgba(255,0,0, 1)";
2628 } else {
2629 ctx.strokeStyle = "rgba(0,0,255, 1)";
2630 ctx.fillStyle = "rgba(0,0,255, 1)";
2631 }
2632 ctx.stroke();
2633 ctx.font = "normal 16px Arial";
2634 ctx.textAlign = "center";
2635 ctx.fillText(label, _px, _py + 5);
2636 ctx.font = "normal 10px Arial";
2637}
2638
Cary Clarkd2eb5812017-01-18 11:00:57 -05002639function drawVisibleOrder(curve, label) {
2640 var s = pt_at_t(curve, 0);
2641 var e = pt_at_t(curve, 1);
2642 var sOn = ptOnScreen(s);
2643 var eOn = ptOnScreen(e);
2644 var defaultT = 0.85;
2645 if (sOn && eOn)
2646 return drawOrder(curve, defaultT, label);
2647 if (sOn || eOn) {
2648 if (eOn) {
2649 defaultT = 1 - defaultT;
2650 }
2651 var step = sOn ? -defaultT / 2 : (1 - defaultT) / 2;
2652 var t = defaultT;
2653 var tries = 16;
2654 do {
2655 var mid = pt_at_t(curve, t);
2656 if (ptOnScreen(mid))
2657 return drawOrder(curve, t, label);
2658 t += step;
2659 step /= 2;
2660 } while (--tries > 0);
2661 drawOrder(curve, defaultT, label);
2662 }
2663 // scattershot until we find a visible point
2664 var denom = 2; // visit odd number num / denom to hit unique pts
2665 var tries = 6; // tries 1/2, 1/4, 3/4, 1/8, 3/8, 5/8, 7/8, 1/16 ...
2666 do {
2667 for (var numer = 1; numer < denom; numer += 2) {
2668 var t = numer / denom + 0.1;
2669 if (t >= 1) {
2670 break;
2671 }
2672 var mid = pt_at_t(curve, t);
2673 if (ptOnScreen(mid))
2674 return drawOrder(curve, t, label);
2675 }
2676 denom *= 2;
2677 } while (--tries > 0);
2678 drawOrder(curve, defaultT, label);
Cary Clarkff114282016-12-14 11:56:16 -05002679}
2680
Cary Clarkd2eb5812017-01-18 11:00:57 -05002681function set_length(pt, newLen) {
2682 var len = Math.sqrt(pt.x * pt.x + pt.y * pt.y);
2683 var scale = newLen / len;
2684 var newPt = { x: pt.x * scale, y: pt.y * scale };
2685 return newPt;
Cary Clarkff114282016-12-14 11:56:16 -05002686}
2687
Cary Clarkd2eb5812017-01-18 11:00:57 -05002688function drawDirection(curve, t) {
Cary Clarkff114282016-12-14 11:56:16 -05002689 var d = dpt_at_t(curve, t);
2690 d = set_length(d, 16);
Cary Clarkd2eb5812017-01-18 11:00:57 -05002691 var pt = localToGlobal(pt_at_t(curve, t));
Cary Clarkff114282016-12-14 11:56:16 -05002692 ctx.beginPath();
2693 ctx.moveTo(pt.x - d.y, pt.y + d.x);
2694 ctx.lineTo(pt.x + d.x, pt.y + d.y);
2695 ctx.lineTo(pt.x + d.y, pt.y - d.x);
2696 ctx.strokeStyle = "rgba(0,75,0, 0.4)";
2697 ctx.stroke();
2698}
2699
Cary Clarkd2eb5812017-01-18 11:00:57 -05002700function drawVisibleDirection(curve) {
2701 var s = pt_at_t(curve, 0);
2702 var e = pt_at_t(curve, 1);
2703 var sOn = ptOnScreen(s);
2704 var eOn = ptOnScreen(e);
2705 var defaultT = 0.65;
2706 if (sOn && eOn) {
2707 return drawDirection(curve, defaultT);
2708 }
2709 if (sOn || eOn) {
2710 if (eOn) {
2711 defaultT = 1 - defaultT;
2712 }
2713 var step = sOn ? -defaultT / 2 : (1 - defaultT) / 2;
2714 var t = defaultT;
2715 var tries = 16;
2716 do {
2717 var mid = pt_at_t(curve, t);
2718 if (ptOnScreen(mid))
2719 return drawDirection(curve, t);
2720 t += step;
2721 step /= 2;
2722 } while (--tries > 0);
2723 drawDirection(curve, defaultT);
2724 }
2725 // scattershot until we find a visible point
2726 var denom = 2; // visit odd number num / denom to hit unique pts
2727 var tries = 6; // tries 1/2, 1/4, 3/4, 1/8, 3/8, 5/8, 7/8, 1/16 ...
2728 do {
2729 for (var numer = 1; numer < denom; numer += 2) {
2730 var t = numer / denom + 0.1;
2731 if (t >= 1) {
2732 break;
2733 }
2734 var mid = pt_at_t(curve, t);
2735 if (ptOnScreen(mid))
2736 return drawDirection(curve, t);
2737 }
2738 denom *= 2;
2739 } while (--tries > 0);
2740 drawDirection(curve, defaultT);
Cary Clarkff114282016-12-14 11:56:16 -05002741}
2742
2743function drawID(curve, t, id) {
2744 var px = x_at_t(curve, t);
2745 var py = y_at_t(curve, t);
caryclarkdac1d172014-06-17 05:15:38 -07002746 var _px = (px - srcLeft) * scale;
2747 var _py = (py - srcTop) * scale;
2748 draw_id_at(id, _px, _py);
2749}
2750
Cary Clarkd2eb5812017-01-18 11:00:57 -05002751function localToGlobal(local) {
2752 var global = {};
2753 global.x = (local.x - srcLeft) * scale;
2754 global.y = (local.y - srcTop) * scale;
2755 return global;
Cary Clarkff114282016-12-14 11:56:16 -05002756}
2757
Cary Clarkd2eb5812017-01-18 11:00:57 -05002758function ptOnScreen(local) {
2759 var pt = localToGlobal(local);
2760 return 10 <= pt.x && pt.x <= screenWidth - 10
2761 && 10 <= pt.y && pt.y <= screenHeight - 10;
Cary Clarkff114282016-12-14 11:56:16 -05002762}
2763
Cary Clarkd2eb5812017-01-18 11:00:57 -05002764function drawVisibleID(curve, defaultT, id) {
2765 // determine if either or both ends are visible
2766 var s = pt_at_t(curve, 0);
2767 var e = pt_at_t(curve, 1);
2768 var sOn = ptOnScreen(s);
2769 var eOn = ptOnScreen(e);
2770 if (sOn && eOn)
2771 return drawID(curve, defaultT, id);
2772 if (sOn || eOn) {
2773 var step = sOn ? -defaultT / 2 : (1 - defaultT) / 2;
2774 var t = defaultT;
2775 var tries = 16;
2776 do {
2777 var mid = pt_at_t(curve, t);
2778 if (ptOnScreen(mid))
2779 return drawID(curve, t, id);
2780 t += step;
2781 step /= 2;
2782 } while (--tries > 0);
2783 drawID(curve, defaultT, id);
2784 }
2785 // scattershot until we find a visible point
2786 var denom = 2; // visit odd number num / denom to hit unique pts
2787 var tries = 6; // tries 1/2, 1/4, 3/4, 1/8, 3/8, 5/8, 7/8, 1/16 ...
2788 do {
2789 for (var numer = 1; numer < denom; numer += 2) {
2790 var t = numer / denom;
2791 var mid = pt_at_t(curve, t);
2792 if (ptOnScreen(mid))
2793 return drawID(curve, t, id);
2794 }
2795 denom *= 2;
2796 } while (--tries > 0);
2797 drawID(curve, defaultT, id);
Cary Clarkff114282016-12-14 11:56:16 -05002798}
2799
caryclarkdac1d172014-06-17 05:15:38 -07002800function draw_id_at(id, _px, _py) {
2801 ctx.beginPath();
2802 ctx.arc(_px, _py, 15, 0, Math.PI * 2, true);
2803 ctx.closePath();
2804 ctx.fillStyle = "white";
2805 ctx.fill();
2806 ctx.strokeStyle = "rgba(127,127,0, 1)";
2807 ctx.fillStyle = "rgba(127,127,0, 1)";
2808 ctx.stroke();
2809 ctx.font = "normal 16px Arial";
2810 ctx.textAlign = "center";
2811 ctx.fillText(id, _px, _py + 5);
2812 ctx.font = "normal 10px Arial";
2813}
2814
2815function drawLinePartialID(id, x1, y1, x2, y2, t1, t2) {
2816 var curve = [x1, y1, x2, y2];
2817 drawCurvePartialID(id, curve, t1, t2);
2818}
2819
caryclark55888e42016-07-18 10:01:36 -07002820function drawLineID(id, x1, y1, x2, y2) {
2821 drawLinePartialID(id, x1, y1, x2, y2, 0, 1);
2822}
2823
caryclarkdac1d172014-06-17 05:15:38 -07002824function drawQuadPartialID(id, x1, y1, x2, y2, x3, y3, t1, t2) {
2825 var curve = [x1, y1, x2, y2, x3, y3];
2826 drawCurvePartialID(id, curve, t1, t2);
2827}
2828
caryclark55888e42016-07-18 10:01:36 -07002829function drawQuadID(id, x1, y1, x2, y2, x3, y3) {
2830 drawQuadPartialID(id, x1, y1, x2, y2, x3, y3, 0, 1);
2831}
2832
caryclark1049f122015-04-20 08:31:59 -07002833function drawConicPartialID(id, x1, y1, x2, y2, x3, y3, w, t1, t2) {
2834 var curve = [x1, y1, x2, y2, x3, y3, w];
2835 drawCurvePartialID(id, curve, t1, t2);
2836}
2837
caryclark55888e42016-07-18 10:01:36 -07002838function drawConicID(id, x1, y1, x2, y2, x3, y3, w) {
2839 drawConicPartialID(id, x1, y1, x2, y2, x3, y3, w, 0, 1);
2840}
2841
caryclarkdac1d172014-06-17 05:15:38 -07002842function drawCubicPartialID(id, x1, y1, x2, y2, x3, y3, x4, y4, t1, t2) {
2843 var curve = [x1, y1, x2, y2, x3, y3, x4, y4];
2844 drawCurvePartialID(id, curve, t1, t2);
2845}
2846
caryclark55888e42016-07-18 10:01:36 -07002847function drawCubicID(id, x1, y1, x2, y2, x3, y3, x4, y4) {
2848 drawCubicPartialID(id, x1, y1, x2, y2, x3, y3, x4, y4, 0, 1);
2849}
2850
caryclarkdac1d172014-06-17 05:15:38 -07002851function drawCurvePartialID(id, curve, t1, t2) {
Cary Clarkff114282016-12-14 11:56:16 -05002852 drawVisibleID(curve, (t1 + t2) / 2, id);
caryclarkdac1d172014-06-17 05:15:38 -07002853}
2854
2855function drawCurveSpecials(test, curve, type) {
2856 if (pt_labels) {
2857 drawPoints(curve, type, pt_labels == 2);
2858 }
2859 if (control_lines != 0) {
2860 drawControlLines(curve, type, control_lines);
2861 }
2862 if (curve_t) {
2863 drawPointAtT(curve, type);
2864 }
2865 if (draw_midpoint) {
2866 var mid = pointAtT(curve, type, 0.5);
2867 drawPoint(mid.x, mid.y, true);
2868 }
2869 if (draw_id) {
2870 var id = idByCurve(test, curve, type);
2871 if (id >= 0) {
Cary Clarkff114282016-12-14 11:56:16 -05002872 drawVisibleID(curve, 0.5, id);
caryclarkdac1d172014-06-17 05:15:38 -07002873 }
2874 }
Cary Clarkd2eb5812017-01-18 11:00:57 -05002875 if (draw_direction) {
2876 drawVisibleDirection(curve);
Cary Clarkff114282016-12-14 11:56:16 -05002877 }
caryclarkdac1d172014-06-17 05:15:38 -07002878 if (type == PATH_LINE) {
2879 return;
2880 }
2881 if (draw_deriviatives > 0) {
2882 var d = dxy_at_t(curve, type, 0);
caryclark03b03ca2015-04-23 09:13:37 -07002883 drawArrow(curve[0], curve[1], d.x, d.y, 1);
caryclarkdac1d172014-06-17 05:15:38 -07002884 if (draw_deriviatives == 2) {
2885 d = dxy_at_t(curve, type, 1);
2886 if (type == PATH_CUBIC) {
caryclark03b03ca2015-04-23 09:13:37 -07002887 drawArrow(curve[6], curve[7], d.x, d.y, 1);
caryclarkdac1d172014-06-17 05:15:38 -07002888 } else {
caryclark03b03ca2015-04-23 09:13:37 -07002889 drawArrow(curve[4], curve[5], d.x, d.y, 1);
caryclarkdac1d172014-06-17 05:15:38 -07002890 }
2891 }
2892 if (draw_midpoint) {
2893 var mid = pointAtT(curve, type, 0.5);
2894 d = dxy_at_t(curve, type, 0.5);
caryclark03b03ca2015-04-23 09:13:37 -07002895 drawArrow(mid.x, mid.y, d.x, d.y, 1);
caryclarkdac1d172014-06-17 05:15:38 -07002896 }
2897 }
2898 if (type != PATH_CUBIC) {
2899 return;
2900 }
caryclarkdac1d172014-06-17 05:15:38 -07002901 if (draw_sequence) {
2902 var ymin = Math.min(curve[1], curve[3], curve[5], curve[7]);
2903 for (var i = 0; i < 8; i+= 2) {
2904 drawLabelX(ymin, i >> 1, curve[i]);
2905 }
2906 var xmin = Math.min(curve[0], curve[2], curve[4], curve[6]);
2907 for (var i = 1; i < 8; i+= 2) {
2908 drawLabelY(xmin, i >> 1, curve[i]);
2909 }
2910 }
2911}
2912
2913function logCurves(test) {
2914 for (curves in test) {
2915 var curve = test[curves];
2916 dumpCurve(curve);
2917 }
2918}
2919
2920function curveToString(curve) {
2921 var str = "{{";
caryclark1049f122015-04-20 08:31:59 -07002922 var length = curve.length == 7 ? 6 : curve.length;
2923 if (curve.length == 7) {
2924 str += "{";
2925 }
2926 for (i = 0; i < length; i += 2) {
caryclarkdac1d172014-06-17 05:15:38 -07002927 str += curve[i].toFixed(decimal_places) + "," + curve[i + 1].toFixed(decimal_places);
2928 if (i < curve.length - 2) {
2929 str += "}, {";
2930 }
2931 }
caryclark1049f122015-04-20 08:31:59 -07002932 str += "}";
2933 if (curve.length == 7) {
2934 str += "}, " + curve[6].toFixed(decimal_places);
2935 }
2936 str += "}";
caryclarkdac1d172014-06-17 05:15:38 -07002937 return str;
2938}
2939
2940function dumpCurve(curve) {
2941 console.log(curveToString(curve));
2942}
2943
2944function draw(test, lines, title) {
2945 ctx.fillStyle = "rgba(0,0,0, 0.1)";
2946 ctx.font = "normal 50px Arial";
2947 ctx.textAlign = "left";
2948 ctx.fillText(title, 50, 50);
2949 ctx.font = "normal 10px Arial";
2950 ctx.lineWidth = "1.001"; "0.999";
2951 var secondPath = test.length;
2952 var closeCount = 0;
2953 logStart = -1;
2954 logRange = 0;
2955 // find last active rec type at this step
2956 var curType = test[0];
2957 var curStep = 0;
2958 var hasOp = false;
2959 var lastActive = 0;
2960 var lastAdd = 0;
caryclark624637c2015-05-11 07:21:27 -07002961 var lastCoin = 0;
caryclarkdac1d172014-06-17 05:15:38 -07002962 var lastSect = 0;
2963 var lastSort = 0;
2964 var lastMark = 0;
caryclark03b03ca2015-04-23 09:13:37 -07002965 var lastTop = 0;
caryclarkdac1d172014-06-17 05:15:38 -07002966 activeCount = 0;
2967 addCount = 0;
2968 angleCount = 0;
2969 opCount = 0;
2970 sectCount = 0;
2971 sortCount = 0;
caryclark03b03ca2015-04-23 09:13:37 -07002972 topCount = 0;
caryclarkdac1d172014-06-17 05:15:38 -07002973 markCount = 0;
2974 activeMax = 0;
2975 addMax = 0;
2976 angleMax = 0;
caryclark624637c2015-05-11 07:21:27 -07002977 coinMax = 0;
caryclarkdac1d172014-06-17 05:15:38 -07002978 opMax = 0;
2979 sectMax = 0;
2980 sectMax2 = 0;
2981 sortMax = 0;
caryclark03b03ca2015-04-23 09:13:37 -07002982 topMax = 0;
caryclarkdac1d172014-06-17 05:15:38 -07002983 markMax = 0;
2984 lastIndex = test.length - 3;
2985 for (var tIndex = 0; tIndex < test.length; tIndex += 3) {
2986 var recType = test[tIndex];
2987 if (!typeof recType == 'number' || recType < REC_TYPE_UNKNOWN || recType > REC_TYPE_LAST) {
2988 console.log("unknown rec type: " + recType);
2989 throw "stop execution";
2990 }
2991 // if (curType == recType && curType != REC_TYPE_ADD) {
2992 // continue;
2993 // }
2994 var inStepRange = step_limit == 0 || curStep < step_limit;
2995 curType = recType;
2996 if (recType == REC_TYPE_OP) {
2997 hasOp = true;
2998 continue;
2999 }
3000 if (recType == REC_TYPE_UNKNOWN) {
3001 // these types do not advance step
3002 continue;
3003 }
3004 var bumpStep = false;
3005 var records = test[tIndex + 2];
3006 var fragType = records[0];
3007 if (recType == REC_TYPE_ADD) {
3008 if (records.length != 2) {
3009 console.log("expect only two elements: " + records.length);
3010 throw "stop execution";
3011 }
3012 if (fragType == ADD_MOVETO || fragType == ADD_CLOSE) {
3013 continue;
3014 }
3015 ++addMax;
3016 if (!draw_add || !inStepRange) {
3017 continue;
3018 }
3019 lastAdd = tIndex;
3020 ++addCount;
3021 bumpStep = true;
3022 }
3023 if (recType == REC_TYPE_PATH && hasOp) {
3024 secondPath = tIndex;
3025 }
caryclark54359292015-03-26 07:52:43 -07003026 if (recType == REC_TYPE_PATH2 && hasOp) {
3027 secondPath = tIndex;
3028 }
caryclarkdac1d172014-06-17 05:15:38 -07003029 if (recType == REC_TYPE_ACTIVE) {
3030 ++activeMax;
3031 if (!draw_active || !inStepRange) {
3032 continue;
3033 }
3034 lastActive = tIndex;
3035 ++activeCount;
3036 bumpStep = true;
3037 }
3038 if (recType == REC_TYPE_ACTIVE_OP) {
3039 ++opMax;
3040 if (!draw_op || !inStepRange) {
3041 continue;
3042 }
3043 lastOp = tIndex;
3044 ++opCount;
3045 bumpStep = true;
3046 }
caryclark54359292015-03-26 07:52:43 -07003047 if (recType == REC_TYPE_AFTERPART) {
3048 if (draw_angle != 3 || !inStepRange) {
3049 continue;
3050 }
3051 lastAngle = tIndex;
3052 ++angleCount;
3053 bumpStep = true;
3054 }
caryclarkdac1d172014-06-17 05:15:38 -07003055 if (recType == REC_TYPE_ANGLE) {
3056 ++angleMax;
caryclark54359292015-03-26 07:52:43 -07003057 if (draw_angle == 0 || draw_angle == 3 || !inStepRange) {
caryclarkdac1d172014-06-17 05:15:38 -07003058 continue;
3059 }
3060 lastAngle = tIndex;
3061 ++angleCount;
3062 bumpStep = true;
3063 }
caryclark624637c2015-05-11 07:21:27 -07003064 if (recType == REC_TYPE_COINCIDENCE) {
3065 ++coinMax;
3066 if (!draw_coincidence || !inStepRange) {
3067 continue;
3068 }
3069 lastCoin = tIndex;
3070 ++coinCount;
3071 bumpStep = true;
3072 }
caryclarkdac1d172014-06-17 05:15:38 -07003073 if (recType == REC_TYPE_SECT) {
3074 if (records.length != 2) {
3075 console.log("expect only two elements: " + records.length);
3076 throw "stop execution";
3077 }
3078 ++sectMax;
3079 var sectBump = 1;
3080 switch (fragType) {
3081 case INTERSECT_LINE:
3082 case INTERSECT_QUAD_LINE:
3083 case INTERSECT_QUAD:
caryclark1049f122015-04-20 08:31:59 -07003084 case INTERSECT_CONIC_LINE:
caryclark55888e42016-07-18 10:01:36 -07003085 case INTERSECT_CONIC_QUAD:
caryclark1049f122015-04-20 08:31:59 -07003086 case INTERSECT_CONIC:
caryclarkdac1d172014-06-17 05:15:38 -07003087 case INTERSECT_SELF_CUBIC:
3088 case INTERSECT_CUBIC_LINE:
3089 case INTERSECT_CUBIC_QUAD:
3090 case INTERSECT_CUBIC:
3091 sectBump = 1;
3092 break;
3093 case INTERSECT_LINE_2:
3094 case INTERSECT_QUAD_LINE_2:
3095 case INTERSECT_QUAD_2:
caryclark1049f122015-04-20 08:31:59 -07003096 case INTERSECT_CONIC_LINE_2:
caryclark55888e42016-07-18 10:01:36 -07003097 case INTERSECT_CONIC_QUAD_2:
caryclark1049f122015-04-20 08:31:59 -07003098 case INTERSECT_CONIC_2:
caryclarkdac1d172014-06-17 05:15:38 -07003099 case INTERSECT_CUBIC_LINE_2:
3100 case INTERSECT_CUBIC_QUAD_2:
3101 case INTERSECT_CUBIC_2:
3102 sectBump = 2;
3103 break;
3104 case INTERSECT_LINE_NO:
3105 case INTERSECT_QUAD_LINE_NO:
3106 case INTERSECT_QUAD_NO:
caryclark1049f122015-04-20 08:31:59 -07003107 case INTERSECT_CONIC_LINE_NO:
caryclark55888e42016-07-18 10:01:36 -07003108 case INTERSECT_CONIC_QUAD_NO:
caryclark1049f122015-04-20 08:31:59 -07003109 case INTERSECT_CONIC_NO:
caryclarkdac1d172014-06-17 05:15:38 -07003110 case INTERSECT_SELF_CUBIC_NO:
3111 case INTERSECT_CUBIC_LINE_NO:
3112 case INTERSECT_CUBIC_QUAD_NO:
3113 case INTERSECT_CUBIC_NO:
3114 sectBump = 0;
3115 break;
caryclark6c3b9cd2016-09-26 05:36:58 -07003116 case INTERSECT_CONIC_QUAD_3:
caryclarkdac1d172014-06-17 05:15:38 -07003117 case INTERSECT_CUBIC_LINE_3:
3118 case INTERSECT_CUBIC_QUAD_3:
3119 case INTERSECT_CUBIC_3:
3120 sectBump = 3;
3121 break;
caryclark6c3b9cd2016-09-26 05:36:58 -07003122 case INTERSECT_CONIC_QUAD_4:
caryclarkdac1d172014-06-17 05:15:38 -07003123 case INTERSECT_CUBIC_QUAD_4:
3124 case INTERSECT_CUBIC_4:
3125 sectBump = 4;
3126 break;
3127 default:
3128 console.log("missing case " + records.length);
3129 throw "stop execution";
3130 }
3131 sectMax2 += sectBump;
3132 if (draw_intersection <= 1 || !inStepRange) {
3133 continue;
3134 }
3135 lastSect = tIndex;
3136 sectCount += sectBump;
3137 bumpStep = true;
3138 }
3139 if (recType == REC_TYPE_SORT) {
3140 ++sortMax;
3141 if (!draw_sort || !inStepRange) {
3142 continue;
3143 }
3144 lastSort = tIndex;
3145 ++sortCount;
3146 bumpStep = true;
3147 }
caryclark03b03ca2015-04-23 09:13:37 -07003148 if (recType == REC_TYPE_TOP) {
3149 ++topMax;
3150 if (!draw_top || !inStepRange) {
3151 continue;
3152 }
3153 lastTop = tIndex;
3154 ++topCount;
3155 bumpStep = true;
3156 }
caryclarkdac1d172014-06-17 05:15:38 -07003157 if (recType == REC_TYPE_MARK) {
3158 ++markMax;
3159 if (!draw_mark || !inStepRange) {
3160 continue;
3161 }
3162 lastMark = tIndex;
3163 ++markCount;
3164 bumpStep = true;
3165 }
3166 if (bumpStep) {
3167 lastIndex = tIndex;
3168 logStart = test[tIndex + 1];
3169 logRange = records.length / 2;
3170 ++curStep;
3171 }
3172 }
3173 stepMax = (draw_add ? addMax : 0)
3174 + (draw_active ? activeMax : 0)
reed0dc4dd62015-03-24 13:55:33 -07003175 + (draw_angle ? angleMax : 0)
caryclark624637c2015-05-11 07:21:27 -07003176 + (draw_coincidence ? coinMax : 0)
caryclark54359292015-03-26 07:52:43 -07003177 + (draw_op ? opMax : 0)
caryclarkdac1d172014-06-17 05:15:38 -07003178 + (draw_sort ? sortMax : 0)
caryclark03b03ca2015-04-23 09:13:37 -07003179 + (draw_top ? topMax : 0)
caryclarkdac1d172014-06-17 05:15:38 -07003180 + (draw_mark ? markMax : 0)
3181 + (draw_intersection == 2 ? sectMax : draw_intersection == 3 ? sectMax2 : 0);
3182 if (stepMax == 0) {
caryclark624637c2015-05-11 07:21:27 -07003183 stepMax = addMax + activeMax + angleMax + coinMax + opMax + sortMax + topMax + markMax;
caryclarkdac1d172014-06-17 05:15:38 -07003184 }
3185 drawnPts = [];
3186 drawnLines = [];
3187 drawnQuads = [];
caryclark1049f122015-04-20 08:31:59 -07003188 drawnConics = [];
caryclarkdac1d172014-06-17 05:15:38 -07003189 drawnCubics = [];
3190 focusXmin = focusYmin = Infinity;
3191 focusXmax = focusYmax = -Infinity;
3192 var pathIndex = 0;
3193 var opLetter = 'S';
3194 for (var tIndex = lastIndex; tIndex >= 0; tIndex -= 3) {
3195 var recType = test[tIndex];
3196 var records = test[tIndex + 2];
3197 for (var recordIndex = 0; recordIndex < records.length; recordIndex += 2) {
3198 var fragType = records[recordIndex];
3199 if (!typeof fragType == 'number' || fragType < 1 || fragType > FRAG_TYPE_LAST) {
3200 console.log("unknown in range frag type: " + fragType);
3201 throw "stop execution";
3202 }
3203 var frags = records[recordIndex + 1];
3204 focus_enabled = false;
3205 switch (recType) {
3206 case REC_TYPE_COMPUTED:
3207 if (draw_computed == 0) {
3208 continue;
3209 }
3210 ctx.lineWidth = 1;
3211 ctx.strokeStyle = pathIndex == 0 ? "black" : "red";
3212 ctx.fillStyle = "blue";
3213 var drawThis = false;
3214 switch (fragType) {
3215 case PATH_QUAD:
caryclark1049f122015-04-20 08:31:59 -07003216 if ((draw_computed & 0x9) == 1 || ((draw_computed & 8) != 0
3217 && (draw_computed & 7) == pathIndex)) {
caryclarkdac1d172014-06-17 05:15:38 -07003218 drawQuad(frags[0], frags[1], frags[2], frags[3],
3219 frags[4], frags[5]);
3220 drawThis = true;
3221 }
3222 break;
caryclark1049f122015-04-20 08:31:59 -07003223 case PATH_CONIC:
3224 if ((draw_computed & 0xA) == 2 || ((draw_computed & 8) != 0
3225 && (draw_computed & 7) == pathIndex)) {
3226 drawConicWithQuads(frags[0], frags[1], frags[2], frags[3],
3227 frags[4], frags[5], frags[6]);
3228 drawThis = true;
3229 }
3230 break;
caryclarkdac1d172014-06-17 05:15:38 -07003231 case PATH_CUBIC:
caryclark1049f122015-04-20 08:31:59 -07003232 if ((draw_computed & 0xC) == 4 || ((draw_computed & 8) != 0
3233 && (draw_computed & 7) == pathIndex)) {
caryclarkdac1d172014-06-17 05:15:38 -07003234 drawCubic(frags[0], frags[1], frags[2], frags[3],
3235 frags[4], frags[5], frags[6], frags[7]);
3236 drawThis = true;
3237 }
3238 ++pathIndex;
3239 break;
3240 case COMPUTED_SET_1:
3241 pathIndex = 0;
3242 break;
3243 case COMPUTED_SET_2:
3244 pathIndex = 1;
3245 break;
3246 default:
3247 console.log("unknown REC_TYPE_COMPUTED frag type: " + fragType);
3248 throw "stop execution";
3249 }
3250 if (!drawThis || collect_bounds) {
3251 break;
3252 }
3253 drawCurveSpecials(test, frags, fragType);
3254 break;
caryclark26ad22a2015-10-16 09:03:38 -07003255 case REC_TYPE_ALIGNED:
3256 if (draw_path < 4) {
3257 continue;
3258 }
caryclarkdac1d172014-06-17 05:15:38 -07003259 case REC_TYPE_PATH:
caryclark54359292015-03-26 07:52:43 -07003260 case REC_TYPE_PATH2:
caryclark26ad22a2015-10-16 09:03:38 -07003261 if (REC_TYPE_ALIGNED != recType && draw_path >= 4) {
3262 continue;
3263 }
caryclarkdac1d172014-06-17 05:15:38 -07003264 if (!draw_path) {
3265 continue;
3266 }
3267 var firstPath = tIndex < secondPath;
3268 if ((draw_path & (firstPath ? 1 : 2)) == 0) {
3269 continue;
3270 }
3271 ctx.lineWidth = 1;
3272 ctx.strokeStyle = firstPath ? "black" : "red";
3273 ctx.fillStyle = "blue";
caryclark55888e42016-07-18 10:01:36 -07003274 var frags2 = [];
caryclarkdac1d172014-06-17 05:15:38 -07003275 switch (fragType) {
3276 case PATH_LINE:
caryclark54359292015-03-26 07:52:43 -07003277 for (var i = 0; i < 4; ++ i) { frags2[i] = frags[i + 1]; }
3278 drawLine(frags2[0], frags2[1], frags2[2], frags2[3]);
caryclarkdac1d172014-06-17 05:15:38 -07003279 break;
3280 case PATH_QUAD:
caryclark54359292015-03-26 07:52:43 -07003281 for (var i = 0; i < 6; ++ i) { frags2[i] = frags[i + 1]; }
3282 drawQuad(frags2[0], frags2[1], frags2[2], frags2[3],
3283 frags2[4], frags2[5]);
caryclarkdac1d172014-06-17 05:15:38 -07003284 break;
caryclark1049f122015-04-20 08:31:59 -07003285 case PATH_CONIC:
3286 for (var i = 0; i < 7; ++ i) { frags2[i] = frags[i + 1]; }
3287 drawConicWithQuads(frags2[0], frags2[1], frags2[2], frags2[3],
3288 frags2[4], frags2[5], frags2[6]);
3289 break;
caryclarkdac1d172014-06-17 05:15:38 -07003290 case PATH_CUBIC:
caryclark54359292015-03-26 07:52:43 -07003291 for (var i = 0; i < 8; ++ i) { frags2[i] = frags[i + 1]; }
3292 drawCubic(frags2[0], frags2[1], frags2[2], frags2[3],
3293 frags2[4], frags2[5], frags2[6], frags2[7]);
caryclarkdac1d172014-06-17 05:15:38 -07003294 break;
3295 default:
caryclark26ad22a2015-10-16 09:03:38 -07003296 console.log("unknown " + recType + " frag type: " + fragType);
caryclarkdac1d172014-06-17 05:15:38 -07003297 throw "stop execution";
3298 }
3299 if (collect_bounds) {
3300 break;
3301 }
caryclark54359292015-03-26 07:52:43 -07003302 drawCurveSpecials(test, frags2, fragType);
caryclarkdac1d172014-06-17 05:15:38 -07003303 break;
3304 case REC_TYPE_OP:
3305 switch (fragType) {
3306 case OP_INTERSECT: opLetter = 'I'; break;
3307 case OP_DIFFERENCE: opLetter = 'D'; break;
3308 case OP_UNION: opLetter = 'U'; break;
3309 case OP_XOR: opLetter = 'X'; break;
3310 default:
3311 console.log("unknown REC_TYPE_OP frag type: " + fragType);
3312 throw "stop execution";
3313 }
3314 break;
3315 case REC_TYPE_ACTIVE:
3316 if (!draw_active || (step_limit > 0 && tIndex < lastActive)) {
3317 continue;
3318 }
3319 var x1 = frags[SPAN_X1];
3320 var y1 = frags[SPAN_Y1];
3321 var x2 = frags[SPAN_X2];
3322 var y2 = frags[SPAN_Y2];
caryclark55888e42016-07-18 10:01:36 -07003323 var x3, y3, x3, y4, w;
caryclarkdac1d172014-06-17 05:15:38 -07003324 ctx.lineWidth = 3;
3325 ctx.strokeStyle = "rgba(0,0,255, 0.3)";
3326 focus_enabled = true;
3327 switch (fragType) {
3328 case ACTIVE_LINE_SPAN:
caryclark55888e42016-07-18 10:01:36 -07003329 drawLine(x1, y1, x2, y2);
caryclarkdac1d172014-06-17 05:15:38 -07003330 if (draw_id) {
caryclark55888e42016-07-18 10:01:36 -07003331 drawLineID(frags[0], x1, y1, x2, y2);
3332 }
3333 if (pt_labels) {
3334 var curve = [x1, y1, x2, y2];
3335 ctx.fillStyle = "blue";
3336 drawPoints(curve, PATH_LINE, pt_labels == 2);
caryclarkdac1d172014-06-17 05:15:38 -07003337 }
3338 break;
3339 case ACTIVE_QUAD_SPAN:
3340 x3 = frags[SPAN_X3];
3341 y3 = frags[SPAN_Y3];
caryclark55888e42016-07-18 10:01:36 -07003342 drawQuad(x1, y1, x2, y2, x3, y3);
caryclarkdac1d172014-06-17 05:15:38 -07003343 if (draw_id) {
caryclark55888e42016-07-18 10:01:36 -07003344 drawQuadID(frags[0], x1, y1, x2, y2, x3, y3);
3345 }
3346 if (pt_labels) {
3347 var curve = [x1, y1, x2, y2, x3, y3];
3348 ctx.fillStyle = "blue";
3349 drawPoints(curve, PATH_QUAD, pt_labels == 2);
caryclarkdac1d172014-06-17 05:15:38 -07003350 }
3351 break;
caryclark1049f122015-04-20 08:31:59 -07003352 case ACTIVE_CONIC_SPAN:
3353 x3 = frags[SPAN_X3];
3354 y3 = frags[SPAN_Y3];
caryclark1049f122015-04-20 08:31:59 -07003355 w = frags[SPAN_K_W];
caryclark55888e42016-07-18 10:01:36 -07003356 drawConicWithQuads(x1, y1, x2, y2, x3, y3, w);
caryclark1049f122015-04-20 08:31:59 -07003357 if (draw_id) {
caryclark55888e42016-07-18 10:01:36 -07003358 drawConicID(frags[0], x1, y1, x2, y2, x3, y3, w);
3359 }
3360 if (pt_labels) {
3361 var curve = [x1, y1, x2, y2, x3, y3, w];
3362 ctx.fillStyle = "blue";
3363 drawPoints(curve, PATH_CONIC, pt_labels == 2);
caryclark1049f122015-04-20 08:31:59 -07003364 }
3365 break;
caryclarkdac1d172014-06-17 05:15:38 -07003366 case ACTIVE_CUBIC_SPAN:
3367 x3 = frags[SPAN_X3];
3368 y3 = frags[SPAN_Y3];
3369 x4 = frags[SPAN_X4];
3370 y4 = frags[SPAN_Y4];
caryclark55888e42016-07-18 10:01:36 -07003371 drawCubic(x1, y1, x2, y2, x3, y3, x4, y4);
caryclarkdac1d172014-06-17 05:15:38 -07003372 if (draw_id) {
caryclark55888e42016-07-18 10:01:36 -07003373 drawCubicID(frags[0], x1, y1, x2, y2, x3, y3, x4, y4);
3374 }
3375 if (pt_labels) {
3376 var curve = [x1, y1, x2, y2, x3, y3, x4, y4];
3377 ctx.fillStyle = "blue";
3378 drawPoints(curve, PATH_CUBIC, pt_labels == 2);
caryclarkdac1d172014-06-17 05:15:38 -07003379 }
3380 break;
3381 default:
3382 console.log("unknown REC_TYPE_ACTIVE frag type: " + fragType);
3383 throw "stop execution";
3384 }
3385 break;
3386 case REC_TYPE_ACTIVE_OP:
3387 if (!draw_op || (step_limit > 0 && tIndex < lastOp)) {
3388 continue;
3389 }
3390 focus_enabled = true;
3391 ctx.lineWidth = 3;
3392 var activeSpan = frags[7] == "1";
3393 ctx.strokeStyle = activeSpan ? "rgba(45,160,0, 0.3)" : "rgba(255,45,0, 0.5)";
3394 var curve = curvePartialByID(test, frags[0], frags[1], frags[2]);
3395 drawCurve(curve);
3396 if (draw_op > 1) {
3397 drawArc(curve, false, frags[3], frags[4]);
3398 drawArc(curve, true, frags[5], frags[6]);
3399 }
3400 break;
3401 case REC_TYPE_ADD:
3402 if (!draw_add) {
3403 continue;
3404 }
3405 ctx.lineWidth = 3;
3406 ctx.strokeStyle = closeCount == 0 ? "rgba(0,0,255, 0.3)"
3407 : closeCount == 1 ? "rgba(0,127,0, 0.3)"
3408 : closeCount == 2 ? "rgba(0,127,127, 0.3)"
3409 : closeCount == 3 ? "rgba(127,127,0, 0.3)"
3410 : "rgba(127,0,127, 0.3)";
3411 focus_enabled = true;
3412 switch (fragType) {
3413 case ADD_MOVETO:
3414 break;
3415 case ADD_LINETO:
3416 if (step_limit == 0 || tIndex >= lastAdd) {
3417 drawLine(frags[0], frags[1], frags[2], frags[3]);
3418 }
3419 break;
3420 case ADD_QUADTO:
3421 if (step_limit == 0 || tIndex >= lastAdd) {
3422 drawQuad(frags[0], frags[1], frags[2], frags[3], frags[4], frags[5]);
3423 }
3424 break;
caryclark1049f122015-04-20 08:31:59 -07003425 case ADD_CONICTO:
3426 if (step_limit == 0 || tIndex >= lastAdd) {
3427 drawConicWithQuads(frags[0], frags[1], frags[2], frags[3],
3428 frags[4], frags[5], frags[6]);
3429 }
3430 break;
caryclarkdac1d172014-06-17 05:15:38 -07003431 case ADD_CUBICTO:
3432 if (step_limit == 0 || tIndex >= lastAdd) {
3433 drawCubic(frags[0], frags[1], frags[2], frags[3],
3434 frags[4], frags[5], frags[6], frags[7]);
3435 }
3436 break;
3437 case ADD_CLOSE:
3438 ++closeCount;
3439 break;
3440 case ADD_FILL:
3441 break;
3442 default:
3443 console.log("unknown REC_TYPE_ADD frag type: " + fragType);
3444 throw "stop execution";
3445 }
3446 break;
3447 case REC_TYPE_ANGLE:
caryclark54359292015-03-26 07:52:43 -07003448 angleBetween = frags[18] == "T";
3449 afterIndex = 0;
3450 if (draw_angle == 0 || draw_angle == 3 || (step_limit > 0 && tIndex < lastAngle)) {
caryclarkdac1d172014-06-17 05:15:38 -07003451 continue;
3452 }
3453 focus_enabled = true;
3454 ctx.lineWidth = 3;
3455 ctx.strokeStyle = "rgba(127,45,127, 0.3)";
caryclark54359292015-03-26 07:52:43 -07003456 var leftCurve = curvePartialByID(test, frags[0], frags[4], frags[5]);
3457 var midCurve = curvePartialByID(test, frags[6], frags[10], frags[11]);
3458 var rightCurve = curvePartialByID(test, frags[12], frags[16], frags[17]);
caryclarkdac1d172014-06-17 05:15:38 -07003459 drawCurve(leftCurve);
3460 drawCurve(rightCurve);
caryclark54359292015-03-26 07:52:43 -07003461 ctx.strokeStyle = angleBetween ? "rgba(0,160,45, 0.3)" : "rgba(255,0,45, 0.5)";
caryclarkdac1d172014-06-17 05:15:38 -07003462 drawCurve(midCurve);
3463 if (draw_angle > 1) {
Cary Clarkff114282016-12-14 11:56:16 -05003464 drawVisibleOrder(leftCurve, 'L');
3465 drawVisibleOrder(rightCurve, 'R');
3466 }
Cary Clarkd2eb5812017-01-18 11:00:57 -05003467 if (draw_id) {
3468 drawVisibleID(leftCurve, 0.5, frags[0]);
3469 drawVisibleID(midCurve, 0.5, frags[6]);
3470 drawVisibleID(rightCurve, 0.5, frags[12]);
caryclarkdac1d172014-06-17 05:15:38 -07003471 }
3472 break;
caryclark54359292015-03-26 07:52:43 -07003473 case REC_TYPE_AFTERPART:
3474 if (draw_angle != 3 || (step_limit > 0 && tIndex < lastAngle)) {
3475 continue;
3476 }
3477 ctx.strokeStyle = afterIndex == 0 ? "rgba(255,0,0, 1.0)"
3478 : (afterIndex == 1) == angleBetween ? "rgba(0,128,0, 1.0)"
Cary Clarkff114282016-12-14 11:56:16 -05003479 : "rgba(0,0,255, 1.0)";
3480 var curve;
3481 var id;
caryclark54359292015-03-26 07:52:43 -07003482 switch (fragType) {
3483 case PATH_LINE:
Cary Clarkff114282016-12-14 11:56:16 -05003484 curve = [ frags[0], frags[1], frags[2], frags[3] ];
3485 id = frags[4];
caryclark54359292015-03-26 07:52:43 -07003486 break;
3487 case PATH_QUAD:
Cary Clarkff114282016-12-14 11:56:16 -05003488 curve = [ frags[0], frags[1], frags[2], frags[3],
3489 frags[4], frags[5] ];
3490 id = frags[6];
caryclark54359292015-03-26 07:52:43 -07003491 break;
caryclark1049f122015-04-20 08:31:59 -07003492 case PATH_CONIC:
Cary Clarkff114282016-12-14 11:56:16 -05003493 curve = [ frags[0], frags[1], frags[2], frags[3],
3494 frags[4], frags[5], frags[6] ];
3495 id = frags[7];
caryclark1049f122015-04-20 08:31:59 -07003496 break;
caryclark54359292015-03-26 07:52:43 -07003497 case PATH_CUBIC:
Cary Clarkff114282016-12-14 11:56:16 -05003498 curve = [ frags[0], frags[1], frags[2], frags[3],
3499 frags[4], frags[5], frags[6], frags[7] ];
3500 id = frags[8];
caryclark54359292015-03-26 07:52:43 -07003501 break;
3502 default:
3503 console.log("unknown REC_TYPE_AFTERPART frag type: " + fragType);
3504 throw "stop execution";
3505 }
Cary Clarkff114282016-12-14 11:56:16 -05003506 drawCurve(curve);
Cary Clarkd2eb5812017-01-18 11:00:57 -05003507 if (draw_id) {
3508 drawVisibleID(curve, 0.5, id);
Cary Clarkff114282016-12-14 11:56:16 -05003509 }
caryclark54359292015-03-26 07:52:43 -07003510 ++afterIndex;
3511 break;
caryclark624637c2015-05-11 07:21:27 -07003512 case REC_TYPE_COINCIDENCE:
3513 if (!draw_coincidence || (step_limit > 0 && tIndex < lastCoin)) {
3514 continue;
3515 }
3516 focus_enabled = true;
3517 ctx.lineWidth = 3;
3518 ctx.strokeStyle = "rgba(127,45,63, 0.3)";
3519 var curve = curvePartialByID(test, frags[0], frags[1], frags[2]);
3520 drawCurve(curve);
3521 break;
caryclarkdac1d172014-06-17 05:15:38 -07003522 case REC_TYPE_SECT:
3523 if (!draw_intersection) {
3524 continue;
3525 }
3526 if (draw_intersection != 1 && (step_limit > 0 && tIndex < lastSect)) {
3527 continue;
3528 }
3529 // draw_intersection == 1 : show all
3530 // draw_intersection == 2 : step == 0 ? show all : show intersection line #step
3531 // draw_intersection == 3 : step == 0 ? show all : show intersection #step
3532 ctx.lineWidth = 1;
3533 ctx.strokeStyle = "rgba(0,0,255, 0.3)";
3534 ctx.fillStyle = "blue";
3535 focus_enabled = true;
3536 var f = [];
3537 var c1s;
3538 var c1l;
3539 var c2s;
3540 var c2l;
3541 switch (fragType) {
3542 case INTERSECT_LINE:
3543 f.push(5, 6, 0, 7);
3544 c1s = 1; c1l = 4; c2s = 8; c2l = 4;
3545 break;
3546 case INTERSECT_LINE_2:
3547 f.push(5, 6, 0, 10);
3548 f.push(8, 9, 7, 15);
3549 c1s = 1; c1l = 4; c2s = 11; c2l = 4;
3550 break;
3551 case INTERSECT_LINE_NO:
3552 c1s = 0; c1l = 4; c2s = 4; c2l = 4;
3553 break;
3554 case INTERSECT_QUAD_LINE:
3555 f.push(7, 8, 0, 9);
3556 c1s = 1; c1l = 6; c2s = 10; c2l = 4;
3557 break;
3558 case INTERSECT_QUAD_LINE_2:
3559 f.push(7, 8, 0, 12);
3560 f.push(10, 11, 9, 17);
3561 c1s = 1; c1l = 6; c2s = 13; c2l = 4;
3562 break;
3563 case INTERSECT_QUAD_LINE_NO:
3564 c1s = 0; c1l = 6; c2s = 6; c2l = 4;
3565 break;
3566 case INTERSECT_QUAD:
3567 f.push(7, 8, 0, 9);
3568 c1s = 1; c1l = 6; c2s = 10; c2l = 6;
3569 break;
3570 case INTERSECT_QUAD_2:
3571 f.push(7, 8, 0, 12);
3572 f.push(10, 11, 9, 19);
3573 c1s = 1; c1l = 6; c2s = 13; c2l = 6;
3574 break;
3575 case INTERSECT_QUAD_NO:
3576 c1s = 0; c1l = 6; c2s = 6; c2l = 6;
3577 break;
caryclark1049f122015-04-20 08:31:59 -07003578 case INTERSECT_CONIC_LINE:
3579 f.push(8, 9, 0, 10);
3580 c1s = 1; c1l = 7; c2s = 11; c2l = 4;
3581 break;
3582 case INTERSECT_CONIC_LINE_2:
3583 f.push(8, 9, 0, 12);
3584 f.push(11, 12, 10, 18);
3585 c1s = 1; c1l = 7; c2s = 14; c2l = 4;
3586 break;
3587 case INTERSECT_CONIC_LINE_NO:
3588 c1s = 0; c1l = 7; c2s = 7; c2l = 4;
3589 break;
caryclark55888e42016-07-18 10:01:36 -07003590 case INTERSECT_CONIC_QUAD:
3591 f.push(8, 9, 0, 10);
3592 c1s = 1; c1l = 7; c2s = 11; c2l = 6;
3593 break;
3594 case INTERSECT_CONIC_QUAD_2:
3595 f.push(8, 9, 0, 12);
3596 f.push(11, 12, 10, 18);
3597 c1s = 1; c1l = 7; c2s = 14; c2l = 6;
3598 break;
caryclark6c3b9cd2016-09-26 05:36:58 -07003599 case INTERSECT_CONIC_QUAD_3:
3600 f.push(8, 9, 0, 15);
3601 f.push(11, 12, 10, 21);
3602 f.push(14, 15, 13, 22);
3603 c1s = 1; c1l = 7; c2s = 17; c2l = 6;
3604 break;
3605 case INTERSECT_CONIC_QUAD_4:
3606 f.push(8, 9, 0, 18);
3607 f.push(11, 12, 10, 24);
3608 f.push(14, 15, 13, 25);
3609 f.push(17, 18, 16, 26);
3610 c1s = 1; c1l = 7; c2s = 20; c2l = 6;
3611 break;
caryclark55888e42016-07-18 10:01:36 -07003612 case INTERSECT_CONIC_QUAD_NO:
3613 c1s = 0; c1l = 7; c2s = 7; c2l = 6;
3614 break;
caryclark1049f122015-04-20 08:31:59 -07003615 case INTERSECT_CONIC:
3616 f.push(8, 9, 0, 10);
3617 c1s = 1; c1l = 7; c2s = 11; c2l = 7;
3618 break;
3619 case INTERSECT_CONIC_2:
3620 f.push(8, 9, 0, 13);
3621 f.push(11, 12, 10, 21);
3622 c1s = 1; c1l = 7; c2s = 14; c2l = 7;
3623 break;
3624 case INTERSECT_CONIC_NO:
3625 c1s = 0; c1l = 7; c2s = 7; c2l = 7;
3626 break;
caryclarkdac1d172014-06-17 05:15:38 -07003627 case INTERSECT_SELF_CUBIC:
3628 f.push(9, 10, 0, 11);
3629 c1s = 1; c1l = 8; c2s = 0; c2l = 0;
3630 break;
3631 case INTERSECT_SELF_CUBIC_NO:
3632 c1s = 0; c1l = 8; c2s = 0; c2l = 0;
3633 break;
3634 case INTERSECT_CUBIC_LINE:
3635 f.push(9, 10, 0, 11);
3636 c1s = 1; c1l = 8; c2s = 12; c2l = 4;
3637 break;
3638 case INTERSECT_CUBIC_LINE_2:
3639 f.push(9, 10, 0, 14);
3640 f.push(12, 13, 11, 19);
3641 c1s = 1; c1l = 8; c2s = 15; c2l = 4;
3642 break;
3643 case INTERSECT_CUBIC_LINE_3:
3644 f.push(9, 10, 0, 17);
3645 f.push(12, 13, 11, 22);
3646 f.push(15, 16, 14, 23);
3647 c1s = 1; c1l = 8; c2s = 18; c2l = 4;
3648 break;
3649 case INTERSECT_CUBIC_QUAD_NO:
3650 c1s = 0; c1l = 8; c2s = 8; c2l = 6;
3651 break;
3652 case INTERSECT_CUBIC_QUAD:
3653 f.push(9, 10, 0, 11);
3654 c1s = 1; c1l = 8; c2s = 12; c2l = 6;
3655 break;
3656 case INTERSECT_CUBIC_QUAD_2:
3657 f.push(9, 10, 0, 14);
3658 f.push(12, 13, 11, 21);
3659 c1s = 1; c1l = 8; c2s = 15; c2l = 6;
3660 break;
3661 case INTERSECT_CUBIC_QUAD_3:
3662 f.push(9, 10, 0, 17);
3663 f.push(12, 13, 11, 24);
3664 f.push(15, 16, 14, 25);
3665 c1s = 1; c1l = 8; c2s = 18; c2l = 6;
3666 break;
3667 case INTERSECT_CUBIC_QUAD_4:
3668 f.push(9, 10, 0, 20);
3669 f.push(12, 13, 11, 27);
3670 f.push(15, 16, 14, 28);
3671 f.push(18, 19, 17, 29);
3672 c1s = 1; c1l = 8; c2s = 21; c2l = 6;
3673 break;
3674 case INTERSECT_CUBIC_LINE_NO:
3675 c1s = 0; c1l = 8; c2s = 8; c2l = 4;
3676 break;
3677 case INTERSECT_CUBIC:
3678 f.push(9, 10, 0, 11);
3679 c1s = 1; c1l = 8; c2s = 12; c2l = 8;
3680 break;
3681 case INTERSECT_CUBIC_2:
3682 f.push(9, 10, 0, 14);
3683 f.push(12, 13, 11, 23);
3684 c1s = 1; c1l = 8; c2s = 15; c2l = 8;
3685 break;
3686 case INTERSECT_CUBIC_3:
3687 f.push(9, 10, 0, 17);
3688 f.push(12, 13, 11, 26);
3689 f.push(15, 16, 14, 27);
3690 c1s = 1; c1l = 8; c2s = 18; c2l = 8;
3691 break;
3692 case INTERSECT_CUBIC_4:
3693 f.push(9, 10, 0, 20);
3694 f.push(12, 13, 11, 29);
3695 f.push(15, 16, 14, 30);
3696 f.push(18, 19, 17, 31);
3697 c1s = 1; c1l = 8; c2s = 21; c2l = 8;
3698 break;
3699 case INTERSECT_CUBIC_NO:
3700 c1s = 0; c1l = 8; c2s = 8; c2l = 8;
3701 break;
3702 default:
3703 console.log("unknown REC_TYPE_SECT frag type: " + fragType);
3704 throw "stop execution";
3705 }
3706 if (draw_intersection != 1) {
3707 var id = -1;
3708 var curve;
3709 switch (c1l) {
caryclark55888e42016-07-18 10:01:36 -07003710 case 4:
caryclarkdac1d172014-06-17 05:15:38 -07003711 drawLine(frags[c1s], frags[c1s + 1], frags[c1s + 2], frags[c1s + 3]);
3712 if (draw_id) {
3713 curve = [frags[c1s], frags[c1s + 1], frags[c1s + 2], frags[c1s + 3]];
3714 id = idByCurve(test, curve, PATH_LINE);
3715 }
3716 break;
3717 case 6:
3718 drawQuad(frags[c1s], frags[c1s + 1], frags[c1s + 2], frags[c1s + 3],
3719 frags[c1s + 4], frags[c1s + 5]);
3720 if (draw_id) {
3721 curve = [frags[c1s], frags[c1s + 1], frags[c1s + 2], frags[c1s + 3],
3722 frags[c1s + 4], frags[c1s + 5]];
3723 id = idByCurve(test, curve, PATH_QUAD);
3724 }
3725 break;
caryclark1049f122015-04-20 08:31:59 -07003726 case 7:
3727 drawConicWithQuads(frags[c1s], frags[c1s + 1], frags[c1s + 2], frags[c1s + 3],
3728 frags[c1s + 4], frags[c1s + 5], frags[c1s + 6]);
3729 if (draw_id) {
3730 curve = [frags[c1s], frags[c1s + 1], frags[c1s + 2], frags[c1s + 3],
3731 frags[c1s + 4], frags[c1s + 5], frags[c1s + 6]];
3732 id = idByCurve(test, curve, PATH_CONIC);
3733 }
3734 break;
caryclarkdac1d172014-06-17 05:15:38 -07003735 case 8:
3736 drawCubic(frags[c1s], frags[c1s + 1], frags[c1s + 2], frags[c1s + 3],
3737 frags[c1s + 4], frags[c1s + 5], frags[c1s + 6], frags[c1s + 7]);
3738 if (draw_id) {
3739 curve = [frags[c1s], frags[c1s + 1], frags[c1s + 2], frags[c1s + 3],
3740 frags[c1s + 4], frags[c1s + 5], frags[c1s + 6], frags[c1s + 7]];
3741 id = idByCurve(test, curve, PATH_CUBIC);
3742 }
3743 break;
3744 }
3745 if (id >= 0) {
Cary Clarkff114282016-12-14 11:56:16 -05003746 drawVisibleID(curve, 0.5, id);
caryclarkdac1d172014-06-17 05:15:38 -07003747 }
3748 id = -1;
3749 switch (c2l) {
3750 case 0:
3751 break;
caryclark55888e42016-07-18 10:01:36 -07003752 case 4:
caryclarkdac1d172014-06-17 05:15:38 -07003753 drawLine(frags[c2s], frags[c2s + 1], frags[c2s + 2], frags[c2s + 3]);
3754 if (draw_id) {
3755 curve = [frags[c2s], frags[c2s + 1], frags[c2s + 2], frags[c2s + 3]];
3756 id = idByCurve(test, curve, PATH_LINE);
3757 }
3758 break;
3759 case 6:
3760 drawQuad(frags[c2s], frags[c2s + 1], frags[c2s + 2], frags[c2s + 3],
3761 frags[c2s + 4], frags[c2s + 5]);
3762 if (draw_id) {
3763 curve = [frags[c2s], frags[c2s + 1], frags[c2s + 2], frags[c2s + 3],
3764 frags[c2s + 4], frags[c2s + 5]];
3765 id = idByCurve(test, curve, PATH_QUAD);
3766 }
3767 break;
caryclark1049f122015-04-20 08:31:59 -07003768 case 7:
3769 drawConicWithQuads(frags[c2s], frags[c2s + 1], frags[c2s + 2], frags[c2s + 3],
3770 frags[c2s + 4], frags[c2s + 5], frags[c2s + 6]);
3771 if (draw_id) {
3772 curve = [frags[c2s], frags[c2s + 1], frags[c2s + 2], frags[c2s + 3],
3773 frags[c2s + 4], frags[c2s + 5], frags[c2s + 6]];
3774 id = idByCurve(test, curve, PATH_CONIC);
3775 }
3776 break;
caryclarkdac1d172014-06-17 05:15:38 -07003777 case 8:
3778 drawCubic(frags[c2s], frags[c2s + 1], frags[c2s + 2], frags[c2s + 3],
3779 frags[c2s + 4], frags[c2s + 5], frags[c2s + 6], frags[c2s + 7]);
3780 if (draw_id) {
3781 curve = [frags[c2s], frags[c2s + 1], frags[c2s + 2], frags[c2s + 3],
3782 frags[c2s + 4], frags[c2s + 5], frags[c2s + 6], frags[c2s + 7]];
3783 id = idByCurve(test, curve, PATH_CUBIC);
3784 }
3785 break;
3786 }
3787 if (id >= 0) {
Cary Clarkff114282016-12-14 11:56:16 -05003788 drawVisibleID(curve, 0.5, id);
caryclarkdac1d172014-06-17 05:15:38 -07003789 }
3790 }
3791 if (collect_bounds) {
3792 break;
3793 }
caryclark54359292015-03-26 07:52:43 -07003794 if (draw_intersection != 3 || step_limit == 0 || tIndex >= lastSect) {
3795 for (var idx = 0; idx < f.length; idx += 4) {
caryclarkdac1d172014-06-17 05:15:38 -07003796 drawPoint(frags[f[idx]], frags[f[idx + 1]], true);
3797 }
3798 }
3799 if (!draw_intersectT) {
3800 break;
3801 }
3802 ctx.fillStyle = "red";
caryclark54359292015-03-26 07:52:43 -07003803 if (draw_intersection != 3 || step_limit == 0 || tIndex >= lastSect) {
3804 for (var idx = 0; idx < f.length; idx += 4) {
caryclarkdac1d172014-06-17 05:15:38 -07003805 drawTAtPointUp(frags[f[idx]], frags[f[idx + 1]], frags[f[idx + 2]]);
3806 drawTAtPointDown(frags[f[idx]], frags[f[idx + 1]], frags[f[idx + 3]]);
3807 }
3808 }
3809 break;
3810 case REC_TYPE_SORT:
3811 if (!draw_sort || (step_limit > 0 && tIndex < lastSort)) {
3812 continue;
3813 }
3814 ctx.lineWidth = 3;
3815 ctx.strokeStyle = "rgba(127,127,0, 0.5)";
3816 focus_enabled = true;
3817 switch (fragType) {
3818 case SORT_UNARY:
3819 case SORT_BINARY:
3820 var curve = curvePartialByID(test, frags[0], frags[6], frags[8]);
3821 drawCurve(curve);
3822 break;
3823 default:
3824 console.log("unknown REC_TYPE_SORT frag type: " + fragType);
3825 throw "stop execution";
3826 }
3827 break;
caryclark03b03ca2015-04-23 09:13:37 -07003828 case REC_TYPE_TOP:
3829 if (!draw_top || (step_limit > 0 && tIndex < lastTop)) {
3830 continue;
3831 }
3832 ctx.lineWidth = 3;
3833 ctx.strokeStyle = "rgba(127,127,0, 0.5)";
3834 focus_enabled = true;
3835 {
3836 var curve = curvePartialByID(test, frags[0], frags[1], frags[2]);
3837 drawCurve(curve);
3838 var type = PATH_LINE + (curve.length / 2 - 2);
3839 var mid = pointAtT(curve, type, 0.5);
3840 var d = dxy_at_t(curve, type, 0.5);
3841 drawArrow(mid.x, mid.y, d.x, d.y, 0.3);
3842 }
3843 break;
caryclarkdac1d172014-06-17 05:15:38 -07003844 case REC_TYPE_MARK:
3845 if (!draw_mark || (step_limit > 0 && tIndex < lastMark)) {
3846 continue;
3847 }
3848 ctx.lineWidth = 3;
3849 ctx.strokeStyle = fragType >= MARK_DONE_LINE ?
3850 "rgba(127,0,127, 0.5)" : "rgba(127,127,0, 0.5)";
3851 focus_enabled = true;
3852 switch (fragType) {
3853 case MARK_LINE:
3854 case MARK_DONE_LINE:
3855 case MARK_UNSORTABLE_LINE:
3856 case MARK_SIMPLE_LINE:
3857 case MARK_SIMPLE_DONE_LINE:
3858 case MARK_DONE_UNARY_LINE:
3859 drawLinePartial(frags[1], frags[2], frags[3], frags[4],
3860 frags[5], frags[9]);
3861 if (draw_id) {
3862 drawLinePartialID(frags[0], frags[1], frags[2], frags[3], frags[4],
3863 frags[5], frags[9]);
3864 }
3865 break;
3866 case MARK_QUAD:
3867 case MARK_DONE_QUAD:
3868 case MARK_UNSORTABLE_QUAD:
3869 case MARK_SIMPLE_QUAD:
3870 case MARK_SIMPLE_DONE_QUAD:
3871 case MARK_DONE_UNARY_QUAD:
3872 drawQuadPartial(frags[1], frags[2], frags[3], frags[4],
3873 frags[5], frags[6], frags[7], frags[11]);
3874 if (draw_id) {
3875 drawQuadPartialID(frags[0], frags[1], frags[2], frags[3], frags[4],
3876 frags[5], frags[6], frags[7], frags[11]);
3877 }
3878 break;
3879 case MARK_CUBIC:
3880 case MARK_DONE_CUBIC:
3881 case MARK_UNSORTABLE_CUBIC:
3882 case MARK_SIMPLE_CUBIC:
3883 case MARK_SIMPLE_DONE_CUBIC:
3884 case MARK_DONE_UNARY_CUBIC:
3885 drawCubicPartial(frags[1], frags[2], frags[3], frags[4],
3886 frags[5], frags[6], frags[7], frags[8], frags[9], frags[13]);
3887 if (draw_id) {
3888 drawCubicPartialID(frags[0], frags[1], frags[2], frags[3], frags[4],
3889 frags[5], frags[6], frags[7], frags[8], frags[9], frags[13]);
3890 }
3891 break;
3892 case MARK_ANGLE_LAST:
3893 // FIXME: ignored for now
3894 break;
3895 default:
3896 console.log("unknown REC_TYPE_MARK frag type: " + fragType);
3897 throw "stop execution";
3898 }
3899 break;
3900 default:
3901 continue;
3902 }
3903 }
3904 switch (recType) {
3905 case REC_TYPE_SORT:
3906 if (!draw_sort || (step_limit > 0 && tIndex < lastSort)) {
3907 break;
3908 }
3909 var angles = []; // use tangent lines to describe arcs
3910 var windFrom = [];
3911 var windTo = [];
3912 var opp = [];
3913 var minXY = Number.MAX_VALUE;
3914 var partial;
3915 focus_enabled = true;
3916 var someUnsortable = false;
3917 for (var recordIndex = 0; recordIndex < records.length; recordIndex += 2) {
3918 var fragType = records[recordIndex];
3919 var frags = records[recordIndex + 1];
3920 var unsortable = (fragType == SORT_UNARY && frags[14]) ||
3921 (fragType == SORT_BINARY && frags[16]);
3922 someUnsortable |= unsortable;
3923 switch (fragType) {
3924 case SORT_UNARY:
3925 case SORT_BINARY:
3926 partial = curvePartialByID(test, frags[0], frags[6], frags[8]);
3927 break;
3928 default:
3929 console.log("unknown REC_TYPE_SORT frag type: " + fragType);
3930 throw "stop execution";
3931 }
3932 var dx = boundsWidth(partial);
3933 var dy = boundsHeight(partial);
3934 minXY = Math.min(minXY, dx * dx + dy * dy);
3935 if (collect_bounds) {
3936 continue;
3937 }
3938 angles.push(tangent(partial));
3939 var from = frags[12];
3940 var to = frags[12];
3941 var sgn = frags[10];
3942 if (sgn < 0) {
3943 from -= frags[11];
3944 } else if (sgn > 0) {
3945 to -= frags[11];
3946 }
3947 windFrom.push(from + (unsortable ? "!" : ""));
3948 windTo.push(to + (unsortable ? "!" : ""));
3949 opp.push(fragType == SORT_BINARY);
3950 if (draw_sort == 1) {
Cary Clarkff114282016-12-14 11:56:16 -05003951 drawVisibleOrder(partial, frags[12]);
caryclarkdac1d172014-06-17 05:15:38 -07003952 } else {
Cary Clarkff114282016-12-14 11:56:16 -05003953 drawVisibleOrder(partial, (recordIndex / 2) + 1);
caryclarkdac1d172014-06-17 05:15:38 -07003954 }
3955 }
3956 var radius = Math.sqrt(minXY) / 2 * scale;
3957 radius = Math.min(50, radius);
3958 var scaledRadius = radius / scale;
3959 var centerX = partial[0];
3960 var centerY = partial[1];
3961 if (collect_bounds) {
3962 if (focus_enabled) {
3963 focusXmin = Math.min(focusXmin, centerX - scaledRadius);
3964 focusYmin = Math.min(focusYmin, centerY - scaledRadius);
3965 focusXmax = Math.max(focusXmax, centerX + scaledRadius);
3966 focusYmax = Math.max(focusYmax, centerY + scaledRadius);
3967 }
3968 break;
3969 }
3970 break;
3971 default:
3972 break;
3973 }
3974 }
3975 if (collect_bounds) {
3976 return;
3977 }
3978 if (draw_log && logStart >= 0) {
3979 ctx.font = "normal 10px Arial";
3980 ctx.textAlign = "left";
3981 ctx.beginPath();
3982 var top = screenHeight - 20 - (logRange + 2) * 10;
3983 ctx.rect(50, top, screenWidth - 100, (logRange + 2) * 10);
3984 ctx.fillStyle = "white";
3985 ctx.fill();
3986 ctx.fillStyle = "rgba(0,0,0, 0.5)";
3987 if (logStart > 0) {
3988 ctx.fillText(lines[logStart - 1], 50, top + 8);
3989 }
3990 ctx.fillStyle = "black";
3991 for (var idx = 0; idx < logRange; ++idx) {
3992 ctx.fillText(lines[logStart + idx], 50, top + 18 + 10 * idx);
3993 }
3994 ctx.fillStyle = "rgba(0,0,0, 0.5)";
3995 if (logStart + logRange < lines.length) {
3996 ctx.fillText(lines[logStart + logRange], 50, top + 18 + 10 * logRange);
3997 }
3998 }
3999 if (draw_legend) {
4000 var pos = 0;
caryclark624637c2015-05-11 07:21:27 -07004001 var drawSomething = draw_add | draw_active | draw_angle | draw_coincidence | draw_sort | draw_mark;
caryclarkdac1d172014-06-17 05:15:38 -07004002 // drawBox(pos++, "yellow", "black", opLetter, true, '');
4003 drawBox(pos++, "rgba(0,0,255, 0.3)", "black", draw_intersection > 1 ? sectCount : sectMax2, draw_intersection, intersectionKey);
4004 drawBox(pos++, "rgba(0,0,255, 0.3)", "black", draw_add ? addCount : addMax, draw_add, addKey);
4005 drawBox(pos++, "rgba(0,0,255, 0.3)", "black", draw_active ? activeCount : activeMax, draw_active, activeKey);
4006 drawBox(pos++, "rgba(127,127,0, 0.3)", "black", draw_angle ? angleCount : angleMax, draw_angle, angleKey);
caryclark624637c2015-05-11 07:21:27 -07004007 drawBox(pos++, "rgba(127,127,0, 0.3)", "black", draw_coincidence ? coinCount : coinMax, draw_coincidence, coincidenceKey);
caryclarkdac1d172014-06-17 05:15:38 -07004008 drawBox(pos++, "rgba(127,127,0, 0.3)", "black", draw_op ? opCount : opMax, draw_op, opKey);
4009 drawBox(pos++, "rgba(127,127,0, 0.3)", "black", draw_sort ? sortCount : sortMax, draw_sort, sortKey);
caryclark03b03ca2015-04-23 09:13:37 -07004010 drawBox(pos++, "rgba(127,127,0, 0.3)", "black", draw_top ? topCount : topMax, draw_top, topKey);
caryclarkdac1d172014-06-17 05:15:38 -07004011 drawBox(pos++, "rgba(127,0,127, 0.3)", "black", draw_mark ? markCount : markMax, draw_mark, markKey);
caryclark55888e42016-07-18 10:01:36 -07004012 drawBox(pos++, "black", "white",
caryclark26ad22a2015-10-16 09:03:38 -07004013 (new Array('P', 'P1', 'P2', 'P', 'p', 'p1', 'p2'))[draw_path], draw_path != 0, pathKey);
caryclarkdac1d172014-06-17 05:15:38 -07004014 drawBox(pos++, "rgba(0,63,0, 0.7)", "white",
4015 (new Array('Q', 'Q', 'C', 'QC', 'Qc', 'Cq'))[draw_computed],
4016 draw_computed != 0, computedKey);
4017 drawBox(pos++, "green", "black", step_limit, drawSomething, '');
4018 drawBox(pos++, "green", "black", stepMax, drawSomething, '');
4019 drawBox(pos++, "rgba(255,0,0, 0.6)", "black", lastIndex, drawSomething & draw_log, '');
4020 drawBox(pos++, "rgba(255,0,0, 0.6)", "black", test.length - 1, drawSomething & draw_log, '');
4021 if (curve_t) {
4022 drawCurveTControl();
4023 }
4024 ctx.font = "normal 20px Arial";
4025 ctx.fillStyle = "rgba(0,0,0, 0.3)";
4026 ctx.textAlign = "right";
4027 ctx.fillText(scale.toFixed(decimal_places) + 'x' , screenWidth - 10, screenHeight - 5);
4028 }
4029 if (draw_hints) {
4030 ctx.font = "normal 10px Arial";
4031 ctx.fillStyle = "rgba(0,0,0, 0.5)";
4032 ctx.textAlign = "right";
4033 var y = 4;
4034 ctx.fillText("control lines : " + controlLinesKey, ctx.screenWidthwidth - 10, pos * 50 + y++ * 10);
4035 ctx.fillText("curve t : " + curveTKey, screenWidth - 10, pos * 50 + y++ * 10);
4036 ctx.fillText("deriviatives : " + deriviativesKey, screenWidth - 10, pos * 50 + y++ * 10);
4037 ctx.fillText("intersect t : " + intersectTKey, screenWidth - 10, pos * 50 + y++ * 10);
caryclarkdac1d172014-06-17 05:15:38 -07004038 ctx.fillText("log : " + logKey, screenWidth - 10, pos * 50 + y++ * 10);
4039 ctx.fillText("log curve : " + logCurvesKey, screenWidth - 10, pos * 50 + y++ * 10);
4040 ctx.fillText("mid point : " + midpointKey, screenWidth - 10, pos * 50 + y++ * 10);
4041 ctx.fillText("points : " + ptsKey, screenWidth - 10, pos * 50 + y++ * 10);
4042 ctx.fillText("sequence : " + sequenceKey, screenWidth - 10, pos * 50 + y++ * 10);
4043 ctx.fillText("xy : " + xyKey, screenWidth - 10, pos * 50 + y++ * 10);
4044 }
4045}
4046
4047function drawBox(y, backC, foreC, str, enable, label) {
4048 ctx.beginPath();
4049 ctx.fillStyle = backC;
4050 ctx.rect(screenWidth - 40, y * 50 + 10, 40, 30);
4051 ctx.fill();
4052 ctx.font = "normal 16px Arial";
4053 ctx.fillStyle = foreC;
4054 ctx.textAlign = "center";
4055 ctx.fillText(str, screenWidth - 20, y * 50 + 32);
4056 if (!enable) {
4057 ctx.fillStyle = "rgba(255,255,255, 0.5)";
4058 ctx.fill();
4059 }
4060 if (label != '') {
4061 ctx.font = "normal 9px Arial";
4062 ctx.fillStyle = "black";
4063 ctx.fillText(label, screenWidth - 47, y * 50 + 40);
4064 }
4065}
4066
4067function drawCurveTControl() {
4068 ctx.lineWidth = 2;
4069 ctx.strokeStyle = "rgba(0,0,0, 0.3)";
4070 ctx.beginPath();
4071 ctx.rect(screenWidth - 80, 40, 28, screenHeight - 80);
4072 ctx.stroke();
4073 var ty = 40 + curveT * (screenHeight - 80);
4074 ctx.beginPath();
4075 ctx.moveTo(screenWidth - 80, ty);
4076 ctx.lineTo(screenWidth - 85, ty - 5);
4077 ctx.lineTo(screenWidth - 85, ty + 5);
4078 ctx.lineTo(screenWidth - 80, ty);
4079 ctx.fillStyle = "rgba(0,0,0, 0.6)";
4080 ctx.fill();
4081 var num = curveT.toFixed(decimal_places);
4082 ctx.font = "normal 10px Arial";
4083 ctx.textAlign = "left";
4084 ctx.fillText(num, screenWidth - 78, ty);
4085}
4086
4087function ptInTControl() {
4088 var e = window.event;
caryclark55888e42016-07-18 10:01:36 -07004089 var tgt = e.target || e.srcElement;
caryclarkdac1d172014-06-17 05:15:38 -07004090 var left = tgt.offsetLeft;
4091 var top = tgt.offsetTop;
4092 var x = (e.clientX - left);
4093 var y = (e.clientY - top);
4094 if (x < screenWidth - 80 || x > screenWidth - 50) {
4095 return false;
4096 }
4097 if (y < 40 || y > screenHeight - 80) {
4098 return false;
4099 }
4100 curveT = (y - 40) / (screenHeight - 120);
4101 if (curveT < 0 || curveT > 1) {
4102 throw "stop execution";
4103 }
4104 return true;
4105}
4106
4107function drawTop() {
4108 if (tests[testIndex] == null) {
4109 var str = testDivs[testIndex].textContent;
4110 parse_all(str);
4111 var title = testDivs[testIndex].id.toString();
4112 testTitles[testIndex] = title;
4113 }
4114 init(tests[testIndex]);
4115 redraw();
4116}
4117
4118function redraw() {
4119 if (focus_on_selection) {
4120 collect_bounds = true;
4121 draw(tests[testIndex], testLines[testIndex], testTitles[testIndex]);
4122 collect_bounds = false;
4123 if (focusXmin < focusXmax && focusYmin < focusYmax) {
4124 setScale(focusXmin, focusXmax, focusYmin, focusYmax);
4125 }
4126 }
4127 ctx.beginPath();
4128 ctx.fillStyle = "white";
4129 ctx.rect(0, 0, screenWidth, screenHeight);
4130 ctx.fill();
4131 draw(tests[testIndex], testLines[testIndex], testTitles[testIndex]);
4132}
4133
4134function dumpCurvePartial(test, id, t0, t1) {
4135 var curve = curveByID(test, id);
4136 var name = ["line", "quad", "cubic"][curve.length / 2 - 2];
4137 console.log("id=" + id + " " + name + "=" + curveToString(curve)
4138 + " t0=" + t0 + " t1=" + t1
4139 + " partial=" + curveToString(curvePartialByID(test, id, t0, t1)));
4140}
4141
4142function dumpAngleTest(test, id, t0, t1) {
4143 var curve = curveByID(test, id);
caryclark55888e42016-07-18 10:01:36 -07004144 console.log(" { {" + curveToString(curve) + "}, "
caryclarkdac1d172014-06-17 05:15:38 -07004145 + curve.length / 2 + ", " + t0 + ", " + t1 + ", {} }, //");
4146}
4147
4148function dumpLogToConsole() {
4149 if (logStart < 0) {
4150 return;
4151 }
4152 var test = tests[testIndex];
4153 var recType = REC_TYPE_UNKNOWN;
4154 var records;
4155 for (var index = 0; index < test.length; index += 3) {
4156 var lastLineNo = test[index + 1];
4157 if (lastLineNo >= logStart && lastLineNo < logStart + logRange) {
4158 recType = test[index];
4159 records = test[index + 2];
4160 break;
4161 }
4162 }
4163 if (recType == REC_TYPE_UNKNOWN) {
4164 return;
4165 }
4166 var lines = testLines[testIndex];
4167 for (var idx = 0; idx < logRange; ++idx) {
4168 var line = lines[logStart + idx];
4169 console.log(line);
4170 for (var recordIndex = 0; recordIndex < records.length; recordIndex += 2) {
4171 var fragType = records[recordIndex];
4172 var frags = records[recordIndex + 1];
4173 if (recType == REC_TYPE_ANGLE && fragType == ANGLE_AFTER) {
caryclarkdac1d172014-06-17 05:15:38 -07004174 dumpCurvePartial(test, frags[0], frags[4], frags[5]);
4175 dumpCurvePartial(test, frags[6], frags[10], frags[11]);
4176 dumpCurvePartial(test, frags[12], frags[16], frags[17]);
4177 console.log("\nstatic IntersectData intersectDataSet[] = { //");
4178 dumpAngleTest(test, frags[0], frags[4], frags[5]);
4179 dumpAngleTest(test, frags[6], frags[10], frags[11]);
4180 dumpAngleTest(test, frags[12], frags[16], frags[17]);
4181 console.log("}; //");
4182 }
4183 }
4184 }
4185}
4186
4187var activeKey = 'a';
4188var pathKey = 'b';
4189var pathBackKey = 'B';
4190var centerKey = 'c';
caryclark624637c2015-05-11 07:21:27 -07004191var coincidenceKey = 'C';
caryclarkdac1d172014-06-17 05:15:38 -07004192var addKey = 'd';
4193var deriviativesKey = 'f';
4194var angleKey = 'g';
4195var angleBackKey = 'G';
caryclarkdac1d172014-06-17 05:15:38 -07004196var intersectionKey = 'i';
4197var intersectionBackKey = 'I';
4198var sequenceKey = 'j';
4199var midpointKey = 'k';
4200var logKey = 'l';
4201var logToConsoleKey = 'L';
4202var markKey = 'm';
4203var sortKey = 'o';
4204var opKey = 'p';
4205var opBackKey = 'P';
4206var computedKey = 'q';
4207var computedBackKey = 'Q';
Cary Clarkff114282016-12-14 11:56:16 -05004208var directionKey = 'r';
caryclarkdac1d172014-06-17 05:15:38 -07004209var stepKey = 's';
4210var stepBackKey = 'S';
4211var intersectTKey = 't';
caryclark03b03ca2015-04-23 09:13:37 -07004212var topKey = 'T';
caryclarkdac1d172014-06-17 05:15:38 -07004213var curveTKey = 'u';
4214var controlLinesBackKey = 'V';
4215var controlLinesKey = 'v';
4216var ptsKey = 'x';
4217var xyKey = 'y';
4218var logCurvesKey = 'z';
4219var focusKey = '`';
4220var idKey = '.';
4221var retinaKey = '\\';
4222
4223function doKeyPress(evt) {
4224 var char = String.fromCharCode(evt.charCode);
4225 var focusWasOn = false;
4226 switch (char) {
4227 case '0':
4228 case '1':
4229 case '2':
4230 case '3':
4231 case '4':
4232 case '5':
4233 case '6':
4234 case '7':
4235 case '8':
4236 case '9':
4237 decimal_places = char - '0';
4238 redraw();
4239 break;
4240 case activeKey:
4241 draw_active ^= true;
caryclark55888e42016-07-18 10:01:36 -07004242 redraw();
caryclarkdac1d172014-06-17 05:15:38 -07004243 break;
4244 case addKey:
4245 draw_add ^= true;
caryclark55888e42016-07-18 10:01:36 -07004246 redraw();
caryclarkdac1d172014-06-17 05:15:38 -07004247 break;
4248 case angleKey:
caryclark54359292015-03-26 07:52:43 -07004249 draw_angle = (draw_angle + 1) % 4;
caryclarkdac1d172014-06-17 05:15:38 -07004250 redraw();
4251 break;
4252 case angleBackKey:
4253 draw_angle = (draw_angle + 2) % 3;
4254 redraw();
4255 break;
4256 case centerKey:
4257 setScale(xmin, xmax, ymin, ymax);
caryclark55888e42016-07-18 10:01:36 -07004258 redraw();
caryclarkdac1d172014-06-17 05:15:38 -07004259 break;
caryclark624637c2015-05-11 07:21:27 -07004260 case coincidenceKey:
4261 draw_coincidence ^= true;
4262 redraw();
4263 break;
caryclarkdac1d172014-06-17 05:15:38 -07004264 case controlLinesBackKey:
4265 control_lines = (control_lines + 3) % 4;
caryclark55888e42016-07-18 10:01:36 -07004266 redraw();
caryclarkdac1d172014-06-17 05:15:38 -07004267 break;
4268 case controlLinesKey:
4269 control_lines = (control_lines + 1) % 4;
caryclark55888e42016-07-18 10:01:36 -07004270 redraw();
caryclarkdac1d172014-06-17 05:15:38 -07004271 break;
4272 case computedBackKey:
4273 draw_computed = (draw_computed + 5) % 6;
caryclark55888e42016-07-18 10:01:36 -07004274 redraw();
caryclarkdac1d172014-06-17 05:15:38 -07004275 break;
4276 case computedKey:
4277 draw_computed = (draw_computed + 1) % 6;
caryclark55888e42016-07-18 10:01:36 -07004278 redraw();
caryclarkdac1d172014-06-17 05:15:38 -07004279 break;
4280 case curveTKey:
4281 curve_t ^= true;
4282 if (curve_t) {
4283 draw_legend = true;
4284 }
4285 redraw();
4286 break;
4287 case deriviativesKey:
4288 draw_deriviatives = (draw_deriviatives + 1) % 3;
4289 redraw();
4290 break;
Cary Clarkff114282016-12-14 11:56:16 -05004291 case directionKey:
4292 draw_direction ^= true;
4293 redraw();
4294 break;
caryclarkdac1d172014-06-17 05:15:38 -07004295 case focusKey:
4296 focus_on_selection ^= true;
4297 setScale(xmin, xmax, ymin, ymax);
4298 redraw();
4299 break;
caryclarkdac1d172014-06-17 05:15:38 -07004300 case idKey:
4301 draw_id ^= true;
4302 redraw();
4303 break;
4304 case intersectionBackKey:
4305 draw_intersection = (draw_intersection + 3) % 4;
caryclark55888e42016-07-18 10:01:36 -07004306 redraw();
caryclarkdac1d172014-06-17 05:15:38 -07004307 break;
4308 case intersectionKey:
4309 draw_intersection = (draw_intersection + 1) % 4;
caryclark55888e42016-07-18 10:01:36 -07004310 redraw();
caryclarkdac1d172014-06-17 05:15:38 -07004311 break;
4312 case intersectTKey:
4313 draw_intersectT ^= true;
4314 redraw();
4315 break;
4316 case logCurvesKey:
4317 logCurves(tests[testIndex]);
4318 break;
4319 case logKey:
4320 draw_log ^= true;
4321 redraw();
4322 break;
4323 case logToConsoleKey:
4324 if (draw_log) {
4325 dumpLogToConsole();
4326 }
4327 break;
4328 case markKey:
4329 draw_mark ^= true;
4330 redraw();
4331 break;
4332 case midpointKey:
4333 draw_midpoint ^= true;
4334 redraw();
4335 break;
4336 case opKey:
4337 draw_op = (draw_op + 1) % 3;
4338 redraw();
4339 break;
4340 case opBackKey:
4341 draw_op = (draw_op + 2) % 3;
4342 redraw();
4343 break;
4344 case pathKey:
caryclark26ad22a2015-10-16 09:03:38 -07004345 draw_path = (draw_path + 1) % (4 + (hasAlignedPath ? 3 : 0));
caryclark55888e42016-07-18 10:01:36 -07004346 redraw();
caryclarkdac1d172014-06-17 05:15:38 -07004347 break;
4348 case pathBackKey:
caryclark26ad22a2015-10-16 09:03:38 -07004349 draw_path = (draw_path + 3 + (hasAlignedPath ? 3 : 0)) % (4 + (hasAlignedPath ? 3 : 0));
caryclark55888e42016-07-18 10:01:36 -07004350 redraw();
caryclarkdac1d172014-06-17 05:15:38 -07004351 break;
4352 case ptsKey:
4353 pt_labels = (pt_labels + 1) % 3;
4354 redraw();
4355 break;
4356 case retinaKey:
4357 retina_scale ^= true;
4358 drawTop();
4359 break;
4360 case sequenceKey:
4361 draw_sequence ^= true;
4362 redraw();
4363 break;
4364 case sortKey:
4365 draw_sort = (draw_sort + 1) % 3;
4366 drawTop();
4367 break;
4368 case stepKey:
4369 step_limit++;
4370 if (step_limit > stepMax) {
4371 step_limit = stepMax;
4372 }
4373 redraw();
4374 break;
4375 case stepBackKey:
4376 step_limit--;
4377 if (step_limit < 0) {
4378 step_limit = 0;
4379 }
4380 redraw();
4381 break;
caryclark03b03ca2015-04-23 09:13:37 -07004382 case topKey:
4383 draw_top ^= true;
4384 redraw();
4385 break;
caryclarkdac1d172014-06-17 05:15:38 -07004386 case xyKey:
4387 debug_xy = (debug_xy + 1) % 3;
4388 redraw();
4389 break;
4390 case '-':
4391 focusWasOn = focus_on_selection;
4392 if (focusWasOn) {
4393 focus_on_selection = false;
4394 scale /= 1.2;
4395 } else {
4396 scale /= 2;
4397 calcLeftTop();
4398 }
4399 redraw();
4400 focus_on_selection = focusWasOn;
4401 break;
4402 case '=':
4403 case '+':
4404 focusWasOn = focus_on_selection;
4405 if (focusWasOn) {
4406 focus_on_selection = false;
4407 scale *= 1.2;
4408 } else {
4409 scale *= 2;
4410 calcLeftTop();
4411 }
4412 redraw();
4413 focus_on_selection = focusWasOn;
4414 break;
4415 case '?':
4416 draw_hints ^= true;
4417 if (draw_hints && !draw_legend) {
4418 draw_legend = true;
4419 }
4420 redraw();
4421 break;
4422 case '/':
4423 draw_legend ^= true;
4424 redraw();
4425 break;
4426 }
4427}
4428
4429function doKeyDown(evt) {
4430 var char = evt.keyCode;
4431 var preventDefault = false;
4432 switch (char) {
4433 case 37: // left arrow
4434 if (evt.shiftKey) {
4435 testIndex -= 9;
4436 }
4437 if (--testIndex < 0)
4438 testIndex = tests.length - 1;
4439 drawTop();
4440 preventDefault = true;
4441 break;
4442 case 39: // right arrow
4443 if (evt.shiftKey) {
4444 testIndex += 9;
4445 }
4446 if (++testIndex >= tests.length)
4447 testIndex = 0;
4448 drawTop();
4449 preventDefault = true;
4450 break;
4451 }
4452 if (preventDefault) {
4453 evt.preventDefault();
4454 return false;
4455 }
4456 return true;
4457}
4458
4459(function() {
4460 var hidden = "hidden";
4461
4462 // Standards:
4463 if (hidden in document)
4464 document.addEventListener("visibilitychange", onchange);
4465 else if ((hidden = "mozHidden") in document)
4466 document.addEventListener("mozvisibilitychange", onchange);
4467 else if ((hidden = "webkitHidden") in document)
4468 document.addEventListener("webkitvisibilitychange", onchange);
4469 else if ((hidden = "msHidden") in document)
4470 document.addEventListener("msvisibilitychange", onchange);
4471 // IE 9 and lower:
4472 else if ('onfocusin' in document)
4473 document.onfocusin = document.onfocusout = onchange;
4474 // All others:
4475 else
caryclark55888e42016-07-18 10:01:36 -07004476 window.onpageshow = window.onpagehide
caryclarkdac1d172014-06-17 05:15:38 -07004477 = window.onfocus = window.onblur = onchange;
4478
4479 function onchange (evt) {
4480 var v = 'visible', h = 'hidden',
caryclark55888e42016-07-18 10:01:36 -07004481 evtMap = {
4482 focus:v, focusin:v, pageshow:v, blur:h, focusout:h, pagehide:h
caryclarkdac1d172014-06-17 05:15:38 -07004483 };
4484
4485 evt = evt || window.event;
4486 if (evt.type in evtMap)
4487 document.body.className = evtMap[evt.type];
caryclark55888e42016-07-18 10:01:36 -07004488 else
caryclarkdac1d172014-06-17 05:15:38 -07004489 document.body.className = this[hidden] ? "hidden" : "visible";
4490 }
4491})();
4492
4493function calcXY() {
4494 var e = window.event;
caryclark55888e42016-07-18 10:01:36 -07004495 var tgt = e.target || e.srcElement;
caryclarkdac1d172014-06-17 05:15:38 -07004496 var left = tgt.offsetLeft;
4497 var top = tgt.offsetTop;
4498 mouseX = (e.clientX - left) / scale + srcLeft;
4499 mouseY = (e.clientY - top) / scale + srcTop;
4500}
4501
4502function calcLeftTop() {
4503 srcLeft = mouseX - screenWidth / 2 / scale;
4504 srcTop = mouseY - screenHeight / 2 / scale;
4505}
4506
4507var disableClick = false;
4508
4509function handleMouseClick() {
4510 if (disableClick) {
4511 return;
4512 }
4513 if (!curve_t || !ptInTControl()) {
4514 calcXY();
4515 calcLeftTop();
4516 }
4517 redraw();
4518// if (!curve_t || !ptInTControl()) {
4519// mouseX = screenWidth / 2 / scale + srcLeft;
4520// mouseY = screenHeight / 2 / scale + srcTop;
4521// }
4522}
4523
4524function handleMouseOver() {
4525 calcXY();
4526 if (debug_xy != 2) {
4527 return;
4528 }
4529 var num = mouseX.toFixed(decimal_places) + ", " + mouseY.toFixed(decimal_places);
4530 ctx.beginPath();
4531 ctx.rect(300,100,num.length * 6,10);
4532 ctx.fillStyle="white";
4533 ctx.fill();
4534 ctx.font = "normal 10px Arial";
4535 ctx.fillStyle="black";
4536 ctx.textAlign = "left";
4537 ctx.fillText(num, 300, 108);
4538}
4539
4540function start() {
4541 for (var i = 0; i < testDivs.length; ++i) {
4542 tests[i] = null;
4543 }
4544 testIndex = 0;
4545 drawTop();
4546 window.addEventListener('keypress', doKeyPress, true);
4547 window.addEventListener('keydown', doKeyDown, true);
4548 window.onresize = function() {
4549 drawTop();
4550 }
4551 /*
4552 window.onpagehide = function() {
4553 disableClick = true;
4554 }
4555 */
4556 window.onpageshow = function () {
4557 disableClick = false;
4558 }
4559}
4560
4561</script>
4562</head>
4563
4564<body onLoad="start();">
4565<canvas id="canvas" width="750" height="500"
4566 onmousemove="handleMouseOver()"
4567 onclick="handleMouseClick()"
4568 ></canvas >
4569</body>
4570</html>