├── clipper.js ├── package.json ├── vendor ├── jquery.repeated-click.js ├── jquery.total-storage.js ├── lodash.math.js └── rgb-color.js ├── README.md ├── demo.css ├── formatter.js ├── demo.html └── demo.js /clipper.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mathisonian/JsClipper/HEAD/clipper.js -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "js-clipper", 3 | "version": "1.0.0", 4 | "description": "common.js compatible version of JSClipper", 5 | "main": "clipper.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "repository": { 10 | "type": "git", 11 | "url": "https://github.com/mathisonian/JsClipper.git" 12 | }, 13 | "keywords": [ 14 | "JsClipper", 15 | "js-clipper", 16 | "clipperlib" 17 | ], 18 | "author": "", 19 | "license": "boost", 20 | "bugs": { 21 | "url": "https://github.com/mathisonian/JsClipper/issues" 22 | }, 23 | "homepage": "https://github.com/mathisonian/JsClipper" 24 | } 25 | -------------------------------------------------------------------------------- /vendor/jquery.repeated-click.js: -------------------------------------------------------------------------------- 1 | /* 2 | * jQuery repeatedclick v1.0.5 3 | * Dual licensed under the MIT (http://www.opensource.org/licenses/mit-license.php) 4 | * and GPL (http://www.opensource.org/licenses/gpl-license.php) licenses. 5 | * Written by: Alexandr Zykov 6 | */ 7 | if (typeof(jQuery) != "undefined") 8 | jQuery.fn.hold = function(h,j){var c=jQuery.extend({duration:300,speed:0,min:150},j);"undefined"===typeof jQuery.repeatedEvents&&(jQuery.repeatedEvents=[]);jQuery.repeatedEvents.push(h);var k=jQuery.repeatedEvents.length-1,d,e;return this.each(function(){d=function(f,b,a){var g=this;jQuery.repeatedEvents[f].call(g,a);e=setTimeout(function(){d.call(g,f,b>c.min?b*c.speed:b,a)},b)};jQuery(this).mousedown(function(a){d.call(this,k,c.duration,a)});var a=function(){"undefined"!==typeof e&&clearInterval(e)};jQuery(this).mouseout(a);jQuery(this).mouseup(a)})}; -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | JsClipper 2 | ========= 3 | 4 | A JavaScript library to perform boolean operations (union, difference etc...) between two SVG paths. 5 | 6 | Online demo : http://delapouite.github.io/JsClipper/demo.html 7 | 8 | Original : http://sourceforge.net/projects/jsclipper 9 | 10 | 11 | 5.0.2.1 - 12 January 2013 12 | * Update: Clipper library updated to version 5.0.2. The Area algorithm has been updated and is faster. 13 | 'CheckInputs' parameter of the OffsetPolygons function has been renamed 'AutoFix'. 14 | * Added: ClipperLib.Clean(), which removes too near vertices to avoid micro-self-intersection-artifacts when offsetting. 15 | * Added: ClipperLib.Lighten(), which reduces count of vertices using perpendicular distance reduction algorithm. 16 | * Added: ClipperLib.Clone(), which make true clone of polygons. 17 | Several updates to the Main Demo: 18 | * Added: Clean, Simplify, Lighten buttons 19 | * Change: Custom Polygons: input boxes to textareas to allow more data 20 | * Added: Polygon Output Formats (Clipper, Plain, SVG) 21 | * Update: Polygon Explorer: Also multipolygon is clickable (on Points column) 22 | * Added: Polygon Explorer: When numbers on Points or Points in subpolygons are clicked, the area of multipolygon or subpolygon is shown 23 | * Update: Several updates to wiki in https://sourceforge.net/p/jsclipper/wiki/Home/ 24 | 25 | 4.9.7.2 - 1 January 2013 26 | * Update: Browser specific speedup for ClipperLib.Clipper.Round(), ClipperLib.Cast_Int32() and ClipperLib.Cast_Int64(). 27 | * Update: Major enhancements for Main Demo. Including benchmark, custom polygons and polygon importer. 28 | * Update: Documentation is updated with new screenshots of Main Demo. Browser speedtest is published in Wiki. 29 | 30 | 4.9.7.1 - 12 December 2012 31 | * Initial release -------------------------------------------------------------------------------- /vendor/jquery.total-storage.js: -------------------------------------------------------------------------------- 1 | /* 2 | * TotalStorage v. 1.1.2 3 | * Copyright (c) 2012 Jared Novack & Upstatement (upstatement.com) 4 | * Dual licensed under the MIT and GPL licenses: 5 | * http://www.opensource.org/licenses/mit-license.php 6 | * http://www.gnu.org/licenses/gpl.html 7 | * @author Jared Novack/jared@upstatement.com 8 | * @url http://upstatement.com/blog/2012/01/jquery-local-storage-done-right-and-easy/ 9 | */ 10 | if (typeof(jQuery) != "undefined") 11 | (function(c){var e=window.localStorage,f;f="undefined"==typeof e||"undefined"==typeof window.JSON?!1:!0;c.totalStorage=function(b,a){return c.totalStorage.impl.init(b,a)};c.totalStorage.setItem=function(b,a){return c.totalStorage.impl.setItem(b,a)};c.totalStorage.getItem=function(b){return c.totalStorage.impl.getItem(b)};c.totalStorage.getAll=function(){return c.totalStorage.impl.getAll()};c.totalStorage.deleteItem=function(b){return c.totalStorage.impl.deleteItem(b)};c.totalStorage.impl={init:function(b, 12 | a){return"undefined"!=typeof a?this.setItem(b,a):this.getItem(b)},setItem:function(b,a){if(!f)try{return c.cookie(b,a),a}catch(d){console.log("Local Storage not supported by this browser. Install the cookie plugin on your site to take advantage of the same functionality. You can get it at https://github.com/carhartl/jquery-cookie")}var g=JSON.stringify(a);e.setItem(b,g);return this.parseResult(g)},getItem:function(b){if(!f)try{return this.parseResult(c.cookie(b))}catch(a){return null}return this.parseResult(e.getItem(b))}, 13 | deleteItem:function(b){if(!f)try{return c.cookie(b,null),!0}catch(a){return!1}e.removeItem(b);return!0},getAll:function(){var b=[];if(f)for(d in e)d.length&&b.push({key:d,value:this.parseResult(e.getItem(d))});else try{for(var a=document.cookie.split(";"),d=0;d 2 8 | math.mean = math.ave = math.average = function(obj, key) { 9 | return math.sum(obj, key) / _.size(obj); 10 | }; 11 | 12 | // math.median([1,2,3,4]) 13 | // => 2.5 14 | // TODO {}, [{}] 15 | math.median = function(arr) { 16 | arr = arr.slice(0); // create copy 17 | var middle = (arr.length + 1) / 2, 18 | sorted = math.sort(arr); 19 | return (sorted.length % 2) ? sorted[middle - 1] : (sorted[middle - 1.5] + sorted[middle - 0.5]) / 2; 20 | }; 21 | 22 | // Power, exponent 23 | // math.pow(2,3) 24 | // => 8 25 | math.pow = math.power = function(x, n) { 26 | if (_.isNumber(x)) 27 | return Math.pow(x, n); 28 | if (_.isArray(x)) 29 | return _.map(x, function(i) { return _.pow(i, n); }); 30 | }; 31 | 32 | // Round 33 | // math.round(12345.6789, 2) 34 | // => 12345.68 35 | math.round = function(number, decimals) { 36 | return Math.round(number * Math.pow(10, decimals)) / Math.pow(10, decimals); 37 | }; 38 | 39 | // Scale to max value 40 | // math.scale(1,[2,5,10]) 41 | // => [ 0.2, 0.5, 1] 42 | math.scale = function(arr, max) { 43 | max = max || 1; 44 | var max0 = _.max(arr); 45 | return _.map(arr, function(i) { return i * (max / max0); }); 46 | }; 47 | 48 | // Slope between two points 49 | // math.slope([0,0],[1,2]) 50 | // => 2 51 | math.slope = function(x, y) { 52 | return (y[1] - x[1]) / (y[0] - x[0]); 53 | }; 54 | 55 | // Numeric sort 56 | // math.sort([3,1,2]) 57 | // => [1,2,3] 58 | math.sort = function(arr) { 59 | return _.sortBy(arr, _.identity); 60 | }; 61 | 62 | // math.stdDeviation([1,2,3]) 63 | // => 0.816496580927726 64 | math.stdDeviation = math.sigma = function(arr) { 65 | return Math.sqrt(_.variance(arr)); 66 | }; 67 | 68 | // Sum of array 69 | // math.sum([1,2,3]) 70 | // => 6 71 | // math.sum([{b: 4},{b: 5},{b: 6}], 'b') 72 | // => 15 73 | math.sum = function(obj, key) { 74 | var arr; 75 | if (_.isArray(obj) && typeof obj[0] === 'number') { 76 | arr = obj; 77 | } else { 78 | key = key || 'value'; 79 | arr = _.pluck(obj, key); 80 | } 81 | var val = 0, i; 82 | for (i = 0; i < arr.length; i++) 83 | val += (arr[i]-0); 84 | return val; 85 | }; 86 | 87 | // math.transpose(([1,2,3], [4,5,6], [7,8,9]]) 88 | // => [[1,4,7], [2,5,8], [3,6,9]] 89 | math.transpose = function(arr) { 90 | var trans = []; 91 | _.each(arr, function(row, y){ 92 | _.each(row, function(col, x){ 93 | if (!trans[x]) trans[x] = []; 94 | trans[x][y] = col; 95 | }); 96 | }); 97 | return trans; 98 | }; 99 | 100 | // math.variance([1,2,3]) 101 | // => 2/3 102 | math.variance = function(arr) { 103 | var mean = _.mean(arr), 104 | variance = function(x) { return _.pow( x - mean, 2); }; 105 | return _(arr).map(variance).mean().value(); 106 | }; 107 | 108 | // Standard score, assuming normal distribution 109 | // math.zscore([1,2,3]) 110 | // => [-1.224744871391589, 0, 1.224744871391589] 111 | math.zscore = function(obj, key) { 112 | var arr; 113 | if (_.isArray(obj) && typeof obj[0] === 'number') { 114 | arr = obj; 115 | } else { 116 | key = key || 'value'; 117 | arr = _.pluck(obj, key); 118 | } 119 | 120 | var mean = _.mean(arr), 121 | sigma = _.stdDeviation(arr), 122 | zscore = function(d) { return (d - mean) / sigma; }; 123 | return _.map(arr, zscore); 124 | }; 125 | 126 | // math.movingAvg([1,2,3,4,5], 3); 127 | // => [2,3,4] 128 | math.movingAvg = math.movingAverage = function(arr, size) { 129 | var win, i, newarr = []; 130 | for(i = size-1; i <= arr.length; i++) { 131 | win = arr.slice(i - size, i); 132 | if (win.length === size) { 133 | newarr.push(_.mean(win)); 134 | } 135 | } 136 | return newarr; 137 | }; 138 | 139 | // add methods to Underscore.js namespace 140 | _.mixin(math); 141 | 142 | })(); 143 | -------------------------------------------------------------------------------- /demo.css: -------------------------------------------------------------------------------- 1 | body { 2 | background-color: #F8F8F8; 3 | font-family: Arial, Helvetica, sans-serif; 4 | font-size: 13px; 5 | } 6 | p { 7 | margin: 0; 8 | padding: 0; 9 | } 10 | fieldset { 11 | background-color: #EEE; 12 | border: 2px solid #AAA; 13 | white-space: nowrap; 14 | } 15 | legend { 16 | font-weight: bold; 17 | } 18 | table { 19 | border:0; 20 | } 21 | th { 22 | background-color: #DDD; 23 | padding: 0; 24 | } 25 | #p, #_p { 26 | background-color: #FFF; 27 | border: 2px solid #AAA; 28 | } 29 | .highlightedPath { 30 | stroke: black; 31 | stroke-width:1; 32 | fill: black; 33 | fill-opacity:0.3; 34 | } 35 | #p1, #_p1 { 36 | fill: #00009C; 37 | fill-opacity: 0.06; 38 | stroke: #D3D3DA; 39 | stroke-opacity: 1.0; 40 | stroke-width: 0.8; 41 | } 42 | #p2, #_p2 { 43 | fill: #9C0000; 44 | fill-opacity: 0.06; 45 | stroke: #FFA07A; 46 | stroke-opacity: 1.0; 47 | stroke-width: 0.8; 48 | } 49 | #p3, #_p3 { 50 | fill: #80ff9C; 51 | fill-opacity: 0.5; 52 | stroke: #003300; 53 | stroke-opacity: 1.0; 54 | stroke-width: 0.8; 55 | } 56 | #svg_source_textarea, #benchmark_exports_textarea { 57 | height: 300px; 58 | width: 1230px; 59 | } 60 | #svgcontainer { 61 | margin-right: 2px; 62 | margin-top: 6px; 63 | } 64 | #benchmark_fieldset { 65 | height: 350px; 66 | width: 367px; 67 | } 68 | .buttons { 69 | background-color: #666; 70 | border-radius: 10px; 71 | color: white; 72 | cursor: pointer; 73 | display: inline-block; 74 | font-size: 13px; 75 | line-height: 20px; 76 | margin-bottom: 2px; 77 | margin-top: 2px; 78 | padding: 0 12px; 79 | text-align: center; 80 | white-space: nowrap; 81 | } 82 | .subpolylinks { 83 | cursor: pointer; 84 | font-size: 13px; 85 | padding: 2px; 86 | } 87 | .subpolylinks:hover { 88 | background-color:#BBB; 89 | } 90 | /* To prevent odd text resizing in mobile Safari */ 91 | @media only screen and (max-device-width: 480px) { 92 | .body, p, fieldset, td, th { 93 | -webkit-text-size-adjust: 100% 94 | } 95 | } 96 | .polygon_explorer { 97 | border-collapse: collapse; 98 | text-align: left; 99 | white-space: normal; 100 | width: 461px; 101 | } 102 | .polygon_explorer > tr > th, .polygon_explorer > tr > td, 103 | .polygon_explorer > tbody > tr > th, .polygon_explorer > tbody > tr > td 104 | { 105 | border:1px solid #666; 106 | padding: 3px 4px 3px 4px; 107 | vertical-align:top; 108 | } 109 | .polygons_fieldset { 110 | border-collapse: collapse; 111 | width: 100%; 112 | } 113 | .polygons_fieldset td { 114 | vertical-align: top; 115 | white-space: nowrap; 116 | } 117 | .polygons_fieldset input[type=radio] { 118 | margin-left: 0; 119 | } 120 | .random { 121 | border-collapse: collapse; 122 | width: 100%; 123 | } 124 | .random td { 125 | padding: 0; 126 | padding-right: 10px; 127 | } 128 | .random_inputs { 129 | width: 25px 130 | } 131 | .random th { 132 | background-color: transparent; 133 | padding: 0; 134 | } 135 | .random_new_th { 136 | background-color: transparent; 137 | } 138 | .random_new_th button { 139 | margin: 0; 140 | } 141 | .random button, .random input { 142 | margin-bottom: 0; 143 | margin-top: 0; 144 | } 145 | #subj_polygon_count { 146 | margin-bottom: 2px; 147 | } 148 | .filltype_cliptype { 149 | border-collapse: collapse; 150 | } 151 | .filltype_cliptype td { 152 | padding: 0; 153 | vertical-align: top; 154 | } 155 | .offset_outer { 156 | border-collapse: collapse; 157 | width: 100%; 158 | } 159 | .offset_outer td { 160 | padding: 0; 161 | vertical-align: top; 162 | white-space: nowrap; 163 | } 164 | .offset_outer input[type=radio] { 165 | margin-left: 0; 166 | } 167 | .offset_inner input[type=text] { 168 | margin-bottom: 2px; 169 | } 170 | .offset_inner { 171 | border-collapse: collapse; 172 | } 173 | .offset_inner td { 174 | height: 100%; 175 | vertical-align: top; 176 | } 177 | #custom_polygons_fieldset, #random_polygons_fieldset, #svg_source_container, #enlarged_svg { 178 | display: none; 179 | } 180 | .custom_polygon_input { 181 | height: 15px; 182 | line-height: 15px; 183 | padding: 2px; 184 | width: 285px; 185 | } 186 | #polygon_explorer_string_inp { 187 | height:15px; 188 | line-height: 15px; 189 | margin: 0; 190 | padding: 2px; 191 | width: 371px; 192 | } 193 | .custom_polygon_inputs_table { 194 | border-collapse: collapse; 195 | } 196 | .bench { 197 | border-collapse: collapse; 198 | margin-bottom: 10px; 199 | width: 100%; 200 | white-space: nowrap; 201 | } 202 | .bench td, .bench th { 203 | border: 1px solid #444; 204 | font-size: 12px; 205 | padding: 2px; 206 | text-align: left; 207 | } 208 | .bench tfoot td { 209 | background-color: #DDD; 210 | font-weight: bold; 211 | } 212 | /* for minus / plus buttons */ 213 | .creaser { 214 | width: 2em; 215 | } -------------------------------------------------------------------------------- /formatter.js: -------------------------------------------------------------------------------- 1 | /* global _, Raphael*/ 2 | /* exported normalizeClipperPolygons */ 3 | 4 | 5 | /* Input can be JSON-stringified version of the following: 6 | - Array of arrays of points [[{"X":10,"Y":10},{"X":10,"Y":10},{"X":10,"Y":10}][{"X":10,"Y":10},{"X":10,"Y":10},{"X":10,"Y":10}]] 7 | - Array of points [{"X":10,"Y":10},{"X":10,"Y":10},{"X":10,"Y":10}] 8 | - The aboves in lowercase 9 | - Array of x,y-coordinates eg. [0, 10, 20, 30, 40, 50] or [0 10 20 30 40 50] or [0 10, 20 30, 40 50]; 10 | - The above without [] 11 | - SVG path string with commands MLVHZ and mlvhz 12 | Returns normalized Clipper Polygons object stringified or false in failure 13 | */ 14 | function normalizeClipperPolygons(polygonString) { 15 | if (typeof polygonString !== 'string') return false; 16 | polygonString = polygonString.trim(); 17 | var np, poly; 18 | if (polygonString.substr(0, 1).toUpperCase() === 'M') { 19 | np = SVGPathToClipperPolygons(polygonString); 20 | if (np === false) { 21 | return !!console.warn('Unable to parse SVG path string'); 22 | } 23 | return JSON.stringify(np); 24 | } 25 | polygonString = polygonString.replace(/[\s,]+/g, ','); 26 | if (polygonString.substr(0, 1) !== '[') polygonString = '[' + polygonString; 27 | if (polygonString.substr(-1, 1) !== ']') polygonString = polygonString + ']'; 28 | try { 29 | poly = JSON.parse(polygonString); 30 | } catch (err) { 31 | return !!console.warn('Unable to parse polygon string'); 32 | } 33 | // if only points without 'X' and 'Y' 34 | var temp_n = [], i; 35 | if (_.isArray(poly) && poly.length && typeof poly[0] === 'number') { 36 | for (i = 0; i < poly.length; i = i + 2) { 37 | temp_n.push({ 38 | X: poly[i], 39 | Y: poly[i + 1] 40 | }); 41 | } 42 | poly = temp_n; 43 | } 44 | // if an array of array of points without 'X' and 'Y' 45 | var temp_n2 = [], j; 46 | if (_.isArray(poly) && poly.length && _.isArray(poly[0]) && typeof poly[0][0] !== 'undefined' && typeof poly[0][0].X === 'undefined' && typeof poly[0][0].x === 'undefined') { 47 | for (j = 0; j < poly.length; j++) { 48 | temp_n = []; 49 | for (i = 0; i < poly[j].length; i = i + 2) { 50 | temp_n.push({ 51 | X: poly[j][i], 52 | Y: poly[j][i + 1] 53 | }); 54 | } 55 | temp_n2.push(temp_n); 56 | } 57 | poly = temp_n2; 58 | } 59 | 60 | // if not array of arrays, convert to array of arrays 61 | if (_.isArray(poly) && poly.length > 0 && !_.isArray(poly[0])) poly = [poly]; 62 | var pp, x, y; 63 | np = [[]]; 64 | for (i = 0; i < poly.length; i++) { 65 | np[i] = []; 66 | for (j = 0; j < poly[i].length; j++) { 67 | pp = {}; 68 | y = null; 69 | x = null; 70 | if (typeof poly[i][j].X !== 'undefined' && !isNaN(Number(poly[i][j].X))) x = Number(poly[i][j].X); 71 | else if (typeof poly[i][j].x !== 'undefined' && !isNaN(Number(poly[i][j].x))) x = Number(poly[i][j].x); 72 | if (typeof poly[i][j].Y !== 'undefined' && !isNaN(Number(poly[i][j].Y))) y = Number(poly[i][j].Y); 73 | else if (typeof poly[i][j].y !== 'undefined' && !isNaN(Number(poly[i][j].y))) y = Number(poly[i][j].y); 74 | if (y !== null && x !== null) { 75 | pp.X = x; 76 | pp.Y = y; 77 | np[i].push(pp); 78 | } else { 79 | return !!console.warn('Unable to parse polygon string Error: Coordinates are not in a right form.'); 80 | } 81 | } 82 | } 83 | return JSON.stringify(np); 84 | } 85 | 86 | // helper function for normalizeClipperPolygons() 87 | function SVGPathToClipperPolygons(d) { 88 | var arr = Raphael.parsePathString(d.trim()); // str to array 89 | arr = Raphael._pathToAbsolute(arr); // mahvstcsqz -> uppercase 90 | var str = _.flatten(arr).join(' '), 91 | paths = str.replace(/M/g, '|M').split('|'), 92 | polygons = [], polygon; 93 | for (var k = 0; k < paths.length; k++) { 94 | if (paths[k].trim() === '') continue; 95 | arr = Raphael.parsePathString(paths[k].trim()); 96 | polygon = []; 97 | var letter = '', 98 | x = 0, 99 | y = 0, 100 | pt = {}, 101 | subPathStart = { 102 | x: '', 103 | y: '' 104 | }; 105 | for (var i = 0; i < arr.length; i++) { 106 | letter = arr[i][0].toUpperCase(); 107 | if (letter !== 'M' && letter !== 'L' && letter !== 'Z') continue; 108 | if (letter !== 'Z') { 109 | for (var j = 1; j < arr[i].length; j = j + 2) { 110 | if (letter === 'V') y = arr[i][j]; 111 | else if (letter === 'H') x = arr[i][j]; 112 | else { 113 | x = arr[i][j]; 114 | y = arr[i][j + 1]; 115 | } 116 | pt = { 117 | X: null, 118 | Y: null 119 | }; 120 | if (typeof x !== 'undefined' && !isNaN(Number(x))) pt.X = Number(x); 121 | if (typeof y !== 'undefined' && !isNaN(Number(y))) pt.Y = Number(y); 122 | if (pt.X !== null && pt.Y !== null) { 123 | polygon.push(pt); 124 | } else { 125 | return false; 126 | } 127 | } 128 | } 129 | if ((letter !== 'Z' && subPathStart.x === '') || letter === 'M') { 130 | subPathStart.x = x; 131 | subPathStart.y = y; 132 | } 133 | if (letter === 'Z') { 134 | x = subPathStart.x; 135 | y = subPathStart.y; 136 | } 137 | } 138 | polygons.push(polygon); 139 | } 140 | return polygons; 141 | } 142 | -------------------------------------------------------------------------------- /vendor/rgb-color.js: -------------------------------------------------------------------------------- 1 | /** 2 | * A class to parse color values 3 | * @author Stoyan Stefanov 4 | * @link http://www.phpied.com/rgb-color-parser-in-javascript/ 5 | * @license Use it if you like it 6 | */ 7 | function RGBColor(color_string) { 8 | if (typeof(color_string) == "undefined") color_string=""; 9 | this.ok = false; 10 | // strip any leading # 11 | if (color_string.charAt(0) == '#') { // remove # if any 12 | color_string = color_string.substr(1, 6); 13 | } 14 | color_string = color_string.replace(/ /g, ''); 15 | color_string = color_string.toLowerCase(); 16 | // before getting into regexps, try simple matches 17 | // and overwrite the input 18 | var simple_colors = { aliceblue:'f0f8ff', antiquewhite:'faebd7', aqua:'00ffff', aquamarine:'7fffd4', azure:'f0ffff', beige:'f5f5dc', bisque:'ffe4c4', black:'000000', blanchedalmond:'ffebcd', blue:'0000ff', blueviolet:'8a2be2', brown:'a52a2a', burlywood:'deb887', cadetblue:'5f9ea0', chartreuse:'7fff00', chocolate:'d2691e', coral:'ff7f50', cornflowerblue:'6495ed', cornsilk:'fff8dc', crimson:'dc143c', cyan:'00ffff', darkblue:'00008b', darkcyan:'008b8b', darkgoldenrod:'b8860b', darkgray:'a9a9a9', darkgreen:'006400', darkkhaki:'bdb76b', darkmagenta:'8b008b', darkolivegreen:'556b2f', darkorange:'ff8c00', darkorchid:'9932cc', darkred:'8b0000', darksalmon:'e9967a', darkseagreen:'8fbc8f', darkslateblue:'483d8b', darkslategray:'2f4f4f', darkturquoise:'00ced1', darkviolet:'9400d3', deeppink:'ff1493', deepskyblue:'00bfff', dimgray:'696969', dodgerblue:'1e90ff', feldspar:'d19275', firebrick:'b22222', floralwhite:'fffaf0', forestgreen:'228b22', fuchsia:'ff00ff', gainsboro:'dcdcdc', ghostwhite:'f8f8ff', gold:'ffd700', goldenrod:'daa520', gray:'808080', green:'008000', greenyellow:'adff2f', honeydew:'f0fff0', hotpink:'ff69b4', indianred:'cd5c5c', indigo:'4b0082', ivory:'fffff0', khaki:'f0e68c', lavender:'e6e6fa', lavenderblush:'fff0f5', lawngreen:'7cfc00', lemonchiffon:'fffacd', lightblue:'add8e6', lightcoral:'f08080', lightcyan:'e0ffff', lightgoldenrodyellow:'fafad2', lightgrey:'d3d3d3', lightgreen:'90ee90', lightpink:'ffb6c1', lightsalmon:'ffa07a', lightseagreen:'20b2aa', lightskyblue:'87cefa', lightslateblue:'8470ff', lightslategray:'778899', lightsteelblue:'b0c4de', lightyellow:'ffffe0', lime:'00ff00', limegreen:'32cd32', linen:'faf0e6', magenta:'ff00ff', maroon:'800000', mediumaquamarine:'66cdaa', mediumblue:'0000cd', mediumorchid:'ba55d3', mediumpurple:'9370d8', mediumseagreen:'3cb371', mediumslateblue:'7b68ee', mediumspringgreen:'00fa9a', mediumturquoise:'48d1cc', mediumvioletred:'c71585', midnightblue:'191970', mintcream:'f5fffa', mistyrose:'ffe4e1', moccasin:'ffe4b5', navajowhite:'ffdead', navy:'000080', oldlace:'fdf5e6', olive:'808000', olivedrab:'6b8e23', orange:'ffa500', orangered:'ff4500', orchid:'da70d6', palegoldenrod:'eee8aa', palegreen:'98fb98', paleturquoise:'afeeee', palevioletred:'d87093', papayawhip:'ffefd5', peachpuff:'ffdab9', peru:'cd853f', pink:'ffc0cb', plum:'dda0dd', powderblue:'b0e0e6', purple:'800080', red:'ff0000', rosybrown:'bc8f8f', royalblue:'4169e1', saddlebrown:'8b4513', salmon:'fa8072', sandybrown:'f4a460', seagreen:'2e8b57', seashell:'fff5ee', sienna:'a0522d', silver:'c0c0c0', skyblue:'87ceeb', slateblue:'6a5acd', slategray:'708090', snow:'fffafa', springgreen:'00ff7f', steelblue:'4682b4', tan:'d2b48c', teal:'008080', thistle:'d8bfd8', tomato:'ff6347', turquoise:'40e0d0', violet:'ee82ee', violetred:'d02090', wheat:'f5deb3', white:'ffffff', whitesmoke:'f5f5f5', yellow:'ffff00', yellowgreen:'9acd32' }; 19 | for (var key in simple_colors) { 20 | if (color_string == key) { 21 | color_string = simple_colors[key]; 22 | } 23 | } 24 | // emd of simple type-in colors 25 | // array of color definition objects 26 | var color_defs = [ 27 | { 28 | re: /^rgb\((\d{1,3}),\s*(\d{1,3}),\s*(\d{1,3})\)$/, 29 | example: ['rgb(123, 234, 45)', 'rgb(255,234,245)'], 30 | process: function (bits) { 31 | return [ 32 | parseInt(bits[1], 10), 33 | parseInt(bits[2], 10), 34 | parseInt(bits[3], 10)]; 35 | } 36 | }, 37 | { 38 | re: /^(\w{2})(\w{2})(\w{2})$/, 39 | example: ['#00ff00', '336699'], 40 | process: function (bits) { 41 | return [ 42 | parseInt(bits[1], 16), 43 | parseInt(bits[2], 16), 44 | parseInt(bits[3], 16)]; 45 | } 46 | }, 47 | { 48 | re: /^(\w{1})(\w{1})(\w{1})$/, 49 | example: ['#fb0', 'f0f'], 50 | process: function (bits) { 51 | return [ 52 | parseInt(bits[1] + bits[1], 16), 53 | parseInt(bits[2] + bits[2], 16), 54 | parseInt(bits[3] + bits[3], 16)]; 55 | } 56 | } 57 | ]; 58 | // search through the definitions to find a match 59 | for (var i = 0; i < color_defs.length; i++) { 60 | var re = color_defs[i].re; 61 | var processor = color_defs[i].process; 62 | var bits = re.exec(color_string); 63 | if (bits) { 64 | channels = processor(bits); 65 | this.r = channels[0]; 66 | this.g = channels[1]; 67 | this.b = channels[2]; 68 | this.ok = true; 69 | } 70 | } 71 | // validate/cleanup values 72 | this.r = (this.r < 0 || isNaN(this.r)) ? 0 : ((this.r > 255) ? 255 : this.r); 73 | this.g = (this.g < 0 || isNaN(this.g)) ? 0 : ((this.g > 255) ? 255 : this.g); 74 | this.b = (this.b < 0 || isNaN(this.b)) ? 0 : ((this.b > 255) ? 255 : this.b); 75 | // some getters 76 | this.toRGB = function () { 77 | return 'rgb(' + this.r + ', ' + this.g + ', ' + this.b + ')'; 78 | }; 79 | this.toHex = function () { 80 | var r = this.r.toString(16); 81 | var g = this.g.toString(16); 82 | var b = this.b.toString(16); 83 | if (r.length == 1) r = '0' + r; 84 | if (g.length == 1) g = '0' + g; 85 | if (b.length == 1) b = '0' + b; 86 | return '#' + r + g + b; 87 | }; 88 | this.flattenRGBA = function (a, bg) { 89 | var alpha = 1 - parseFloat(a); 90 | this.r = Math.round((a * (this.r / 255) + (alpha * (bg.r / 255))) * 255); 91 | this.g = Math.round((a * (this.g / 255) + (alpha * (bg.g / 255))) * 255); 92 | this.b = Math.round((a * (this.b / 255) + (alpha * (bg.b / 255))) * 255); 93 | return this.toHex(); 94 | }; 95 | } -------------------------------------------------------------------------------- /demo.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Javascript Clipper Main Demo 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 264 | 359 | 372 | 373 |
21 |
22 | Polygons 23 | 24 | 25 | 33 | 41 | 49 | 55 | 56 |
26 | 27 |
28 | 29 |
30 | 31 |
32 |
34 | 35 |
36 | 37 |
38 | 39 |
40 |
42 | 43 |
44 | 45 |
46 | 47 |
48 |
50 | 51 |
52 | 53 |
54 |
57 |
58 |
59 | Your own custom polygons 60 | 61 | 74 | 75 |
76 | 77 | 78 | 81 | 84 | 85 | 86 | 89 | 92 | 93 |
79 | Subj 80 | 82 | 83 |
87 | Clip 88 | 90 | 91 |
94 | 95 | 96 | 97 | 98 | 99 |
100 |
101 |
102 | Random polygon settings 103 | 104 | 105 | 106 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 118 | 123 | 128 | 129 | 130 | 133 | 138 | 143 | 144 |
107 | 108 | Polygon countPoint count
116 | Subject 117 | 119 | 120 | 121 | 122 | 124 | 125 | 126 | 127 |
131 | Clip 132 | 134 | 135 | 136 | 137 | 139 | 140 | 141 | 142 |
145 |
146 | 147 | 148 | 155 | 162 | 163 |
149 |
150 | Subject FillType 151 |   152 | 153 |
154 |
156 |
157 | Clip FillType 158 |   159 | 160 |
161 |
164 |
165 | Clip type (operation) 166 |

167 |   168 |   169 |   170 |   171 | 172 |

173 |
174 |
175 | Cleaning and simplifying 176 |

177 | 181 |   182 |   186 | 190 | 191 |

192 |
193 |
194 | Offsetting 195 | 196 | 197 | 205 | 214 | 241 | 242 |
198 | Polygon 199 | 200 |
201 | 202 |
203 | 204 |
206 | JoinType 207 | 208 |
209 | 210 |
211 | 212 |
213 |
215 | 216 | 217 | 223 | 224 | 225 | 230 | 231 | 232 | 238 | 239 |
218 | Delta 219 | 220 | 221 | 222 |
MiterLimit 226 | 227 | 228 | 229 |
233 | 237 |
240 |
243 |
244 |
245 | Scale 246 |

247 | 248 | 249 |   250 | Bigints used: 251 | 252 |

253 |
254 |
255 | Misc 256 |   257 |   258 | 262 |
263 |
265 |
266 |
267 | Polygon explorer 268 | 272 |
273 | 274 | 275 | 291 | 292 | 293 | 294 | 295 | 296 | 297 | 298 | 299 | 302 | 305 | 308 | 311 | 312 | 313 | 316 | 319 | 321 | 324 | 325 | 326 | 329 | 332 | 335 | 339 | 340 | 341 | 344 | 347 | 350 | 354 | 355 |
276 | 277 | 278 | 281 | 288 | 289 |
279 | 280 | 282 | 287 |
290 |
TypePolysPointsPoints in subpolygons
300 | Subj 301 | 303 | 304 | 306 | 307 | 309 | 310 |
314 | Clip 315 | 317 | 318 | 320 | 322 | 323 |
327 | Solu 328 | 330 | 331 | 333 | 334 | 336 | 337 | 338 |
342 | Total 343 | 345 | 346 | 348 | 349 | 351 |
Area: Click above to see polygon area!
352 | 353 |
356 |
357 |
358 |
360 |
361 | Benchmark 362 | 363 | 364 | 365 | 366 |
367 |
368 |
369 |
370 |
371 |
374 |
375 | 376 |
377 |
378 |
379 | 380 | 381 | -------------------------------------------------------------------------------- /demo.js: -------------------------------------------------------------------------------- 1 | /* globals $, _, Raphael, ClipperLib, RGBColor */ 2 | var selectedPolygons = 1; // Texts 3 | var subj = { 4 | fillType: 1, 5 | random: null, 6 | subPolygons: 0, 7 | totalPoints: 0 8 | }; 9 | var clip = { 10 | fillType: 1, 11 | random: null, 12 | subPolygons: 0, 13 | totalPoints: 0 14 | }; 15 | var solution = { 16 | subPolygons: 0, 17 | totalPoints: 0 18 | }; 19 | var clipType = 3; // Xor 20 | var clean = true; 21 | var cleanDeltaDefault = 0.1; 22 | var cleanDelta = cleanDeltaDefault; 23 | var simplify = true; 24 | var lighten = true; 25 | var lightenDistanceDefault = 0.1; 26 | var lightenDistance = lightenDistanceDefault; 27 | var offsettablePoly = 'solution'; //, subject, clip 28 | var joinType = 0; 29 | var delta = -1; 30 | var miterLimit = 2.0; 31 | var autoFix = true; 32 | var scale = 100; 33 | var scaleAddition = 100; 34 | var dontRoundAndScale = false; 35 | var bevel = 0; 36 | var explorerEnabled = true; 37 | var clipper = new ClipperLib.Clipper(); 38 | var ss, cc, sss; 39 | var offsetResult; 40 | var p, p1, p2, p3; 41 | var bench; 42 | var lastCompletedBenchmark; 43 | var benchmarkGlob = []; 44 | var benchmarkElapsedTime = 0; 45 | var benchmarkExports = ''; 46 | var benchmarkRunning = false; 47 | var benchmarkAutomaticClick = false; 48 | var benchmarkClickedButtonId; 49 | var benchmarkRepeat = 0; 50 | var benchmarkRepeatTimes; 51 | // The Phantom image 52 | var defaultCustomSubjectPolygon = '[[{"X":-29.42,"Y":106.23},{"X":-26.7,"Y":105.45},{"X":-11.55,"Y":101.73},{"X":0.12,"Y":99.72},{"X":9.69,"Y":98.94},{"X":17.63,"Y":99.17},{"X":24.29,"Y":100.23},{"X":23.93,"Y":92.91},{"X":24.08,"Y":81.36},{"X":25.12,"Y":70.62},{"X":26.99,"Y":60.59},{"X":29.66,"Y":51.22},{"X":33.11,"Y":42.43},{"X":37.31,"Y":34.29},{"X":42.16,"Y":26.9},{"X":47.77,"Y":20.05},{"X":53.98,"Y":13.98},{"X":60.82,"Y":8.61},{"X":68.2,"Y":4.01},{"X":76.04,"Y":0.24},{"X":84.37,"Y":-2.73},{"X":92.97,"Y":-4.8},{"X":101.89,"Y":-5.98},{"X":110.88,"Y":-6.23},{"X":120,"Y":-5.53},{"X":128.99,"Y":-3.88},{"X":137.63,"Y":-1.36},{"X":145.94,"Y":2.06},{"X":153.87,"Y":6.32},{"X":161.29,"Y":11.4},{"X":168.03,"Y":17.14},{"X":174.22,"Y":23.66},{"X":179.7,"Y":30.8},{"X":184.49,"Y":38.59},{"X":188.54,"Y":46.95},{"X":191.9,"Y":56.1},{"X":194.44,"Y":65.81},{"X":196.16,"Y":76.18},{"X":197,"Y":87.09},{"X":196.94,"Y":98.79},{"X":195.88,"Y":111.18},{"X":207.51,"Y":112.86},{"X":220.6,"Y":115.46},{"X":233.18,"Y":118.91},{"X":245.2,"Y":123.18},{"X":256.72,"Y":128.26},{"X":267.97,"Y":134.26},{"X":278.87,"Y":141.16},{"X":289.73,"Y":149.16},{"X":300.72,"Y":158.47},{"X":312.07,"Y":169.38},{"X":312.06,"Y":169.37},{"X":336.14,"Y":177.32},{"X":355.16,"Y":183.81},{"X":367.78,"Y":189},{"X":378.1,"Y":194.19},{"X":387.04,"Y":199.69},{"X":395.07,"Y":205.73},{"X":400.6,"Y":210.78},{"X":405.18,"Y":216.34},{"X":409.93,"Y":223.8},{"X":420.35,"Y":243.91},{"X":425.91,"Y":253.51},{"X":431.07,"Y":260.69},{"X":436.35,"Y":266.43},{"X":436.34,"Y":266.42},{"X":443.69,"Y":272.81},{"X":469.07,"Y":291.49},{"X":477.42,"Y":298.56},{"X":483.68,"Y":305.01},{"X":487.79,"Y":310.56},{"X":497.28,"Y":326.73},{"X":502.53,"Y":334.76},{"X":511.53,"Y":345.81},{"X":337.97,"Y":345.86},{"X":315.38,"Y":321.1},{"X":303.25,"Y":308.84},{"X":303.26,"Y":308.85},{"X":292.72,"Y":299.47},{"X":292.69,"Y":299.5},{"X":290.88,"Y":300.26},{"X":290.89,"Y":300.25},{"X":283.26,"Y":304.12},{"X":283.27,"Y":304.11},{"X":275.98,"Y":308.87},{"X":268.76,"Y":314.74},{"X":261.42,"Y":322.02},{"X":261.43,"Y":322.01},{"X":253.55,"Y":331.26},{"X":242.73,"Y":345.84},{"X":-29.42,"Y":345.86}],[{"X":127.69,"Y":269.76},{"X":127.68,"Y":269.77},{"X":133.88,"Y":268.63},{"X":133.87,"Y":268.64},{"X":139.54,"Y":266.65},{"X":139.53,"Y":266.66},{"X":144.66,"Y":263.86},{"X":144.65,"Y":263.87},{"X":149.4,"Y":260.18},{"X":149.39,"Y":260.19},{"X":153.81,"Y":255.5},{"X":158.06,"Y":249.51},{"X":162.29,"Y":241.74},{"X":166.81,"Y":231.1},{"X":166.8,"Y":231.11},{"X":176.87,"Y":202.06},{"X":182.04,"Y":188.77},{"X":182.04,"Y":188.78},{"X":182.02,"Y":188.77},{"X":181.74,"Y":188.64},{"X":181.75,"Y":188.65},{"X":179.85,"Y":188.27},{"X":178.29,"Y":188.8},{"X":178.3,"Y":188.79},{"X":176.74,"Y":190.4},{"X":176.75,"Y":190.39},{"X":173.98,"Y":196.05},{"X":173.14,"Y":196.87},{"X":172.34,"Y":196.57},{"X":171.01,"Y":194.4},{"X":174.86,"Y":188.74},{"X":180.8,"Y":179.01},{"X":185.49,"Y":169.61},{"X":185.48,"Y":169.62},{"X":188.88,"Y":160.79},{"X":188.87,"Y":160.8},{"X":191.15,"Y":152.4},{"X":191.14,"Y":152.41},{"X":192.39,"Y":144.4},{"X":192.38,"Y":144.41},{"X":192.65,"Y":136.76},{"X":192.65,"Y":136.77},{"X":191.95,"Y":129.43},{"X":191.96,"Y":129.44},{"X":190.36,"Y":122.45},{"X":189.2,"Y":126.33},{"X":186.64,"Y":132.72},{"X":183.5,"Y":138.19},{"X":179.85,"Y":142.75},{"X":175.82,"Y":146.34},{"X":171.49,"Y":149.01},{"X":166.88,"Y":150.79},{"X":162.01,"Y":151.66},{"X":157.07,"Y":151.61},{"X":152.08,"Y":150.61},{"X":147.07,"Y":148.62},{"X":142.21,"Y":145.63},{"X":137.56,"Y":141.62},{"X":133.27,"Y":136.62},{"X":129.46,"Y":130.68},{"X":129.03,"Y":130.72},{"X":129.04,"Y":130.71},{"X":124.06,"Y":131.87},{"X":124.07,"Y":131.86},{"X":119.96,"Y":133.69},{"X":116.46,"Y":136.26},{"X":116.47,"Y":136.25},{"X":113.27,"Y":139.82},{"X":107.23,"Y":149.32},{"X":104.14,"Y":153.18},{"X":101,"Y":155.72},{"X":97.49,"Y":157.4},{"X":93.11,"Y":158.38},{"X":88.02,"Y":158.61},{"X":83.43,"Y":157.91},{"X":79.22,"Y":156.35},{"X":75,"Y":153.77},{"X":70.26,"Y":149.63},{"X":60.57,"Y":138.77},{"X":54.38,"Y":132.43},{"X":54.39,"Y":132.44},{"X":49.11,"Y":128.26},{"X":43.79,"Y":125.19},{"X":43.54,"Y":126.2},{"X":43.55,"Y":126.19},{"X":43.13,"Y":133.69},{"X":43.13,"Y":133.68},{"X":43.66,"Y":140.71},{"X":43.65,"Y":140.7},{"X":45.09,"Y":147.46},{"X":45.08,"Y":147.45},{"X":47.49,"Y":154.24},{"X":47.48,"Y":154.23},{"X":51.23,"Y":161.76},{"X":63.98,"Y":182.09},{"X":67.55,"Y":189.18},{"X":69.73,"Y":195.4},{"X":70.92,"Y":201.58},{"X":71.16,"Y":207.87},{"X":70.43,"Y":214.58},{"X":68.63,"Y":221.85},{"X":68.56,"Y":221.68},{"X":68.68,"Y":203.83},{"X":68.68,"Y":203.84},{"X":68.16,"Y":197.1},{"X":68.17,"Y":197.11},{"X":67.05,"Y":192.75},{"X":67.06,"Y":192.76},{"X":65.5,"Y":189.85},{"X":65.51,"Y":189.86},{"X":63.49,"Y":187.86},{"X":60.94,"Y":186.59},{"X":60.95,"Y":186.6},{"X":57.55,"Y":186.01},{"X":57.78,"Y":189.41},{"X":57.77,"Y":189.4},{"X":59.32,"Y":201.46},{"X":59.31,"Y":201.45},{"X":61.68,"Y":212.76},{"X":61.67,"Y":212.75},{"X":64.76,"Y":223.11},{"X":64.75,"Y":223.1},{"X":68.47,"Y":232.45},{"X":72.73,"Y":240.71},{"X":77.44,"Y":247.84},{"X":82.45,"Y":253.81},{"X":82.44,"Y":253.8},{"X":87.82,"Y":258.8},{"X":93.45,"Y":262.8},{"X":93.44,"Y":262.79},{"X":99.44,"Y":265.89},{"X":99.43,"Y":265.88},{"X":105.67,"Y":268.07},{"X":105.66,"Y":268.06},{"X":112.58,"Y":269.42},{"X":112.57,"Y":269.41},{"X":120.65,"Y":270.08}],[{"X":121.49,"Y":240.71},{"X":118.05,"Y":239.68},{"X":115.54,"Y":238.06},{"X":113.86,"Y":235.97},{"X":112.96,"Y":233.43},{"X":112.86,"Y":230.29},{"X":112.9,"Y":230.33},{"X":114.24,"Y":231.32},{"X":114.23,"Y":231.31},{"X":117.3,"Y":232.52},{"X":117.29,"Y":232.51},{"X":122.05,"Y":233.17},{"X":132.1,"Y":233.03},{"X":140.49,"Y":233.06},{"X":139.8,"Y":234.49},{"X":137.79,"Y":236.7},{"X":134.63,"Y":238.72},{"X":130.41,"Y":240.25},{"X":125.83,"Y":240.94}],[{"X":90.76,"Y":219.11},{"X":91.11,"Y":218.28},{"X":92.59,"Y":216.41},{"X":95.22,"Y":214.69},{"X":99.6,"Y":213.14},{"X":106.53,"Y":211.9},{"X":117,"Y":211.2},{"X":143.09,"Y":211.3},{"X":151.49,"Y":210.93},{"X":151.31,"Y":211.49},{"X":149.72,"Y":213.46},{"X":147.43,"Y":214.88},{"X":143.97,"Y":215.82},{"X":138.58,"Y":216.09},{"X":117.5,"Y":214.37},{"X":117.51,"Y":214.38},{"X":108.81,"Y":214.35},{"X":101.81,"Y":215.22},{"X":101.82,"Y":215.21},{"X":95.89,"Y":216.85},{"X":95.9,"Y":216.84},{"X":90.72,"Y":219.22}],[{"X":131.9,"Y":198.38},{"X":131.72,"Y":195.25},{"X":132.38,"Y":192.96},{"X":133.78,"Y":191.21},{"X":136.84,"Y":189.34},{"X":140.91,"Y":187.09},{"X":142.52,"Y":185.35},{"X":143.3,"Y":183.24},{"X":143.3,"Y":183.25},{"X":143.22,"Y":183.13},{"X":141.54,"Y":180.12},{"X":139.65,"Y":174.9},{"X":138.32,"Y":168.14},{"X":137.62,"Y":158.87},{"X":137.76,"Y":144.77},{"X":142.77,"Y":159.79},{"X":145.49,"Y":170.4},{"X":146.69,"Y":178.4},{"X":146.78,"Y":184.55},{"X":146.02,"Y":189.28},{"X":144.58,"Y":192.89},{"X":142.54,"Y":195.66},{"X":139.94,"Y":197.69},{"X":136.5,"Y":199.14},{"X":132.22,"Y":199.86}],[{"X":108.17,"Y":188.43},{"X":106.35,"Y":187.41},{"X":105.13,"Y":185.72},{"X":104.56,"Y":183.25},{"X":104.61,"Y":183.31},{"X":104.81,"Y":183.53},{"X":104.8,"Y":183.52},{"X":106.39,"Y":184.64},{"X":106.38,"Y":184.63},{"X":108.44,"Y":184.92},{"X":114,"Y":183.64},{"X":116.83,"Y":183.49},{"X":119.09,"Y":184.26},{"X":121.14,"Y":185.99},{"X":120.5,"Y":186.31},{"X":114.98,"Y":188.22},{"X":110.98,"Y":188.8}],[{"X":163.89,"Y":141.31},{"X":166.4,"Y":137.22},{"X":174.87,"Y":127.72},{"X":177.63,"Y":123.62},{"X":179.28,"Y":119.59},{"X":179.28,"Y":119.6},{"X":179.24,"Y":119.6},{"X":179.25,"Y":119.59},{"X":176.7,"Y":119.79},{"X":176.71,"Y":119.78},{"X":170.65,"Y":120.87},{"X":170.66,"Y":120.86},{"X":164.55,"Y":122.95},{"X":164.56,"Y":122.94},{"X":148.93,"Y":130.62},{"X":148.93,"Y":130.61},{"X":149.21,"Y":132.61},{"X":149.2,"Y":132.6},{"X":150.57,"Y":136.41},{"X":152.55,"Y":139.41},{"X":152.54,"Y":139.4},{"X":155.11,"Y":141.71},{"X":155.1,"Y":141.7},{"X":158.43,"Y":143.41},{"X":158.42,"Y":143.4},{"X":162.62,"Y":144.5}],[{"X":90.87,"Y":144.21},{"X":90.86,"Y":144.22},{"X":93.93,"Y":139.6},{"X":97.47,"Y":134.4},{"X":99.02,"Y":130.65},{"X":99.02,"Y":130.66},{"X":98.92,"Y":130.62},{"X":98.93,"Y":130.63},{"X":63.23,"Y":119.65},{"X":67.31,"Y":125.14},{"X":73.8,"Y":132.62},{"X":73.79,"Y":132.61},{"X":79.3,"Y":137.68},{"X":84.84,"Y":141.56},{"X":84.83,"Y":141.55},{"X":90.59,"Y":144.44}],[{"X":128.47,"Y":127.41},{"X":128.46,"Y":127.42},{"X":134.55,"Y":125.73},{"X":134.54,"Y":125.74},{"X":141.57,"Y":122.7},{"X":141.56,"Y":122.71},{"X":154.9,"Y":115.21},{"X":164.19,"Y":110.32},{"X":171.16,"Y":107.57},{"X":177.57,"Y":106},{"X":183.83,"Y":105.4},{"X":190.12,"Y":105.74},{"X":182.19,"Y":101.42},{"X":182.2,"Y":101.43},{"X":175.96,"Y":98.85},{"X":175.97,"Y":98.86},{"X":170.13,"Y":97.45},{"X":170.14,"Y":97.46},{"X":164,"Y":96.98},{"X":157.13,"Y":97.46},{"X":157.08,"Y":97.55},{"X":156.47,"Y":98.59},{"X":153.09,"Y":103.35},{"X":149.58,"Y":106.83},{"X":145.83,"Y":109.3},{"X":141.79,"Y":110.89},{"X":137.21,"Y":111.67},{"X":131.97,"Y":111.55},{"X":125.78,"Y":110.38},{"X":117.8,"Y":107.78},{"X":92.32,"Y":96.78},{"X":92.33,"Y":96.79},{"X":83.94,"Y":93.95},{"X":83.95,"Y":93.96},{"X":77.47,"Y":92.65},{"X":77.48,"Y":92.66},{"X":72.09,"Y":92.45},{"X":67.49,"Y":93.16},{"X":67.5,"Y":93.15},{"X":63.28,"Y":94.72},{"X":63.29,"Y":94.71},{"X":59.49,"Y":97.13},{"X":55.9,"Y":100.53},{"X":55.91,"Y":100.52},{"X":52.52,"Y":105.09},{"X":49.25,"Y":111.18},{"X":52.77,"Y":110.06},{"X":58.91,"Y":108.7},{"X":64.9,"Y":108.31},{"X":70.86,"Y":108.86},{"X":77.27,"Y":110.42},{"X":84.53,"Y":113.27},{"X":105.04,"Y":123.87},{"X":105.03,"Y":123.86},{"X":111.74,"Y":126.51},{"X":111.73,"Y":126.5},{"X":117.29,"Y":127.77},{"X":117.28,"Y":127.76},{"X":122.82,"Y":128.06}]]'; 53 | // The Phantom Skull Ring 54 | var defaultCustomClipPolygon = '[[{"X":385.77,"Y":166.95},{"X":386.68,"Y":182.21},{"X":386.15,"Y":187.13},{"X":384.96,"Y":190.99},{"X":382.95,"Y":194.32},{"X":379.91,"Y":197.42},{"X":375.8,"Y":200.17},{"X":370.59,"Y":202.47},{"X":364.37,"Y":204.13},{"X":357.67,"Y":204.95},{"X":350.93,"Y":204.85},{"X":344.71,"Y":203.87},{"X":339.59,"Y":202.19},{"X":335.52,"Y":199.95},{"X":332.61,"Y":197.37},{"X":330.67,"Y":194.53},{"X":329.62,"Y":191.41},{"X":329.4,"Y":187.83},{"X":330.02,"Y":183.99},{"X":331.34,"Y":181.14},{"X":333.27,"Y":179.05},{"X":336.11,"Y":177.4},{"X":340.71,"Y":176.05},{"X":352.22,"Y":173.98},{"X":356.3,"Y":172.51},{"X":361.25,"Y":169.4},{"X":370.03,"Y":163.12},{"X":373.94,"Y":161.22},{"X":377.01,"Y":160.6},{"X":379.53,"Y":160.94},{"X":381.9,"Y":162.19},{"X":384.3,"Y":164.67},{"X":385.77,"Y":166.93},{"X":385.77,"Y":166.95}],[{"X":270.77,"Y":163.84},{"X":273.88,"Y":163.4},{"X":276.36,"Y":163.91},{"X":280.12,"Y":166.08},{"X":285.42,"Y":169.2},{"X":291.02,"Y":171.33},{"X":299.79,"Y":173.33},{"X":307.68,"Y":175.13},{"X":311.52,"Y":176.78},{"X":314.01,"Y":178.71},{"X":315.73,"Y":181.15},{"X":316.83,"Y":184.41},{"X":317.2,"Y":188.89},{"X":316.7,"Y":192.44},{"X":315.33,"Y":195.6},{"X":313.05,"Y":198.56},{"X":309.77,"Y":201.19},{"X":305.39,"Y":203.45},{"X":299.95,"Y":205.12},{"X":293.7,"Y":205.99},{"X":287.12,"Y":205.96},{"X":280.75,"Y":205},{"X":275.02,"Y":203.24},{"X":270.05,"Y":200.77},{"X":266.08,"Y":197.81},{"X":263.1,"Y":194.47},{"X":260.95,"Y":190.7},{"X":259.68,"Y":186.54},{"X":259.29,"Y":181.92},{"X":259.86,"Y":176.86},{"X":261.36,"Y":171.68},{"X":263.13,"Y":168.56},{"X":265.48,"Y":166.25},{"X":268.64,"Y":164.55},{"X":270.77,"Y":163.84},{"X":270.77,"Y":163.84}],[{"X":303.94,"Y":227.57},{"X":303.74,"Y":222.63},{"X":304.44,"Y":218.35},{"X":305.94,"Y":214.59},{"X":308.24,"Y":211.27},{"X":311.35,"Y":208.46},{"X":315.13,"Y":206.32},{"X":319.55,"Y":204.91},{"X":324.31,"Y":204.37},{"X":329.09,"Y":204.77},{"X":333.4,"Y":206.03},{"X":337.08,"Y":208.03},{"X":339.99,"Y":210.61},{"X":342.11,"Y":213.69},{"X":343.43,"Y":217.19},{"X":343.94,"Y":221.2},{"X":343.59,"Y":225.38},{"X":342.53,"Y":228.01},{"X":340.69,"Y":230.17},{"X":337.79,"Y":232.02},{"X":333.81,"Y":233.34},{"X":328.46,"Y":234.03},{"X":322.02,"Y":233.83},{"X":315.23,"Y":232.68},{"X":309.37,"Y":230.81},{"X":305.39,"Y":228.73},{"X":303.99,"Y":227.61},{"X":303.94,"Y":227.57}],[{"X":421.16,"Y":64.34},{"X":421.16,"Y":64.45},{"X":422.7,"Y":96.81},{"X":424.28,"Y":149.29},{"X":425.26,"Y":216.18},{"X":425.57,"Y":327.02},{"X":220.65,"Y":327.02},{"X":220.41,"Y":312.05},{"X":219.69,"Y":230.46},{"X":219.9,"Y":144.66},{"X":221.01,"Y":65.92},{"X":233.74,"Y":65.34},{"X":264.63,"Y":64.78},{"X":325.38,"Y":65.31},{"X":363.93,"Y":65.31},{"X":393.46,"Y":64.48},{"X":420.05,"Y":62.8},{"X":420.8,"Y":62.92},{"X":421.16,"Y":64.34}],[{"X":404.57,"Y":215.13},{"X":404.58,"Y":215.08},{"X":405.83,"Y":205.87},{"X":406.55,"Y":194.49},{"X":406.3,"Y":183.7},{"X":405.16,"Y":173.57},{"X":403.17,"Y":164.03},{"X":400.34,"Y":155.01},{"X":396.73,"Y":146.61},{"X":392.34,"Y":138.76},{"X":387.23,"Y":131.54},{"X":381.47,"Y":125.02},{"X":375.05,"Y":119.16},{"X":368.04,"Y":114.01},{"X":360.39,"Y":109.58},{"X":352.3,"Y":105.99},{"X":343.88,"Y":103.28},{"X":335.22,"Y":101.47},{"X":326.42,"Y":100.59},{"X":317.57,"Y":100.64},{"X":308.77,"Y":101.63},{"X":300.3,"Y":103.53},{"X":292.06,"Y":106.33},{"X":284.32,"Y":109.94},{"X":277.01,"Y":114.36},{"X":270.11,"Y":119.65},{"X":263.83,"Y":125.67},{"X":258.83,"Y":131.66},{"X":253.44,"Y":139.77},{"X":248.35,"Y":149.13},{"X":244.11,"Y":158.88},{"X":241,"Y":168.28},{"X":239,"Y":177.21},{"X":238.09,"Y":185.4},{"X":238.17,"Y":192.9},{"X":239.13,"Y":199.57},{"X":240.91,"Y":205.61},{"X":243.45,"Y":211.04},{"X":246.09,"Y":214.67},{"X":249.63,"Y":217.9},{"X":254.56,"Y":221.04},{"X":270.07,"Y":228.23},{"X":275.76,"Y":231.57},{"X":279.77,"Y":234.93},{"X":282.82,"Y":238.64},{"X":285.08,"Y":242.87},{"X":286.61,"Y":247.72},{"X":287.31,"Y":253.67},{"X":287.19,"Y":274.82},{"X":287.8,"Y":281.39},{"X":288.94,"Y":285.57},{"X":290.57,"Y":288.43},{"X":292.56,"Y":290.24},{"X":295.1,"Y":291.3},{"X":295.83,"Y":283.75},{"X":296,"Y":265.6},{"X":296.31,"Y":250.76},{"X":297.29,"Y":241.67},{"X":299.29,"Y":240.75},{"X":303.08,"Y":239.94},{"X":307.26,"Y":240},{"X":307.66,"Y":242.7},{"X":309.02,"Y":256.43},{"X":310.57,"Y":291.19},{"X":311.49,"Y":291.54},{"X":314.95,"Y":293.31},{"X":316.6,"Y":294.82},{"X":316.6,"Y":295.52},{"X":315.35,"Y":295.94},{"X":315.99,"Y":296.02},{"X":317.2,"Y":295.47},{"X":318.2,"Y":293.99},{"X":319.04,"Y":290.81},{"X":319.39,"Y":284.37},{"X":318.41,"Y":262.35},{"X":318.37,"Y":251.85},{"X":319.08,"Y":245.75},{"X":320.27,"Y":242.05},{"X":321.29,"Y":240.77},{"X":323.08,"Y":240.08},{"X":328.27,"Y":240},{"X":329.31,"Y":244.13},{"X":330.19,"Y":252.03},{"X":330.63,"Y":273.92},{"X":331.25,"Y":284.25},{"X":332.33,"Y":289.99},{"X":333.7,"Y":293.31},{"X":335.26,"Y":295.12},{"X":337.01,"Y":295.94},{"X":337.81,"Y":294.94},{"X":339.33,"Y":291.52},{"X":340.32,"Y":286.68},{"X":340.61,"Y":279.64},{"X":339.38,"Y":260.18},{"X":339.31,"Y":251.49},{"X":340.05,"Y":245.84},{"X":341.39,"Y":241.87},{"X":342.36,"Y":240.75},{"X":344.31,"Y":240.04},{"X":351.49,"Y":240},{"X":351.67,"Y":240.9},{"X":352.45,"Y":248.35},{"X":352.58,"Y":274.14},{"X":353.27,"Y":282.2},{"X":354.5,"Y":287.31},{"X":356.13,"Y":290.68},{"X":358.13,"Y":292.86},{"X":359.27,"Y":289.89},{"X":360.62,"Y":284.2},{"X":361.32,"Y":276.58},{"X":361.16,"Y":258.89},{"X":361.45,"Y":247.8},{"X":365.47,"Y":242.21},{"X":370.89,"Y":236.4},{"X":377.72,"Y":230.54},{"X":385.94,"Y":224.78},{"X":395.31,"Y":219.41},{"X":404.57,"Y":215.13}]]'; 55 | var outputFormat = 'Clipper'; //, Plain, SVG 56 | // this hold the original ClipperLib.MaxSteps value during benchmarks, ClipperLib.MaxSteps is set to 10 to make benchmarks comparable 57 | var ClipperLibOriginalMaxSteps; 58 | var windowWidth = $(document).width() * 0.9; 59 | var updateEnlargedSVG = false; 60 | var updateSVGSource = false; 61 | var lsk = 0; 62 | var randomSettings = { 63 | current: 'norm', 64 | rect: { 65 | 'default': { 66 | clipPolygonCount: 1, 67 | clipPointCount: 4, 68 | subjPolygonCount: 2, 69 | subjPointCount: 8 70 | }, 71 | min: { 72 | clipPolygonCount: 1, 73 | clipPointCount: 4, 74 | subjPolygonCount: 1, 75 | subjPointCount: 4 76 | }, 77 | max: { 78 | clipPolygonCount: 100, 79 | clipPointCount: 100, 80 | subjPolygonCount: 100, 81 | subjPointCount: 100 82 | } 83 | }, 84 | norm: { 85 | 'default': { 86 | clipPolygonCount: 1, 87 | clipPointCount: 3, 88 | subjPolygonCount: 2, 89 | subjPointCount: 8 90 | }, 91 | min: { 92 | clipPolygonCount: 1, 93 | clipPointCount: 3, 94 | subjPolygonCount: 1, 95 | subjPointCount: 3 96 | }, 97 | max: { 98 | clipPolygonCount: 100, 99 | clipPointCount: 100, 100 | subjPolygonCount: 100, 101 | subjPointCount: 100 102 | } 103 | } 104 | }; 105 | var randomSetting = selectedPolygons === 4 ? randomSettings.rect['default'] : randomSettings.norm['default']; 106 | var defaultPolygons = [ 107 | { // GB and arrows 108 | subj: '[[{"X":189,"Y":154},{"X":192,"Y":155},{"X":193,"Y":154},{"X":194,"Y":151},{"X":194,"Y":150},{"X":196,"Y":151},{"X":199,"Y":151},{"X":200,"Y":150},{"X":203,"Y":149},{"X":204,"Y":149},{"X":205,"Y":149},{"X":206,"Y":149},{"X":209,"Y":150},{"X":211,"Y":149},{"X":212,"Y":149},{"X":212,"Y":152},{"X":212,"Y":155},{"X":213,"Y":156},{"X":213,"Y":156},{"X":213,"Y":159},{"X":214,"Y":159},{"X":216,"Y":161},{"X":216,"Y":161},{"X":216,"Y":163},{"X":217,"Y":163},{"X":218,"Y":166},{"X":218,"Y":166},{"X":217,"Y":163},{"X":217,"Y":162},{"X":218,"Y":162},{"X":218,"Y":163},{"X":220,"Y":165},{"X":218,"Y":167},{"X":218,"Y":167},{"X":215,"Y":168},{"X":214,"Y":170},{"X":214,"Y":171},{"X":215,"Y":170},{"X":217,"Y":168},{"X":220,"Y":168},{"X":221,"Y":168},{"X":222,"Y":170},{"X":223,"Y":172},{"X":223,"Y":174},{"X":224,"Y":176},{"X":223,"Y":178},{"X":223,"Y":179},{"X":223,"Y":179},{"X":223,"Y":180},{"X":222,"Y":180},{"X":222,"Y":180},{"X":221,"Y":178},{"X":222,"Y":177},{"X":222,"Y":174},{"X":221,"Y":174},{"X":220,"Y":172},{"X":218,"Y":172},{"X":218,"Y":174},{"X":220,"Y":174},{"X":218,"Y":174},{"X":220,"Y":176},{"X":220,"Y":178},{"X":217,"Y":180},{"X":221,"Y":179},{"X":221,"Y":180},{"X":222,"Y":181},{"X":221,"Y":182},{"X":218,"Y":183},{"X":218,"Y":183},{"X":217,"Y":182},{"X":214,"Y":184},{"X":214,"Y":187},{"X":214,"Y":189},{"X":211,"Y":191},{"X":210,"Y":191},{"X":210,"Y":190},{"X":209,"Y":189},{"X":207,"Y":189},{"X":206,"Y":189},{"X":207,"Y":189},{"X":209,"Y":191},{"X":209,"Y":191},{"X":210,"Y":191},{"X":207,"Y":192},{"X":205,"Y":191},{"X":204,"Y":191},{"X":204,"Y":191},{"X":204,"Y":192},{"X":204,"Y":194},{"X":204,"Y":195},{"X":206,"Y":195},{"X":206,"Y":198},{"X":206,"Y":199},{"X":206,"Y":200},{"X":206,"Y":202},{"X":206,"Y":203},{"X":210,"Y":206},{"X":209,"Y":207},{"X":207,"Y":211},{"X":209,"Y":212},{"X":210,"Y":212},{"X":210,"Y":213},{"X":207,"Y":212},{"X":207,"Y":213},{"X":206,"Y":213},{"X":207,"Y":215},{"X":209,"Y":216},{"X":209,"Y":218},{"X":210,"Y":222},{"X":209,"Y":226},{"X":211,"Y":226},{"X":209,"Y":231},{"X":207,"Y":232},{"X":206,"Y":234},{"X":205,"Y":237},{"X":205,"Y":240},{"X":202,"Y":246},{"X":201,"Y":247},{"X":200,"Y":247},{"X":200,"Y":247},{"X":200,"Y":248},{"X":201,"Y":249},{"X":201,"Y":248},{"X":201,"Y":250},{"X":202,"Y":251},{"X":201,"Y":254},{"X":200,"Y":254},{"X":201,"Y":253},{"X":199,"Y":254},{"X":199,"Y":253},{"X":199,"Y":253},{"X":196,"Y":254},{"X":194,"Y":251},{"X":192,"Y":253},{"X":193,"Y":251},{"X":192,"Y":251},{"X":192,"Y":251},{"X":191,"Y":251},{"X":192,"Y":253},{"X":191,"Y":253},{"X":190,"Y":254},{"X":189,"Y":255},{"X":189,"Y":255},{"X":190,"Y":254},{"X":190,"Y":253},{"X":190,"Y":251},{"X":189,"Y":251},{"X":189,"Y":249},{"X":189,"Y":251},{"X":189,"Y":253},{"X":189,"Y":253},{"X":188,"Y":255},{"X":185,"Y":254},{"X":187,"Y":253},{"X":185,"Y":253},{"X":185,"Y":253},{"X":185,"Y":254},{"X":184,"Y":254},{"X":183,"Y":254},{"X":179,"Y":254},{"X":177,"Y":255},{"X":177,"Y":255},{"X":176,"Y":255},{"X":174,"Y":255},{"X":176,"Y":256},{"X":177,"Y":257},{"X":176,"Y":257},{"X":176,"Y":258},{"X":172,"Y":258},{"X":172,"Y":260},{"X":171,"Y":260},{"X":170,"Y":260},{"X":169,"Y":259},{"X":169,"Y":260},{"X":168,"Y":260},{"X":169,"Y":261},{"X":167,"Y":262},{"X":166,"Y":264},{"X":166,"Y":264},{"X":162,"Y":265},{"X":161,"Y":264},{"X":161,"Y":264},{"X":162,"Y":262},{"X":163,"Y":261},{"X":160,"Y":262},{"X":158,"Y":261},{"X":158,"Y":262},{"X":159,"Y":262},{"X":160,"Y":264},{"X":160,"Y":265},{"X":160,"Y":265},{"X":158,"Y":267},{"X":157,"Y":267},{"X":156,"Y":267},{"X":155,"Y":267},{"X":155,"Y":267},{"X":154,"Y":268},{"X":154,"Y":270},{"X":154,"Y":269},{"X":151,"Y":269},{"X":150,"Y":272},{"X":149,"Y":272},{"X":149,"Y":270},{"X":147,"Y":270},{"X":147,"Y":272},{"X":146,"Y":272},{"X":146,"Y":272},{"X":144,"Y":270},{"X":143,"Y":272},{"X":141,"Y":270},{"X":141,"Y":272},{"X":140,"Y":272},{"X":140,"Y":271},{"X":140,"Y":273},{"X":139,"Y":273},{"X":139,"Y":273},{"X":139,"Y":273},{"X":138,"Y":272},{"X":138,"Y":273},{"X":137,"Y":273},{"X":137,"Y":273},{"X":136,"Y":272},{"X":137,"Y":270},{"X":136,"Y":269},{"X":136,"Y":270},{"X":135,"Y":270},{"X":134,"Y":270},{"X":134,"Y":272},{"X":133,"Y":272},{"X":133,"Y":272},{"X":132,"Y":272},{"X":132,"Y":270},{"X":129,"Y":272},{"X":130,"Y":272},{"X":128,"Y":272},{"X":128,"Y":271},{"X":127,"Y":272},{"X":127,"Y":271},{"X":127,"Y":271},{"X":129,"Y":269},{"X":132,"Y":269},{"X":134,"Y":267},{"X":134,"Y":267},{"X":128,"Y":269},{"X":127,"Y":269},{"X":128,"Y":268},{"X":129,"Y":267},{"X":136,"Y":266},{"X":136,"Y":266},{"X":136,"Y":265},{"X":136,"Y":265},{"X":135,"Y":264},{"X":135,"Y":262},{"X":135,"Y":264},{"X":134,"Y":266},{"X":126,"Y":266},{"X":126,"Y":267},{"X":124,"Y":267},{"X":123,"Y":267},{"X":122,"Y":267},{"X":122,"Y":267},{"X":122,"Y":267},{"X":122,"Y":266},{"X":123,"Y":267},{"X":123,"Y":266},{"X":123,"Y":265},{"X":123,"Y":265},{"X":125,"Y":265},{"X":126,"Y":264},{"X":125,"Y":264},{"X":125,"Y":262},{"X":127,"Y":261},{"X":127,"Y":262},{"X":127,"Y":261},{"X":129,"Y":261},{"X":128,"Y":261},{"X":130,"Y":259},{"X":133,"Y":259},{"X":134,"Y":259},{"X":132,"Y":259},{"X":129,"Y":260},{"X":128,"Y":260},{"X":127,"Y":260},{"X":127,"Y":260},{"X":122,"Y":262},{"X":122,"Y":261},{"X":121,"Y":261},{"X":121,"Y":260},{"X":122,"Y":259},{"X":121,"Y":258},{"X":119,"Y":259},{"X":118,"Y":260},{"X":118,"Y":258},{"X":117,"Y":258},{"X":117,"Y":256},{"X":119,"Y":256},{"X":121,"Y":256},{"X":119,"Y":255},{"X":119,"Y":255},{"X":121,"Y":254},{"X":121,"Y":254},{"X":126,"Y":251},{"X":127,"Y":250},{"X":127,"Y":251},{"X":127,"Y":251},{"X":128,"Y":249},{"X":129,"Y":249},{"X":132,"Y":249},{"X":128,"Y":248},{"X":127,"Y":248},{"X":127,"Y":249},{"X":126,"Y":248},{"X":123,"Y":249},{"X":122,"Y":248},{"X":121,"Y":248},{"X":119,"Y":248},{"X":121,"Y":249},{"X":121,"Y":249},{"X":118,"Y":248},{"X":119,"Y":249},{"X":117,"Y":249},{"X":116,"Y":248},{"X":116,"Y":248},{"X":116,"Y":247},{"X":117,"Y":247},{"X":116,"Y":246},{"X":117,"Y":246},{"X":117,"Y":247},{"X":118,"Y":247},{"X":118,"Y":245},{"X":119,"Y":245},{"X":121,"Y":244},{"X":123,"Y":244},{"X":123,"Y":245},{"X":125,"Y":246},{"X":126,"Y":244},{"X":125,"Y":243},{"X":126,"Y":242},{"X":126,"Y":244},{"X":127,"Y":246},{"X":129,"Y":246},{"X":129,"Y":246},{"X":129,"Y":246},{"X":132,"Y":246},{"X":132,"Y":245},{"X":128,"Y":245},{"X":128,"Y":243},{"X":129,"Y":244},{"X":129,"Y":243},{"X":130,"Y":240},{"X":128,"Y":239},{"X":128,"Y":239},{"X":133,"Y":238},{"X":134,"Y":237},{"X":135,"Y":238},{"X":135,"Y":237},{"X":134,"Y":237},{"X":134,"Y":237},{"X":135,"Y":235},{"X":136,"Y":235},{"X":138,"Y":236},{"X":138,"Y":235},{"X":141,"Y":236},{"X":147,"Y":234},{"X":147,"Y":235},{"X":148,"Y":235},{"X":149,"Y":234},{"X":151,"Y":234},{"X":151,"Y":234},{"X":154,"Y":234},{"X":150,"Y":233},{"X":149,"Y":233},{"X":149,"Y":232},{"X":148,"Y":231},{"X":147,"Y":231},{"X":147,"Y":232},{"X":144,"Y":235},{"X":143,"Y":234},{"X":141,"Y":236},{"X":140,"Y":235},{"X":141,"Y":234},{"X":139,"Y":234},{"X":137,"Y":234},{"X":137,"Y":233},{"X":136,"Y":232},{"X":137,"Y":234},{"X":134,"Y":234},{"X":134,"Y":235},{"X":129,"Y":234},{"X":128,"Y":234},{"X":132,"Y":234},{"X":135,"Y":231},{"X":136,"Y":229},{"X":138,"Y":229},{"X":138,"Y":227},{"X":139,"Y":226},{"X":139,"Y":224},{"X":141,"Y":223},{"X":140,"Y":223},{"X":138,"Y":223},{"X":138,"Y":223},{"X":139,"Y":222},{"X":143,"Y":217},{"X":146,"Y":217},{"X":147,"Y":217},{"X":147,"Y":217},{"X":149,"Y":217},{"X":147,"Y":217},{"X":149,"Y":217},{"X":149,"Y":217},{"X":150,"Y":217},{"X":150,"Y":217},{"X":150,"Y":216},{"X":151,"Y":215},{"X":150,"Y":215},{"X":149,"Y":215},{"X":149,"Y":214},{"X":150,"Y":213},{"X":150,"Y":213},{"X":150,"Y":212},{"X":148,"Y":212},{"X":146,"Y":213},{"X":139,"Y":213},{"X":138,"Y":213},{"X":138,"Y":211},{"X":138,"Y":211},{"X":137,"Y":213},{"X":137,"Y":213},{"X":137,"Y":212},{"X":137,"Y":211},{"X":137,"Y":210},{"X":137,"Y":210},{"X":138,"Y":210},{"X":137,"Y":209},{"X":137,"Y":210},{"X":137,"Y":209},{"X":137,"Y":209},{"X":137,"Y":209},{"X":137,"Y":209},{"X":136,"Y":210},{"X":135,"Y":210},{"X":134,"Y":209},{"X":133,"Y":209},{"X":133,"Y":207},{"X":133,"Y":207},{"X":135,"Y":206},{"X":135,"Y":206},{"X":135,"Y":206},{"X":135,"Y":206},{"X":133,"Y":206},{"X":133,"Y":206},{"X":133,"Y":206},{"X":133,"Y":206},{"X":132,"Y":206},{"X":132,"Y":207},{"X":129,"Y":206},{"X":128,"Y":205},{"X":127,"Y":206},{"X":127,"Y":205},{"X":126,"Y":205},{"X":127,"Y":203},{"X":129,"Y":204},{"X":128,"Y":203},{"X":128,"Y":202},{"X":127,"Y":201},{"X":126,"Y":201},{"X":128,"Y":201},{"X":128,"Y":200},{"X":132,"Y":201},{"X":129,"Y":198},{"X":134,"Y":198},{"X":134,"Y":196},{"X":134,"Y":194},{"X":136,"Y":193},{"X":138,"Y":194},{"X":139,"Y":193},{"X":138,"Y":193},{"X":139,"Y":192},{"X":138,"Y":192},{"X":139,"Y":191},{"X":139,"Y":191},{"X":139,"Y":190},{"X":136,"Y":190},{"X":135,"Y":190},{"X":134,"Y":190},{"X":134,"Y":190},{"X":134,"Y":188},{"X":136,"Y":189},{"X":136,"Y":189},{"X":136,"Y":189},{"X":136,"Y":187},{"X":136,"Y":187},{"X":136,"Y":188},{"X":136,"Y":187},{"X":136,"Y":187},{"X":135,"Y":184},{"X":135,"Y":183},{"X":136,"Y":183},{"X":135,"Y":183},{"X":136,"Y":182},{"X":135,"Y":182},{"X":135,"Y":183},{"X":134,"Y":182},{"X":134,"Y":182},{"X":134,"Y":182},{"X":135,"Y":181},{"X":134,"Y":181},{"X":135,"Y":180},{"X":134,"Y":180},{"X":135,"Y":179},{"X":135,"Y":179},{"X":133,"Y":178},{"X":133,"Y":179},{"X":133,"Y":179},{"X":133,"Y":180},{"X":132,"Y":180},{"X":132,"Y":180},{"X":132,"Y":181},{"X":132,"Y":182},{"X":130,"Y":182},{"X":132,"Y":178},{"X":132,"Y":178},{"X":130,"Y":177},{"X":132,"Y":177},{"X":132,"Y":177},{"X":134,"Y":174},{"X":134,"Y":177},{"X":135,"Y":178},{"X":135,"Y":179},{"X":134,"Y":178},{"X":134,"Y":178},{"X":136,"Y":179},{"X":136,"Y":177},{"X":136,"Y":178},{"X":136,"Y":177},{"X":136,"Y":177},{"X":136,"Y":176},{"X":136,"Y":174},{"X":138,"Y":176},{"X":143,"Y":176},{"X":144,"Y":178},{"X":146,"Y":177},{"X":147,"Y":177},{"X":147,"Y":178},{"X":148,"Y":179},{"X":148,"Y":179},{"X":148,"Y":180},{"X":148,"Y":180},{"X":149,"Y":181},{"X":149,"Y":181},{"X":151,"Y":178},{"X":154,"Y":178},{"X":156,"Y":180},{"X":157,"Y":179},{"X":157,"Y":179},{"X":158,"Y":180},{"X":160,"Y":181},{"X":161,"Y":181},{"X":160,"Y":180},{"X":160,"Y":180},{"X":161,"Y":179},{"X":162,"Y":179},{"X":161,"Y":178},{"X":161,"Y":178},{"X":162,"Y":178},{"X":162,"Y":178},{"X":161,"Y":177},{"X":160,"Y":178},{"X":159,"Y":177},{"X":161,"Y":176},{"X":161,"Y":174},{"X":161,"Y":174},{"X":163,"Y":174},{"X":162,"Y":173},{"X":163,"Y":172},{"X":163,"Y":173},{"X":167,"Y":173},{"X":168,"Y":171},{"X":168,"Y":170},{"X":170,"Y":168},{"X":170,"Y":168},{"X":171,"Y":168},{"X":170,"Y":168},{"X":168,"Y":168},{"X":167,"Y":168},{"X":167,"Y":168},{"X":167,"Y":168},{"X":166,"Y":168},{"X":163,"Y":170},{"X":163,"Y":168},{"X":166,"Y":168},{"X":166,"Y":168},{"X":163,"Y":168},{"X":163,"Y":168},{"X":161,"Y":168},{"X":160,"Y":168},{"X":157,"Y":166},{"X":158,"Y":165},{"X":157,"Y":165},{"X":158,"Y":165},{"X":158,"Y":163},{"X":160,"Y":162},{"X":165,"Y":163},{"X":163,"Y":162},{"X":162,"Y":162},{"X":163,"Y":162},{"X":166,"Y":163},{"X":162,"Y":160},{"X":163,"Y":160},{"X":167,"Y":160},{"X":166,"Y":159},{"X":166,"Y":159},{"X":167,"Y":159},{"X":168,"Y":159},{"X":167,"Y":159},{"X":166,"Y":158},{"X":166,"Y":159},{"X":165,"Y":158},{"X":165,"Y":156},{"X":167,"Y":156},{"X":166,"Y":156},{"X":165,"Y":154},{"X":166,"Y":154},{"X":166,"Y":152},{"X":167,"Y":154},{"X":167,"Y":152},{"X":168,"Y":152},{"X":168,"Y":152},{"X":168,"Y":152},{"X":168,"Y":151},{"X":169,"Y":150},{"X":171,"Y":150},{"X":171,"Y":150},{"X":171,"Y":150},{"X":171,"Y":151},{"X":172,"Y":150},{"X":174,"Y":150},{"X":174,"Y":148},{"X":174,"Y":147},{"X":176,"Y":148},{"X":176,"Y":149},{"X":177,"Y":149},{"X":177,"Y":150},{"X":177,"Y":150},{"X":178,"Y":150},{"X":177,"Y":150},{"X":178,"Y":150},{"X":178,"Y":150},{"X":178,"Y":149},{"X":177,"Y":149},{"X":177,"Y":147},{"X":178,"Y":147},{"X":178,"Y":147},{"X":178,"Y":150},{"X":179,"Y":150},{"X":180,"Y":151},{"X":180,"Y":152},{"X":181,"Y":151},{"X":180,"Y":148},{"X":180,"Y":150},{"X":180,"Y":149},{"X":180,"Y":148},{"X":179,"Y":148},{"X":179,"Y":147},{"X":180,"Y":147},{"X":181,"Y":146},{"X":182,"Y":147},{"X":182,"Y":149},{"X":183,"Y":151},{"X":183,"Y":151},{"X":183,"Y":152},{"X":181,"Y":155},{"X":182,"Y":155},{"X":182,"Y":155},{"X":181,"Y":155},{"X":180,"Y":157},{"X":182,"Y":155},{"X":184,"Y":154},{"X":184,"Y":154},{"X":184,"Y":151},{"X":183,"Y":148},{"X":184,"Y":148},{"X":183,"Y":147},{"X":184,"Y":147},{"X":184,"Y":147},{"X":184,"Y":147},{"X":187,"Y":146},{"X":187,"Y":146},{"X":187,"Y":147},{"X":189,"Y":147},{"X":187,"Y":146},{"X":187,"Y":145},{"X":187,"Y":145},{"X":187,"Y":144},{"X":185,"Y":144},{"X":185,"Y":144},{"X":189,"Y":144},{"X":190,"Y":145},{"X":191,"Y":146},{"X":195,"Y":148},{"X":195,"Y":149},{"X":191,"Y":151}],[{"X":236,"Y":34},{"X":237,"Y":35},{"X":238,"Y":35},{"X":239,"Y":35},{"X":239,"Y":36},{"X":240,"Y":35},{"X":239,"Y":35},{"X":239,"Y":35},{"X":240,"Y":36},{"X":242,"Y":37},{"X":242,"Y":37},{"X":240,"Y":40},{"X":242,"Y":38},{"X":242,"Y":37},{"X":243,"Y":37},{"X":243,"Y":36},{"X":245,"Y":36},{"X":246,"Y":37},{"X":247,"Y":38},{"X":246,"Y":40},{"X":247,"Y":37},{"X":249,"Y":37},{"X":250,"Y":38},{"X":250,"Y":38},{"X":250,"Y":37},{"X":251,"Y":37},{"X":251,"Y":36},{"X":253,"Y":37},{"X":254,"Y":36},{"X":254,"Y":36},{"X":256,"Y":36},{"X":257,"Y":36},{"X":260,"Y":36},{"X":262,"Y":36},{"X":262,"Y":36},{"X":262,"Y":36},{"X":264,"Y":35},{"X":266,"Y":36},{"X":266,"Y":35},{"X":265,"Y":34},{"X":266,"Y":33},{"X":266,"Y":34},{"X":269,"Y":34},{"X":269,"Y":35},{"X":271,"Y":34},{"X":271,"Y":35},{"X":270,"Y":38},{"X":270,"Y":39},{"X":271,"Y":39},{"X":270,"Y":44},{"X":269,"Y":44},{"X":268,"Y":46},{"X":266,"Y":47},{"X":264,"Y":51},{"X":258,"Y":53},{"X":257,"Y":55},{"X":256,"Y":56},{"X":254,"Y":58},{"X":254,"Y":60},{"X":253,"Y":60},{"X":251,"Y":61},{"X":250,"Y":61},{"X":250,"Y":62},{"X":253,"Y":62},{"X":254,"Y":61},{"X":255,"Y":61},{"X":255,"Y":62},{"X":256,"Y":62},{"X":257,"Y":60},{"X":258,"Y":61},{"X":256,"Y":63},{"X":254,"Y":66},{"X":254,"Y":66},{"X":254,"Y":66},{"X":253,"Y":66},{"X":250,"Y":67},{"X":248,"Y":66},{"X":248,"Y":68},{"X":246,"Y":69},{"X":246,"Y":70},{"X":249,"Y":67},{"X":253,"Y":67},{"X":253,"Y":66},{"X":254,"Y":67},{"X":251,"Y":69},{"X":251,"Y":69},{"X":251,"Y":70},{"X":250,"Y":71},{"X":250,"Y":72},{"X":249,"Y":71},{"X":249,"Y":72},{"X":249,"Y":73},{"X":250,"Y":73},{"X":250,"Y":73},{"X":250,"Y":73},{"X":253,"Y":71},{"X":253,"Y":70},{"X":253,"Y":69},{"X":256,"Y":69},{"X":260,"Y":68},{"X":262,"Y":68},{"X":264,"Y":66},{"X":266,"Y":64},{"X":271,"Y":68},{"X":275,"Y":66},{"X":276,"Y":67},{"X":277,"Y":67},{"X":283,"Y":68},{"X":284,"Y":68},{"X":286,"Y":67},{"X":287,"Y":68},{"X":289,"Y":67},{"X":291,"Y":67},{"X":291,"Y":68},{"X":292,"Y":67},{"X":293,"Y":68},{"X":293,"Y":69},{"X":293,"Y":70},{"X":294,"Y":73},{"X":294,"Y":73},{"X":294,"Y":74},{"X":295,"Y":74},{"X":290,"Y":81},{"X":289,"Y":84},{"X":290,"Y":86},{"X":287,"Y":91},{"X":287,"Y":93},{"X":286,"Y":96},{"X":283,"Y":97},{"X":283,"Y":97},{"X":283,"Y":101},{"X":283,"Y":101},{"X":281,"Y":102},{"X":282,"Y":103},{"X":281,"Y":105},{"X":278,"Y":107},{"X":277,"Y":108},{"X":276,"Y":108},{"X":275,"Y":108},{"X":273,"Y":108},{"X":272,"Y":108},{"X":271,"Y":108},{"X":267,"Y":111},{"X":266,"Y":112},{"X":267,"Y":112},{"X":268,"Y":111},{"X":275,"Y":108},{"X":276,"Y":110},{"X":276,"Y":111},{"X":276,"Y":112},{"X":276,"Y":112},{"X":277,"Y":113},{"X":279,"Y":113},{"X":280,"Y":116},{"X":278,"Y":117},{"X":276,"Y":117},{"X":273,"Y":117},{"X":272,"Y":117},{"X":269,"Y":121},{"X":269,"Y":122},{"X":267,"Y":123},{"X":265,"Y":124},{"X":261,"Y":123},{"X":258,"Y":123},{"X":258,"Y":124},{"X":259,"Y":124},{"X":262,"Y":124},{"X":265,"Y":125},{"X":266,"Y":124},{"X":267,"Y":125},{"X":269,"Y":125},{"X":270,"Y":126},{"X":271,"Y":126},{"X":272,"Y":125},{"X":273,"Y":125},{"X":275,"Y":124},{"X":275,"Y":123},{"X":276,"Y":122},{"X":279,"Y":122},{"X":280,"Y":124},{"X":280,"Y":124},{"X":282,"Y":124},{"X":286,"Y":127},{"X":289,"Y":127},{"X":289,"Y":127},{"X":290,"Y":129},{"X":292,"Y":133},{"X":294,"Y":136},{"X":295,"Y":136},{"X":295,"Y":137},{"X":295,"Y":137},{"X":295,"Y":138},{"X":298,"Y":138},{"X":298,"Y":138},{"X":299,"Y":140},{"X":300,"Y":141},{"X":300,"Y":144},{"X":299,"Y":146},{"X":300,"Y":147},{"X":300,"Y":149},{"X":301,"Y":152},{"X":301,"Y":154},{"X":303,"Y":158},{"X":304,"Y":160},{"X":304,"Y":161},{"X":306,"Y":166},{"X":306,"Y":168},{"X":309,"Y":169},{"X":308,"Y":169},{"X":309,"Y":170},{"X":309,"Y":172},{"X":309,"Y":172},{"X":309,"Y":172},{"X":309,"Y":171},{"X":312,"Y":172},{"X":315,"Y":173},{"X":319,"Y":176},{"X":321,"Y":176},{"X":322,"Y":177},{"X":322,"Y":178},{"X":323,"Y":180},{"X":325,"Y":182},{"X":326,"Y":183},{"X":327,"Y":187},{"X":331,"Y":188},{"X":328,"Y":189},{"X":327,"Y":191},{"X":330,"Y":195},{"X":333,"Y":200},{"X":335,"Y":204},{"X":335,"Y":206},{"X":335,"Y":206},{"X":335,"Y":205},{"X":335,"Y":204},{"X":333,"Y":204},{"X":333,"Y":204},{"X":332,"Y":204},{"X":330,"Y":204},{"X":327,"Y":201},{"X":326,"Y":201},{"X":324,"Y":202},{"X":322,"Y":203},{"X":320,"Y":202},{"X":319,"Y":203},{"X":319,"Y":203},{"X":321,"Y":203},{"X":322,"Y":203},{"X":323,"Y":203},{"X":326,"Y":202},{"X":327,"Y":203},{"X":328,"Y":204},{"X":332,"Y":206},{"X":333,"Y":206},{"X":333,"Y":207},{"X":334,"Y":210},{"X":336,"Y":210},{"X":336,"Y":211},{"X":337,"Y":212},{"X":339,"Y":217},{"X":341,"Y":220},{"X":339,"Y":222},{"X":336,"Y":225},{"X":335,"Y":229},{"X":334,"Y":229},{"X":334,"Y":229},{"X":335,"Y":229},{"X":336,"Y":229},{"X":336,"Y":231},{"X":338,"Y":233},{"X":341,"Y":232},{"X":342,"Y":234},{"X":342,"Y":233},{"X":342,"Y":232},{"X":343,"Y":227},{"X":344,"Y":226},{"X":346,"Y":226},{"X":347,"Y":226},{"X":350,"Y":226},{"X":352,"Y":226},{"X":352,"Y":226},{"X":353,"Y":226},{"X":354,"Y":226},{"X":353,"Y":225},{"X":354,"Y":225},{"X":355,"Y":225},{"X":356,"Y":226},{"X":360,"Y":226},{"X":363,"Y":229},{"X":368,"Y":233},{"X":368,"Y":233},{"X":370,"Y":236},{"X":370,"Y":238},{"X":370,"Y":240},{"X":370,"Y":243},{"X":370,"Y":245},{"X":368,"Y":249},{"X":368,"Y":251},{"X":368,"Y":255},{"X":365,"Y":257},{"X":364,"Y":261},{"X":361,"Y":259},{"X":361,"Y":260},{"X":359,"Y":260},{"X":358,"Y":260},{"X":363,"Y":260},{"X":360,"Y":264},{"X":361,"Y":264},{"X":361,"Y":262},{"X":363,"Y":264},{"X":363,"Y":264},{"X":360,"Y":266},{"X":358,"Y":267},{"X":357,"Y":266},{"X":356,"Y":266},{"X":355,"Y":266},{"X":354,"Y":267},{"X":353,"Y":268},{"X":350,"Y":268},{"X":352,"Y":269},{"X":352,"Y":269},{"X":354,"Y":267},{"X":355,"Y":268},{"X":355,"Y":269},{"X":355,"Y":272},{"X":354,"Y":272},{"X":353,"Y":272},{"X":354,"Y":272},{"X":354,"Y":272},{"X":354,"Y":272},{"X":355,"Y":272},{"X":356,"Y":272},{"X":353,"Y":276},{"X":349,"Y":276},{"X":348,"Y":277},{"X":346,"Y":277},{"X":345,"Y":277},{"X":344,"Y":278},{"X":345,"Y":278},{"X":346,"Y":277},{"X":347,"Y":277},{"X":350,"Y":277},{"X":352,"Y":278},{"X":350,"Y":279},{"X":349,"Y":279},{"X":348,"Y":279},{"X":347,"Y":279},{"X":348,"Y":280},{"X":349,"Y":280},{"X":350,"Y":280},{"X":350,"Y":280},{"X":350,"Y":279},{"X":352,"Y":280},{"X":352,"Y":279},{"X":352,"Y":278},{"X":355,"Y":279},{"X":356,"Y":281},{"X":355,"Y":281},{"X":353,"Y":281},{"X":355,"Y":281},{"X":361,"Y":280},{"X":367,"Y":279},{"X":366,"Y":281},{"X":365,"Y":282},{"X":366,"Y":284},{"X":366,"Y":288},{"X":365,"Y":289},{"X":363,"Y":290},{"X":361,"Y":290},{"X":360,"Y":291},{"X":358,"Y":292},{"X":357,"Y":293},{"X":357,"Y":295},{"X":354,"Y":295},{"X":352,"Y":297},{"X":350,"Y":298},{"X":344,"Y":300},{"X":343,"Y":302},{"X":342,"Y":303},{"X":337,"Y":302},{"X":333,"Y":300},{"X":322,"Y":302},{"X":322,"Y":303},{"X":321,"Y":302},{"X":321,"Y":304},{"X":320,"Y":304},{"X":317,"Y":302},{"X":319,"Y":302},{"X":317,"Y":301},{"X":317,"Y":301},{"X":316,"Y":301},{"X":315,"Y":301},{"X":316,"Y":301},{"X":317,"Y":302},{"X":314,"Y":302},{"X":315,"Y":302},{"X":315,"Y":301},{"X":314,"Y":301},{"X":314,"Y":303},{"X":313,"Y":303},{"X":313,"Y":303},{"X":313,"Y":301},{"X":313,"Y":300},{"X":311,"Y":301},{"X":312,"Y":302},{"X":312,"Y":303},{"X":309,"Y":301},{"X":308,"Y":299},{"X":305,"Y":298},{"X":305,"Y":299},{"X":306,"Y":299},{"X":309,"Y":302},{"X":308,"Y":303},{"X":305,"Y":303},{"X":304,"Y":304},{"X":301,"Y":304},{"X":299,"Y":304},{"X":300,"Y":304},{"X":300,"Y":304},{"X":298,"Y":304},{"X":297,"Y":304},{"X":295,"Y":306},{"X":295,"Y":304},{"X":293,"Y":304},{"X":292,"Y":306},{"X":293,"Y":305},{"X":293,"Y":306},{"X":295,"Y":306},{"X":295,"Y":308},{"X":295,"Y":308},{"X":295,"Y":309},{"X":294,"Y":310},{"X":293,"Y":310},{"X":292,"Y":310},{"X":290,"Y":309},{"X":284,"Y":309},{"X":284,"Y":309},{"X":283,"Y":310},{"X":284,"Y":311},{"X":283,"Y":312},{"X":283,"Y":311},{"X":280,"Y":308},{"X":277,"Y":305},{"X":275,"Y":305},{"X":272,"Y":306},{"X":270,"Y":306},{"X":268,"Y":306},{"X":265,"Y":310},{"X":264,"Y":309},{"X":262,"Y":306},{"X":262,"Y":310},{"X":261,"Y":312},{"X":261,"Y":314},{"X":260,"Y":315},{"X":260,"Y":316},{"X":261,"Y":317},{"X":261,"Y":317},{"X":260,"Y":317},{"X":259,"Y":319},{"X":259,"Y":319},{"X":258,"Y":320},{"X":258,"Y":321},{"X":258,"Y":322},{"X":256,"Y":323},{"X":255,"Y":322},{"X":255,"Y":322},{"X":254,"Y":322},{"X":253,"Y":320},{"X":251,"Y":319},{"X":249,"Y":319},{"X":247,"Y":319},{"X":247,"Y":317},{"X":246,"Y":317},{"X":246,"Y":317},{"X":247,"Y":317},{"X":246,"Y":319},{"X":245,"Y":319},{"X":244,"Y":317},{"X":243,"Y":317},{"X":240,"Y":317},{"X":239,"Y":319},{"X":236,"Y":319},{"X":235,"Y":319},{"X":235,"Y":317},{"X":234,"Y":319},{"X":233,"Y":322},{"X":231,"Y":321},{"X":229,"Y":322},{"X":228,"Y":322},{"X":228,"Y":324},{"X":227,"Y":324},{"X":228,"Y":324},{"X":227,"Y":324},{"X":227,"Y":321},{"X":227,"Y":321},{"X":226,"Y":322},{"X":227,"Y":323},{"X":226,"Y":324},{"X":227,"Y":324},{"X":226,"Y":324},{"X":226,"Y":325},{"X":225,"Y":325},{"X":226,"Y":326},{"X":226,"Y":327},{"X":226,"Y":328},{"X":224,"Y":328},{"X":224,"Y":331},{"X":223,"Y":328},{"X":222,"Y":326},{"X":221,"Y":326},{"X":217,"Y":324},{"X":216,"Y":324},{"X":216,"Y":325},{"X":215,"Y":326},{"X":213,"Y":327},{"X":212,"Y":326},{"X":213,"Y":325},{"X":212,"Y":323},{"X":213,"Y":324},{"X":216,"Y":321},{"X":218,"Y":322},{"X":220,"Y":321},{"X":221,"Y":321},{"X":222,"Y":320},{"X":223,"Y":317},{"X":225,"Y":316},{"X":225,"Y":315},{"X":227,"Y":315},{"X":228,"Y":313},{"X":227,"Y":312},{"X":228,"Y":311},{"X":228,"Y":311},{"X":229,"Y":310},{"X":229,"Y":310},{"X":231,"Y":309},{"X":234,"Y":309},{"X":234,"Y":306},{"X":235,"Y":305},{"X":236,"Y":304},{"X":238,"Y":303},{"X":238,"Y":299},{"X":239,"Y":295},{"X":240,"Y":295},{"X":243,"Y":295},{"X":244,"Y":295},{"X":246,"Y":294},{"X":247,"Y":293},{"X":245,"Y":291},{"X":246,"Y":291},{"X":246,"Y":290},{"X":246,"Y":290},{"X":255,"Y":288},{"X":259,"Y":288},{"X":260,"Y":288},{"X":262,"Y":289},{"X":264,"Y":290},{"X":266,"Y":290},{"X":268,"Y":289},{"X":270,"Y":289},{"X":271,"Y":288},{"X":271,"Y":288},{"X":271,"Y":286},{"X":272,"Y":286},{"X":272,"Y":282},{"X":275,"Y":281},{"X":277,"Y":279},{"X":278,"Y":279},{"X":283,"Y":271},{"X":284,"Y":270},{"X":284,"Y":269},{"X":284,"Y":270},{"X":283,"Y":270},{"X":278,"Y":276},{"X":275,"Y":277},{"X":272,"Y":278},{"X":272,"Y":278},{"X":272,"Y":278},{"X":271,"Y":278},{"X":269,"Y":279},{"X":269,"Y":280},{"X":268,"Y":280},{"X":268,"Y":281},{"X":267,"Y":282},{"X":264,"Y":282},{"X":260,"Y":281},{"X":258,"Y":279},{"X":257,"Y":279},{"X":255,"Y":278},{"X":254,"Y":275},{"X":250,"Y":275},{"X":250,"Y":275},{"X":250,"Y":277},{"X":247,"Y":277},{"X":247,"Y":277},{"X":246,"Y":278},{"X":244,"Y":277},{"X":244,"Y":276},{"X":245,"Y":275},{"X":246,"Y":275},{"X":246,"Y":275},{"X":248,"Y":275},{"X":249,"Y":273},{"X":249,"Y":272},{"X":248,"Y":273},{"X":247,"Y":272},{"X":244,"Y":272},{"X":244,"Y":272},{"X":243,"Y":271},{"X":243,"Y":270},{"X":244,"Y":271},{"X":243,"Y":269},{"X":243,"Y":268},{"X":243,"Y":269},{"X":242,"Y":269},{"X":242,"Y":270},{"X":237,"Y":270},{"X":236,"Y":272},{"X":235,"Y":272},{"X":234,"Y":273},{"X":233,"Y":275},{"X":231,"Y":275},{"X":228,"Y":273},{"X":228,"Y":272},{"X":227,"Y":272},{"X":227,"Y":272},{"X":228,"Y":272},{"X":228,"Y":272},{"X":228,"Y":272},{"X":229,"Y":272},{"X":233,"Y":271},{"X":229,"Y":270},{"X":226,"Y":270},{"X":226,"Y":272},{"X":225,"Y":270},{"X":224,"Y":269},{"X":225,"Y":269},{"X":226,"Y":268},{"X":227,"Y":268},{"X":227,"Y":266},{"X":225,"Y":266},{"X":223,"Y":265},{"X":223,"Y":262},{"X":225,"Y":264},{"X":225,"Y":262},{"X":227,"Y":261},{"X":227,"Y":260},{"X":229,"Y":261},{"X":231,"Y":261},{"X":232,"Y":261},{"X":232,"Y":260},{"X":233,"Y":261},{"X":234,"Y":260},{"X":234,"Y":259},{"X":235,"Y":259},{"X":236,"Y":257},{"X":236,"Y":257},{"X":236,"Y":256},{"X":240,"Y":256},{"X":243,"Y":254},{"X":244,"Y":254},{"X":246,"Y":253},{"X":248,"Y":250},{"X":249,"Y":248},{"X":250,"Y":244},{"X":251,"Y":243},{"X":253,"Y":242},{"X":250,"Y":242},{"X":248,"Y":240},{"X":250,"Y":237},{"X":251,"Y":235},{"X":250,"Y":236},{"X":249,"Y":235},{"X":248,"Y":235},{"X":248,"Y":234},{"X":249,"Y":232},{"X":248,"Y":231},{"X":243,"Y":231},{"X":242,"Y":232},{"X":242,"Y":233},{"X":242,"Y":234},{"X":240,"Y":235},{"X":238,"Y":233},{"X":238,"Y":234},{"X":236,"Y":233},{"X":236,"Y":234},{"X":236,"Y":233},{"X":236,"Y":232},{"X":238,"Y":231},{"X":240,"Y":229},{"X":244,"Y":226},{"X":244,"Y":223},{"X":245,"Y":223},{"X":245,"Y":223},{"X":248,"Y":220},{"X":249,"Y":218},{"X":250,"Y":218},{"X":254,"Y":217},{"X":255,"Y":217},{"X":254,"Y":216},{"X":256,"Y":216},{"X":257,"Y":217},{"X":259,"Y":217},{"X":265,"Y":215},{"X":266,"Y":215},{"X":266,"Y":216},{"X":270,"Y":220},{"X":270,"Y":217},{"X":268,"Y":214},{"X":268,"Y":214},{"X":271,"Y":212},{"X":271,"Y":213},{"X":273,"Y":216},{"X":276,"Y":217},{"X":277,"Y":217},{"X":278,"Y":216},{"X":277,"Y":216},{"X":275,"Y":216},{"X":272,"Y":213},{"X":270,"Y":210},{"X":272,"Y":204},{"X":276,"Y":202},{"X":271,"Y":202},{"X":270,"Y":199},{"X":271,"Y":195},{"X":275,"Y":194},{"X":275,"Y":195},{"X":276,"Y":193},{"X":275,"Y":193},{"X":275,"Y":193},{"X":275,"Y":193},{"X":273,"Y":192},{"X":275,"Y":190},{"X":276,"Y":190},{"X":276,"Y":189},{"X":276,"Y":187},{"X":276,"Y":185},{"X":275,"Y":185},{"X":273,"Y":188},{"X":272,"Y":188},{"X":271,"Y":185},{"X":270,"Y":189},{"X":269,"Y":191},{"X":269,"Y":191},{"X":267,"Y":189},{"X":267,"Y":188},{"X":267,"Y":188},{"X":268,"Y":188},{"X":268,"Y":183},{"X":267,"Y":187},{"X":266,"Y":187},{"X":264,"Y":183},{"X":264,"Y":181},{"X":259,"Y":176},{"X":260,"Y":172},{"X":261,"Y":170},{"X":262,"Y":168},{"X":264,"Y":167},{"X":264,"Y":166},{"X":265,"Y":163},{"X":266,"Y":162},{"X":266,"Y":163},{"X":267,"Y":163},{"X":267,"Y":162},{"X":267,"Y":162},{"X":267,"Y":161},{"X":268,"Y":160},{"X":270,"Y":161},{"X":271,"Y":161},{"X":271,"Y":160},{"X":270,"Y":160},{"X":270,"Y":160},{"X":271,"Y":160},{"X":271,"Y":159},{"X":269,"Y":159},{"X":267,"Y":160},{"X":264,"Y":160},{"X":264,"Y":160},{"X":262,"Y":160},{"X":261,"Y":160},{"X":261,"Y":160},{"X":261,"Y":160},{"X":261,"Y":163},{"X":260,"Y":163},{"X":258,"Y":162},{"X":257,"Y":163},{"X":256,"Y":162},{"X":256,"Y":163},{"X":256,"Y":162},{"X":256,"Y":162},{"X":255,"Y":163},{"X":256,"Y":165},{"X":253,"Y":167},{"X":251,"Y":167},{"X":251,"Y":165},{"X":250,"Y":166},{"X":249,"Y":166},{"X":248,"Y":165},{"X":248,"Y":162},{"X":247,"Y":165},{"X":246,"Y":162},{"X":245,"Y":162},{"X":244,"Y":161},{"X":244,"Y":162},{"X":244,"Y":162},{"X":244,"Y":165},{"X":246,"Y":165},{"X":245,"Y":166},{"X":246,"Y":169},{"X":245,"Y":169},{"X":242,"Y":169},{"X":240,"Y":166},{"X":237,"Y":165},{"X":236,"Y":162},{"X":236,"Y":162},{"X":234,"Y":163},{"X":233,"Y":165},{"X":234,"Y":169},{"X":235,"Y":169},{"X":235,"Y":169},{"X":236,"Y":170},{"X":235,"Y":170},{"X":234,"Y":169},{"X":234,"Y":168},{"X":229,"Y":162},{"X":228,"Y":160},{"X":229,"Y":158},{"X":231,"Y":158},{"X":232,"Y":158},{"X":232,"Y":160},{"X":233,"Y":162},{"X":233,"Y":161},{"X":232,"Y":158},{"X":232,"Y":157},{"X":233,"Y":154},{"X":236,"Y":150},{"X":236,"Y":147},{"X":237,"Y":146},{"X":238,"Y":144},{"X":240,"Y":144},{"X":240,"Y":141},{"X":239,"Y":140},{"X":239,"Y":140},{"X":239,"Y":139},{"X":239,"Y":138},{"X":237,"Y":137},{"X":237,"Y":136},{"X":235,"Y":134},{"X":236,"Y":133},{"X":236,"Y":130},{"X":235,"Y":127},{"X":236,"Y":126},{"X":237,"Y":125},{"X":238,"Y":127},{"X":243,"Y":127},{"X":240,"Y":125},{"X":238,"Y":124},{"X":237,"Y":122},{"X":237,"Y":124},{"X":238,"Y":124},{"X":237,"Y":124},{"X":236,"Y":124},{"X":236,"Y":122},{"X":237,"Y":121},{"X":236,"Y":121},{"X":236,"Y":119},{"X":236,"Y":119},{"X":235,"Y":121},{"X":236,"Y":122},{"X":236,"Y":124},{"X":235,"Y":124},{"X":235,"Y":124},{"X":234,"Y":128},{"X":233,"Y":128},{"X":233,"Y":126},{"X":232,"Y":124},{"X":232,"Y":127},{"X":229,"Y":126},{"X":229,"Y":124},{"X":229,"Y":124},{"X":229,"Y":127},{"X":228,"Y":127},{"X":229,"Y":129},{"X":227,"Y":128},{"X":226,"Y":127},{"X":227,"Y":124},{"X":228,"Y":122},{"X":229,"Y":121},{"X":229,"Y":119},{"X":233,"Y":118},{"X":233,"Y":117},{"X":235,"Y":115},{"X":234,"Y":116},{"X":233,"Y":116},{"X":232,"Y":118},{"X":228,"Y":119},{"X":226,"Y":124},{"X":225,"Y":124},{"X":225,"Y":124},{"X":225,"Y":125},{"X":225,"Y":126},{"X":225,"Y":128},{"X":227,"Y":130},{"X":227,"Y":132},{"X":226,"Y":133},{"X":225,"Y":134},{"X":224,"Y":136},{"X":224,"Y":137},{"X":224,"Y":138},{"X":224,"Y":138},{"X":224,"Y":139},{"X":222,"Y":144},{"X":222,"Y":144},{"X":222,"Y":144},{"X":223,"Y":145},{"X":222,"Y":147},{"X":220,"Y":148},{"X":217,"Y":147},{"X":217,"Y":144},{"X":220,"Y":144},{"X":220,"Y":139},{"X":220,"Y":138},{"X":221,"Y":136},{"X":221,"Y":135},{"X":224,"Y":129},{"X":222,"Y":132},{"X":221,"Y":130},{"X":221,"Y":129},{"X":223,"Y":126},{"X":221,"Y":127},{"X":221,"Y":126},{"X":223,"Y":122},{"X":222,"Y":123},{"X":221,"Y":126},{"X":220,"Y":126},{"X":221,"Y":124},{"X":222,"Y":123},{"X":222,"Y":122},{"X":223,"Y":121},{"X":224,"Y":121},{"X":223,"Y":119},{"X":224,"Y":117},{"X":223,"Y":119},{"X":222,"Y":119},{"X":223,"Y":117},{"X":223,"Y":115},{"X":223,"Y":112},{"X":224,"Y":112},{"X":225,"Y":108},{"X":229,"Y":108},{"X":227,"Y":107},{"X":226,"Y":107},{"X":226,"Y":107},{"X":226,"Y":107},{"X":225,"Y":107},{"X":226,"Y":106},{"X":227,"Y":106},{"X":228,"Y":105},{"X":229,"Y":105},{"X":227,"Y":105},{"X":226,"Y":105},{"X":227,"Y":102},{"X":228,"Y":102},{"X":228,"Y":102},{"X":229,"Y":101},{"X":232,"Y":101},{"X":233,"Y":101},{"X":232,"Y":101},{"X":229,"Y":101},{"X":233,"Y":95},{"X":231,"Y":97},{"X":229,"Y":97},{"X":228,"Y":100},{"X":227,"Y":101},{"X":227,"Y":101},{"X":225,"Y":103},{"X":224,"Y":105},{"X":221,"Y":106},{"X":221,"Y":106},{"X":220,"Y":105},{"X":220,"Y":105},{"X":217,"Y":104},{"X":215,"Y":103},{"X":215,"Y":102},{"X":216,"Y":101},{"X":217,"Y":101},{"X":221,"Y":100},{"X":222,"Y":101},{"X":224,"Y":101},{"X":222,"Y":101},{"X":220,"Y":100},{"X":218,"Y":101},{"X":217,"Y":100},{"X":212,"Y":100},{"X":211,"Y":99},{"X":213,"Y":97},{"X":215,"Y":97},{"X":216,"Y":96},{"X":217,"Y":97},{"X":218,"Y":97},{"X":218,"Y":96},{"X":218,"Y":97},{"X":220,"Y":96},{"X":220,"Y":96},{"X":218,"Y":95},{"X":218,"Y":94},{"X":221,"Y":94},{"X":221,"Y":94},{"X":222,"Y":94},{"X":222,"Y":94},{"X":221,"Y":94},{"X":221,"Y":94},{"X":221,"Y":93},{"X":217,"Y":92},{"X":218,"Y":93},{"X":220,"Y":93},{"X":218,"Y":92},{"X":220,"Y":90},{"X":221,"Y":89},{"X":221,"Y":90},{"X":222,"Y":91},{"X":225,"Y":90},{"X":223,"Y":90},{"X":222,"Y":90},{"X":222,"Y":89},{"X":222,"Y":88},{"X":221,"Y":88},{"X":221,"Y":86},{"X":222,"Y":85},{"X":223,"Y":85},{"X":225,"Y":88},{"X":226,"Y":86},{"X":224,"Y":86},{"X":224,"Y":85},{"X":223,"Y":83},{"X":222,"Y":83},{"X":223,"Y":83},{"X":223,"Y":82},{"X":223,"Y":81},{"X":223,"Y":80},{"X":225,"Y":80},{"X":225,"Y":80},{"X":227,"Y":82},{"X":227,"Y":81},{"X":226,"Y":81},{"X":225,"Y":80},{"X":222,"Y":80},{"X":222,"Y":80},{"X":223,"Y":78},{"X":225,"Y":77},{"X":226,"Y":74},{"X":225,"Y":77},{"X":224,"Y":78},{"X":223,"Y":77},{"X":224,"Y":77},{"X":224,"Y":75},{"X":221,"Y":78},{"X":220,"Y":78},{"X":220,"Y":75},{"X":221,"Y":75},{"X":220,"Y":75},{"X":221,"Y":74},{"X":220,"Y":74},{"X":220,"Y":72},{"X":221,"Y":70},{"X":221,"Y":70},{"X":222,"Y":71},{"X":222,"Y":70},{"X":223,"Y":72},{"X":223,"Y":72},{"X":224,"Y":72},{"X":225,"Y":71},{"X":224,"Y":71},{"X":223,"Y":70},{"X":223,"Y":70},{"X":223,"Y":70},{"X":222,"Y":69},{"X":222,"Y":68},{"X":221,"Y":68},{"X":221,"Y":64},{"X":223,"Y":64},{"X":223,"Y":64},{"X":222,"Y":64},{"X":221,"Y":63},{"X":221,"Y":62},{"X":221,"Y":60},{"X":223,"Y":60},{"X":223,"Y":60},{"X":223,"Y":62},{"X":224,"Y":63},{"X":224,"Y":62},{"X":225,"Y":62},{"X":225,"Y":60},{"X":224,"Y":60},{"X":224,"Y":58},{"X":225,"Y":58},{"X":225,"Y":58},{"X":225,"Y":60},{"X":227,"Y":60},{"X":227,"Y":58},{"X":232,"Y":60},{"X":232,"Y":60},{"X":228,"Y":58},{"X":228,"Y":57},{"X":228,"Y":57},{"X":229,"Y":59},{"X":232,"Y":58},{"X":233,"Y":60},{"X":234,"Y":61},{"X":234,"Y":60},{"X":232,"Y":58},{"X":233,"Y":58},{"X":233,"Y":58},{"X":231,"Y":56},{"X":229,"Y":55},{"X":228,"Y":53},{"X":228,"Y":53},{"X":227,"Y":52},{"X":227,"Y":51},{"X":229,"Y":52},{"X":229,"Y":52},{"X":232,"Y":52},{"X":232,"Y":52},{"X":231,"Y":51},{"X":232,"Y":51},{"X":231,"Y":50},{"X":232,"Y":50},{"X":231,"Y":50},{"X":231,"Y":50},{"X":229,"Y":49},{"X":229,"Y":49},{"X":228,"Y":47},{"X":228,"Y":46},{"X":231,"Y":48},{"X":233,"Y":47},{"X":233,"Y":48},{"X":234,"Y":47},{"X":237,"Y":48},{"X":236,"Y":47},{"X":237,"Y":47},{"X":235,"Y":47},{"X":234,"Y":46},{"X":234,"Y":45},{"X":234,"Y":45},{"X":233,"Y":45},{"X":234,"Y":41},{"X":236,"Y":42},{"X":235,"Y":41},{"X":235,"Y":41},{"X":235,"Y":41},{"X":235,"Y":40},{"X":236,"Y":40},{"X":237,"Y":40},{"X":236,"Y":39},{"X":234,"Y":38},{"X":234,"Y":38},{"X":236,"Y":37}]]', 109 | clip: '[[{"X":246,"Y":146},{"X":313,"Y":146},{"X":290,"Y":168},{"X":335,"Y":191},{"X":290,"Y":235},{"X":268,"Y":191},{"X":246,"Y":213}],[{"X":246,"Y":57},{"X":268,"Y":79},{"X":290,"Y":35},{"X":335,"Y":79},{"X":290,"Y":102},{"X":313,"Y":124},{"X":246,"Y":124}],[{"X":224,"Y":146},{"X":224,"Y":213},{"X":201,"Y":191},{"X":179,"Y":235},{"X":134,"Y":191},{"X":179,"Y":168},{"X":157,"Y":146}],[{"X":179,"Y":102},{"X":134,"Y":79},{"X":179,"Y":35},{"X":201,"Y":79},{"X":224,"Y":57},{"X":224,"Y":124},{"X":157,"Y":124}]]' 110 | }, { // Texts 111 | subj: '[[{"X":"28.18","Y":"205.95"},{"X":"28.18","Y":"105.07"},{"X":"48.27","Y":"105.07"},{"X":"48.28","Y":"110.23"},{"X":"54.15","Y":"107.22"},{"X":"59.69","Y":"105.39"},{"X":"65.04","Y":"104.66"},{"X":"72.07","Y":"105.08"},{"X":"78.09","Y":"106.31"},{"X":"81.57","Y":"107.68"},{"X":"84.84","Y":"110.05"},{"X":"88.03","Y":"113.63"},{"X":"90.87","Y":"118.22"},{"X":"92.71","Y":"123.12"},{"X":"94.06","Y":"129.73"},{"X":"94.70","Y":"138.25"},{"X":"94.41","Y":"147.24"},{"X":"93.31","Y":"155.42"},{"X":"91.66","Y":"161.49"},{"X":"89.46","Y":"166.25"},{"X":"86.67","Y":"170.32"},{"X":"83.75","Y":"173.13"},{"X":"80.65","Y":"174.92"},{"X":"75.51","Y":"176.56"},{"X":"69.28","Y":"177.50"},{"X":"63.74","Y":"177.55"},{"X":"57.05","Y":"176.72"},{"X":"51.42","Y":"175.15"},{"X":"48.27","Y":"173.79"},{"X":"48.27","Y":"205.95"},{"X":"48.27","Y":"205.95"},{"X":"28.18","Y":"205.95"}],[{"X":"48.28","Y":"120.42"},{"X":"48.38","Y":"164.32"},{"X":"52.31","Y":"166.53"},{"X":"56.14","Y":"167.74"},{"X":"61.35","Y":"168.35"},{"X":"65.96","Y":"167.83"},{"X":"69.49","Y":"166.59"},{"X":"72.20","Y":"164.73"},{"X":"74.29","Y":"162.19"},{"X":"76.19","Y":"157.95"},{"X":"77.71","Y":"152.00"},{"X":"78.63","Y":"144.11"},{"X":"78.66","Y":"136.61"},{"X":"77.89","Y":"129.16"},{"X":"76.59","Y":"124.08"},{"X":"74.84","Y":"120.60"},{"X":"72.55","Y":"118.04"},{"X":"69.77","Y":"116.28"},{"X":"65.91","Y":"115.07"},{"X":"60.69","Y":"114.57"},{"X":"56.85","Y":"115.18"},{"X":"53.10","Y":"116.68"},{"X":"48.91","Y":"119.57"},{"X":"48.28","Y":"120.39"},{"X":"48.28","Y":"120.42"}],[{"X":"132.15","Y":"104.65"},{"X":"139.94","Y":"105.10"},{"X":"146.11","Y":"106.30"},{"X":"151.03","Y":"108.11"},{"X":"155.15","Y":"110.57"},{"X":"158.60","Y":"113.67"},{"X":"161.35","Y":"117.41"},{"X":"163.45","Y":"121.89"},{"X":"165.10","Y":"127.80"},{"X":"166.07","Y":"135.09"},{"X":"166.22","Y":"143.93"},{"X":"165.51","Y":"151.69"},{"X":"164.06","Y":"158.12"},{"X":"162.01","Y":"163.28"},{"X":"159.40","Y":"167.47"},{"X":"156.32","Y":"170.74"},{"X":"152.52","Y":"173.40"},{"X":"147.87","Y":"175.49"},{"X":"142.07","Y":"176.99"},{"X":"134.92","Y":"177.77"},{"X":"127.42","Y":"177.67"},{"X":"120.74","Y":"176.71"},{"X":"115.29","Y":"175.07"},{"X":"110.74","Y":"172.78"},{"X":"106.95","Y":"169.86"},{"X":"103.92","Y":"166.34"},{"X":"101.48","Y":"162.04"},{"X":"99.57","Y":"156.68"},{"X":"98.29","Y":"150.05"},{"X":"97.78","Y":"141.98"},{"X":"98.18","Y":"134.19"},{"X":"99.36","Y":"127.55"},{"X":"101.22","Y":"122.01"},{"X":"103.68","Y":"117.38"},{"X":"106.77","Y":"113.52"},{"X":"110.41","Y":"110.41"},{"X":"114.84","Y":"107.89"},{"X":"120.07","Y":"106.06"},{"X":"126.27","Y":"104.95"},{"X":"132.11","Y":"104.65"},{"X":"132.15","Y":"104.65"}],[{"X":"117.86","Y":"140.93"},{"X":"118.75","Y":"153.65"},{"X":"119.63","Y":"158.05"},{"X":"121.31","Y":"161.73"},{"X":"123.57","Y":"164.71"},{"X":"126.01","Y":"166.43"},{"X":"129.14","Y":"167.44"},{"X":"133.32","Y":"167.70"},{"X":"137.17","Y":"167.11"},{"X":"140.03","Y":"165.83"},{"X":"142.14","Y":"163.92"},{"X":"143.62","Y":"161.33"},{"X":"145.05","Y":"155.97"},{"X":"145.97","Y":"148.23"},{"X":"146.12","Y":"137.89"},{"X":"145.44","Y":"129.22"},{"X":"144.13","Y":"122.91"},{"X":"142.80","Y":"119.58"},{"X":"140.91","Y":"117.26"},{"X":"138.39","Y":"115.66"},{"X":"135.07","Y":"114.75"},{"X":"131.03","Y":"114.64"},{"X":"127.21","Y":"115.38"},{"X":"124.25","Y":"116.82"},{"X":"122.07","Y":"118.86"},{"X":"120.53","Y":"121.59"},{"X":"119.03","Y":"126.93"},{"X":"118.09","Y":"134.21"},{"X":"117.86","Y":"140.81"},{"X":"117.86","Y":"140.93"}],[{"X":"172.03","Y":"177.00"},{"X":"172.03","Y":"76.33"},{"X":"191.91","Y":"76.33"},{"X":"191.91","Y":"177.00"},{"X":"191.91","Y":"177.00"},{"X":"172.03","Y":"177.00"}],[{"X":"224.60","Y":"196.88"},{"X":"221.39","Y":"198.11"},{"X":"215.61","Y":"199.00"},{"X":"208.60","Y":"199.21"},{"X":"204.09","Y":"190.40"},{"X":"211.28","Y":"190.55"},{"X":"214.82","Y":"189.98"},{"X":"217.84","Y":"188.66"},{"X":"220.35","Y":"186.54"},{"X":"222.45","Y":"183.44"},{"X":"224.33","Y":"178.55"},{"X":"225.80","Y":"173.86"},{"X":"195.43","Y":"105.07"},{"X":"215.95","Y":"105.07"},{"X":"235.40","Y":"149.04"},{"X":"252.44","Y":"105.07"},{"X":"265.17","Y":"105.14"},{"X":"233.73","Y":"186.25"},{"X":"231.07","Y":"190.77"},{"X":"228.03","Y":"194.27"},{"X":"224.70","Y":"196.82"},{"X":"224.60","Y":"196.88"}],[{"X":"292.60","Y":"192.98"},{"X":"298.73","Y":"192.56"},{"X":"303.08","Y":"191.46"},{"X":"305.98","Y":"189.91"},{"X":"307.86","Y":"187.98"},{"X":"308.96","Y":"185.54"},{"X":"309.26","Y":"183.06"},{"X":"309.20","Y":"173.81"},{"X":"304.04","Y":"175.83"},{"X":"298.03","Y":"177.13"},{"X":"291.00","Y":"177.63"},{"X":"284.29","Y":"177.05"},{"X":"278.60","Y":"175.70"},{"X":"274.88","Y":"174.11"},{"X":"271.82","Y":"171.71"},{"X":"268.90","Y":"168.11"},{"X":"266.25","Y":"163.24"},{"X":"264.52","Y":"157.97"},{"X":"263.31","Y":"150.88"},{"X":"262.81","Y":"141.60"},{"X":"263.34","Y":"132.62"},{"X":"264.61","Y":"125.23"},{"X":"266.40","Y":"119.67"},{"X":"268.74","Y":"115.31"},{"X":"271.95","Y":"111.17"},{"X":"275.11","Y":"108.42"},{"X":"278.30","Y":"106.76"},{"X":"283.81","Y":"105.35"},{"X":"290.52","Y":"104.67"},{"X":"295.16","Y":"104.90"},{"X":"299.98","Y":"105.99"},{"X":"306.08","Y":"108.50"},{"X":"309.26","Y":"110.23"},{"X":"309.26","Y":"105.06"},{"X":"329.35","Y":"105.06"},{"X":"329.23","Y":"182.37"},{"X":"328.37","Y":"186.78"},{"X":"326.76","Y":"190.49"},{"X":"324.35","Y":"193.73"},{"X":"321.15","Y":"196.44"},{"X":"316.95","Y":"198.74"},{"X":"311.55","Y":"200.55"},{"X":"304.61","Y":"201.78"},{"X":"296.23","Y":"202.25"},{"X":"286.50","Y":"201.75"},{"X":"279.10","Y":"200.55"},{"X":"271.33","Y":"198.26"},{"X":"269.50","Y":"197.28"},{"X":"268.04","Y":"186.11"},{"X":"273.14","Y":"188.62"},{"X":"280.19","Y":"191.16"},{"X":"286.81","Y":"192.48"},{"X":"292.48","Y":"192.97"},{"X":"292.60","Y":"192.98"}],[{"X":"309.26","Y":"120.42"},{"X":"308.13","Y":"119.26"},{"X":"303.52","Y":"116.46"},{"X":"299.14","Y":"114.93"},{"X":"296.63","Y":"114.57"},{"X":"291.87","Y":"115.12"},{"X":"288.19","Y":"116.39"},{"X":"285.33","Y":"118.31"},{"X":"282.99","Y":"121.03"},{"X":"281.19","Y":"124.65"},{"X":"279.81","Y":"130.01"},{"X":"278.92","Y":"137.91"},{"X":"278.88","Y":"145.11"},{"X":"279.69","Y":"152.40"},{"X":"281.18","Y":"158.05"},{"X":"283.08","Y":"162.12"},{"X":"285.18","Y":"164.65"},{"X":"287.89","Y":"166.53"},{"X":"291.41","Y":"167.79"},{"X":"296.02","Y":"168.34"},{"X":"301.23","Y":"167.79"},{"X":"305.10","Y":"166.63"},{"X":"309.03","Y":"164.44"},{"X":"309.26","Y":"164.24"},{"X":"309.26","Y":"164.24"},{"X":"309.26","Y":"120.42"}],[{"X":"369.84","Y":"104.65"},{"X":"377.62","Y":"105.10"},{"X":"383.80","Y":"106.30"},{"X":"388.72","Y":"108.11"},{"X":"392.84","Y":"110.56"},{"X":"396.29","Y":"113.67"},{"X":"399.04","Y":"117.41"},{"X":"401.13","Y":"121.89"},{"X":"402.78","Y":"127.80"},{"X":"403.75","Y":"135.08"},{"X":"403.90","Y":"143.93"},{"X":"403.19","Y":"151.69"},{"X":"401.74","Y":"158.12"},{"X":"399.70","Y":"163.28"},{"X":"397.08","Y":"167.47"},{"X":"394.00","Y":"170.74"},{"X":"390.20","Y":"173.40"},{"X":"385.55","Y":"175.49"},{"X":"379.75","Y":"176.99"},{"X":"372.60","Y":"177.77"},{"X":"365.11","Y":"177.67"},{"X":"358.43","Y":"176.71"},{"X":"352.98","Y":"175.07"},{"X":"348.43","Y":"172.78"},{"X":"344.63","Y":"169.86"},{"X":"341.60","Y":"166.34"},{"X":"339.16","Y":"162.04"},{"X":"337.26","Y":"156.68"},{"X":"335.98","Y":"150.05"},{"X":"335.46","Y":"141.97"},{"X":"335.86","Y":"134.19"},{"X":"337.04","Y":"127.55"},{"X":"338.90","Y":"122.01"},{"X":"341.37","Y":"117.38"},{"X":"344.45","Y":"113.52"},{"X":"348.10","Y":"110.41"},{"X":"352.52","Y":"107.89"},{"X":"357.76","Y":"106.06"},{"X":"363.95","Y":"104.95"},{"X":"369.79","Y":"104.65"},{"X":"369.84","Y":"104.65"}],[{"X":"355.55","Y":"140.93"},{"X":"356.44","Y":"153.65"},{"X":"357.32","Y":"158.05"},{"X":"358.99","Y":"161.73"},{"X":"361.25","Y":"164.71"},{"X":"363.70","Y":"166.43"},{"X":"366.83","Y":"167.44"},{"X":"371.01","Y":"167.70"},{"X":"374.86","Y":"167.11"},{"X":"377.72","Y":"165.83"},{"X":"379.82","Y":"163.92"},{"X":"381.31","Y":"161.33"},{"X":"382.74","Y":"155.97"},{"X":"383.65","Y":"148.23"},{"X":"383.81","Y":"137.89"},{"X":"383.12","Y":"129.22"},{"X":"381.82","Y":"122.91"},{"X":"380.48","Y":"119.58"},{"X":"378.60","Y":"117.26"},{"X":"376.07","Y":"115.66"},{"X":"372.76","Y":"114.75"},{"X":"368.72","Y":"114.64"},{"X":"364.90","Y":"115.38"},{"X":"361.94","Y":"116.82"},{"X":"359.76","Y":"118.86"},{"X":"358.22","Y":"121.60"},{"X":"356.71","Y":"126.93"},{"X":"355.77","Y":"134.21"},{"X":"355.55","Y":"140.81"},{"X":"355.55","Y":"140.93"}],[{"X":"471.82","Y":"121.68"},{"X":"471.82","Y":"177.00"},{"X":"456.69","Y":"177.00"},{"X":"456.58","Y":"122.81"},{"X":"455.77","Y":"120.25"},{"X":"454.20","Y":"118.25"},{"X":"451.80","Y":"116.74"},{"X":"448.06","Y":"115.65"},{"X":"442.84","Y":"115.25"},{"X":"438.30","Y":"116.22"},{"X":"435.19","Y":"117.70"},{"X":"432.97","Y":"119.70"},{"X":"430.36","Y":"123.35"},{"X":"429.69","Y":"124.95"},{"X":"429.69","Y":"177.00"},{"X":"409.38","Y":"177.00"},{"X":"409.38","Y":"105.07"},{"X":"429.69","Y":"105.07"},{"X":"429.70","Y":"110.91"},{"X":"434.67","Y":"107.84"},{"X":"440.16","Y":"105.83"},{"X":"445.62","Y":"104.85"},{"X":"452.21","Y":"104.70"},{"X":"457.71","Y":"105.40"},{"X":"461.98","Y":"106.78"},{"X":"465.33","Y":"108.76"},{"X":"468.28","Y":"111.73"},{"X":"470.35","Y":"115.03"},{"X":"471.52","Y":"118.58"},{"X":"471.82","Y":"121.56"},{"X":"471.82","Y":"121.68"}]]', 112 | clip: '[[{"X":"115.54","Y":"216.41"},{"X":"113.01","Y":"217.26"},{"X":"105.79","Y":"218.58"},{"X":"96.36","Y":"219.18"},{"X":"88.73","Y":"218.69"},{"X":"82.86","Y":"217.48"},{"X":"78.40","Y":"215.73"},{"X":"74.91","Y":"213.42"},{"X":"72.12","Y":"210.49"},{"X":"69.88","Y":"206.77"},{"X":"68.13","Y":"201.83"},{"X":"66.93","Y":"195.19"},{"X":"66.45","Y":"186.51"},{"X":"67.03","Y":"179.19"},{"X":"68.36","Y":"173.03"},{"X":"70.25","Y":"168.30"},{"X":"72.58","Y":"164.82"},{"X":"75.62","Y":"161.94"},{"X":"79.35","Y":"159.71"},{"X":"84.02","Y":"158.09"},{"X":"89.93","Y":"157.11"},{"X":"96.97","Y":"156.93"},{"X":"105.18","Y":"157.69"},{"X":"114.58","Y":"159.65"},{"X":"116.44","Y":"168.59"},{"X":"110.93","Y":"166.65"},{"X":"105.50","Y":"165.51"},{"X":"98.32","Y":"165.06"},{"X":"94.16","Y":"165.58"},{"X":"90.96","Y":"166.82"},{"X":"88.62","Y":"168.68"},{"X":"86.96","Y":"171.17"},{"X":"85.31","Y":"175.67"},{"X":"84.32","Y":"181.28"},{"X":"84.15","Y":"188.62"},{"X":"84.83","Y":"196.53"},{"X":"86.18","Y":"202.53"},{"X":"87.64","Y":"205.97"},{"X":"89.52","Y":"208.29"},{"X":"92.02","Y":"209.92"},{"X":"95.18","Y":"210.85"},{"X":"99.07","Y":"210.96"},{"X":"105.48","Y":"210.28"},{"X":"111.84","Y":"208.54"},{"X":"116.32","Y":"206.45"},{"X":"116.62","Y":"206.17"},{"X":"115.55","Y":"216.31"},{"X":"115.54","Y":"216.41"}],[{"X":"120.11","Y":"219.00"},{"X":"120.11","Y":"132.31"},{"X":"137.23","Y":"132.31"},{"X":"137.23","Y":"219.00"},{"X":"137.23","Y":"219.00"},{"X":"120.11","Y":"219.00"}],[{"X":"153.34","Y":"132.13"},{"X":"156.60","Y":"132.56"},{"X":"159.17","Y":"133.77"},{"X":"161.19","Y":"135.77"},{"X":"162.61","Y":"138.40"},{"X":"163.19","Y":"141.48"},{"X":"162.87","Y":"144.75"},{"X":"161.71","Y":"147.51"},{"X":"159.79","Y":"149.80"},{"X":"157.51","Y":"151.22"},{"X":"154.46","Y":"151.96"},{"X":"151.02","Y":"151.84"},{"X":"148.34","Y":"150.92"},{"X":"146.08","Y":"149.20"},{"X":"144.28","Y":"146.63"},{"X":"143.38","Y":"143.78"},{"X":"143.37","Y":"140.64"},{"X":"144.20","Y":"137.77"},{"X":"145.94","Y":"135.15"},{"X":"148.14","Y":"133.37"},{"X":"150.80","Y":"132.38"},{"X":"153.33","Y":"132.13"},{"X":"153.34","Y":"132.13"}],[{"X":"144.58","Y":"219.00"},{"X":"144.58","Y":"157.06"},{"X":"161.88","Y":"157.06"},{"X":"161.88","Y":"219.00"},{"X":"161.88","Y":"219.00"},{"X":"144.58","Y":"219.00"}],[{"X":"168.78","Y":"243.93"},{"X":"168.78","Y":"157.06"},{"X":"186.09","Y":"157.06"},{"X":"186.19","Y":"161.44"},{"X":"191.55","Y":"158.75"},{"X":"196.41","Y":"157.22"},{"X":"201.17","Y":"156.70"},{"X":"207.60","Y":"157.21"},{"X":"212.99","Y":"158.51"},{"X":"216.03","Y":"160.11"},{"X":"219.02","Y":"162.82"},{"X":"222.00","Y":"166.95"},{"X":"223.86","Y":"171.04"},{"X":"225.25","Y":"176.56"},{"X":"226.01","Y":"184.02"},{"X":"225.94","Y":"191.67"},{"X":"225.03","Y":"199.56"},{"X":"223.55","Y":"205.37"},{"X":"221.48","Y":"209.86"},{"X":"218.90","Y":"213.53"},{"X":"216.12","Y":"216.03"},{"X":"213.05","Y":"217.58"},{"X":"207.99","Y":"218.94"},{"X":"201.87","Y":"219.54"},{"X":"195.30","Y":"219.05"},{"X":"189.90","Y":"217.79"},{"X":"186.09","Y":"216.23"},{"X":"186.09","Y":"243.93"},{"X":"186.09","Y":"243.93"},{"X":"168.78","Y":"243.93"}],[{"X":"186.09","Y":"170.27"},{"X":"186.13","Y":"208.05"},{"X":"189.79","Y":"210.09"},{"X":"193.53","Y":"211.16"},{"X":"197.86","Y":"211.53"},{"X":"201.86","Y":"210.97"},{"X":"204.91","Y":"209.73"},{"X":"207.25","Y":"207.87"},{"X":"209.01","Y":"205.27"},{"X":"210.72","Y":"200.64"},{"X":"211.90","Y":"194.30"},{"X":"212.32","Y":"186.82"},{"X":"211.80","Y":"179.19"},{"X":"210.69","Y":"174.07"},{"X":"209.11","Y":"170.68"},{"X":"207.06","Y":"168.30"},{"X":"204.40","Y":"166.63"},{"X":"200.81","Y":"165.59"},{"X":"196.18","Y":"165.25"},{"X":"192.24","Y":"166.16"},{"X":"188.91","Y":"167.87"},{"X":"186.21","Y":"169.99"},{"X":"186.09","Y":"170.26"},{"X":"186.09","Y":"170.27"}],[{"X":"231.09","Y":"243.93"},{"X":"231.09","Y":"157.06"},{"X":"248.39","Y":"157.06"},{"X":"248.50","Y":"161.44"},{"X":"253.86","Y":"158.75"},{"X":"258.72","Y":"157.22"},{"X":"263.48","Y":"156.70"},{"X":"269.91","Y":"157.21"},{"X":"275.30","Y":"158.51"},{"X":"278.34","Y":"160.11"},{"X":"281.33","Y":"162.82"},{"X":"284.31","Y":"166.96"},{"X":"286.17","Y":"171.04"},{"X":"287.56","Y":"176.57"},{"X":"288.32","Y":"184.02"},{"X":"288.25","Y":"191.67"},{"X":"287.34","Y":"199.56"},{"X":"285.86","Y":"205.37"},{"X":"283.79","Y":"209.86"},{"X":"281.21","Y":"213.53"},{"X":"278.43","Y":"216.04"},{"X":"275.35","Y":"217.58"},{"X":"270.29","Y":"218.94"},{"X":"264.18","Y":"219.54"},{"X":"257.60","Y":"219.05"},{"X":"252.21","Y":"217.78"},{"X":"248.40","Y":"216.23"},{"X":"248.40","Y":"243.93"},{"X":"248.40","Y":"243.93"},{"X":"231.09","Y":"243.93"}],[{"X":"248.39","Y":"170.27"},{"X":"248.44","Y":"208.05"},{"X":"252.10","Y":"210.09"},{"X":"255.84","Y":"211.16"},{"X":"260.17","Y":"211.53"},{"X":"264.17","Y":"210.97"},{"X":"267.22","Y":"209.73"},{"X":"269.56","Y":"207.87"},{"X":"271.32","Y":"205.27"},{"X":"273.03","Y":"200.64"},{"X":"274.21","Y":"194.30"},{"X":"274.63","Y":"186.82"},{"X":"274.12","Y":"179.19"},{"X":"273.00","Y":"174.07"},{"X":"271.42","Y":"170.68"},{"X":"269.38","Y":"168.30"},{"X":"266.72","Y":"166.64"},{"X":"263.12","Y":"165.59"},{"X":"258.49","Y":"165.25"},{"X":"254.56","Y":"166.16"},{"X":"251.23","Y":"167.86"},{"X":"248.52","Y":"169.99"},{"X":"248.40","Y":"170.26"},{"X":"248.39","Y":"170.27"}],[{"X":"302.11","Y":"132.13"},{"X":"305.37","Y":"132.56"},{"X":"307.93","Y":"133.77"},{"X":"309.95","Y":"135.77"},{"X":"311.37","Y":"138.40"},{"X":"311.95","Y":"141.48"},{"X":"311.63","Y":"144.75"},{"X":"310.47","Y":"147.51"},{"X":"308.56","Y":"149.80"},{"X":"306.27","Y":"151.22"},{"X":"303.22","Y":"151.96"},{"X":"299.79","Y":"151.84"},{"X":"297.10","Y":"150.92"},{"X":"294.85","Y":"149.20"},{"X":"293.04","Y":"146.63"},{"X":"292.14","Y":"143.78"},{"X":"292.13","Y":"140.64"},{"X":"292.97","Y":"137.77"},{"X":"294.71","Y":"135.15"},{"X":"296.90","Y":"133.37"},{"X":"299.56","Y":"132.38"},{"X":"302.10","Y":"132.13"},{"X":"302.11","Y":"132.13"}],[{"X":"293.34","Y":"219.00"},{"X":"293.34","Y":"157.06"},{"X":"310.65","Y":"157.06"},{"X":"310.65","Y":"219.00"},{"X":"310.65","Y":"219.00"},{"X":"293.34","Y":"219.00"}],[{"X":"371.24","Y":"171.37"},{"X":"371.24","Y":"219.00"},{"X":"358.21","Y":"219.00"},{"X":"358.11","Y":"172.27"},{"X":"357.35","Y":"170.01"},{"X":"355.81","Y":"168.19"},{"X":"353.32","Y":"166.83"},{"X":"349.52","Y":"165.99"},{"X":"345.63","Y":"165.91"},{"X":"341.71","Y":"166.90"},{"X":"339.11","Y":"168.36"},{"X":"336.70","Y":"171.02"},{"X":"335.06","Y":"173.87"},{"X":"334.96","Y":"219.00"},{"X":"317.48","Y":"219.00"},{"X":"317.48","Y":"157.06"},{"X":"334.96","Y":"157.06"},{"X":"335.01","Y":"162.07"},{"X":"339.49","Y":"159.34"},{"X":"344.58","Y":"157.56"},{"X":"349.77","Y":"156.78"},{"X":"355.76","Y":"156.84"},{"X":"360.47","Y":"157.70"},{"X":"364.07","Y":"159.18"},{"X":"366.81","Y":"161.26"},{"X":"369.25","Y":"164.29"},{"X":"370.67","Y":"167.42"},{"X":"371.23","Y":"170.82"},{"X":"371.24","Y":"171.27"},{"X":"371.24","Y":"171.37"}],[{"X":"401.90","Y":"232.76"},{"X":"407.58","Y":"232.33"},{"X":"411.33","Y":"231.29"},{"X":"413.88","Y":"229.75"},{"X":"415.39","Y":"227.89"},{"X":"416.16","Y":"225.48"},{"X":"416.21","Y":"216.25"},{"X":"411.46","Y":"218.08"},{"X":"405.72","Y":"219.22"},{"X":"399.44","Y":"219.51"},{"X":"393.19","Y":"218.76"},{"X":"388.30","Y":"217.32"},{"X":"385.44","Y":"215.70"},{"X":"382.67","Y":"212.97"},{"X":"380.07","Y":"208.95"},{"X":"378.24","Y":"204.52"},{"X":"376.93","Y":"198.51"},{"X":"376.28","Y":"190.44"},{"X":"376.52","Y":"182.65"},{"X":"377.58","Y":"175.38"},{"X":"379.16","Y":"170.07"},{"X":"381.22","Y":"166.08"},{"X":"384.14","Y":"162.28"},{"X":"387.11","Y":"159.77"},{"X":"390.08","Y":"158.35"},{"X":"395.48","Y":"157.12"},{"X":"401.76","Y":"156.70"},{"X":"406.66","Y":"157.40"},{"X":"412.02","Y":"159.31"},{"X":"416.24","Y":"161.51"},{"X":"416.24","Y":"157.06"},{"X":"433.55","Y":"157.06"},{"X":"433.43","Y":"223.84"},{"X":"432.54","Y":"227.93"},{"X":"430.90","Y":"231.30"},{"X":"428.49","Y":"234.16"},{"X":"425.23","Y":"236.55"},{"X":"420.86","Y":"238.51"},{"X":"415.19","Y":"239.93"},{"X":"407.89","Y":"240.69"},{"X":"399.04","Y":"240.53"},{"X":"391.61","Y":"239.58"},{"X":"384.09","Y":"237.51"},{"X":"382.01","Y":"236.48"},{"X":"380.74","Y":"226.84"},{"X":"385.59","Y":"229.19"},{"X":"391.82","Y":"231.36"},{"X":"398.16","Y":"232.49"},{"X":"401.75","Y":"232.75"},{"X":"401.90","Y":"232.76"}],[{"X":"416.25","Y":"170.27"},{"X":"414.97","Y":"169.05"},{"X":"410.96","Y":"166.71"},{"X":"406.83","Y":"165.39"},{"X":"404.44","Y":"165.28"},{"X":"400.31","Y":"165.96"},{"X":"397.15","Y":"167.34"},{"X":"394.75","Y":"169.35"},{"X":"392.82","Y":"172.20"},{"X":"391.40","Y":"176.14"},{"X":"390.35","Y":"182.50"},{"X":"390.04","Y":"190.14"},{"X":"390.67","Y":"197.15"},{"X":"391.97","Y":"202.39"},{"X":"393.71","Y":"206.20"},{"X":"395.76","Y":"208.58"},{"X":"398.42","Y":"210.25"},{"X":"401.86","Y":"211.27"},{"X":"406.04","Y":"211.51"},{"X":"410.92","Y":"210.69"},{"X":"414.49","Y":"209.16"},{"X":"416.25","Y":"208.01"},{"X":"416.25","Y":"170.27"},{"X":"416.25","Y":"170.27"}]]' 113 | }, { // Rectangles 114 | subj: '[[{"X":155,"Y":61.67},{"X":155,"Y":212.7},{"X":288.98,"Y":212.7},{"X":288.98,"Y":61.67},{"X":173.01999999999998,"Y":61.67},{"X":155,"Y":61.67}],[{"X":274.37,"Y":190.77},{"X":171.24,"Y":190.77},{"X":171.24,"Y":81.16},{"X":274.37,"Y":81.16},{"X":274.37,"Y":81.16},{"X":274.37,"Y":190.77}]]', 115 | clip: '[[{"X":217.69,"Y":126.14},{"X":217.69,"Y":277.17},{"X":351.66999999999996,"Y":277.17},{"X":351.66999999999996,"Y":126.14},{"X":253.71,"Y":126.14},{"X":217.69,"Y":126.14}],[{"X":337.05,"Y":255.25},{"X":233.93,"Y":255.25},{"X":233.93,"Y":145.63},{"X":337.05,"Y":145.63},{"X":337.05,"Y":145.63},{"X":337.05,"Y":255.25}]]' 116 | }, { // Same self intersecting 117 | subj: '[[{"X":172,"Y":90},{"X":222,"Y":90},{"X":222,"Y":240},{"X":322,"Y":240},{"X":322,"Y":140},{"X":172,"Y":140}]]', 118 | clip: '[[{"X":172,"Y":90},{"X":222,"Y":90},{"X":222,"Y":240},{"X":322,"Y":240},{"X":322,"Y":140},{"X":172,"Y":140}]]' 119 | }, null, null, { // Star and rectangles 120 | subj: '[[{"X":147.47,"Y":312.74},{"X":247.07,"Y":33.510000000000005},{"X":337.66,"Y":312.04},{"X":86.36,"Y":122.7},{"X":404.07,"Y":123.57},{"X":148.11,"Y":312.27},{"X":147.47,"Y":312.74}]]', 121 | clip: '[[{"X":336.36,"Y":261.38},{"X":155.25,"Y":260.49},{"X":155.25,"Y":84.06},{"X":336.36,"Y":84.06},{"X":336.36,"Y":261.38},{"X":336.36,"Y":261.38}]]' 122 | }, { // Spiral and rectangles 123 | subj: '[[{"X":222.02,"Y":294.08},{"X":202.56,"Y":292.96},{"X":183.69,"Y":289.52},{"X":165.670002,"Y":283.86},{"X":148.5,"Y":275.99},{"X":132.45999999999998,"Y":266.02},{"X":117.8,"Y":254.11},{"X":104.75,"Y":240.45},{"X":93.72,"Y":225.49},{"X":84.85,"Y":209.5},{"X":78.12,"Y":192.5},{"X":73.73,"Y":175.06},{"X":71.6,"Y":156.89},{"X":71.83,"Y":139.51},{"X":74.33,"Y":123.52},{"X":79.1,"Y":108.05},{"X":86.16,"Y":93.15},{"X":95.270001,"Y":79.41},{"X":106.41,"Y":66.85},{"X":119.19,"Y":55.97},{"X":133.6,"Y":46.79},{"X":149.15,"Y":39.7},{"X":165.51999999999998,"Y":34.82},{"X":182.41,"Y":32.2300004},{"X":199.5,"Y":31.97},{"X":214.94,"Y":34.03},{"X":229.61,"Y":38.33},{"X":243.45,"Y":44.81},{"X":256.13,"Y":53.36},{"X":267.330004,"Y":63.75},{"X":276.63,"Y":75.5},{"X":283.960004,"Y":88.57},{"X":289.03,"Y":102.35},{"X":291.840003,"Y":116.77},{"X":292.340003,"Y":131.44},{"X":290.53999999999996,"Y":144.5},{"X":286.49,"Y":157.05},{"X":280.16999999999996,"Y":168.96},{"X":271.9,"Y":179.61},{"X":261.710004,"Y":188.89},{"X":250.1,"Y":196.31},{"X":237.4,"Y":201.68},{"X":223.99,"Y":204.85},{"X":209.93,"Y":205.76},{"X":197.13,"Y":204.33},{"X":185.11,"Y":200.63},{"X":173.99,"Y":194.74},{"X":164.19,"Y":186.85},{"X":156.22,"Y":177.51},{"X":150.18,"Y":166.82},{"X":146.41,"Y":155.44},{"X":144.89,"Y":143.56},{"X":145.63,"Y":132.5},{"X":148.59,"Y":122.14},{"X":153.8,"Y":112.36},{"X":160.93,"Y":103.88},{"X":169.89,"Y":96.86},{"X":180.09,"Y":91.81},{"X":191.1,"Y":88.95},{"X":202.47,"Y":88.37},{"X":212.8,"Y":90.1},{"X":222.22,"Y":93.95},{"X":230.55,"Y":99.81},{"X":237.37,"Y":107.36},{"X":242.28,"Y":116.28},{"X":244.92,"Y":125.8},{"X":245.3,"Y":135.670002},{"X":243.42,"Y":144.44},{"X":239.27,"Y":152.74},{"X":233.18,"Y":159.73},{"X":225.31,"Y":165.19},{"X":216.34,"Y":168.54},{"X":206.82,"Y":169.6},{"X":198.23,"Y":168.4},{"X":190.26,"Y":164.97},{"X":183.5,"Y":159.55},{"X":178.57999999999998,"Y":152.77},{"X":175.66,"Y":144.92},{"X":175,"Y":136.87},{"X":176.64,"Y":132.74},{"X":180.14,"Y":130},{"X":184.55,"Y":129.420002},{"X":188.66,"Y":131.13},{"X":191.34,"Y":134.670002},{"X":192.98,"Y":143.46},{"X":196.15,"Y":148.15},{"X":201.12,"Y":151.43},{"X":206.97,"Y":152.6},{"X":214.06,"Y":151.54},{"X":220.43,"Y":148.24},{"X":225.15,"Y":143.26},{"X":227.84,"Y":137.26},{"X":228.34,"Y":130.41},{"X":226.58,"Y":122.84},{"X":222.68,"Y":116.12},{"X":216.8,"Y":110.59},{"X":209.61,"Y":106.92},{"X":201.39,"Y":105.35},{"X":191.84,"Y":106.08},{"X":182.76,"Y":109.12},{"X":174.94,"Y":114.11},{"X":168.57999999999998,"Y":120.86},{"X":164.26,"Y":128.730002},{"X":162.09,"Y":137.44},{"X":162.230002,"Y":147.31},{"X":164.64,"Y":157.2},{"X":169.35,"Y":166.56},{"X":176.03,"Y":174.64},{"X":184.51999999999998,"Y":181.28},{"X":194.25,"Y":185.91},{"X":204.75,"Y":188.36},{"X":216.73,"Y":188.57},{"X":228.83,"Y":186.5},{"X":240.34,"Y":182.2},{"X":250.83,"Y":175.81},{"X":259.9,"Y":167.54},{"X":267.03,"Y":157.91},{"X":272.02,"Y":147.35},{"X":274.830004,"Y":136.01},{"X":275.340003,"Y":123.74},{"X":273.580004,"Y":110.68},{"X":269.580004,"Y":98.12},{"X":263.3,"Y":86.19},{"X":255.05,"Y":75.52},{"X":244.91,"Y":66.18},{"X":233.35,"Y":58.67},{"X":220.7,"Y":53.21},{"X":207.02,"Y":49.86},{"X":192.67,"Y":48.8},{"X":176.82999999999998,"Y":50},{"X":161.34,"Y":53.51},{"X":146.540002,"Y":59.27},{"X":132.76,"Y":67.17},{"X":120.53999999999999,"Y":76.85},{"X":109.92,"Y":88.25},{"X":101.32,"Y":100.89},{"X":94.75999999999999,"Y":114.7},{"X":90.52,"Y":129.07},{"X":88.57,"Y":143.93},{"X":88.92,"Y":160.71},{"X":91.63,"Y":177.58},{"X":96.66,"Y":193.91},{"X":103.9,"Y":209.38},{"X":113.37,"Y":223.97},{"X":124.72,"Y":237.14},{"X":137.93,"Y":248.89},{"X":152.59,"Y":258.78999999999996},{"X":168.44,"Y":266.65},{"X":185.18,"Y":272.34},{"X":202.83,"Y":275.85},{"X":221.07,"Y":277.07},{"X":241.43,"Y":276},{"X":261.24,"Y":272.63},{"X":280.52,"Y":266.98},{"X":299,"Y":259.12},{"X":316.43,"Y":249.14},{"X":332.56,"Y":237.17},{"X":346.94,"Y":223.57},{"X":359.59,"Y":208.35},{"X":370.15,"Y":191.97},{"X":378.51,"Y":174.7},{"X":384.69,"Y":156.54},{"X":388.59,"Y":137.75},{"X":390.64,"Y":115.98},{"X":393.21,"Y":112.35},{"X":397.26,"Y":110.5},{"X":401.4,"Y":110.83},{"X":405.08,"Y":113.33},{"X":407,"Y":117.34},{"X":406.15,"Y":134.39},{"X":402.81,"Y":154.2},{"X":397.18,"Y":173.48},{"X":389.22,"Y":192.25},{"X":379.12,"Y":209.96},{"X":366.88,"Y":226.64},{"X":352.8,"Y":241.8},{"X":336.88,"Y":255.47},{"X":319.51,"Y":267.26},{"X":300.93,"Y":277.02},{"X":281.38,"Y":284.66},{"X":260.81,"Y":290.13},{"X":239.75,"Y":293.26},{"X":222.07,"Y":294.08},{"X":222.02,"Y":294.08}]]', 124 | clip: '[[{"X":210.91,"Y":210.89},{"X":107.65,"Y":210.65},{"X":107.65,"Y":27.58},{"X":210.91,"Y":27.75},{"X":210.91,"Y":36.45},{"X":210.91,"Y":210.89}],[{"X":304.24,"Y":323.13},{"X":210.91,"Y":322.86},{"X":210.91,"Y":70.9},{"X":304.24,"Y":70.91},{"X":304.24,"Y":148.61},{"X":304.24,"Y":323.13}],[{"X":407.5,"Y":254.59},{"X":304.24,"Y":254.35},{"X":304.24,"Y":71.28},{"X":407.5,"Y":71.28},{"X":407.5,"Y":71.28},{"X":407.5,"Y":254.59}]]' 125 | }, { // Rounded grid and stars 126 | subj: '[[{"X":346.2,"Y":66.31},{"X":332.04,"Y":53.81},{"X":316.43,"Y":43.18},{"X":299.87,"Y":34.73995},{"X":282.39,"Y":28.44},{"X":263.95,"Y":24.33},{"X":245.15,"Y":22.56002},{"X":226.27,"Y":23.13},{"X":207.6,"Y":26.04},{"X":189.74,"Y":31.18},{"X":172.6702,"Y":38.53},{"X":156.65,"Y":47.95},{"X":141.69,"Y":59.49},{"X":128.2902,"Y":72.8},{"X":116.65,"Y":87.67},{"X":107.11,"Y":103.62},{"X":99.64,"Y":120.65},{"X":94.37,"Y":138.47},{"X":91.33,"Y":157.11},{"X":90.63,"Y":175.99},{"X":92.2599,"Y":194.8},{"X":96.2401,"Y":213.27},{"X":102.42,"Y":230.8},{"X":110.74,"Y":247.42},{"X":121.26,"Y":263.1},{"X":133.6702,"Y":277.35},{"X":147.74,"Y":289.95},{"X":163.2698,"Y":300.69},{"X":179.77,"Y":309.25},{"X":197.21,"Y":315.68},{"X":215.62,"Y":319.92},{"X":234.41,"Y":321.81},{"X":253.29,"Y":321.38},{"X":271.98,"Y":318.6},{"X":289.87,"Y":313.58},{"X":307,"Y":306.36},{"X":323.09,"Y":297.05},{"X":338.12,"Y":285.62},{"X":351.62,"Y":272.4},{"X":363.37,"Y":257.61},{"X":373.02,"Y":241.73},{"X":380.61,"Y":224.76},{"X":386,"Y":206.97},{"X":389.18,"Y":188.35},{"X":390.01,"Y":169.48},{"X":388.5,"Y":150.65},{"X":384.65,"Y":132.16},{"X":378.61,"Y":114.59},{"X":370.4,"Y":97.91},{"X":359.99,"Y":82.15},{"X":347.69,"Y":67.82},{"X":346.21,"Y":66.32},{"X":346.2,"Y":66.31}],[{"X":375.03,"Y":172.21},{"X":373.83,"Y":190.15},{"X":370.54,"Y":206.57},{"X":362.32,"Y":203.86},{"X":365.47,"Y":187.07},{"X":366.32,"Y":169.7},{"X":364.79,"Y":152.38},{"X":360.96,"Y":135.73},{"X":354.9,"Y":119.76},{"X":346.72,"Y":104.76},{"X":336.39,"Y":90.77},{"X":324.26,"Y":78.32},{"X":320.42,"Y":74.77},{"X":325.57,"Y":67.97},{"X":338.69,"Y":80.27},{"X":350.08,"Y":94.19},{"X":359.52,"Y":109.5},{"X":366.74,"Y":125.65},{"X":371.75,"Y":142.61},{"X":374.49,"Y":160.09},{"X":375.03,"Y":172.07},{"X":375.03,"Y":172.21}],[{"X":129.2698,"Y":172.21},{"X":130.44,"Y":156.06},{"X":133.9598,"Y":140.26},{"X":139.75,"Y":125.15},{"X":147.69,"Y":111.05},{"X":157.6,"Y":98.25},{"X":169.15,"Y":87.09},{"X":174.15,"Y":94.2},{"X":163.0798,"Y":105.17},{"X":153.78,"Y":117.67},{"X":146.4802,"Y":131.44},{"X":141.37,"Y":146.17},{"X":138.57,"Y":161.5},{"X":138.13,"Y":177.08},{"X":140.05,"Y":192.54},{"X":140.87,"Y":196.58},{"X":132.61,"Y":199.24},{"X":129.82,"Y":183.3},{"X":129.2698,"Y":172.22},{"X":129.2698,"Y":172.21}],[{"X":327.6,"Y":172.21},{"X":326.42,"Y":186.54},{"X":325.15,"Y":191.85},{"X":317.08,"Y":189.04},{"X":318.84,"Y":175.67},{"X":318.28,"Y":162.2},{"X":315.43,"Y":149.02},{"X":310.34,"Y":136.54},{"X":303.19,"Y":125.11},{"X":293.99,"Y":114.85},{"X":292.48,"Y":113.21},{"X":297.61,"Y":106.36},{"X":307.64,"Y":116.67},{"X":315.86,"Y":128.4802},{"X":322.02,"Y":141.48},{"X":325.96,"Y":155.31},{"X":327.56,"Y":169.6},{"X":327.6,"Y":172},{"X":327.6,"Y":172.21}],[{"X":153.0198,"Y":172.21},{"X":154.19,"Y":157.87},{"X":157.7098,"Y":143.92},{"X":163.49,"Y":130.75},{"X":171.35,"Y":118.7},{"X":181.07,"Y":108.1},{"X":183.26,"Y":106.49},{"X":188.11,"Y":113.5},{"X":178.65,"Y":123.52},{"X":171.2098,"Y":134.7698},{"X":165.8,"Y":147.12},{"X":162.61,"Y":160.22},{"X":161.7098,"Y":173.67},{"X":163.13,"Y":187.08},{"X":163.36,"Y":189.28},{"X":155.22,"Y":191.74},{"X":153.18,"Y":177.51},{"X":153.0198,"Y":172.41},{"X":153.0198,"Y":172.21}],[{"X":303.92,"Y":172.21},{"X":302.73,"Y":184.43},{"X":294.39,"Y":181.76},{"X":295.2104,"Y":170.41},{"X":293.6597,"Y":159.14},{"X":289.8,"Y":148.43},{"X":283.81,"Y":138.76},{"X":278.44,"Y":132.51},{"X":283.57,"Y":125.63},{"X":291.73,"Y":134.82},{"X":297.98,"Y":145.39},{"X":302.07,"Y":156.97},{"X":303.84,"Y":169.12},{"X":303.92,"Y":172.12},{"X":303.92,"Y":172.21}],[{"X":200.38,"Y":172.21},{"X":201.53,"Y":162.7},{"X":204.93,"Y":153.75},{"X":210.37,"Y":145.87},{"X":211.36,"Y":145.15},{"X":216.39,"Y":152.18},{"X":211.93,"Y":159.27},{"X":209.51,"Y":167.29},{"X":209.16,"Y":174.43},{"X":200.68,"Y":177.07},{"X":200.38,"Y":172.28},{"X":200.38,"Y":172.21}],[{"X":279.9196,"Y":177.17},{"X":271.4,"Y":174.36},{"X":270.87,"Y":166.01},{"X":268.12,"Y":158.1},{"X":264.19,"Y":152.1},{"X":269.5,"Y":145.05},{"X":275.1597,"Y":152.78},{"X":278.81,"Y":161.64},{"X":280.22,"Y":171.11},{"X":279.93,"Y":177.09},{"X":279.9196,"Y":177.17}],[{"X":251.65,"Y":183.77},{"X":247.81,"Y":186.59},{"X":247.94,"Y":182.57},{"X":251.37,"Y":183.68},{"X":251.65,"Y":183.77}],[{"X":252.45,"Y":168.26},{"X":254.89,"Y":165.21},{"X":256.24,"Y":169.49},{"X":252.54,"Y":168.29},{"X":252.45,"Y":168.26}],[{"X":240.31,"Y":159.45},{"X":238.03,"Y":156.14},{"X":242.64,"Y":156.24},{"X":240.35,"Y":159.39},{"X":240.31,"Y":159.45}],[{"X":228.17,"Y":168.26},{"X":224.41,"Y":169.28},{"X":225.81,"Y":165.03},{"X":228.11,"Y":168.18},{"X":228.17,"Y":168.26}],[{"X":232.81,"Y":182.52},{"X":232.69,"Y":186.53},{"X":229.1,"Y":183.73},{"X":232.52,"Y":182.62},{"X":232.81,"Y":182.52}],[{"X":247.81,"Y":202.54},{"X":255.59,"Y":199.43},{"X":262.26,"Y":194.37},{"X":266.99,"Y":188.75},{"X":275.13,"Y":191.69},{"X":269.4604,"Y":199.41},{"X":262.13,"Y":205.57},{"X":253.54,"Y":209.81},{"X":247.81,"Y":211.35},{"X":247.81,"Y":211.35},{"X":247.81,"Y":202.54}],[{"X":252.07,"Y":143.27},{"X":243.96,"Y":141.17},{"X":235.59,"Y":141.32},{"X":228.44,"Y":143.14},{"X":223.38,"Y":136.11},{"X":232.48,"Y":133.12},{"X":242.03,"Y":132.38},{"X":251.47,"Y":133.94},{"X":257.2,"Y":136.21},{"X":252.09,"Y":143.25},{"X":252.07,"Y":143.27}],[{"X":213.83,"Y":188.68},{"X":219.16,"Y":195.14},{"X":226,"Y":199.96},{"X":232.81,"Y":202.54},{"X":232.71,"Y":211.33},{"X":223.6,"Y":208.4},{"X":215.45,"Y":203.37},{"X":208.72,"Y":196.55},{"X":205.5,"Y":191.38},{"X":213.77,"Y":188.7},{"X":213.83,"Y":188.68}],[{"X":232.81,"Y":226.54},{"X":232.63,"Y":235.34},{"X":220.63,"Y":232.69},{"X":209.38,"Y":227.76},{"X":199.29,"Y":220.77},{"X":190.72,"Y":211.98},{"X":183.98,"Y":201.71},{"X":182.64,"Y":198.8},{"X":190.9,"Y":196.16},{"X":196.92,"Y":205.81},{"X":204.8,"Y":214.02},{"X":214.19,"Y":220.45},{"X":224.71,"Y":224.8},{"X":232.61,"Y":226.52},{"X":232.81,"Y":226.54}],[{"X":247.81,"Y":226.54},{"X":258.86,"Y":223.83},{"X":269.11,"Y":218.89},{"X":278.13,"Y":211.95},{"X":285.53,"Y":203.31},{"X":289.8,"Y":196.15},{"X":298.05,"Y":198.84},{"X":291.8403,"Y":209.44},{"X":283.7104,"Y":218.65},{"X":273.98,"Y":226.14},{"X":262.99,"Y":231.62},{"X":251.15,"Y":234.87},{"X":247.81,"Y":235.36},{"X":247.81,"Y":235.36},{"X":247.81,"Y":226.54}],[{"X":266.2,"Y":123.84},{"X":255.67,"Y":119.53},{"X":244.47,"Y":117.5},{"X":233.1,"Y":117.82},{"X":222.03,"Y":120.47},{"X":214.38,"Y":123.79},{"X":209.48,"Y":116.59},{"X":220.74,"Y":111.68},{"X":232.73,"Y":109.05},{"X":245.01,"Y":108.77},{"X":257.11,"Y":110.86},{"X":268.5804,"Y":115.25},{"X":271.2896,"Y":116.84},{"X":266.35,"Y":123.63},{"X":266.2,"Y":123.84}],[{"X":202.29,"Y":132.6702},{"X":194.93,"Y":141.35},{"X":189.51,"Y":151.35},{"X":186.28,"Y":162.26},{"X":185.4,"Y":173.61},{"X":186.15,"Y":181.89},{"X":177.9,"Y":184.53},{"X":176.7,"Y":172.31},{"X":177.86,"Y":160.08},{"X":181.36,"Y":148.31},{"X":187.07,"Y":137.44},{"X":194.76,"Y":127.86},{"X":197.29,"Y":125.8},{"X":202.24,"Y":132.6},{"X":202.29,"Y":132.6702}],[{"X":168.2,"Y":203.48},{"X":174.63,"Y":215.34},{"X":182.98,"Y":225.92},{"X":193.01,"Y":234.94},{"X":204.42,"Y":242.12},{"X":216.89,"Y":247.24},{"X":230.06,"Y":250.14},{"X":232.81,"Y":250.45},{"X":232.66,"Y":259.23},{"X":218.49,"Y":256.8},{"X":204.91,"Y":252.05},{"X":192.3,"Y":245.13},{"X":180.99,"Y":236.24},{"X":171.2902,"Y":225.63},{"X":163.44,"Y":213.57},{"X":160.07,"Y":206.12},{"X":168.06,"Y":203.53},{"X":168.2,"Y":203.48}],[{"X":247.81,"Y":250.45},{"X":261.07,"Y":248.02},{"X":273.72,"Y":243.35},{"X":285.37,"Y":236.57},{"X":295.7104,"Y":227.91},{"X":304.42,"Y":217.62},{"X":311.26,"Y":206},{"X":312.63,"Y":203.56},{"X":320.65,"Y":206.36},{"X":313.94,"Y":219.08},{"X":305.24,"Y":230.53},{"X":294.7896,"Y":240.41},{"X":282.86,"Y":248.46},{"X":269.78,"Y":254.44},{"X":255.89,"Y":258.1696},{"X":247.81,"Y":259.24},{"X":247.81,"Y":259.24},{"X":247.81,"Y":250.45}],[{"X":280.24,"Y":104.53},{"X":268.0903,"Y":98.68},{"X":255.12,"Y":95},{"X":241.71,"Y":93.61},{"X":228.26,"Y":94.52},{"X":215.16,"Y":97.73},{"X":202.81,"Y":103.15},{"X":200.26,"Y":104.37},{"X":195.31,"Y":97.37},{"X":208.19,"Y":90.97},{"X":221.96,"Y":86.79},{"X":236.22,"Y":84.94},{"X":250.6,"Y":85.45},{"X":264.69,"Y":88.31},{"X":278.12,"Y":93.47},{"X":285.3304,"Y":97.52},{"X":280.4,"Y":104.31},{"X":280.24,"Y":104.53}],[{"X":240.31,"Y":69.85},{"X":224.77,"Y":71.03},{"X":209.88,"Y":74.47},{"X":195.4,"Y":80.25},{"X":186.27,"Y":85.13},{"X":181.44,"Y":78.15},{"X":195.74,"Y":70.57},{"X":211,"Y":65.16},{"X":226.88,"Y":62.04},{"X":243.04,"Y":61.27},{"X":259.15,"Y":62.84},{"X":274.86,"Y":66.7401},{"X":289.8304,"Y":72.9},{"X":299.23,"Y":78.4},{"X":294.06,"Y":85.16},{"X":280.23,"Y":77.97},{"X":265.47,"Y":72.98},{"X":250.12,"Y":70.31},{"X":240.53,"Y":69.85},{"X":240.31,"Y":69.85}],[{"X":145.5798,"Y":210.82},{"X":152.56,"Y":224.76},{"X":161.57,"Y":237.47},{"X":172.4,"Y":248.69},{"X":184.79,"Y":258.14},{"X":198.47,"Y":265.6},{"X":213.13,"Y":270.89},{"X":228.42,"Y":273.88},{"X":232.81,"Y":274.29},{"X":232.64,"Y":282.91},{"X":216.62,"Y":280.63},{"X":201.1,"Y":276.03},{"X":186.42,"Y":269.2},{"X":172.89,"Y":260.32},{"X":160.7902,"Y":249.58},{"X":150.36,"Y":237.2},{"X":141.8298,"Y":223.44},{"X":137.4202,"Y":213.47},{"X":145.41,"Y":210.88},{"X":145.5798,"Y":210.82}],[{"X":247.81,"Y":274.29},{"X":263.22,"Y":271.97},{"X":277.81,"Y":267.44},{"X":291.82,"Y":260.61},{"X":304.63,"Y":251.73},{"X":315.96,"Y":241.02},{"X":325.54,"Y":228.73},{"X":333.15,"Y":215.13},{"X":335.12,"Y":210.85},{"X":343.34,"Y":213.56},{"X":336.21,"Y":228.09},{"X":327.03,"Y":241.42},{"X":316.03,"Y":253.29},{"X":303.43,"Y":263.45},{"X":289.49,"Y":271.68},{"X":274.5,"Y":277.79},{"X":258.78,"Y":281.63},{"X":247.81,"Y":282.92},{"X":247.81,"Y":282.92},{"X":247.81,"Y":274.29}],[{"X":339.67,"Y":196.56},{"X":342.21,"Y":181.18},{"X":342.39,"Y":165.6},{"X":340.21,"Y":150.16},{"X":335.7,"Y":135.25},{"X":328.96,"Y":121.19},{"X":320.17,"Y":108.32},{"X":309.54,"Y":96.93},{"X":306.51,"Y":93.91},{"X":311.67,"Y":87.25},{"X":323.27,"Y":98.54},{"X":333.13,"Y":111.37},{"X":341.03,"Y":125.5},{"X":346.77,"Y":140.63},{"X":350.23,"Y":156.45},{"X":351.35,"Y":172.59},{"X":350.12,"Y":188.73},{"X":347.95,"Y":199.24},{"X":339.68,"Y":196.56},{"X":339.67,"Y":196.56}],[{"X":313.32,"Y":59.03},{"X":307.96,"Y":65.9601},{"X":292.9604,"Y":57.76},{"X":277,"Y":51.68},{"X":260.35,"Y":47.83},{"X":243.33,"Y":46.27},{"X":225.96,"Y":47.04},{"X":209.16,"Y":50.13},{"X":192.93,"Y":55.47},{"X":177.58,"Y":62.97},{"X":172.2698,"Y":65.87},{"X":167.5,"Y":58.9},{"X":182.96,"Y":50.31},{"X":199.42,"Y":43.83},{"X":216.59,"Y":39.58},{"X":234.17,"Y":37.62005},{"X":252.15,"Y":38},{"X":269.63,"Y":40.7},{"X":286.6,"Y":45.68},{"X":302.76,"Y":52.86},{"X":313.12,"Y":58.91},{"X":313.32,"Y":59.03}],[{"X":155.18,"Y":67.87},{"X":160.1,"Y":75.1},{"X":147.49,"Y":87.07},{"X":136.63,"Y":100.65},{"X":127.73,"Y":115.58},{"X":121.08,"Y":131.32},{"X":116.64,"Y":147.82},{"X":114.48,"Y":164.77},{"X":114.66,"Y":182.16},{"X":117.15,"Y":199.06},{"X":118.19,"Y":203.94},{"X":110.01,"Y":206.46},{"X":106.64,"Y":189.1},{"X":105.59,"Y":171.14},{"X":106.92,"Y":153.21},{"X":110.56,"Y":135.9},{"X":116.45,"Y":119.22},{"X":124.48,"Y":103.46},{"X":134.7,"Y":88.66},{"X":146.78,"Y":75.33},{"X":155.07,"Y":67.9601},{"X":155.18,"Y":67.87}],[{"X":114.68,"Y":220.85},{"X":123.06,"Y":218.44},{"X":130.4202,"Y":233.86},{"X":139.99,"Y":248.38},{"X":151.45,"Y":261.4604},{"X":164.59,"Y":272.84},{"X":179.16,"Y":282.33},{"X":194.62,"Y":289.61},{"X":210.92,"Y":294.71},{"X":227.77,"Y":297.55},{"X":232.81,"Y":297.95},{"X":232.52,"Y":306.7},{"X":214.97,"Y":304.53},{"X":197.86,"Y":300.07},{"X":181.48,"Y":293.39},{"X":166.12,"Y":284.61},{"X":151.82,"Y":273.7},{"X":139.0798,"Y":261.01},{"X":128.14,"Y":246.73},{"X":119.31,"Y":231.41},{"X":114.72,"Y":220.97},{"X":114.68,"Y":220.85}],[{"X":247.81,"Y":306.71},{"X":248.04,"Y":297.93},{"X":264.99,"Y":295.74},{"X":281.48,"Y":291.27},{"X":297.2,"Y":284.59},{"X":311.88,"Y":275.84},{"X":325.47,"Y":264.99},{"X":337.44,"Y":252.39},{"X":347.59,"Y":238.27},{"X":355.57,"Y":223.16},{"X":357.93,"Y":218.25},{"X":365.83,"Y":221.11},{"X":358.32,"Y":237.13},{"X":348.6,"Y":252.26},{"X":336.95,"Y":265.97},{"X":323.6,"Y":278.02},{"X":308.77,"Y":288.19},{"X":292.99,"Y":296.19},{"X":276.3,"Y":302.04},{"X":258.98,"Y":305.63},{"X":247.94,"Y":306.71},{"X":247.81,"Y":306.71}]]', 127 | clip: '[[{"X":240.31,"Y":12.26},{"X":292.45,"Y":117.59},{"X":408.23,"Y":134.69},{"X":324.43,"Y":216.63},{"X":344.16,"Y":332.1},{"X":240.06,"Y":277.63},{"X":136.4,"Y":332},{"X":155.99,"Y":216.19},{"X":72.33,"Y":134.4202},{"X":188.37,"Y":117.5},{"X":240.28,"Y":12.30999},{"X":240.31,"Y":12.26}]]' 128 | }, { // Glyph and grid 129 | subj: '[[{"X":105.65,"Y":51.37},{"X":105.65,"Y":295.26},{"X":395.09,"Y":295.26},{"X":395.01,"Y":51.37},{"X":108.51,"Y":51.37},{"X":105.65,"Y":51.37}],[{"X":380.09,"Y":89.4799},{"X":349.33,"Y":89.4799},{"X":349.33,"Y":66.37},{"X":380.09,"Y":66.37},{"X":380.09,"Y":66.37},{"X":380.09,"Y":89.4799}],[{"X":257.87,"Y":127.7},{"X":257.87,"Y":104.48},{"X":288.63,"Y":104.48},{"X":288.44,"Y":127.7},{"X":283.0396,"Y":127.7},{"X":257.87,"Y":127.7}],[{"X":288.63,"Y":142.7},{"X":288.63,"Y":165.81},{"X":257.87,"Y":165.81},{"X":257.87,"Y":142.7},{"X":257.87,"Y":142.7},{"X":288.63,"Y":142.7}],[{"X":242.87,"Y":127.7},{"X":212.11,"Y":127.7},{"X":212.11,"Y":104.48},{"X":242.87,"Y":104.48},{"X":242.87,"Y":104.48},{"X":242.87,"Y":127.7}],[{"X":242.87,"Y":142.7},{"X":242.87,"Y":165.81},{"X":212.11,"Y":165.81},{"X":212.11,"Y":142.7},{"X":212.11,"Y":142.7},{"X":242.87,"Y":142.7}],[{"X":197.11,"Y":165.81},{"X":166.41,"Y":165.81},{"X":166.41,"Y":142.7},{"X":197.11,"Y":142.7},{"X":197.11,"Y":142.7},{"X":197.11,"Y":165.81}],[{"X":197.11,"Y":180.81},{"X":197.11,"Y":203.92},{"X":166.41,"Y":203.92},{"X":166.41,"Y":180.81},{"X":166.41,"Y":180.81},{"X":197.11,"Y":180.81}],[{"X":212.11,"Y":180.81},{"X":242.87,"Y":180.81},{"X":242.87,"Y":203.92},{"X":212.11,"Y":203.92},{"X":212.11,"Y":203.92},{"X":212.11,"Y":180.81}],[{"X":242.87,"Y":218.92},{"X":242.87,"Y":242.14},{"X":212.11,"Y":242.14},{"X":212.11,"Y":218.92},{"X":212.11,"Y":218.92},{"X":242.87,"Y":218.92}],[{"X":257.87,"Y":218.92},{"X":288.63,"Y":218.92},{"X":288.63,"Y":242.14},{"X":257.87,"Y":242.14},{"X":257.87,"Y":242.14},{"X":257.87,"Y":218.92}],[{"X":257.87,"Y":203.92},{"X":257.87,"Y":180.81},{"X":288.63,"Y":180.81},{"X":288.63,"Y":203.92},{"X":288.63,"Y":203.92},{"X":257.87,"Y":203.92}],[{"X":303.63,"Y":180.81},{"X":334.33004,"Y":180.81},{"X":334.33004,"Y":203.92},{"X":303.63,"Y":203.92},{"X":303.63,"Y":203.92},{"X":303.63,"Y":180.81}],[{"X":303.63,"Y":165.81},{"X":303.63,"Y":142.7},{"X":334.33004,"Y":142.7},{"X":334.33004,"Y":165.81},{"X":334.33004,"Y":165.81},{"X":303.63,"Y":165.81}],[{"X":303.63,"Y":127.7},{"X":303.63,"Y":104.48},{"X":334.33004,"Y":104.48},{"X":334.07,"Y":127.7},{"X":328.6696,"Y":127.7},{"X":303.63,"Y":127.7}],[{"X":303.63,"Y":89.4799},{"X":303.63,"Y":66.37},{"X":334.33004,"Y":66.37},{"X":334.15,"Y":89.4799},{"X":316.15,"Y":89.4799},{"X":303.63,"Y":89.4799}],[{"X":288.63,"Y":89.4799},{"X":257.87,"Y":89.4799},{"X":257.87,"Y":66.37},{"X":288.63,"Y":66.37},{"X":288.63,"Y":89.4799},{"X":288.63,"Y":89.4799}],[{"X":242.87,"Y":89.4799},{"X":212.11,"Y":89.4799},{"X":212.11,"Y":66.37},{"X":242.87,"Y":66.37},{"X":242.87,"Y":66.37},{"X":242.87,"Y":89.4799}],[{"X":197.11,"Y":89.4799},{"X":166.41,"Y":89.4799},{"X":166.41,"Y":66.37},{"X":197.11,"Y":66.37},{"X":197.11,"Y":66.37},{"X":197.11,"Y":89.4799}],[{"X":197.11,"Y":104.48},{"X":196.93,"Y":127.7},{"X":166.41,"Y":127.7},{"X":166.41,"Y":104.48},{"X":166.41,"Y":104.48},{"X":197.11,"Y":104.48}],[{"X":151.41,"Y":127.7},{"X":120.65,"Y":127.7},{"X":120.65,"Y":104.48},{"X":151.41,"Y":104.48},{"X":151.41,"Y":104.48},{"X":151.41,"Y":127.7}],[{"X":151.41,"Y":142.7},{"X":151.41,"Y":165.81},{"X":120.65,"Y":165.81},{"X":120.65,"Y":142.7},{"X":120.65,"Y":142.7},{"X":151.41,"Y":142.7}],[{"X":151.41,"Y":180.81},{"X":151.41,"Y":203.92},{"X":120.65,"Y":203.92},{"X":120.65,"Y":180.81},{"X":120.65,"Y":180.81},{"X":151.41,"Y":180.81}],[{"X":151.41,"Y":218.92},{"X":151.41,"Y":242.14},{"X":120.65,"Y":242.14},{"X":120.65,"Y":218.92},{"X":120.65,"Y":218.92},{"X":151.41,"Y":218.92}],[{"X":166.41,"Y":218.92},{"X":197.11,"Y":218.92},{"X":197.11,"Y":242.14},{"X":166.41,"Y":242.14},{"X":166.41,"Y":242.14},{"X":166.41,"Y":218.92}],[{"X":197.11,"Y":257.14},{"X":197.11,"Y":280.26},{"X":166.41,"Y":280.26},{"X":166.41,"Y":257.14},{"X":166.41,"Y":257.14},{"X":197.11,"Y":257.14}],[{"X":212.11,"Y":257.14},{"X":242.87,"Y":257.14},{"X":242.87,"Y":280.26},{"X":212.11,"Y":280.26},{"X":212.11,"Y":280.26},{"X":212.11,"Y":257.14}],[{"X":257.87,"Y":257.14},{"X":288.63,"Y":257.14},{"X":288.63,"Y":280.26},{"X":257.87,"Y":280.26},{"X":257.87,"Y":280.26},{"X":257.87,"Y":257.14}],[{"X":303.63,"Y":257.14},{"X":334.33004,"Y":257.14},{"X":334.33004,"Y":280.26},{"X":303.63,"Y":280.26},{"X":303.63,"Y":280.26},{"X":303.63,"Y":257.14}],[{"X":303.63,"Y":242.14},{"X":303.63,"Y":218.92},{"X":334.33004,"Y":218.92},{"X":334.33004,"Y":242.14},{"X":334.33004,"Y":242.14},{"X":303.63,"Y":242.14}],[{"X":349.33,"Y":218.92},{"X":380.09,"Y":218.92},{"X":380.09,"Y":242.14},{"X":349.33,"Y":242.14},{"X":349.33,"Y":242.14},{"X":349.33,"Y":218.92}],[{"X":349.33,"Y":203.92},{"X":349.33,"Y":180.81},{"X":380.09,"Y":180.81},{"X":380.09,"Y":203.92},{"X":380.09,"Y":203.92},{"X":349.33,"Y":203.92}],[{"X":349.33,"Y":165.81},{"X":349.33,"Y":142.7},{"X":380.09,"Y":142.7},{"X":380.09,"Y":165.81},{"X":380.09,"Y":165.81},{"X":349.33,"Y":165.81}],[{"X":349.33,"Y":127.7},{"X":349.33,"Y":104.48},{"X":380.09,"Y":104.48},{"X":379.9,"Y":127.7},{"X":374.5,"Y":127.7},{"X":349.33,"Y":127.7}],[{"X":151.41,"Y":66.37},{"X":151.12,"Y":89.4799},{"X":120.65,"Y":89.4799},{"X":120.65,"Y":66.37},{"X":120.65,"Y":66.37},{"X":151.41,"Y":66.37}],[{"X":120.65,"Y":257.14},{"X":151.41,"Y":257.14},{"X":151.41,"Y":280.26},{"X":120.65,"Y":280.26},{"X":120.65,"Y":280.26},{"X":120.65,"Y":257.14}],[{"X":349.33,"Y":280.26},{"X":349.33,"Y":257.14},{"X":380.09,"Y":257.14},{"X":380.09,"Y":280.26},{"X":380.09,"Y":280.26},{"X":349.33,"Y":280.26}]]', 130 | clip: '[[{"X":305.08004,"Y":241.97},{"X":306,"Y":251.51},{"X":308.18,"Y":256.4},{"X":311.72,"Y":259.09003},{"X":317.31,"Y":260.01},{"X":324.71004,"Y":259.01},{"X":332.45,"Y":255.86},{"X":335.57,"Y":257.5396},{"X":337.6,"Y":260.44},{"X":336.94,"Y":262.33004},{"X":328.27,"Y":268.74},{"X":317.9,"Y":273.4196},{"X":307.94,"Y":275.49},{"X":296.26,"Y":275.23},{"X":286.64,"Y":272.99},{"X":279.7896,"Y":269.31},{"X":274.14,"Y":263.55},{"X":271.6597,"Y":260.21004},{"X":269.2,"Y":261.06},{"X":254.83,"Y":268.51},{"X":242.11,"Y":272.97},{"X":227.59,"Y":275.23},{"X":209.91,"Y":275.48},{"X":197.47,"Y":273.63},{"X":187.91,"Y":270.13},{"X":180.48002,"Y":265.09003},{"X":175.32,"Y":258.88},{"X":172.2098,"Y":251.44},{"X":171.1,"Y":242.23},{"X":172.24,"Y":233.63},{"X":175.49,"Y":226.24},{"X":181,"Y":219.54},{"X":189.42002,"Y":213.3},{"X":201.36,"Y":207.73},{"X":217.23,"Y":203.25},{"X":238.28,"Y":200.1},{"X":265.24,"Y":198.78},{"X":269.37,"Y":198.47},{"X":269.98,"Y":182.93},{"X":268.74,"Y":171.32},{"X":266.05,"Y":163.7098},{"X":261.58004,"Y":157.72},{"X":255.24,"Y":153.24},{"X":247.06,"Y":150.3298},{"X":235.44,"Y":149.13},{"X":224.71,"Y":150.05},{"X":215.91,"Y":153},{"X":210.23002,"Y":156.86},{"X":207.64,"Y":160.85},{"X":207.19,"Y":165.28},{"X":209.34,"Y":169.86},{"X":212.0198,"Y":174.15},{"X":212.14,"Y":177.99},{"X":209.8,"Y":181.78},{"X":204.22,"Y":185.79},{"X":197.62,"Y":187.68},{"X":188.65,"Y":187.43},{"X":182.41,"Y":185.39},{"X":178.45,"Y":181.77},{"X":176.2098,"Y":176.9},{"X":176.03,"Y":170.64},{"X":178.2,"Y":164.13},{"X":183.09,"Y":157.7},{"X":191.04002,"Y":151.36},{"X":202.01,"Y":145.8298},{"X":216.09,"Y":141.57},{"X":232.08,"Y":139.24},{"X":250.07,"Y":139.18},{"X":266.13,"Y":141.23002},{"X":279.05,"Y":145.06},{"X":289.1597,"Y":150.3},{"X":295.9196,"Y":156.19},{"X":300.73,"Y":163.41},{"X":303.85,"Y":172.47},{"X":305.07,"Y":183.78},{"X":305.07,"Y":241.97},{"X":305.08004,"Y":241.97}],[{"X":243.99,"Y":64.95},{"X":255.92,"Y":66.07},{"X":266.21004,"Y":69.28},{"X":274.98,"Y":74.44},{"X":280.65,"Y":80.19},{"X":284.03,"Y":86.85},{"X":285.26,"Y":94.52001},{"X":284.28,"Y":102.84},{"X":281.24,"Y":109.66},{"X":276.0396,"Y":115.43},{"X":267.89,"Y":120.46},{"X":257.68,"Y":123.93},{"X":245.79,"Y":125.33},{"X":232.93,"Y":124.53},{"X":222.21,"Y":121.74},{"X":213.14,"Y":117.11},{"X":207.36,"Y":111.92},{"X":203.7,"Y":105.75},{"X":201.94,"Y":98.18},{"X":202.34,"Y":90.12},{"X":204.86,"Y":83.4},{"X":210.01,"Y":76.81},{"X":217.49,"Y":71.33},{"X":227.17,"Y":67.31},{"X":238.35,"Y":65.2},{"X":243.75,"Y":64.95},{"X":243.99,"Y":64.95}],[{"X":269.99,"Y":212.88},{"X":269.48,"Y":208.76},{"X":266.59003,"Y":208.36},{"X":245.76,"Y":210.86},{"X":230.95,"Y":214.67},{"X":220.9,"Y":219.34},{"X":213.82,"Y":224.85},{"X":209.69,"Y":230.71},{"X":207.92002,"Y":237.03},{"X":208.4,"Y":244.49},{"X":210.86,"Y":250.57},{"X":215.2,"Y":255.08},{"X":221.69,"Y":258.13},{"X":230.57,"Y":259.43},{"X":242.52,"Y":258.58004},{"X":255.27,"Y":255.23},{"X":266.07,"Y":250.04},{"X":269.34003,"Y":247.02},{"X":269.99,"Y":244.81},{"X":269.99,"Y":212.88},{"X":269.99,"Y":212.88}],[{"X":243.63,"Y":73.34},{"X":235.93,"Y":74.4},{"X":230.07,"Y":77.36},{"X":225.65,"Y":82.21001},{"X":223.05,"Y":88.57},{"X":222.41,"Y":96.92},{"X":223.94,"Y":104.53},{"X":227.23,"Y":110.22},{"X":231.99,"Y":114.29},{"X":238.44,"Y":116.65},{"X":246.81,"Y":116.94},{"X":253.73,"Y":115.1},{"X":258.87,"Y":111.5},{"X":262.63,"Y":106.12},{"X":264.65,"Y":98.93},{"X":264.59003,"Y":90.25},{"X":262.47,"Y":83.41},{"X":258.6597,"Y":78.43},{"X":253.37,"Y":75.08},{"X":246.08,"Y":73.43},{"X":243.68,"Y":73.34},{"X":243.63,"Y":73.34}]]' 131 | }, getCustomPolygons() 132 | ]; 133 | var SVG = { 134 | scaledPaths: [], 135 | subPolyLinks: null, 136 | total: null, 137 | create: function () { 138 | p = Raphael('svgcontainer', 500, 350); 139 | p.canvas.id = 'p'; 140 | var filter = ''; 141 | filter += ''; 142 | filter += ''; 143 | filter += ''; 144 | filter += ''; // changed to 1.0 for speed 145 | filter += ''; 146 | filter += ''; 147 | filter += ''; 148 | filter += ''; 149 | filter += ''; // changed to 1.0 for speed 150 | filter += ''; 151 | filter += ''; 152 | filter += ''; 153 | // Markers to show start, mid and end points of path 154 | var markers = ''; 155 | markers += ''; 156 | markers += ''; 157 | markers += ''; 158 | markers += ''; 159 | markers += ''; 160 | markers += ''; 161 | markers += ''; 162 | markers += ''; 163 | 164 | // This second invisible marker is needed to avoid noisy after images in Chrome: 165 | markers += ''; 166 | markers += ''; 167 | markers += ''; 168 | markers += ''; 169 | markers += ''; 170 | markers += ''; 171 | markers += ''; 172 | markers += ''; 173 | markers += ''; 174 | // http://stackoverflow.com/questions/3642035/jquerys-append-not-working-with-svg-element 175 | $('body').append(''); 176 | $('#p defs').append($('#innerbevel'), $('#dummy marker')); 177 | $('#dummy').remove(); 178 | return p; 179 | }, 180 | update: function() { 181 | if (!p) p = SVG.create(); 182 | if (p1) p1.remove(); 183 | if (p2) p2.remove(); 184 | if (p3) p3.remove(); 185 | }, 186 | addPaths: function (a, b, c, subjFillType, clipFillType) { 187 | if (a) { 188 | subj.subPolygons = a.length; 189 | a = this.polysToPath(a, 1); 190 | if (explorerEnabled) { 191 | if (typeof subj.subPolygons === 'undefined') subj.subPolygons = 0; 192 | $('#subj_subpolygons').html(subj.subPolygons); 193 | $('#subj_points_in_subpolygons').html(this.subPolyLinks); 194 | $('#subj_points_total').html(this.total.toString()); 195 | subj.totalPoints = this.total; 196 | } 197 | } 198 | if (b) { 199 | clip.subPolygons = b.length; 200 | b = this.polysToPath(b, 2); 201 | if (explorerEnabled) { 202 | if (typeof clip.subPolygons === 'undefined') clip.subPolygons = 0; 203 | $('#clip_subpolygons').html(clip.subPolygons); 204 | $('#clip_points_in_subpolygons').html(this.subPolyLinks); 205 | $('#clip_points_total').html(this.total.toString()); 206 | clip.totalPoints = this.total; 207 | } 208 | } 209 | solution.subPolygons = (typeof c !== 'undefined' && typeof c.length !== 'undefined') ? c.length : 0; 210 | if (c) { 211 | c = this.polysToPath(c, 3); 212 | if (explorerEnabled) { 213 | $('#solution_subpolygons').html(solution.subPolygons); 214 | $('#solution_points_in_subpolygons').html(this.subPolyLinks); 215 | $('#solution_points_total').html(this.total.toString()); 216 | solution.totalPoints = this.total; 217 | } 218 | } 219 | if (explorerEnabled) { 220 | $('#points_total').html((subj.totalPoints + clip.totalPoints + solution.totalPoints).toString()); 221 | if (isNaN(subj.subPolygons)) subj.subPolygons = 0; 222 | else if (isNaN(clip.subPolygons)) clip.subPolygons = 0; 223 | else if (isNaN(solution.subPolygons)) solution.subPolygons = 0; 224 | $('#all_subpolygons').html(subj.subPolygons + clip.subPolygons + solution.subPolygons); 225 | } 226 | if (a) { 227 | p1 = p.path(a); 228 | p1.node.id = 'p1'; 229 | $('#p1').removeAttr('fill stroke') 230 | .attr('fill-rule', subjFillType === 0 ? 'evenodd' : 'nonzero'); 231 | } 232 | if (b) { 233 | p2 = p.path(b); 234 | p2.node.id = 'p2'; 235 | $('#p2').removeAttr('fill stroke') 236 | .attr('fill-rule', clipFillType === 0 ? 'evenodd' : 'nonzero'); 237 | } 238 | if (c) { 239 | p3 = p.path(c); 240 | p3.node.id = 'p3'; 241 | $('#p3').removeAttr('fill stroke'); 242 | if (bevel) { 243 | $('#p3').attr('filter', 'url(#innerbevel)'); 244 | } else { 245 | $('#p3').removeAttr('filter'); 246 | } 247 | } 248 | }, 249 | polysToPath: function (a, fr) { 250 | this.scaledPaths[fr] = []; 251 | var path = '', i, j, d; 252 | this.subPolyCounts = []; 253 | this.subPolyLinks = []; 254 | this.total = 0; 255 | if (!scale) scale = 1; 256 | for (i = 0; i < a.length; i++) { 257 | this.subPolyCounts.push(a[i].length); 258 | d = ''; 259 | for (j = 0; j < a[i].length; j++) { 260 | this.total++; 261 | if (j === 0) { 262 | d += 'M'; 263 | } else { 264 | d += 'L'; 265 | } 266 | d += (a[i][j].X / scale) + ', ' + (a[i][j].Y / scale); 267 | } 268 | d += 'Z'; 269 | path += d; 270 | if (explorerEnabled) { 271 | if (d.trim() === 'Z') d = ''; 272 | this.scaledPaths[fr].push(d); 273 | this.subPolyLinks.push('' + a[i].length + ''); 274 | } 275 | } 276 | if (explorerEnabled) this.subPolyLinks = this.subPolyLinks.join(', '); 277 | if (path.trim() === 'Z') path = ''; 278 | 279 | return path; 280 | } 281 | }; 282 | 283 | function formatOutput(polygonString) { 284 | if (typeof polygonString !== 'string' || polygonString === '') return ''; 285 | if (outputFormat === 'Clipper') { 286 | return polygonString; 287 | } 288 | var polygons; 289 | try { 290 | polygons = JSON.parse(polygonString); 291 | } catch (err) { 292 | console.warn('Unable to parse polygon for output', err.message); 293 | return ''; 294 | } 295 | function getCoords(segment) { 296 | return segment.X + ',' + segment.Y; 297 | } 298 | if (outputFormat === 'Plain') { 299 | return '[' + polygons.map(function(polygon) { 300 | return '[' + polygon.map(getCoords).join(', ') + ']'; 301 | }).join(',') + ']'; 302 | } 303 | if (outputFormat === 'SVG') { 304 | var result = polygons.map(function(polygon) { 305 | return 'M' + polygon.map(getCoords).join(' L') + 'Z'; 306 | }).join(' '); 307 | return (result.trim() !== 'MZ') ? result : ''; 308 | } 309 | } 310 | 311 | function getCustomPolygons() { 312 | var value = $('#custom_polygons_select').val(); 313 | if (value) { 314 | var customPolygons = $.totalStorage('custom_polygons'); 315 | return { 316 | subj: customPolygons[value].subj, 317 | clip: customPolygons[value].clip 318 | }; 319 | } 320 | return { 321 | subj: defaultCustomSubjectPolygon, 322 | clip: defaultCustomClipPolygon 323 | }; 324 | } 325 | 326 | function getRandomPolygons(which, polygon) { 327 | var pointCount = randomSetting[which + 'PointCount']; 328 | var polygonCount = randomSetting[which + 'PolygonCount']; 329 | if (arguments.length === 1) polygon = _.parseInt($('input[name="polygons"]:checked').val()); 330 | if (polygon !== 4 && polygon !== 5) return new ClipperLib.Polygons(); 331 | var svg = $('#p'); 332 | var margin = 10; 333 | randomSetting.randomMinX = 100 * margin; 334 | randomSetting.randomMaxX = 100 * (parseFloat(svg.attr('width'), 10) - margin); 335 | randomSetting.randomMinY = 100 * margin; 336 | randomSetting.randomMaxY = 100 * (parseFloat(svg.attr('height'), 10) - margin); 337 | var i, j, pp, np = new ClipperLib.Polygons(), 338 | previousX = null, 339 | previousY = null, 340 | vertical = null, 341 | previousVertical = null; 342 | for (i = 0; i < polygonCount; i++) { 343 | np[i] = new ClipperLib.Polygon(); 344 | for (j = 0; j < pointCount; j++) { 345 | pp = new ClipperLib.IntPoint(); 346 | if (polygon === 4) { 347 | vertical = !!_.random(0, 1); // 0 = horiz, 1 = vertic 348 | if (previousVertical === vertical) { 349 | vertical = !vertical; 350 | } 351 | // horiz => y remains same 352 | if (!vertical) { 353 | pp.X = _.random(randomSetting.randomMinX, randomSetting.randomMaxX); 354 | pp.Y = (previousY === null) ? _.random(randomSetting.randomMinY, randomSetting.randomMaxY) : previousY; 355 | // vertic => x remains same 356 | } else { 357 | pp.Y = _.random(randomSetting.randomMinY, randomSetting.randomMaxY); 358 | pp.X = (previousX === null) ? _.random(randomSetting.randomMinX, randomSetting.randomMaxX) : previousX; 359 | } 360 | previousX = pp.X; 361 | previousY = pp.Y; 362 | previousVertical = vertical; 363 | // last point fix 364 | if (j === pointCount - 1 && pointCount !== 1) { 365 | // horiz => y remains same 366 | if (!vertical) { 367 | pp.X = np[i][0].X; 368 | // vertic => x remains same 369 | } else { 370 | pp.Y = np[i][0].Y; 371 | } 372 | } 373 | } else { 374 | pp.X = _.random(randomSetting.randomMinX, randomSetting.randomMaxX); 375 | pp.Y = _.random(randomSetting.randomMinY, randomSetting.randomMaxY); 376 | } 377 | np[i].push(pp); 378 | } 379 | previousX = null; 380 | previousY = null; 381 | vertical = null; 382 | previousVertical = null; 383 | } 384 | randomSetting.scale = scale; 385 | return np; 386 | } 387 | 388 | function getPolygons(scaleAgain) { 389 | var polygon = _.parseInt($('input[name="polygons"]:checked').val()); 390 | if(polygon !== 4 && polygon !== 5) { 391 | ss = deserializeClipperPolygon(defaultPolygons[polygon].subj); 392 | cc = deserializeClipperPolygon(defaultPolygons[polygon].clip); 393 | } else { 394 | if (!subj.random) subj.random = getRandomPolygons('subj'); 395 | if (!clip.random) clip.random = getRandomPolygons('clip'); 396 | if (scaleAgain) { 397 | subj.random = scaleAgainRandomPoly(subj.random); 398 | clip.random = scaleAgainRandomPoly(clip.random); 399 | randomSetting.scale = scale; 400 | } 401 | ss = subj.random; 402 | cc = clip.random; 403 | } 404 | sss = [[]]; 405 | } 406 | 407 | function scaleAgainRandomPoly(poly) { 408 | for (var i = 0; i < poly.length; i++) { 409 | for (var j = 0; j < poly[i].length; j++) { 410 | poly[i][j].X = round(poly[i][j].X / randomSetting.scale); 411 | poly[i][j].Y = round(poly[i][j].Y / randomSetting.scale); 412 | } 413 | } 414 | return poly; 415 | } 416 | 417 | function round(a) { 418 | if (dontRoundAndScale) return a; 419 | return Math.floor(a * scale); 420 | } 421 | 422 | function deserializeClipperPolygon(polygonString) { 423 | lsk++; 424 | var rawPolygons = JSON.parse(polygonString), 425 | polygons = [[]], point; 426 | for (var i = 0; i < rawPolygons.length; i++) { 427 | polygons[i] = []; 428 | for (var j = 0; j < rawPolygons[i].length; j++) { 429 | if (isNaN(Number(rawPolygons[i][j].X)) || isNaN(Number(rawPolygons[i][j].Y))) { 430 | return [[]]; 431 | } 432 | point = new ClipperLib.IntPoint(round(Number(rawPolygons[i][j].X)), round(Number(rawPolygons[i][j].Y))); 433 | if (benchmarkRunning) { 434 | if (point.X > bench.maxPointX) bench.maxPointX = point.X; 435 | if (point.Y > bench.maxPointY) bench.maxPointY = point.Y; 436 | if (point.X < bench.minPointX) bench.minPointX = point.X; 437 | if (point.Y < bench.minPointY) bench.minPointY = point.Y; 438 | if (typeof bench.points['L' + point.X] === 'undefined') bench.points['L' + point.X] = scale + ':' + point.X + ':' + rawPolygons[i][j].X; 439 | if (typeof bench.points['L' + point.Y] === 'undefined') bench.points['L' + point.Y] = scale + ':' + point.Y + ':' + rawPolygons[i][j].Y; 440 | } 441 | polygons[i].push(point); 442 | } 443 | } 444 | return polygons; 445 | } 446 | 447 | function saveCustomPolygon(polygon, index) { 448 | var customPolygons = $.totalStorage('custom_polygons'); 449 | if (!_.isArray(customPolygons) || _.isEmpty(customPolygons)) customPolygons = []; 450 | if (typeof index === 'undefined') { 451 | customPolygons.push(polygon); 452 | } else { 453 | customPolygons[index] = polygon; 454 | } 455 | updateCustomPolygonsSelect(); 456 | return $.totalStorage('custom_polygons', customPolygons); 457 | } 458 | 459 | function setDefaultCustomPolygons(reset) { 460 | if (reset) $.totalStorage('custom_polygons', []); 461 | saveCustomPolygon({ 462 | subj: defaultCustomSubjectPolygon, 463 | clip: defaultCustomClipPolygon 464 | }, 0); 465 | } 466 | 467 | function updateCustomPolygonsSelect() { 468 | var arr = $.totalStorage('custom_polygons'); 469 | var value = _.parseInt($('#custom_polygons_select').val()) || 0; 470 | $('#custom_polygons_select option').remove(); 471 | var i, arr_length = _.isArray(arr) ? arr.length : 0; 472 | if (arr_length > 0) 473 | for (i = 0; i < arr_length; i++) { 474 | if (arr[i] !== null) $('#custom_polygons_select').append(''); 475 | } 476 | // If previously selected value is removed, select the next one 477 | if (arr_length > 0 && arr[value] === null) 478 | for (i = _.parseInt(value); i < arr_length; i++) { 479 | if (arr[i] !== null) { 480 | $('#custom_polygons_select').val(i); 481 | break; 482 | } 483 | } 484 | $('#custom_polygons_select').change(); 485 | } 486 | 487 | function updateEnlargedSVGSource() { 488 | var source = $('#svgcontainer').html().replace(/\>/g, '>\n'); 489 | if (updateSVGSource) { 490 | $('#svg_source_textarea').val(source); 491 | } 492 | if (updateEnlargedSVG) { 493 | $('#enlarged_svg').html(source.replace(/ id=\"/g, ' id="_')); 494 | var originalHeight = $('#_p').attr('height'); 495 | var originalWidth = $('#_p').attr('width'); 496 | // get bbox of all children of svg 497 | $('body').append(''); 498 | $('#g123').append($('#_p').children().clone()); 499 | $('#dummy').html($('#dummy').html()); 500 | var bBox = $('#g123')[0].getBBox(); 501 | $('#dummy').remove(); 502 | $('#_p').attr('viewBox', (bBox.x - 5) + ' ' + (bBox.y - 5) + ' ' + (bBox.width + 10) + ' ' + (bBox.height + 10)); 503 | $('#enlarged_svg').html($('#enlarged_svg').html()).show(); 504 | $('#_p').attr('width', windowWidth).attr('height', _.parseInt((windowWidth / originalWidth) * originalHeight)); 505 | $('#_p1, #_p2, #_p3').css('stroke-width', 0.8 * (originalWidth / windowWidth)); 506 | } 507 | } 508 | 509 | function benchmark2(i) { 510 | var startTime = new Date().getTime(); 511 | var obj = benchmarkGlob[i]; 512 | clean = false; 513 | $('#clean').prop('checked', clean); 514 | lighten = false; 515 | $('#lighten').prop('checked', lighten); 516 | joinType = obj.joinType; 517 | $('input[name="joinType"][value="' + joinType + '"]').prop('checked', true); 518 | offsettablePoly = obj.offsettablePoly; 519 | $('input[name="offsettable_poly"][value="' + offsettablePoly + '"]').prop('checked', true); 520 | delta = obj.delta; 521 | $('#delta').val(delta); 522 | miterLimit = obj.miterLimit; 523 | $('#miterLimit').val(miterLimit); 524 | autoFix = obj.autoFix; 525 | $('#autoFix').prop('checked', autoFix); 526 | simplify = obj.simplify; 527 | $('#simplify').prop('checked', simplify); 528 | subj.fillType = obj.subjectFillType; 529 | $('input[name="subject_fillType"][value="' + subj.fillType + '"]').prop('checked', true); 530 | clip.fillType = obj.clipFillType; 531 | $('input[name="clip_fillType"][value="' + clip.fillType + '"]').prop('checked', true); 532 | clipType = obj.clipType; 533 | $('input[name="clipType"][value="' + clipType + '"]').prop('checked', true); 534 | scale = obj.scale; 535 | $('#scale').val(scale); 536 | if (obj.polygonId === 4 || obj.polygonId === 5) randomSetting = obj.randomSetting; 537 | $('input[name="polygons"][value="' + obj.polygonId + '"]').prop('checked', true).trigger('change'); 538 | obj = null; 539 | lastCompletedBenchmark = i; 540 | var endTime = new Date().getTime(); 541 | var time = endTime - startTime; 542 | benchmarkElapsedTime += time; 543 | benchmarkGlob[i].measuredTime = time; 544 | benchmarkGlob[i].elapsedTime = benchmarkElapsedTime; 545 | // update next timeouts 546 | for (var lsk = i + 1; lsk < benchmarkGlob.length; lsk++) { 547 | clearTimeout(benchmarkGlob[lsk].setTimeout); 548 | benchmarkGlob[lsk].setTimeout = setTimeout('benchmark2(' + lsk + ')', benchmarkGlob[lsk].elapsedTime + lsk * benchmarkGlob[lsk].time); 549 | } 550 | var multipleRunsTable; 551 | var elapsedTime = endTime - bench.list[0].start; 552 | var results = Math.floor((i + 1) / benchmarkGlob.length * 100) + ' % ('; 553 | results += (elapsedTime / 1000).toFixed(1) + ' s) of '; 554 | results += 'benchmark ' + (benchmarkRepeat + 1) + ' / ' + benchmarkRepeatTimes + '. '; 555 | results += 'Remaining: ' + Math.floor((((elapsedTime / (i + 1)) * (benchmarkGlob.length - i + 1)) / 1000)) + ' s.'; 556 | $('#benchmark_multiple_status').html(results).css('display', 'table-cell'); 557 | if (i === 0) { 558 | multipleRunsTable = bench.printMultipleRuns(); 559 | if ($('#benchmark_multiple_table').length) $('#benchmark_multiple_table').remove(); 560 | $('#benchmark_multiple_table_cont').append(multipleRunsTable); 561 | } else if (i === benchmarkGlob.length - 1) { 562 | if (!$('#benchmark_exports_textarea').length) { 563 | var textarea = '
'; 564 | textarea += '
'; 565 | textarea += '
'; 566 | $('#benchmark_exports_container').append(textarea); 567 | } 568 | if (!_.contains(benchmarkExports, 'maxPointX')) { 569 | benchmarkExports += 'bench.maxPointX:' + bench.maxPointX + '\n'; 570 | benchmarkExports += 'bench.maxPointY:' + bench.maxPointY + '\n'; 571 | benchmarkExports += 'bench.minPointX:' + bench.minPointX + '\n'; 572 | benchmarkExports += 'bench.minPointY:' + bench.minPointY + '\n'; 573 | } 574 | benchmarkExports += bench.totals + ';' + JSON.stringify($.browser) + '\n'; 575 | $('#benchmark_exports_textarea').val(benchmarkExports); 576 | bench.totals_arr_multiple.push(bench.totals_arr[0]); 577 | multipleRunsTable = bench.printMultipleRuns(); 578 | if ($('#benchmark_multiple_table').length) $('#benchmark_multiple_table').remove(); 579 | $('#benchmark_multiple_table_cont').append(multipleRunsTable); 580 | benchmarkRepeat++; 581 | var clickedBenchmark = $('#' + benchmarkClickedButtonId); 582 | if (benchmarkRepeat < benchmarkRepeatTimes) { 583 | benchmarkAutomaticClick = true; 584 | clickedBenchmark.trigger('click'); 585 | } else { 586 | disableBenchmarkButton(clickedBenchmark); 587 | } 588 | } 589 | } 590 | 591 | function disableBenchmarkButton(button) { 592 | benchmarkGlob.length = 0; 593 | benchmarkRepeat = 0; 594 | benchmarkRunning = false; 595 | ClipperLib.MaxSteps = ClipperLibOriginalMaxSteps; 596 | button.html(button.html().replace('Stop', 'Run')).attr('title', button.attr('title').replace('Stop', 'Execute')); 597 | $('button, input, select').prop('disabled', false); 598 | $('#explorer_enabled').trigger('change'); 599 | } 600 | 601 | var Benchmark = function () { 602 | this.list = []; 603 | this.cats = []; 604 | this.cats.arr = []; 605 | this.includeSVG = true; 606 | this.totals = ''; 607 | this.totals_arr = []; 608 | this.totals_arr_multiple = []; 609 | this.maxPointX = Number.NEGATIVE_INFINITY; 610 | this.minPointX = Number.POSITIVE_INFINITY; 611 | this.maxPointY = Number.NEGATIVE_INFINITY; 612 | this.minPointY = Number.POSITIVE_INFINITY; 613 | this.points = []; 614 | }; 615 | // cat = category, which name belongs to, name = code region name or function, which is measured 616 | Benchmark.prototype.start = function (cat, name) { 617 | if (!cat || !name) return; 618 | this.list.push({ 619 | start: new Date().getTime(), 620 | name: name, 621 | cat: cat 622 | }); 623 | return this.list.length - 1; 624 | }; 625 | Benchmark.prototype.end = function (index) { 626 | this.list[index].end = new Date().getTime(); 627 | this.list[index].time = this.list[index].end - this.list[index].start; 628 | var this_list_cat = this.list[index].cat; 629 | var this_list_cat_counts = this_list_cat + '_counts'; 630 | var this_list_cat_time_sum = this_list_cat + '_time_sum'; 631 | if (typeof this.cats[this_list_cat_counts] === 'undefined') this.cats.arr.push(this_list_cat); 632 | if (typeof this.cats[this_list_cat_time_sum] === 'undefined') this.cats[this_list_cat_time_sum] = 0; 633 | if (typeof this.cats[this_list_cat_counts] === 'undefined') this.cats[this_list_cat_counts] = 0; 634 | this.cats[this_list_cat_time_sum] += this.list[index].time; 635 | this.cats[this_list_cat_counts]++; 636 | if (benchmarkGlob.length > 0) { 637 | this.list[index].benchmarkGlob_index = lastCompletedBenchmark; 638 | } 639 | }; 640 | Benchmark.prototype.clear = function () { 641 | this.list = []; 642 | this.cats = []; 643 | this.cats.arr = []; 644 | this.includeSVG = true; 645 | }; 646 | Benchmark.prototype.print = function (all) { 647 | var i, tbl = ''; 648 | if (!_.isEmpty(this.list)) { 649 | var startIndex = 0; 650 | if (!all) { 651 | startIndex = benchmarkGlob.length ? this.list.length - 3 : this.list.length - 16; 652 | if (startIndex < 0) startIndex = 0; 653 | } 654 | for (i = startIndex; i < this.list.length; i++) { 655 | tbl += ''; 656 | } 657 | } 658 | tbl += '
NumNameCategoryTime
' + (i + 1) + '' + this.list[i].name + '' + this.list[i].cat + '' + this.list[i].time + '
'; 659 | this.totals = ''; 660 | this.totals_arr = []; 661 | var tbl2 = '', 662 | totals_arr_item = [], 663 | item, 664 | counts_sum = 0, 665 | cat_time_sum = 0, 666 | this_list_i_cat, this_list_i_cat_time_sum, this_list_i_cat_counts; 667 | if (this.cats.arr.length > 0) 668 | for (i = 0; i < this.cats.arr.length; i++) { 669 | tbl2 += ''; 683 | } 684 | tbl2 += ''; 685 | if (this.cats.arr.length > 0) { 686 | tbl2 += ''; 687 | totals_arr_item.push(counts_sum); 688 | this.totals += counts_sum + ';'; 689 | tbl2 += ''; 690 | totals_arr_item.push(cat_time_sum); 691 | this.totals += cat_time_sum + ';'; 692 | tbl2 += ''; 693 | item = (cat_time_sum / counts_sum).toFixed(4); 694 | totals_arr_item.push(item); 695 | this.totals += item; 696 | tbl2 += ''; 697 | tbl2 += ''; 698 | } 699 | tbl2 += '
NumCategoryCallsSumAvg
' + (i + 1) + ''; 670 | this_list_i_cat = this.cats.arr[i]; 671 | tbl2 += this_list_i_cat; 672 | tbl2 += ''; 673 | this_list_i_cat_counts = this.cats[this_list_i_cat + '_counts']; 674 | tbl2 += this_list_i_cat_counts; 675 | counts_sum += this_list_i_cat_counts; 676 | tbl2 += ''; 677 | this_list_i_cat_time_sum = this.cats[this_list_i_cat + '_time_sum']; 678 | tbl2 += this_list_i_cat_time_sum; 679 | cat_time_sum += this_list_i_cat_time_sum; 680 | tbl2 += ''; 681 | tbl2 += (this_list_i_cat_time_sum / this_list_i_cat_counts).toFixed(4); 682 | tbl2 += '
Total' + counts_sum + '' + cat_time_sum + '' + item + '
'; 700 | this.totals_arr.push(totals_arr_item); 701 | tbl += tbl2; 702 | var disabled = benchmarkRunning ? 'disabled' : ''; 703 | tbl += ''; 704 | tbl += ''; 705 | return tbl; 706 | }; 707 | Benchmark.prototype.printMultipleRuns = function () { 708 | var table = ''; 709 | var i, times = []; 710 | for (i = 0; i < this.totals_arr_multiple.length; i++) { 711 | times.push(this.totals_arr_multiple[i][1]); 712 | } 713 | var max = _.max(times); 714 | var min = _.min(times); 715 | var range = max - min; 716 | var average = +_.average(times).toFixed(4); 717 | var standardDeviation = _.stdDeviation(times).toFixed(4); 718 | var minusRange = min - average; 719 | var plusRange = max - average; 720 | for (i = 0; i < this.totals_arr_multiple.length; i++) { 721 | table += ''; 730 | } 731 | table += ''; 732 | if (!isNaN(average)) { 733 | table += ''; 746 | } 747 | table += ''; 748 | return table; 749 | }; 750 | 751 | function colorizeBoxes() { 752 | var bgColor = new RGBColor($('#p').css('background-color')), 753 | fillColor, strokeColor, fillOpacity, strokeOpacity; 754 | for (var i = 1; i <= 3; i++) { 755 | fillColor = new RGBColor($('#p' + i).css('fill')); 756 | fillOpacity = $('#p' + i).css('fill-opacity'); 757 | fillColor = fillColor.flattenRGBA(fillOpacity, bgColor); 758 | strokeColor = new RGBColor($('#p' + i).css('stroke')); 759 | strokeOpacity = $('#p' + i).css('stroke-opacity'); 760 | strokeColor = strokeColor.flattenRGBA(strokeOpacity, bgColor); 761 | $('#' + ['subject', 'clip', 'solution'][i - 1] + '_box').css('background-color', fillColor); 762 | } 763 | } 764 | 765 | function bindHelp() { 766 | $('#help_custom_polygon').click(function () { 767 | var txt = 'A) You can add your own custom polygons in several formats:\n\n'; 768 | txt += '1) The program uses as an inner default the following format: JSON-stringified array of arrays of point objects eg. [[{"X":100,"Y":100},{"X":200,"Y":100},{"X":200,"Y":200},{"X":100,"Y":200}],[{"X":110,"Y":110},{"X":210,"Y":110},{"X":210,"Y":210},{"X":110,"Y":210}]]. This format allows to input sub polygons. Each sub polygon is an array of point objects. This format makes it easy to transfer polygons to other programs that use Clipper library and is suitable for storing polygons in database.\n\n'; 769 | txt += '2) JSON-stringified array of point objects eg. [{"X":100,"Y":100},{"X":200,"Y":100},{"X":200,"Y":200},{"X":100,"Y":200}]. This format doesn\'t allow to input sub polygons.\n\n'; 770 | txt += '3) JSON-stringified array of arrays of coordinates without "X" and "Y" eg. [[100,100,200,100,200,200,100,200],[110,110,210,110,210,210,110,210]]. This format allows to input sub polygons. Each sub polygon is an array of coordinates so that each x coordinate is followed by an y coordinate. This format makes it easy to transfer polygons to other programs that use Clipper library and is suitable for storing polygons in database.\n\n'; 771 | txt += '4) JSON-stringified array of x and y coordinates eg. [100,100,200,100,200,200,100,200] or [100 100 200 100 200 200 100 200] or [100 100,200 100,200 200,100 200] or the same without []:s. This format doesn\'t allow to input sub polygons.\n\n'; 772 | txt += '5) SVG path strings with commands MLVHZ or mlvhz eg. M100,100 L200,100 L200,200 L100,200Z M110,110 L210,110 L210,210 L110,210Z. This format allows to input sub polygons. Each subpolygon starts with M (moveto) command.\n\n'; 773 | txt += 'B) Custom polygons are saved in browser\'s Local Storage, so they should be tolerant for page reload and browser crashes.'; 774 | alert(txt); 775 | }); 776 | $('#help_builtin_polygon_sets').click(function() { 777 | var txt = 'Builtin polygon sets\n\n'; 778 | txt += 'You can add builtin polygon sets into Subj and Clip input fields to edit copies of them.\n\n'; 779 | txt += 'Note! Before saving, nothing happens. After saving, the SVG window is also updated.'; 780 | alert(txt); 781 | }); 782 | $('#help_output_format').click(function() { 783 | var txt = 'Output format\n\n'; 784 | txt += 'To change the polygon coordinate output format please use the above dropdown. The available formats are:\n\n'; 785 | txt += '- Clipper: [[{"X":100,"Y":100},{"X":200,"Y":200}]]\n\n'; 786 | txt += '- Plain: [[100,100,200,200]]\n\n'; 787 | txt += '- SVG: M100,100L200,200Z\n\n'; 788 | txt += 'There are two places where this has effect: 1) the above text box 2) the Subj and Clip text boxes in Custom Polygon fieldset.'; 789 | alert(txt); 790 | }); 791 | } 792 | 793 | function bindInputListeners() { 794 | // reveal custom fieldsets 795 | $('input[type="radio"][name="polygons"]').change(function () { 796 | var val = _.parseInt($(this).val()); 797 | $('#custom_polygons_fieldset, #random_polygons_fieldset').hide(); 798 | if (val === 10) { 799 | $('#custom_polygons_fieldset').show(); 800 | updateCustomPolygonsSelect(); 801 | $('#custom_polygons_select').change(); 802 | } 803 | if (val === 4 || val === 5) { 804 | $('#random_polygons_fieldset').show(); 805 | randomSettings.current = (val === 4) ? 'rect' : 'norm'; 806 | var r = randomSetting, rs = randomSettings; 807 | // Test for ranges 808 | if (r.clipPointCount < rs[rs.current].min.clipPointCount) r.clipPointCount = rs[rs.current].min.clipPointCount; 809 | if (r.clipPointCount > rs[rs.current].max.clipPointCount) r.clipPointCount = rs[rs.current].max.clipPointCount; 810 | $('#clip_point_count').val(r.clipPointCount); 811 | if (r.clipPolygonCount < rs[rs.current].min.clipPolygonCount) r.clipPolygonCount = rs[rs.current].min.clipPolygonCount; 812 | if (r.clipPolygonCount > rs[rs.current].max.clipPolygonCount) r.clipPolygonCount = rs[rs.current].max.clipPolygonCount; 813 | $('#clip_polygon_count').val(r.clipPolygonCount); 814 | if (r.subjPointCount < rs[rs.current].min.subjPointCount) r.subjPointCount = rs[rs.current].min.subjPointCount; 815 | if (r.subjPointCount > rs[rs.current].max.subjPointCount) r.subjPointCount = rs[rs.current].max.subjPointCount; 816 | $('#subj_point_count').val(r.subjPointCount); 817 | if (r.subjPolygonCount < rs[rs.current].min.subjPolygonCount) r.subjPolygonCount = rs[rs.current].min.subjPolygonCount; 818 | if (r.subjPolygonCount > rs[rs.current].max.subjPolygonCount) r.subjPolygonCount = rs[rs.current].max.subjPolygonCount; 819 | $('#subj_polygon_count').val(r.subjPolygonCount); 820 | subj.random = getRandomPolygons('subj', val); 821 | clip.random = getRandomPolygons('clip', val); 822 | } 823 | makeClip(); 824 | }); 825 | $('#generate_random_polygons').hold(function () { 826 | subj.random = getRandomPolygons('subj'); 827 | clip.random = getRandomPolygons('clip'); 828 | makeClip(); 829 | }); 830 | // Select dropdown 831 | $('#sample_custom_polygon').change(function () { 832 | var polygon = _.parseInt($(this).val()); 833 | var subj = '', clip = ''; 834 | dontRoundAndScale = true; 835 | if(polygon !== 4 && polygon !== 5) { 836 | subj = deserializeClipperPolygon(defaultPolygons[polygon].subj); 837 | clip = deserializeClipperPolygon(defaultPolygons[polygon].clip); 838 | } else { 839 | subj = getRandomPolygons('subj', polygon); 840 | clip = getRandomPolygons('clip', polygon); 841 | } 842 | dontRoundAndScale = false; 843 | if (subj !== '') subj = JSON.stringify(subj); 844 | if (clip !== '') clip = JSON.stringify(clip); 845 | $('#custom_polygon_subj').val(formatOutput(subj)); 846 | $('#custom_polygon_clip').val(formatOutput(clip)); 847 | }); 848 | $('#save_custom_polygon').click(function () { 849 | var subj = normalizeClipperPolygons($('#custom_polygon_subj').val()); 850 | var clip = normalizeClipperPolygons($('#custom_polygon_clip').val()); 851 | if (subj === false || clip === false) return false; 852 | var value = _.parseInt($('#custom_polygons_select').val()); 853 | if (value) { 854 | saveCustomPolygon({ 855 | subj: subj, 856 | clip: clip 857 | }, value); 858 | alert('Polygon ' + value + ' updated!'); 859 | } else if (value === 0) { 860 | alert('The default custom polygon cannot be overwrited. If you want to modify it, save it first as a new.'); 861 | } 862 | else alert('Polygon update failed!'); 863 | }); 864 | $('#add_as_new_custom_polygon').click(function () { 865 | var subj = normalizeClipperPolygons($('#custom_polygon_subj').val()); 866 | var clip = normalizeClipperPolygons($('#custom_polygon_clip').val()); 867 | if (subj === false || clip === false) return false; 868 | var customPolygons = saveCustomPolygon({ 869 | subj: subj, 870 | clip: clip 871 | }); 872 | $('#custom_polygons_select').val(customPolygons.length - 1).change(); 873 | alert('New polygon ' + (customPolygons.length - 1) + ' added!'); 874 | }); 875 | $('#custom_polygons_select').change(function () { 876 | var value = _.parseInt($('#custom_polygons_select').val()); 877 | var customPolygons = $.totalStorage('custom_polygons'); 878 | if (_.isArray(customPolygons) && customPolygons[value]) { 879 | $('#custom_polygon_subj').val(formatOutput(customPolygons[value].subj)); 880 | $('#custom_polygon_clip').val(formatOutput(customPolygons[value].clip)); 881 | makeClip(); 882 | } 883 | }); 884 | $('#remove_custom_polygon').click(function () { 885 | var value = _.parseInt($('#custom_polygons_select').val()); 886 | if (value === 0) { 887 | alert('Cannot remove the default polygon.'); 888 | } else if (value) { 889 | if (confirm('Remove custom polygon ' + value + '?')) { 890 | saveCustomPolygon(null, value); 891 | } 892 | } 893 | }); 894 | $('#removeall_custom_polygon').click(function () { 895 | var count = $('#custom_polygons_select option').length; 896 | if (count > 1) { 897 | if (confirm('Remove all ' + (count -1) + ' custom polygons?')) { 898 | setDefaultCustomPolygons(true); 899 | } 900 | } 901 | }); 902 | 903 | // Subject FillType 904 | $('input[name="subject_fillType"]').change(function () { 905 | subj.fillType = _.parseInt(this.value); 906 | makeClip(); 907 | }); 908 | 909 | // Clip FillType 910 | $('input[name="clip_fillType"]').change(function () { 911 | clip.fillType = _.parseInt(this.value); 912 | makeClip(); 913 | }); 914 | 915 | // Clip type (operation) 916 | $('input[name="clipType"]').change(function () { 917 | offsettablePoly = $('input[name="clipType"][value=""]').is(':checked') ? 'subject' : 'solution'; 918 | $('input[name="offsettable_poly"][value="' + offsettablePoly + '"]').prop('checked', true); 919 | clipType = $('input[name="clipType"]:checked').val(); 920 | if (clipType !== '') clipType = _.parseInt(clipType); 921 | makeClip(); 922 | }); 923 | 924 | // Cleaning and simplifying 925 | $('#clean').change(function () { 926 | clean = $(this).prop('checked'); 927 | if (clean && !$('#cleandelta').val()+''.trim()) { 928 | cleanDelta = cleanDeltaDefault; 929 | $('#cleandelta').val(cleanDelta); 930 | } 931 | makeClip(); 932 | }); 933 | $('#cleandelta').change(function () { 934 | var value = parseFloat(this.value); 935 | if (!isNaN(value)) cleanDelta = value; 936 | makeClip(); 937 | }); 938 | $('#simplify').change(function () { 939 | simplify = $(this).prop('checked'); 940 | makeClip(); 941 | }); 942 | $('#lighten').change(function () { 943 | lighten = $(this).prop('checked'); 944 | if (lighten && !$('#lighten_distance').val()+''.trim()) { 945 | lightenDistance = lightenDistanceDefault; 946 | $('#lighten_distance').val(lightenDistance); 947 | } 948 | makeClip(); 949 | }); 950 | $('#lighten_distance').change(function () { 951 | var value = parseFloat(this.value); 952 | if (!isNaN(value)) lightenDistance = value; 953 | makeClip(); 954 | }); 955 | 956 | // Offsetting 957 | $('input[name="offsettable_poly"]').change(function () { 958 | offsettablePoly = this.value; 959 | // When offsettable poly is set to Subject or Clip, then boolean operations are not done. 960 | // To show this to user, set clipType to "No" 961 | if (offsettablePoly === 'subject' || offsettablePoly === 'clip') { 962 | $('input[name="clipType"][value=""]').prop('checked', true); 963 | clipType = ''; 964 | } 965 | makeClip(); 966 | }); 967 | $('input[name="joinType"]').change(function () { 968 | joinType = _.parseInt(this.value); 969 | makeClip(); 970 | }); 971 | 972 | function getDeltaChanger(direction) { 973 | return function () { 974 | var original = $('#delta').val(); 975 | if (!isNaN(original)) delta = parseFloat(original); 976 | delta += direction; 977 | makeClip(); 978 | }; 979 | } 980 | $('#delta_minus').hold(getDeltaChanger(-1)); 981 | $('#delta').change(getDeltaChanger(0)); 982 | $('#delta_plus').hold(getDeltaChanger(1)); 983 | 984 | function getMiterChanger(direction) { 985 | return function() { 986 | var original = $('#miterLimit').val(); 987 | if (!isNaN(original)) miterLimit = parseFloat(original); 988 | miterLimit += direction; 989 | if (miterLimit < 1.0) miterLimit = 1.0; 990 | makeClip(); 991 | }; 992 | } 993 | $('#miterLimit_minus').hold(getMiterChanger(-0.1)); 994 | $('#miterLimit').change(getMiterChanger(0)); 995 | $('#miterLimit_plus').hold(getMiterChanger(0.1)); 996 | 997 | $('#autoFix').change(function () { 998 | autoFix = $(this).prop('checked'); 999 | makeClip(); 1000 | }); 1001 | 1002 | // Scale 1003 | $('#scale_minus').hold(function () { 1004 | var original = $('#scale').val(); 1005 | if (original && !isNaN(original) && _.parseInt(original).toString() !== '0') scale = parseFloat(original); 1006 | scale = Math.round((scale - scaleAddition) / scaleAddition) * scaleAddition; 1007 | if (scale <= 0) scale = 1.0; 1008 | $('#scale').val(scale.toFixed(1)).trigger('change'); 1009 | }); 1010 | $('#scale').change(function () { 1011 | if (this.value && !isNaN(this.value) && _.parseInt(this.value).toString() !== '0') { 1012 | scale = parseFloat(this.value); 1013 | getPolygons(true); 1014 | sss = cc; 1015 | makeClip(); 1016 | } 1017 | }); 1018 | $('#scale_plus').hold(function () { 1019 | var original = $('#scale').val(); 1020 | if (original && !isNaN(original) && _.parseInt(original).toString() !== '0') scale = parseFloat(original); 1021 | scale = Math.round((scale + scaleAddition) / scaleAddition) * scaleAddition; 1022 | $('#scale').val(scale.toFixed(1)).trigger('change'); 1023 | }); 1024 | 1025 | function getChanger(key, direction) { 1026 | return function() { 1027 | var input = this.id.match('((.*)count)(_?.*)')[1], 1028 | original = $('#' + input).val(), 1029 | r = randomSetting, rs = randomSettings; 1030 | if (!isNaN(original)) r[key] = parseFloat(original); 1031 | r[key] += direction; 1032 | if (!direction || direction === -1) { 1033 | if (r[key] < rs[rs.current].min[key]) r[key] = rs[rs.current].min[key]; 1034 | } else if (!direction || direction === 1) { 1035 | if (r[key] > rs[rs.current].max[key]) r[key] = rs[rs.current].max[key]; 1036 | } 1037 | $('#' + input).val(r[key]); 1038 | subj.random = getRandomPolygons('subj'); 1039 | clip.random = getRandomPolygons('clip'); 1040 | makeClip(); 1041 | }; 1042 | } 1043 | $('#subj_polygon_count_minus').hold(getChanger('subjPolygonCount', -1)); 1044 | $('#subj_polygon_count').change(getChanger('subjPolygonCount', 0)); 1045 | $('#subj_polygon_count_plus').hold(getChanger('subjPolygonCount', 1)); 1046 | $('#subj_point_count_minus').hold(getChanger('subjPointCount', -1)); 1047 | $('#subj_point_count').change(getChanger('subjPointCount', 0)); 1048 | $('#subj_point_count_plus').hold(getChanger('subjPointCount', 1)); 1049 | $('#clip_polygon_count_minus').hold(getChanger('clipPolygonCount', -1)); 1050 | $('#clip_polygon_count').change(getChanger('clipPolygonCount', 0)); 1051 | $('#clip_polygon_count_plus').hold(getChanger('clipPolygonCount', 1)); 1052 | $('#clip_point_count_minus').hold(getChanger('clipPointCount', -1)); 1053 | $('#clip_point_count').change(getChanger('clipPointCount', 0)); 1054 | $('#clip_point_count_plus').hold(getChanger('clipPointCount', 1)); 1055 | 1056 | // Bevel checkbox 1057 | $('#bevel').change(function () { 1058 | bevel = $(this).prop('checked'); 1059 | if (bevel) { 1060 | $('#p3').attr('filter', 'url(#innerbevel)'); 1061 | } else { 1062 | $('#p3').removeAttr('filter'); 1063 | } 1064 | updateEnlargedSVGSource(); 1065 | }); 1066 | $('#show_svg_source').click(function() { 1067 | updateSVGSource = !updateSVGSource; 1068 | $('#svg_source_container').toggle(updateSVGSource); 1069 | updateEnlargedSVGSource(); 1070 | }); 1071 | $('#show_enlarged_svg').click(function() { 1072 | updateEnlargedSVG = !updateEnlargedSVG; 1073 | $('#enlarged_svg').toggle(updateEnlargedSVG); 1074 | updateEnlargedSVGSource(); 1075 | }); 1076 | $('#explorer_enabled').change(function () { 1077 | explorerEnabled = $(this).prop('checked'); 1078 | if (explorerEnabled) { 1079 | SVG.update(); 1080 | SVG.addPaths(ss, cc, offsetResult, subj.fillType, clip.fillType); 1081 | } else { 1082 | $('#subj_subpolygons, #subj_points_in_subpolygons, #subj_points_total, #clip_subpolygons, #clip_points_in_subpolygons, #clip_points_total, #solution_subpolygons, #solution_points_in_subpolygons, #solution_points_total, #points_total, #all_subpolygons').html(''); 1083 | } 1084 | }); 1085 | // formats internal representation of polygons to specified output format and prints them on input fields 1086 | $('#output_format').change(function () { 1087 | outputFormat = $(this).val(); 1088 | if (!$('#custom_polygons_fieldset').is(':hidden')) { 1089 | var subj = normalizeClipperPolygons($('#custom_polygon_subj').val()); 1090 | var clip = normalizeClipperPolygons($('#custom_polygon_clip').val()); 1091 | if (subj !== false && clip !== false) { 1092 | $('#custom_polygon_subj').val(formatOutput(subj)); 1093 | $('#custom_polygon_clip').val(formatOutput(clip)); 1094 | } 1095 | } 1096 | var polygonExplorerString = normalizeClipperPolygons($('#polygon_explorer_string_inp').val()); 1097 | if (polygonExplorerString !== false) { 1098 | $('#polygon_explorer_string_inp').val(formatOutput(polygonExplorerString)); 1099 | } 1100 | }); 1101 | 1102 | $('#benchmark1, #benchmark2, #benchmark1b, #benchmark2b').click(function () { 1103 | benchmarkClickedButtonId = this.id; 1104 | if (benchmarkRunning && !benchmarkAutomaticClick) { 1105 | for (var lsk = 0; lsk < benchmarkGlob.length; lsk++) { 1106 | clearTimeout(benchmarkGlob[lsk].setTimeout); 1107 | } 1108 | return disableBenchmarkButton($(this)); 1109 | } 1110 | // disable buttons that are not allowed to click when running 1111 | $('button, input, select').prop('disabled', true); 1112 | $('#benchmark1, #benchmark2, #benchmark1b, #benchmark2b').each(function () { 1113 | $(this).prop('disabled', this.id !== benchmarkClickedButtonId); 1114 | }); 1115 | $(this).html($(this).html().replace('Run', 'Stop')).attr('title', $(this).attr('title').replace('Execute', 'Stop')); 1116 | benchmarkAutomaticClick = false; 1117 | benchmarkRunning = true; 1118 | ClipperLib.MaxSteps = 10; 1119 | bench.clear(); 1120 | bench.includeSVG = false; 1121 | lastCompletedBenchmark = ''; 1122 | benchmarkGlob.length = 0; 1123 | benchmarkRepeatTimes = (this.id === 'benchmark1b' || this.id === 'benchmark2b') ? 5 : 1; 1124 | var polygonId; 1125 | var deltaLocal, clipTypeLocal, joinTypeLocal; 1126 | var offsettablePolyLocal, offsettablePolyLocal_start, offsettablePolyLocal_end; 1127 | var miterLimitLocal, miterLimitLocal_end; 1128 | var fillTypeLocal, fillTypeLocal_start; 1129 | var timeout_time = 0; 1130 | var timeout_time_addition = 0; 1131 | var deltaLocals = [-5, 0, 10, 30], deltaLocal_i; 1132 | var scaleLocal = (this.id === 'benchmark1' || this.id === 'benchmark1b') ? 100 : 100000000; 1133 | for (polygonId = 0; polygonId < 10; polygonId++) { 1134 | if (!(polygonId === 0 || polygonId === 1 || polygonId === 7 || polygonId === 8 || polygonId === 9)) continue; 1135 | fillTypeLocal_start = (polygonId === 4 || polygonId === 5) ? 0 : 1; 1136 | for (fillTypeLocal = fillTypeLocal_start; fillTypeLocal < 2; fillTypeLocal++) { 1137 | for (clipTypeLocal = 0; clipTypeLocal < 5; clipTypeLocal++) { 1138 | if (clipTypeLocal === 0) { 1139 | offsettablePolyLocal_start = 1; 1140 | offsettablePolyLocal_end = 2; 1141 | } else { 1142 | offsettablePolyLocal_start = 3; 1143 | offsettablePolyLocal_end = 3; 1144 | } 1145 | for (offsettablePolyLocal = offsettablePolyLocal_start; offsettablePolyLocal < offsettablePolyLocal_end + 1; offsettablePolyLocal++) { 1146 | if (polygonId === 0 && offsettablePolyLocal === 2) continue; 1147 | for (joinTypeLocal = 0; joinTypeLocal < 3; joinTypeLocal++) { 1148 | for (deltaLocal_i = 0; deltaLocal_i < deltaLocals.length; deltaLocal_i++) { 1149 | deltaLocal = deltaLocals[deltaLocal_i]; 1150 | miterLimitLocal_end = (joinTypeLocal === 2 && deltaLocal !== 0) ? 6 : 1; 1151 | for (miterLimitLocal = 1; miterLimitLocal < miterLimitLocal_end + 1; miterLimitLocal += 2) { 1152 | benchmarkGlob[benchmarkGlob.length] = { 1153 | polygonId: polygonId, 1154 | joinType: joinTypeLocal, // 0,1 1155 | offsettablePoly: ['', 'subject', 'clip', 'solution'][offsettablePolyLocal], 1156 | delta: deltaLocal, // -10 - 10 1157 | miterLimit: miterLimitLocal, // 1 - 5 1158 | autoFix: true, // false, true 1159 | simplify: false, // false, true 1160 | subjectFillType: fillTypeLocal, // 0,1 1161 | clipFillType: fillTypeLocal, //0, 1 1162 | clipType: (clipTypeLocal === 0) ? '' : clipTypeLocal - 1, // '',0,1,2,3 1163 | scale: scaleLocal, // 100, 100 000, 1000 000 000 1164 | randomSetting: { 1165 | clipPolygonCount: 4, 1166 | clipPointCount: 4, 1167 | subjPolygonCount: 4, 1168 | subjPointCount: 4 1169 | } 1170 | }; 1171 | timeout_time += timeout_time_addition; 1172 | benchmarkGlob[benchmarkGlob.length - 1].setTimeout = setTimeout('benchmark2(' + (benchmarkGlob.length - 1) + ')', timeout_time); 1173 | benchmarkGlob[benchmarkGlob.length - 1].timeout_time = timeout_time; 1174 | } 1175 | } 1176 | } 1177 | } 1178 | } 1179 | } 1180 | } 1181 | }); 1182 | 1183 | $('.polygon_explorer').on({ 1184 | // set and show hightlighted path 1185 | mouseover: function() { 1186 | if (benchmarkRunning) return false; 1187 | var id = this.dataset.id, 1188 | role = this.dataset.role, 1189 | d = typeof id === 'undefined' ? SVG.scaledPaths[role].join(' ') : SVG.scaledPaths[role][id]; 1190 | SVG.highlightedPath = p.path(d); 1191 | $(SVG.highlightedPath.node).removeAttr('fill stroke').attr({ 1192 | 'class': 'highlightedPath', 1193 | 'fill-rule': $('#p' + role).attr('fill-rule'), 1194 | 'vector-effect': 'non-scaling-stroke' 1195 | }); 1196 | }, 1197 | // enlarge highligthed path 1198 | click: function() { 1199 | if (benchmarkRunning) return false; 1200 | var id = this.dataset.id, 1201 | role = this.dataset.role, 1202 | d = typeof id === 'undefined' ? SVG.scaledPaths[role].join(' ') : SVG.scaledPaths[role][id], 1203 | points_string = normalizeClipperPolygons(d), 1204 | area = 0; 1205 | if (points_string !== false) { 1206 | if (typeof id === 'undefined') { 1207 | $('#polygon_explorer_string_inp').val(formatOutput(points_string)); 1208 | for (var j = 0; j < SVG.scaledPaths.length; j++) { 1209 | var points_str = normalizeClipperPolygons(SVG.scaledPaths[role][j], true); 1210 | if (points_str !== false) { 1211 | var polygon = JSON.parse(points_str.replace(/^\[\[/, '[').replace(/\]\]$/, ']')); 1212 | area += ClipperLib.Clipper.Area(polygon); 1213 | } 1214 | } 1215 | } else { 1216 | $('#polygon_explorer_string_inp').val(formatOutput(points_string).replace(/^\[\[/, '[').replace(/\]\]$/, ']')); 1217 | area = ClipperLib.Clipper.Area(JSON.parse(points_string.replace(/^\[\[/, '[').replace(/\]\]$/, ']'))); 1218 | } 1219 | $('#area').html('Area: ' + area); 1220 | } else { 1221 | $('#polygon_explorer_string_inp').val('Some error occurred when parsing polygon points!'); 1222 | } 1223 | $(SVG.highlightedPath.node).removeAttr('fill stroke').attr({ 1224 | 'class': 'highlightedPath', 1225 | 'fill-rule': $('#p' + role).attr('fill-rule'), 1226 | 'vector-effect': 'non-scaling-stroke' 1227 | }); 1228 | var bBox = SVG.highlightedPath.node.getBBox(); 1229 | var SVGWidth = _.parseInt($('#p').attr('width')); 1230 | var SVGHeight = _.parseInt($('#p').attr('height')); 1231 | var scal = Math.min((SVGWidth - 20) / bBox.width, (SVGHeight - 20) / bBox.height); 1232 | var xTrans = -(bBox.x + bBox.width / 2) + SVGWidth / 2; 1233 | var yTrans = -(bBox.y + bBox.height / 2) + SVGHeight / 2; 1234 | $('#StartMarker')[0].setAttribute('markerWidth', 10 / scal * 2); 1235 | $('#StartMarker')[0].setAttribute('markerHeight', 10 / scal * 2); 1236 | $('#MidMarker')[0].setAttribute('markerWidth', 4 / scal * 2); 1237 | $('#MidMarker')[0].setAttribute('markerHeight', 4 / scal * 2); 1238 | $('#EndMarker')[0].setAttribute('markerWidth', 4 / scal * 2); 1239 | $('#EndMarker')[0].setAttribute('markerHeight', 4 / scal * 2); 1240 | SVG.highlightedPath.animate({ 1241 | 'transform': 't' + xTrans + ' ' + yTrans + 's' + scal + ' ' + scal 1242 | }, 500, function () { 1243 | $(SVG.highlightedPath.node).attr({ 1244 | 'marker-start': 'url(#StartMarker)', 1245 | 'marker-mid': 'url(#MidMarker)', 1246 | 'marker-end': 'url(#EndMarker)' 1247 | }); 1248 | }); 1249 | }, 1250 | // hide highlighted path 1251 | mouseout: function() { 1252 | if (!SVG.highlightedPath) return; 1253 | $(SVG.highlightedPath.node).attr({ 1254 | 'marker-start': 'url(#StartMarker2)', 1255 | 'marker-mid': 'url(#MidMarker2)', 1256 | 'marker-end': 'url(#EndMarker2)' 1257 | }); 1258 | if ($(SVG.highlightedPath.node).attr('transform')) 1259 | SVG.highlightedPath.animate({ 1260 | 'transform': 's1 1' 1261 | }, 500, function () { 1262 | this.animate({ 1263 | 'opacity': '0' 1264 | }, 500, function () { 1265 | this.remove(); 1266 | }); 1267 | }); 1268 | else 1269 | SVG.highlightedPath.animate({ 1270 | 'opacity': '0' 1271 | }, 300, function () { 1272 | this.remove(); 1273 | }); 1274 | } 1275 | }, '.subpolylinks'); 1276 | } 1277 | 1278 | function setInputValues() { 1279 | $('input[name="polygons"][value="' + selectedPolygons + '"]').prop('checked', true).change(); 1280 | $('#subj_polygon_count').val(randomSetting.subjPolygonCount); 1281 | $('#subj_point_count').val(randomSetting.subjPointCount); 1282 | $('#clip_polygon_count').val(randomSetting.clipPolygonCount); 1283 | $('#clip_point_count').val(randomSetting.clipPointCount); 1284 | $('input[name="subject_fillType"][value="' + subj.fillType + '"]').prop('checked', true); 1285 | $('input[name="clip_fillType"][value="' + clip.fillType + '"]').prop('checked', true); 1286 | $('input[name="offsettable_poly"][value="' + offsettablePoly + '"]').prop('checked', true); 1287 | $('#delta').val(delta.toFixed(1)); 1288 | $('#miterLimit').val(miterLimit.toFixed(1)); 1289 | $('#autoFix').prop('checked', autoFix); 1290 | $('#clean').prop('checked', clean); 1291 | $('#cleandelta').val(cleanDeltaDefault); 1292 | $('#simplify').prop('checked', simplify); 1293 | $('#lighten').prop('checked', lighten); 1294 | $('#lighten_distance').val(lightenDistanceDefault); 1295 | $('#scale').val(scale.toFixed(1)); 1296 | $('#bevel').prop('checked', bevel); 1297 | $('#explorer_enabled').prop('checked', explorerEnabled); 1298 | $('#output_format').val(outputFormat); 1299 | } 1300 | 1301 | function makeClip() { 1302 | var benchId; 1303 | ClipperLib.biginteger_used = null; 1304 | clipper.Clear(); 1305 | getPolygons(); 1306 | if (clipType !== '' && offsettablePoly === 'solution') { 1307 | clipper.AddPolygons(ss, ClipperLib.PolyType.ptSubject); 1308 | clipper.AddPolygons(cc, ClipperLib.PolyType.ptClip); 1309 | sss = new ClipperLib.Polygons(); 1310 | benchId = bench.start('Boolean', 'Execute(' + clipType + ', sss, ' + subj.fillType + ', ' + clip.fillType + ')'); 1311 | clipper.Execute(clipType, sss, subj.fillType, clip.fillType); 1312 | bench.end(benchId); 1313 | } 1314 | 1315 | offsettablePoly = $('input[name="offsettable_poly"]:checked').val(); 1316 | if (offsettablePoly === 'subject') { 1317 | offsetResult = ClipperLib.Clone(ss); 1318 | } else if (offsettablePoly === 'clip') { 1319 | offsetResult = ClipperLib.Clone(cc); 1320 | } else if (offsettablePoly === 'solution') { 1321 | offsetResult = sss; 1322 | } 1323 | 1324 | if (typeof offsetResult === 'undefined' || !_.isArray(sss)) offsetResult = [[]]; 1325 | 1326 | if (ClipperLib.biginteger_used === null) ClipperLib.biginteger_used = 0; 1327 | 1328 | if (clean) { 1329 | offsetResult = ClipperLib.Clean(offsetResult, cleanDelta * scale); 1330 | } 1331 | 1332 | // Must simplify before offsetting, to get offsetting right in certain cases. 1333 | // Other operations (boolean ones) doesn't need this. 1334 | // This is needed when offsetting polygons that has selfintersecting parts ( eg. 5-point star needs this ) 1335 | if (simplify) { 1336 | // Simplifying is only needed when offsetting original polys, because results of boolean operations are already simplified. 1337 | // Note! if clip polygon is the same as subject polygon then it seems that simplifying is needed also for result of boolean operation (ie. solution). 1338 | if (offsettablePoly === 'subject') { 1339 | offsetResult = clipper.SimplifyPolygons(offsetResult, subj.fillType); 1340 | } 1341 | if (offsettablePoly === 'clip') { 1342 | offsetResult = clipper.SimplifyPolygons(offsetResult, clip.fillType); 1343 | } 1344 | if (offsettablePoly === 'solution') { 1345 | offsetResult = clipper.SimplifyPolygons(offsetResult, clip.fillType); 1346 | if (subj.fillType !== clip.fillType) { 1347 | console.log('Subject filltype and Clip filltype are different. We used Clip filltype in SimplifyPolygons().'); 1348 | } 1349 | } 1350 | } 1351 | 1352 | // Actual offset operation 1353 | if (delta) { 1354 | clipper.Clear(); 1355 | var paramDelta = _.round(delta * scale, 3); 1356 | var paramMiterLimit = _.round(miterLimit, 3); 1357 | benchId = bench.start('Offset', 'Offset(' + paramDelta + ', ' + joinType + ', ' + paramMiterLimit + ', ' + autoFix + ')'); 1358 | offsetResult = clipper.OffsetPolygons(offsetResult, paramDelta, joinType, paramMiterLimit, autoFix); 1359 | bench.end(benchId); 1360 | } 1361 | 1362 | if (lighten) { 1363 | offsetResult = ClipperLib.Lighten(offsetResult, lightenDistance * scale); 1364 | // Because lighten may produce self-intersections, must Simplify to be sure that result is free of them, but only if user wants 1365 | if (simplify) { 1366 | offsetResult = clipper.SimplifyPolygons(offsetResult, subj.fillType); 1367 | } 1368 | } 1369 | 1370 | SVG.update(); 1371 | if (bench.includeSVG) benchId = bench.start('SVG', 'addPaths(ss, cc, offsetResult, ' + subj.fillType + ', ' + clip.fillType + ')'); 1372 | SVG.addPaths(ss, cc, offsetResult, subj.fillType, clip.fillType); 1373 | if (bench.includeSVG) bench.end(benchId); 1374 | 1375 | if (ClipperLib.biginteger_used !== null) { 1376 | $('#biginteger_used').html(ClipperLib.biginteger_used ? 'true' : 'false'); 1377 | } 1378 | else $('#biginteger_used').html('unknown'); 1379 | ClipperLib.biginteger_used = null; 1380 | 1381 | // Update delta to form 1382 | $('#delta').val(delta.toFixed(1)); 1383 | // Update miterlimit to form 1384 | $('#miterLimit').val(miterLimit.toFixed(1)); 1385 | // Print benchmark 1386 | $('#benchmark_div').html(bench.print()); 1387 | updateEnlargedSVGSource(); 1388 | } 1389 | 1390 | window.onload = function () { 1391 | ClipperLibOriginalMaxSteps = ClipperLib.MaxSteps; 1392 | bench = new Benchmark(); 1393 | p = SVG.create(); 1394 | bindHelp(); 1395 | bindInputListeners(); 1396 | setInputValues(); 1397 | makeClip(); 1398 | colorizeBoxes(); 1399 | setDefaultCustomPolygons(); 1400 | }; --------------------------------------------------------------------------------
NumCallsSumAvg
'; 722 | table += (i + 1); 723 | table += ''; 724 | table += this.totals_arr_multiple[i][0]; 725 | table += ''; 726 | table += this.totals_arr_multiple[i][1]; 727 | table += ''; 728 | table += this.totals_arr_multiple[i][2]; 729 | table += '
'; 734 | table += 'Average: ' + average + ' ms
'; 735 | table += 'Min: ' + min + ' ms
'; 736 | table += 'Max: ' + max + ' ms
'; 737 | table += 'Range: ' + range.toFixed(4) + ' ms
'; 738 | table += 'Minus-Range: ' + minusRange.toFixed(4) + ' ms
'; 739 | table += 'Plus-Range: ' + plusRange.toFixed(4) + ' ms
'; 740 | table += 'Stdev: ' + standardDeviation + ' ms
'; 741 | table += 'Range/Average %: ' + (range / average * 100).toFixed(4) + '
'; 742 | table += 'Minus-Range/Average %: ' + (minusRange / average * 100).toFixed(4) + '
'; 743 | table += 'Plus-Range/Average %: ' + (plusRange / average * 100).toFixed(4) + '
'; 744 | table += 'Stdev/Average %: ' + (standardDeviation / average * 100).toFixed(4) + '
'; 745 | table += '