From a5465283fd636fa12f922533a8ae169258356ac6 Mon Sep 17 00:00:00 2001 From: Ruben van de Ven Date: Thu, 28 Jan 2021 13:03:16 +0100 Subject: [PATCH] Use clipper to get more precise score for annotation --- www/index.html | 1 + www/js/clipper.js | 255 ++++++++++++++++++++++++++++++++++++++++++++++ www/js/game.js | 135 +++++++++++++++++++++++- www/js/svg.js | 8 +- 4 files changed, 395 insertions(+), 4 deletions(-) create mode 100644 www/js/clipper.js diff --git a/www/index.html b/www/index.html index 39df254..a996720 100644 --- a/www/index.html +++ b/www/index.html @@ -67,6 +67,7 @@ + \ No newline at end of file diff --git a/www/js/clipper.js b/www/js/clipper.js new file mode 100644 index 0000000..875d798 --- /dev/null +++ b/www/js/clipper.js @@ -0,0 +1,255 @@ +/******************************************************************************* + * * + * Author : Angus Johnson * + * Version : 6.4.2 * + * Date : 27 February 2017 * + * Website : http://www.angusj.com * + * Copyright : Angus Johnson 2010-2017 * + * * + * License: * + * Use, modification & distribution is subject to Boost Software License Ver 1. * + * http://www.boost.org/LICENSE_1_0.txt * + * * + * Attributions: * + * The code in this library is an extension of Bala Vatti's clipping algorithm: * + * "A generic solution to polygon clipping" * + * Communications of the ACM, Vol 35, Issue 7 (July 1992) pp 56-63. * + * http://portal.acm.org/citation.cfm?id=129906 * + * * + * Computer graphics and geometric modeling: implementation and algorithms * + * By Max K. Agoston * + * Springer; 1 edition (January 4, 2005) * + * http://books.google.com/books?q=vatti+clipping+agoston * + * * + * See also: * + * "Polygon Offsetting by Computing Winding Numbers" * + * Paper no. DETC2005-85513 pp. 565-575 * + * ASME 2005 International Design Engineering Technical Conferences * + * and Computers and Information in Engineering Conference (IDETC/CIE2005) * + * September 24-28, 2005 , Long Beach, California, USA * + * http://www.me.berkeley.edu/~mcmains/pubs/DAC05OffsetPolygon.pdf * + * * + *******************************************************************************/ +/******************************************************************************* + * * + * Author : Timo * + * Version : 6.4.2.2 * + * Date : 8 September 2017 * + * * + * This is a translation of the C# Clipper library to Javascript. * + * Int128 struct of C# is implemented using JSBN of Tom Wu. * + * Because Javascript lacks support for 64-bit integers, the space * + * is a little more restricted than in C# version. * + * * + * C# version has support for coordinate space: * + * +-4611686018427387903 ( sqrt(2^127 -1)/2 ) * + * while Javascript version has support for space: * + * +-4503599627370495 ( sqrt(2^106 -1)/2 ) * + * * + * Tom Wu's JSBN proved to be the fastest big integer library: * + * http://jsperf.com/big-integer-library-test * + * * + * This class can be made simpler when (if ever) 64-bit integer support comes * + * or floating point Clipper is released. * + * * + *******************************************************************************/ +/******************************************************************************* + * * + * Basic JavaScript BN library - subset useful for RSA encryption. * + * http://www-cs-students.stanford.edu/~tjw/jsbn/ * + * Copyright (c) 2005 Tom Wu * + * All Rights Reserved. * + * See "LICENSE" for details: * + * http://www-cs-students.stanford.edu/~tjw/jsbn/LICENSE * + * * + *******************************************************************************/ +(function(){function k(a,b,c){d.biginteger_used=1;null!=a&&("number"==typeof a&&"undefined"==typeof b?this.fromInt(a):"number"==typeof a?this.fromNumber(a,b,c):null==b&&"string"!=typeof a?this.fromString(a,256):this.fromString(a,b))}function q(){return new k(null,void 0,void 0)}function R(a,b,c,e,d,g){for(;0<=--g;){var f=b*this[a++]+c[e]+d;d=Math.floor(f/67108864);c[e++]=f&67108863}return d}function S(a,b,c,e,d,g){var f=b&32767;for(b>>=15;0<=--g;){var m=this[a]&32767,k=this[a++]>>15,n=b*m+k*f;m=f* +m+((n&32767)<<15)+c[e]+(d&1073741823);d=(m>>>30)+(n>>>15)+b*k+(d>>>30);c[e++]=m&1073741823}return d}function T(a,b,c,e,d,g){var f=b&16383;for(b>>=14;0<=--g;){var m=this[a]&16383,k=this[a++]>>14,n=b*m+k*f;m=f*m+((n&16383)<<14)+c[e]+d;d=(m>>28)+(n>>14)+b*k;c[e++]=m&268435455}return d}function M(a,b){var c=E[a.charCodeAt(b)];return null==c?-1:c}function y(a){var b=q();b.fromInt(a);return b}function F(a){var b=1,c;0!=(c=a>>>16)&&(a=c,b+=16);0!=(c=a>>8)&&(a=c,b+=8);0!=(c=a>>4)&&(a=c,b+=4);0!=(c=a>>2)&& +(a=c,b+=2);0!=a>>1&&(b+=1);return b}function z(a){this.m=a}function B(a){this.m=a;this.mp=a.invDigit();this.mpl=this.mp&32767;this.mph=this.mp>>15;this.um=(1<=x;++x)E[v++]=x;v=97;for(x=10;36> +x;++x)E[v++]=x;v=65;for(x=10;36>x;++x)E[v++]=x;z.prototype.convert=function(a){return 0>a.s||0<=a.compareTo(this.m)?a.mod(this.m):a};z.prototype.revert=function(a){return a};z.prototype.reduce=function(a){a.divRemTo(this.m,null,a)};z.prototype.mulTo=function(a,b,c){a.multiplyTo(b,c);this.reduce(c)};z.prototype.sqrTo=function(a,b){a.squareTo(b);this.reduce(b)};B.prototype.convert=function(a){var b=q();a.abs().dlShiftTo(this.m.t,b);b.divRemTo(this.m,null,b);0>a.s&&0>15)*this.mpl&this.um)<<15)&a.DM;c=b+this.m.t;for(a[c]+=this.m.am(0,e,a,b,0,this.m.t);a[c]>=a.DV;)a[c]-=a.DV,a[++c]++}a.clamp();a.drShiftTo(this.m.t,a);0<=a.compareTo(this.m)&&a.subTo(this.m,a)};B.prototype.mulTo=function(a,b,c){a.multiplyTo(b,c);this.reduce(c)};B.prototype.sqrTo= +function(a,b){a.squareTo(b);this.reduce(b)};k.prototype.copyTo=function(a){for(var b=this.t-1;0<=b;--b)a[b]=this[b];a.t=this.t;a.s=this.s};k.prototype.fromInt=function(a){this.t=1;this.s=0>a?-1:0;0a?this[0]=a+this.DV:this.t=0};k.prototype.fromString=function(a,b){if(16==b)var c=4;else if(8==b)c=3;else if(256==b)c=8;else if(2==b)c=1;else if(32==b)c=5;else if(4==b)c=2;else{this.fromRadix(a,b);return}this.s=this.t=0;for(var e=a.length,d=!1,g=0;0<=--e;){var h=8==c?a[e]&255:M(a,e);0>h? +"-"==a.charAt(e)&&(d=!0):(d=!1,0==g?this[this.t++]=h:g+c>this.DB?(this[this.t-1]|=(h&(1<>this.DB-g):this[this.t-1]|=h<=this.DB&&(g-=this.DB))}8==c&&0!=(a[0]&128)&&(this.s=-1,0>e|h,h=(this[m]&d)<=this.t)b.t=0;else{var e=a%this.DB, +d=this.DB-e,g=(1<>e;for(var h=c+1;h>e;0>=this.DB;if(a.t>=this.DB;e+=this.s}else{for(e+=this.s;c>=this.DB;e-=a.s}b.s=0>e?-1:0;-1>e?b[c++]=this.DV+e:0=b.DV&&(a[c+b.t]-=b.DV,a[c+b.t+1]=1)}0=e.t)){var d=this.abs();if(d.t>this.F2:0),n=this.FV/l;l=(1<h&&k.ZERO.subTo(c,c)}}}};k.prototype.invDigit=function(){if(1>this.t)return 0;var a=this[0];if(0==(a&1))return 0;var b=a&3;b=b*(2-(a&15)*b)&15;b=b*(2-(a&255)*b)&255;b=b*(2-((a&65535)*b&65535))&65535;b=b*(2-a*b%this.DV)%this.DV;return 0a)return k.ONE;var c=q(),e=q(),d=b.convert(this),g=F(a)-1;for(d.copyTo(c);0<=--g;)if(b.sqrTo(c,e),0<(a&1<this.s)return"-"+this.negate().toString(a);if(16==a)a=4;else if(8==a)a=3;else if(2==a)a=1;else if(32==a)a=5;else if(4==a)a=2;else return this.toRadix(a);var b=(1<>h)&&(e=!0,d="0123456789abcdefghijklmnopqrstuvwxyz".charAt(c));0<=g;)h>(h+=this.DB-a)):(c=this[g]>>(h-=a)&b,0>=h&&(h+=this.DB,--g)),0this.s?this.negate():this};k.prototype.compareTo=function(a){var b= +this.s-a.s;if(0!=b)return b;var c=this.t;b=c-a.t;if(0!=b)return 0>this.s?-b:b;for(;0<=--c;)if(0!=(b=this[c]-a[c]))return b;return 0};k.prototype.bitLength=function(){return 0>=this.t?0:this.DB*(this.t-1)+F(this[this.t-1]^this.s&this.DM)};k.prototype.mod=function(a){var b=q();this.abs().divRemTo(a,null,b);0>this.s&&0a||b.isEven()?new z(b):new B(b);return this.exp(a,c)};k.ZERO=y(0);k.ONE=y(1);D.prototype.convert= +P;D.prototype.revert=P;D.prototype.mulTo=function(a,b,c){a.multiplyTo(b,c)};D.prototype.sqrTo=function(a,b){a.squareTo(b)};C.prototype.convert=function(a){if(0>a.s||a.t>2*this.m.t)return a.mod(this.m);if(0>a.compareTo(this.m))return a;var b=q();a.copyTo(b);this.reduce(b);return b};C.prototype.revert=function(a){return a};C.prototype.reduce=function(a){a.drShiftTo(this.m.t-1,this.r2);a.t>this.m.t+1&&(a.t=this.m.t+1,a.clamp());this.mu.multiplyUpperTo(this.r2,this.m.t+1,this.q3);for(this.m.multiplyLowerTo(this.q3, +this.m.t+1,this.r2);0>a.compareTo(this.r2);)a.dAddOffset(1,this.m.t+1);for(a.subTo(this.r2,a);0<=a.compareTo(this.m);)a.subTo(this.m,a)};C.prototype.mulTo=function(a,b,c){a.multiplyTo(b,c);this.reduce(c)};C.prototype.sqrTo=function(a,b){a.squareTo(b);this.reduce(b)};var w=[2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97,101,103,107,109,113,127,131,137,139,149,151,157,163,167,173,179,181,191,193,197,199,211,223,227,229,233,239,241,251,257,263,269,271,277,281,283,293,307,311, +313,317,331,337,347,349,353,359,367,373,379,383,389,397,401,409,419,421,431,433,439,443,449,457,461,463,467,479,487,491,499,503,509,521,523,541,547,557,563,569,571,577,587,593,599,601,607,613,617,619,631,641,643,647,653,659,661,673,677,683,691,701,709,719,727,733,739,743,751,757,761,769,773,787,797,809,811,821,823,827,829,839,853,857,859,863,877,881,883,887,907,911,919,929,937,941,947,953,967,971,977,983,991,997],W=67108864/w[w.length-1];k.prototype.chunkSize=function(a){return Math.floor(Math.LN2* +this.DB/Math.log(a))};k.prototype.toRadix=function(a){null==a&&(a=10);if(0==this.signum()||2>a||36l?"-"==a.charAt(m)&&0==this.signum()&& +(d=!0):(h=b*h+l,++g>=c&&(this.dMultiply(e),this.dAddOffset(h,0),h=g=0))}0a)this.fromInt(1);else for(this.fromNumber(a,c),this.testBit(a-1)||this.bitwiseTo(k.ONE.shiftLeft(a-1),H,this),this.isEven()&&this.dAddOffset(1,0);!this.isProbablePrime(b);)this.dAddOffset(2,0),this.bitLength()>a&&this.subTo(k.ONE.shiftLeft(a-1),this);else{c=[];var e=a&7;c.length= +(a>>3)+1;b.nextBytes(c);c[0]=0>=this.DB;if(a.t>=this.DB;e+=this.s}else{for(e+=this.s;c>=this.DB;e+=a.s}b.s=0>e?-1:0;0e&&(b[c++]=this.DV+e);b.t=c;b.clamp()};k.prototype.dMultiply=function(a){this[this.t]=this.am(0,a-1,this,0,0,this.t);++this.t;this.clamp()};k.prototype.dAddOffset=function(a,b){if(0!=a){for(;this.t<=b;)this[this.t++]=0;for(this[b]+=a;this[b]>=this.DV;)this[b]-= +this.DV,++b>=this.t&&(this[this.t++]=0),++this[b]}};k.prototype.multiplyLowerTo=function(a,b,c){var e=Math.min(this.t+a.t,b);c.s=0;for(c.t=e;0=a)return 0;var b=this.DV%a,c=0>this.s?a-1:0;if(0=c)return!1;var e=b.shiftRight(c);a=a+1>>1;a>w.length&&(a=w.length);for(var d=q(),g=0;gthis.s){if(1==this.t)return this[0]-this.DV;if(0==this.t)return-1}else{if(1==this.t)return this[0];if(0==this.t)return 0}return(this[1]&(1<<32-this.DB)-1)<>24};k.prototype.shortValue=function(){return 0==this.t?this.s:this[0]<< +16>>16};k.prototype.signum=function(){return 0>this.s?-1:0>=this.t||1==this.t&&0>=this[0]?0:1};k.prototype.toByteArray=function(){var a=this.t,b=[];b[0]=this.s;var c=this.DB-a*this.DB%8,e,d=0;if(0>c)!=(this.s&this.DM)>>c&&(b[d++]=e|this.s<c?(e=(this[a]&(1<>(c+=this.DB-8)):(e=this[a]>>(c-=8)&255,0>=c&&(c+=this.DB,--a)),0!=(e&128)&&(e|=-256),0==d&&(this.s&128)!=(e&128)&&++d,0this.compareTo(a)?this:a};k.prototype.max=function(a){return 0a?this.rShiftTo(-a,b):this.lShiftTo(a,b);return b};k.prototype.shiftRight=function(a){var b=q();0>a?this.lShiftTo(-a,b):this.rShiftTo(a,b);return b};k.prototype.getLowestSetBit=function(){for(var a=0;a>=16,c+=16);0==(a&255)&&(a>>=8,c+=8);0==(a&15)&&(a>>=4,c+=4);0==(a&3)&&(a>>=2,c+=2);0==(a&1)&&++c;a=c}return b+ +a}return 0>this.s?this.t*this.DB:-1};k.prototype.bitCount=function(){for(var a=0,b=this.s&this.DM,c=0;c=this.t?0!=this.s:0!=(this[b]&1<=c)return e;var d=18> +c?1:48>c?3:144>c?4:768>c?5:6;var g=8>c?new z(b):b.isEven()?new C(b):new B(b);var h=[],m=3,k=d-1,n=(1<=k)var u=a[r]>>c-k&n;else u=(a[r]&(1<>this.DB+c-k);for(m=d;0==(u&1);)u>>=1,--m;0>(c-=m)&&(c+=this.DB,--r);if(p)h[u].copyTo(e),p=!1;else{for(;1--c&&(c=this.DB-1,--r)}return g.revert(e)};k.prototype.modInverse=function(a){var b=a.isEven();if(this.isEven()&&b||0==a.signum())return k.ZERO;for(var c=a.clone(),e=this.clone(),d=y(1),g=y(0),h=y(0),m=y(1);0!=c.signum();){for(;c.isEven();)c.rShiftTo(1,c),b?(d.isEven()&&g.isEven()||(d.addTo(this,d),g.subTo(a,g)),d.rShiftTo(1,d)):g.isEven()||g.subTo(a,g),g.rShiftTo(1,g);for(;e.isEven();)e.rShiftTo(1,e),b?(h.isEven()&&m.isEven()||(h.addTo(this, +h),m.subTo(a,m)),h.rShiftTo(1,h)):m.isEven()||m.subTo(a,m),m.rShiftTo(1,m);0<=c.compareTo(e)?(c.subTo(e,c),b&&d.subTo(h,d),g.subTo(m,g)):(e.subTo(c,e),b&&h.subTo(d,h),m.subTo(g,m))}if(0!=e.compareTo(k.ONE))return k.ZERO;if(0<=m.compareTo(a))return m.subtract(a);if(0>m.signum())m.addTo(a,m);else return m;return 0>m.signum()?m.add(a):m};k.prototype.pow=function(a){return this.exp(a,new D)};k.prototype.gcd=function(a){var b=0>this.s?this.negate():this.clone();a=0>a.s?a.negate():a.clone();if(0>b.compareTo(a)){var c= +b;b=a;a=c}c=b.getLowestSetBit();var e=a.getLowestSetBit();if(0>e)return b;c +a.compareTo(b)?!0:!1};k.op_Addition=function(a,b){return(new k(a,void 0,void 0)).add(new k(b,void 0,void 0))};k.op_Subtraction=function(a,b){return(new k(a,void 0,void 0)).subtract(new k(b,void 0,void 0))};k.Int128Mul=function(a,b){return(new k(a,void 0,void 0)).multiply(new k(b,void 0,void 0))};k.op_Division=function(a,b){return a.divide(b)};k.prototype.ToDouble=function(){return parseFloat(this.toString())};v=function(a,b){var c;if("undefined"===typeof Object.getOwnPropertyNames)for(c in b.prototype){if("undefined"=== +typeof a.prototype[c]||a.prototype[c]===Object.prototype[c])a.prototype[c]=b.prototype[c]}else for(var e=Object.getOwnPropertyNames(b.prototype),d=0;da||2147483647a?Math.ceil(a):Math.floor(a):~~a}:J&&"function"===typeof Number.toInteger?function(a){return Number.toInteger(a)}:V||L?function(a){return parseInt(a,10)}:u?function(a){return-2147483648>a||2147483647a?Math.ceil(a):Math.floor(a):a|0}:function(a){return 0>a?Math.ceil(a): +Math.floor(a)};d.Clear=function(a){a.length=0};d.PI=3.141592653589793;d.PI2=6.283185307179586;d.IntPoint=function(){var a=arguments;var b=a.length;this.Y=this.X=0;d.use_xyz?(this.Z=0,3===b?(this.X=a[0],this.Y=a[1],this.Z=a[2]):2===b?(this.X=a[0],this.Y=a[1],this.Z=0):1===b?a[0]instanceof d.DoublePoint?(a=a[0],this.X=d.Clipper.Round(a.X),this.Y=d.Clipper.Round(a.Y),this.Z=0):(a=a[0],"undefined"===typeof a.Z&&(a.Z=0),this.X=a.X,this.Y=a.Y,this.Z=a.Z):this.Z=this.Y=this.X=0):2===b?(this.X=a[0],this.Y= +a[1]):1===b?a[0]instanceof d.DoublePoint?(a=a[0],this.X=d.Clipper.Round(a.X),this.Y=d.Clipper.Round(a.Y)):(a=a[0],this.X=a.X,this.Y=a.Y):this.Y=this.X=0};d.IntPoint.op_Equality=function(a,b){return a.X===b.X&&a.Y===b.Y};d.IntPoint.op_Inequality=function(a,b){return a.X!==b.X||a.Y!==b.Y};d.IntPoint0=function(){this.Y=this.X=0;d.use_xyz&&(this.Z=0)};d.IntPoint0.prototype=d.IntPoint.prototype;d.IntPoint1=function(a){this.X=a.X;this.Y=a.Y;d.use_xyz&&(this.Z="undefined"===typeof a.Z?0:a.Z)};d.IntPoint1.prototype= +d.IntPoint.prototype;d.IntPoint1dp=function(a){this.X=d.Clipper.Round(a.X);this.Y=d.Clipper.Round(a.Y);d.use_xyz&&(this.Z=0)};d.IntPoint1dp.prototype=d.IntPoint.prototype;d.IntPoint2=function(a,b,c){this.X=a;this.Y=b;d.use_xyz&&(this.Z="undefined"===typeof c?0:c)};d.IntPoint2.prototype=d.IntPoint.prototype;d.IntRect=function(){var a=arguments,b=a.length;4===b?(this.left=a[0],this.top=a[1],this.right=a[2],this.bottom=a[3]):1===b?(a=a[0],this.left=a.left,this.top=a.top,this.right=a.right,this.bottom= +a.bottom):this.bottom=this.right=this.top=this.left=0};d.IntRect0=function(){this.bottom=this.right=this.top=this.left=0};d.IntRect0.prototype=d.IntRect.prototype;d.IntRect1=function(a){this.left=a.left;this.top=a.top;this.right=a.right;this.bottom=a.bottom};d.IntRect1.prototype=d.IntRect.prototype;d.IntRect4=function(a,b,c,e){this.left=a;this.top=b;this.right=c;this.bottom=e};d.IntRect4.prototype=d.IntRect.prototype;d.ClipType={ctIntersection:0,ctUnion:1,ctDifference:2,ctXor:3};d.PolyType={ptSubject:0, +ptClip:1};d.PolyFillType={pftEvenOdd:0,pftNonZero:1,pftPositive:2,pftNegative:3};d.JoinType={jtSquare:0,jtRound:1,jtMiter:2};d.EndType={etOpenSquare:0,etOpenRound:1,etOpenButt:2,etClosedLine:3,etClosedPolygon:4};d.EdgeSide={esLeft:0,esRight:1};d.Direction={dRightToLeft:0,dLeftToRight:1};d.TEdge=function(){this.Bot=new d.IntPoint0;this.Curr=new d.IntPoint0;this.Top=new d.IntPoint0;this.Delta=new d.IntPoint0;this.Dx=0;this.PolyTyp=d.PolyType.ptSubject;this.Side=d.EdgeSide.esLeft;this.OutIdx=this.WindCnt2= +this.WindCnt=this.WindDelta=0;this.PrevInSEL=this.NextInSEL=this.PrevInAEL=this.NextInAEL=this.NextInLML=this.Prev=this.Next=null};d.IntersectNode=function(){this.Edge2=this.Edge1=null;this.Pt=new d.IntPoint0};d.MyIntersectNodeSort=function(){};d.MyIntersectNodeSort.Compare=function(a,b){var c=b.Pt.Y-a.Pt.Y;return 0c?-1:0};d.LocalMinima=function(){this.Y=0;this.Next=this.RightBound=this.LeftBound=null};d.Scanbeam=function(){this.Y=0;this.Next=null};d.Maxima=function(){this.X=0;this.Prev=this.Next= +null};d.OutRec=function(){this.Idx=0;this.IsOpen=this.IsHole=!1;this.PolyNode=this.BottomPt=this.Pts=this.FirstLeft=null};d.OutPt=function(){this.Idx=0;this.Pt=new d.IntPoint0;this.Prev=this.Next=null};d.Join=function(){this.OutPt2=this.OutPt1=null;this.OffPt=new d.IntPoint0};d.ClipperBase=function(){this.m_CurrentLM=this.m_MinimaList=null;this.m_edges=[];this.PreserveCollinear=this.m_HasOpenPaths=this.m_UseFullRange=!1;this.m_ActiveEdges=this.m_PolyOuts=this.m_Scanbeam=null};d.ClipperBase.horizontal= +-9007199254740992;d.ClipperBase.Skip=-2;d.ClipperBase.Unassigned=-1;d.ClipperBase.tolerance=1E-20;d.ClipperBase.loRange=47453132;d.ClipperBase.hiRange=0xfffffffffffff;d.ClipperBase.near_zero=function(a){return a>-d.ClipperBase.tolerance&&ab.X===a.Xb.Y===a.Yb.X===a.Xb.Y===a.Yd.ClipperBase.hiRange||a.Y>d.ClipperBase.hiRange||-a.X>d.ClipperBase.hiRange||-a.Y>d.ClipperBase.hiRange)&&d.Error("Coordinate outside allowed range in RangeTest().");else if(a.X>d.ClipperBase.loRange||a.Y>d.ClipperBase.loRange||-a.X>d.ClipperBase.loRange||-a.Y>d.ClipperBase.loRange)b.Value=!0,this.RangeTest(a, +b)};d.ClipperBase.prototype.InitEdge=function(a,b,c,e){a.Next=b;a.Prev=c;a.Curr.X=e.X;a.Curr.Y=e.Y;d.use_xyz&&(a.Curr.Z=e.Z);a.OutIdx=-1};d.ClipperBase.prototype.InitEdge2=function(a,b){a.Curr.Y>=a.Next.Curr.Y?(a.Bot.X=a.Curr.X,a.Bot.Y=a.Curr.Y,d.use_xyz&&(a.Bot.Z=a.Curr.Z),a.Top.X=a.Next.Curr.X,a.Top.Y=a.Next.Curr.Y,d.use_xyz&&(a.Top.Z=a.Next.Curr.Z)):(a.Top.X=a.Curr.X,a.Top.Y=a.Curr.Y,d.use_xyz&&(a.Top.Z=a.Curr.Z),a.Bot.X=a.Next.Curr.X,a.Bot.Y=a.Next.Curr.Y,d.use_xyz&&(a.Bot.Z=a.Next.Curr.Z));this.SetDx(a); +a.PolyTyp=b};d.ClipperBase.prototype.FindNextLocMin=function(a){for(var b;;){for(;d.IntPoint.op_Inequality(a.Bot,a.Prev.Bot)||d.IntPoint.op_Equality(a.Curr,a.Top);)a=a.Next;if(a.Dx!==d.ClipperBase.horizontal&&a.Prev.Dx!==d.ClipperBase.horizontal)break;for(;a.Prev.Dx===d.ClipperBase.horizontal;)a=a.Prev;for(b=a;a.Dx===d.ClipperBase.horizontal;)a=a.Next;if(a.Top.Y!==a.Prev.Bot.Y){b.Prev.Bot.Xc.Next.Top.X&&(c=e.Prev)}for(;a!==c;)a.NextInLML=a.Next,a.Dx===d.ClipperBase.horizontal&&a!==f&&a.Bot.X!==a.Prev.Top.X&&this.ReverseHorizontal(a),a=a.Next;a.Dx===d.ClipperBase.horizontal&& +a!==f&&a.Bot.X!==a.Prev.Top.X&&this.ReverseHorizontal(a);c=c.Next}else{for(;c.Top.Y===c.Prev.Bot.Y&&c.Prev.OutIdx!==d.ClipperBase.Skip;)c=c.Prev;if(c.Dx===d.ClipperBase.horizontal&&c.Prev.OutIdx!==d.ClipperBase.Skip){for(e=c;e.Next.Dx===d.ClipperBase.horizontal;)e=e.Next;if(e.Next.Top.X===c.Prev.Top.X||e.Next.Top.X>c.Prev.Top.X)c=e.Next}for(;a!==c;)a.NextInLML=a.Prev,a.Dx===d.ClipperBase.horizontal&&a!==f&&a.Bot.X!==a.Next.Top.X&&this.ReverseHorizontal(a),a=a.Prev;a.Dx===d.ClipperBase.horizontal&& +a!==f&&a.Bot.X!==a.Next.Top.X&&this.ReverseHorizontal(a);c=c.Prev}return c};d.ClipperBase.prototype.AddPath=function(a,b,c){d.use_lines?c||b!==d.PolyType.ptClip||d.Error("AddPath: Open paths must be subject."):c||d.Error("AddPath: Open paths have been disabled.");var e=a.length-1;if(c)for(;0e||!c&&1>e)return!1;for(var f=[],g=0;g<=e;g++)f.push(new d.TEdge);var h=!0;f[1].Curr.X=a[1].X;f[1].Curr.Y=a[1].Y; +d.use_xyz&&(f[1].Curr.Z=a[1].Z);var m={Value:this.m_UseFullRange};this.RangeTest(a[0],m);this.m_UseFullRange=m.Value;m.Value=this.m_UseFullRange;this.RangeTest(a[e],m);this.m_UseFullRange=m.Value;this.InitEdge(f[0],f[1],f[e],a[0]);this.InitEdge(f[e],f[0],f[e-1],a[e]);for(g=e-1;1<=g;--g)m.Value=this.m_UseFullRange,this.RangeTest(a[g],m),this.m_UseFullRange=m.Value,this.InitEdge(f[g],f[g+1],f[g-1],a[g]);for(g=a=e=f[0];;)if(a.Curr!==a.Next.Curr||!c&&a.Next===e){if(a.Prev===a.Next)break;else if(c&&d.ClipperBase.SlopesEqual4(a.Prev.Curr, +a.Curr,a.Next.Curr,this.m_UseFullRange)&&(!this.PreserveCollinear||!this.Pt2IsBetweenPt1AndPt3(a.Prev.Curr,a.Curr,a.Next.Curr))){a===e&&(e=a.Next);a=this.RemoveEdge(a);g=a=a.Prev;continue}a=a.Next;if(a===g||!c&&a.Next===e)break}else{if(a===a.Next)break;a===e&&(e=a.Next);g=a=this.RemoveEdge(a)}if(!c&&a===a.Next||c&&a.Prev===a.Next)return!1;c||(this.m_HasOpenPaths=!0,e.Prev.OutIdx=d.ClipperBase.Skip);a=e;do this.InitEdge2(a,b),a=a.Next,h&&a.Curr.Y!==e.Curr.Y&&(h=!1);while(a!==e);if(h){if(c)return!1; +a.Prev.OutIdx=d.ClipperBase.Skip;b=new d.LocalMinima;b.Next=null;b.Y=a.Bot.Y;b.LeftBound=null;b.RightBound=a;b.RightBound.Side=d.EdgeSide.esRight;for(b.RightBound.WindDelta=0;;){a.Bot.X!==a.Prev.Top.X&&this.ReverseHorizontal(a);if(a.Next.OutIdx===d.ClipperBase.Skip)break;a=a.NextInLML=a.Next}this.InsertLocalMinima(b);this.m_edges.push(f);return!0}this.m_edges.push(f);h=null;d.IntPoint.op_Equality(a.Prev.Bot,a.Prev.Top)&&(a=a.Next);for(;;){a=this.FindNextLocMin(a);if(a===h)break;else null===h&&(h= +a);b=new d.LocalMinima;b.Next=null;b.Y=a.Bot.Y;a.Dxa.X===b.Xa.Y===b.Y=this.m_MinimaList.Y)a.Next=this.m_MinimaList,this.m_MinimaList=a;else{for(var b=this.m_MinimaList;null!==b.Next&&a.Ythis.m_Scanbeam.Y){var b=new d.Scanbeam;b.Y=a;b.Next= +this.m_Scanbeam;this.m_Scanbeam=b}else{for(b=this.m_Scanbeam;null!==b.Next&&a<=b.Next.Y;)b=b.Next;if(a!==b.Y){var c=new d.Scanbeam;c.Y=a;c.Next=b.Next;b.Next=c}}};d.ClipperBase.prototype.PopScanbeam=function(a){if(null===this.m_Scanbeam)return a.v=0,!1;a.v=this.m_Scanbeam.Y;this.m_Scanbeam=this.m_Scanbeam.Next;return!0};d.ClipperBase.prototype.LocalMinimaPending=function(){return null!==this.m_CurrentLM};d.ClipperBase.prototype.CreateOutRec=function(){var a=new d.OutRec;a.Idx=d.ClipperBase.Unassigned; +a.IsHole=!1;a.IsOpen=!1;a.FirstLeft=null;a.Pts=null;a.BottomPt=null;a.PolyNode=null;this.m_PolyOuts.push(a);a.Idx=this.m_PolyOuts.length-1;return a};d.ClipperBase.prototype.DisposeOutRec=function(a){this.m_PolyOuts[a].Pts=null;this.m_PolyOuts[a]=null};d.ClipperBase.prototype.UpdateEdgeIntoAEL=function(a){null===a.NextInLML&&d.Error("UpdateEdgeIntoAEL: invalid call");var b=a.PrevInAEL,c=a.NextInAEL;a.NextInLML.OutIdx=a.OutIdx;null!==b?b.NextInAEL=a.NextInLML:this.m_ActiveEdges=a.NextInLML;null!==c&& +(c.PrevInAEL=a.NextInLML);a.NextInLML.Side=a.Side;a.NextInLML.WindDelta=a.WindDelta;a.NextInLML.WindCnt=a.WindCnt;a.NextInLML.WindCnt2=a.WindCnt2;a=a.NextInLML;a.Curr.X=a.Bot.X;a.Curr.Y=a.Bot.Y;a.PrevInAEL=b;a.NextInAEL=c;d.ClipperBase.IsHorizontal(a)||this.InsertScanbeam(a.Top.Y);return a};d.ClipperBase.prototype.SwapPositionsInAEL=function(a,b){if(a.NextInAEL!==a.PrevInAEL&&b.NextInAEL!==b.PrevInAEL){if(a.NextInAEL===b){var c=b.NextInAEL;null!==c&&(c.PrevInAEL=a);var e=a.PrevInAEL;null!==e&&(e.NextInAEL= +b);b.PrevInAEL=e;b.NextInAEL=a;a.PrevInAEL=b;a.NextInAEL=c}else b.NextInAEL===a?(c=a.NextInAEL,null!==c&&(c.PrevInAEL=b),e=b.PrevInAEL,null!==e&&(e.NextInAEL=a),a.PrevInAEL=e,a.NextInAEL=b,b.PrevInAEL=a,b.NextInAEL=c):(c=a.NextInAEL,e=a.PrevInAEL,a.NextInAEL=b.NextInAEL,null!==a.NextInAEL&&(a.NextInAEL.PrevInAEL=a),a.PrevInAEL=b.PrevInAEL,null!==a.PrevInAEL&&(a.PrevInAEL.NextInAEL=a),b.NextInAEL=c,null!==b.NextInAEL&&(b.NextInAEL.PrevInAEL=b),b.PrevInAEL=e,null!==b.PrevInAEL&&(b.PrevInAEL.NextInAEL= +b));null===a.PrevInAEL?this.m_ActiveEdges=a:null===b.PrevInAEL&&(this.m_ActiveEdges=b)}};d.ClipperBase.prototype.DeleteFromAEL=function(a){var b=a.PrevInAEL,c=a.NextInAEL;if(null!==b||null!==c||a===this.m_ActiveEdges)null!==b?b.NextInAEL=c:this.m_ActiveEdges=c,null!==c&&(c.PrevInAEL=b),a.NextInAEL=null,a.PrevInAEL=null};d.Clipper=function(a){"undefined"===typeof a&&(a=0);this.m_PolyOuts=null;this.m_ClipType=d.ClipType.ctIntersection;this.m_IntersectNodeComparer=this.m_IntersectList=this.m_SortedEdges= +this.m_ActiveEdges=this.m_Maxima=this.m_Scanbeam=null;this.m_ExecuteLocked=!1;this.m_SubjFillType=this.m_ClipFillType=d.PolyFillType.pftEvenOdd;this.m_GhostJoins=this.m_Joins=null;this.StrictlySimple=this.ReverseSolution=this.m_UsingPolyTree=!1;d.ClipperBase.call(this);this.m_SortedEdges=this.m_ActiveEdges=this.m_Maxima=this.m_Scanbeam=null;this.m_IntersectList=[];this.m_IntersectNodeComparer=d.MyIntersectNodeSort.Compare;this.m_UsingPolyTree=this.m_ExecuteLocked=!1;this.m_PolyOuts=[];this.m_Joins= +[];this.m_GhostJoins=[];this.ReverseSolution=0!==(1&a);this.StrictlySimple=0!==(2&a);this.PreserveCollinear=0!==(4&a);d.use_xyz&&(this.ZFillFunction=null)};d.Clipper.ioReverseSolution=1;d.Clipper.ioStrictlySimple=2;d.Clipper.ioPreserveCollinear=4;d.Clipper.prototype.Clear=function(){0!==this.m_edges.length&&(this.DisposeAllPolyPts(),d.ClipperBase.prototype.Clear.call(this))};d.Clipper.prototype.InsertMaxima=function(a){var b=new d.Maxima;b.X=a;if(null===this.m_Maxima)this.m_Maxima=b,this.m_Maxima.Next= +null,this.m_Maxima.Prev=null;else if(a=c.Next.X;)c=c.Next;a!==c.X&&(b.Next=c.Next,b.Prev=c,null!==c.Next&&(c.Next.Prev=b),c.Next=b)}};d.Clipper.prototype.Execute=function(){var a;var b=arguments;var c=b.length;var e=b[1]instanceof d.PolyTree;if(4!==c||e){if(4===c&&e){c=b[0];var f=b[1];e=b[2];b=b[3];if(this.m_ExecuteLocked)return!1;this.m_ExecuteLocked=!0;this.m_SubjFillType=e;this.m_ClipFillType= +b;this.m_ClipType=c;this.m_UsingPolyTree=!0;try{(a=this.ExecuteInternal())&&this.BuildResult2(f)}finally{this.DisposeAllPolyPts(),this.m_ExecuteLocked=!1}return a}if(2===c&&!e||2===c&&e)return c=b[0],f=b[1],this.Execute(c,f,d.PolyFillType.pftEvenOdd,d.PolyFillType.pftEvenOdd)}else{c=b[0];f=b[1];e=b[2];b=b[3];if(this.m_ExecuteLocked)return!1;this.m_HasOpenPaths&&d.Error("Error: PolyTree struct is needed for open path clipping.");this.m_ExecuteLocked=!0;d.Clear(f);this.m_SubjFillType=e;this.m_ClipFillType= +b;this.m_ClipType=c;this.m_UsingPolyTree=!1;try{(a=this.ExecuteInternal())&&this.BuildResult(f)}finally{this.DisposeAllPolyPts(),this.m_ExecuteLocked=!1}return a}};d.Clipper.prototype.FixHoleLinkage=function(a){if(null!==a.FirstLeft&&(a.IsHole===a.FirstLeft.IsHole||null===a.FirstLeft.Pts)){for(var b=a.FirstLeft;null!==b&&(b.IsHole===a.IsHole||null===b.Pts);)b=b.FirstLeft;a.FirstLeft=b}};d.Clipper.prototype.ExecuteInternal=function(){try{this.Reset();this.m_Maxima=this.m_SortedEdges=null;var a={}, +b={};if(!this.PopScanbeam(a))return!1;for(this.InsertLocalMinimaIntoAEL(a.v);this.PopScanbeam(b)||this.LocalMinimaPending();){this.ProcessHorizontals();this.m_GhostJoins.length=0;if(!this.ProcessIntersections(b.v))return!1;this.ProcessEdgesAtTopOfScanbeam(b.v);a.v=b.v;this.InsertLocalMinimaIntoAEL(a.v)}var c;var e=0;for(c=this.m_PolyOuts.length;ea.Top.Y?b.Top.Xd.Clipper.TopX(b,a.Top.Y):b.Curr.Xa.WindCnt2}case d.ClipType.ctUnion:switch(c){case d.PolyFillType.pftEvenOdd:case d.PolyFillType.pftNonZero:return 0===a.WindCnt2;case d.PolyFillType.pftPositive:return 0>= +a.WindCnt2;default:return 0<=a.WindCnt2}case d.ClipType.ctDifference:if(a.PolyTyp===d.PolyType.ptSubject)switch(c){case d.PolyFillType.pftEvenOdd:case d.PolyFillType.pftNonZero:return 0===a.WindCnt2;case d.PolyFillType.pftPositive:return 0>=a.WindCnt2;default:return 0<=a.WindCnt2}else switch(c){case d.PolyFillType.pftEvenOdd:case d.PolyFillType.pftNonZero:return 0!==a.WindCnt2;case d.PolyFillType.pftPositive:return 0a.WindCnt2}case d.ClipType.ctXor:if(0===a.WindDelta)switch(c){case d.PolyFillType.pftEvenOdd:case d.PolyFillType.pftNonZero:return 0=== +a.WindCnt2;case d.PolyFillType.pftPositive:return 0>=a.WindCnt2;default:return 0<=a.WindCnt2}}return!0};d.Clipper.prototype.SetWindingCount=function(a){for(var b=a.PrevInAEL;null!==b&&(b.PolyTyp!==a.PolyTyp||0===b.WindDelta);)b=b.PrevInAEL;if(null===b)b=a.PolyTyp===d.PolyType.ptSubject?this.m_SubjFillType:this.m_ClipFillType,a.WindCnt=0===a.WindDelta?b===d.PolyFillType.pftNegative?-1:1:a.WindDelta,a.WindCnt2=0,b=this.m_ActiveEdges;else{if(0===a.WindDelta&&this.m_ClipType!==d.ClipType.ctUnion)a.WindCnt= +1;else if(this.IsEvenOddFillType(a))if(0===a.WindDelta){for(var c=!0,e=b.PrevInAEL;null!==e;)e.PolyTyp===b.PolyTyp&&0!==e.WindDelta&&(c=!c),e=e.PrevInAEL;a.WindCnt=c?0:1}else a.WindCnt=a.WindDelta;else a.WindCnt=0>b.WindCnt*b.WindDelta?1b.WindDelta*a.WindDelta?b.WindCnt:b.WindCnt+a.WindDelta:0===a.WindDelta?1:a.WindDelta:0===a.WindDelta?0>b.WindCnt?b.WindCnt-1:b.WindCnt+1:0>b.WindDelta*a.WindDelta?b.WindCnt:b.WindCnt+a.WindDelta;a.WindCnt2=b.WindCnt2;b=b.NextInAEL}if(this.IsEvenOddAltFillType(a))for(;b!== +a;)0!==b.WindDelta&&(a.WindCnt2=0===a.WindCnt2?1:0),b=b.NextInAEL;else for(;b!==a;)a.WindCnt2+=b.WindDelta,b=b.NextInAEL};d.Clipper.prototype.AddEdgeToSEL=function(a){null===this.m_SortedEdges?(this.m_SortedEdges=a,a.PrevInSEL=null,a.NextInSEL=null):(a.NextInSEL=this.m_SortedEdges,a.PrevInSEL=null,this.m_SortedEdges=this.m_SortedEdges.PrevInSEL=a)};d.Clipper.prototype.PopEdgeFromSEL=function(a){a.v=this.m_SortedEdges;if(null===a.v)return!1;var b=a.v;this.m_SortedEdges=a.v.NextInSEL;null!==this.m_SortedEdges&& +(this.m_SortedEdges.PrevInSEL=null);b.NextInSEL=null;b.PrevInSEL=null;return!0};d.Clipper.prototype.CopyAELToSEL=function(){var a=this.m_ActiveEdges;for(this.m_SortedEdges=a;null!==a;)a.PrevInSEL=a.PrevInAEL,a=a.NextInSEL=a.NextInAEL};d.Clipper.prototype.SwapPositionsInSEL=function(a,b){if(null!==a.NextInSEL||null!==a.PrevInSEL)if(null!==b.NextInSEL||null!==b.PrevInSEL){if(a.NextInSEL===b){var c=b.NextInSEL;null!==c&&(c.PrevInSEL=a);var e=a.PrevInSEL;null!==e&&(e.NextInSEL=b);b.PrevInSEL=e;b.NextInSEL= +a;a.PrevInSEL=b;a.NextInSEL=c}else b.NextInSEL===a?(c=a.NextInSEL,null!==c&&(c.PrevInSEL=b),e=b.PrevInSEL,null!==e&&(e.NextInSEL=a),a.PrevInSEL=e,a.NextInSEL=b,b.PrevInSEL=a,b.NextInSEL=c):(c=a.NextInSEL,e=a.PrevInSEL,a.NextInSEL=b.NextInSEL,null!==a.NextInSEL&&(a.NextInSEL.PrevInSEL=a),a.PrevInSEL=b.PrevInSEL,null!==a.PrevInSEL&&(a.PrevInSEL.NextInSEL=a),b.NextInSEL=c,null!==b.NextInSEL&&(b.NextInSEL.PrevInSEL=b),b.PrevInSEL=e,null!==b.PrevInSEL&&(b.PrevInSEL.NextInSEL=b));null===a.PrevInSEL?this.m_SortedEdges= +a:null===b.PrevInSEL&&(this.m_SortedEdges=b)}};d.Clipper.prototype.AddLocalMaxPoly=function(a,b,c){this.AddOutPt(a,c);0===b.WindDelta&&this.AddOutPt(b,c);a.OutIdx===b.OutIdx?(a.OutIdx=-1,b.OutIdx=-1):a.OutIdxb.Dx){var e=this.AddOutPt(a,c);b.OutIdx=a.OutIdx;a.Side=d.EdgeSide.esLeft;b.Side=d.EdgeSide.esRight;var f=a;a=f.PrevInAEL===b?b.PrevInAEL:f.PrevInAEL}else e= +this.AddOutPt(b,c),a.OutIdx=b.OutIdx,a.Side=d.EdgeSide.esRight,b.Side=d.EdgeSide.esLeft,f=b,a=f.PrevInAEL===a?a.PrevInAEL:f.PrevInAEL;if(null!==a&&0<=a.OutIdx&&a.Top.Ya.OutIdx){var c= +this.CreateOutRec();c.IsOpen=0===a.WindDelta;var e=new d.OutPt;c.Pts=e;e.Idx=c.Idx;e.Pt.X=b.X;e.Pt.Y=b.Y;d.use_xyz&&(e.Pt.Z=b.Z);e.Next=e;e.Prev=e;c.IsOpen||this.SetHoleState(a,c);a.OutIdx=c.Idx}else{c=this.m_PolyOuts[a.OutIdx];var f=c.Pts,g=a.Side===d.EdgeSide.esLeft;if(g&&d.IntPoint.op_Equality(b,f.Pt))return f;if(!g&&d.IntPoint.op_Equality(b,f.Prev.Pt))return f.Prev;e=new d.OutPt;e.Idx=c.Idx;e.Pt.X=b.X;e.Pt.Y=b.Y;d.use_xyz&&(e.Pt.Z=b.Z);e.Next=f;e.Prev=f.Prev;e.Prev.Next=e;f.Prev=e;g&&(c.Pts=e)}return e}; +d.Clipper.prototype.GetLastOutPt=function(a){var b=this.m_PolyOuts[a.OutIdx];return a.Side===d.EdgeSide.esLeft?b.Pts:b.Pts.Prev};d.Clipper.prototype.SwapPoints=function(a,b){var c=new d.IntPoint1(a.Value);a.Value.X=b.Value.X;a.Value.Y=b.Value.Y;d.use_xyz&&(a.Value.Z=b.Value.Z);b.Value.X=c.X;b.Value.Y=c.Y;d.use_xyz&&(b.Value.Z=c.Z)};d.Clipper.prototype.HorzSegmentsOverlap=function(a,b,c,e){if(a>b){var d=a;a=b;b=d}c>e&&(d=c,c=e,e=d);return a=g&&e>=c||f>=g&&f>=c};d.Clipper.prototype.GetBottomPt=function(a){for(var b=null,c=a.Next;c!==a;)c.Pt.Y>a.Pt.Y?(a=c,b=null):c.Pt.Y===a.Pt.Y&&c.Pt.X<=a.Pt.X&& +(c.Pt.Xe.Pt.Y?a:c.Pt.Ye.Pt.X?b:c.Next===c?b:e.Next===e?a:this.FirstIsBottomPt(c, +e)?a:b};d.Clipper.prototype.OutRec1RightOfOutRec2=function(a,b){do if(a=a.FirstLeft,a===b)return!0;while(null!==a);return!1};d.Clipper.prototype.GetOutRec=function(a){for(a=this.m_PolyOuts[a];a!==this.m_PolyOuts[a.Idx];)a=this.m_PolyOuts[a.Idx];return a};d.Clipper.prototype.AppendPolygon=function(a,b){var c=this.m_PolyOuts[a.OutIdx],e=this.m_PolyOuts[b.OutIdx];var f=this.OutRec1RightOfOutRec2(c,e)?e:this.OutRec1RightOfOutRec2(e,c)?c:this.GetLowermostRec(c,e);var g=c.Pts,h=g.Prev,m=e.Pts,k=m.Prev; +a.Side===d.EdgeSide.esLeft?b.Side===d.EdgeSide.esLeft?(this.ReversePolyPtLinks(m),m.Next=g,g.Prev=m,h.Next=k,k.Prev=h,c.Pts=k):(k.Next=g,g.Prev=k,m.Prev=h,h.Next=m,c.Pts=m):b.Side===d.EdgeSide.esRight?(this.ReversePolyPtLinks(m),h.Next=k,k.Prev=h,m.Next=g,g.Prev=m):(h.Next=m,m.Prev=h,g.Prev=k,k.Next=g);c.BottomPt=null;f===e&&(e.FirstLeft!==c&&(c.FirstLeft=e.FirstLeft),c.IsHole=e.IsHole);e.Pts=null;e.BottomPt=null;e.FirstLeft=c;f=a.OutIdx;g=b.OutIdx;a.OutIdx=-1;b.OutIdx=-1;for(h=this.m_ActiveEdges;null!== +h;){if(h.OutIdx===g){h.OutIdx=f;h.Side=a.Side;break}h=h.NextInAEL}e.Idx=c.Idx};d.Clipper.prototype.ReversePolyPtLinks=function(a){if(null!==a){var b=a;do{var c=b.Next;b.Next=b.Prev;b=b.Prev=c}while(b!==a)}};d.Clipper.SwapSides=function(a,b){var c=a.Side;a.Side=b.Side;b.Side=c};d.Clipper.SwapPolyIndexes=function(a,b){var c=a.OutIdx;a.OutIdx=b.OutIdx;b.OutIdx=c};d.Clipper.prototype.IntersectEdges=function(a,b,c){var e=0<=a.OutIdx,f=0<=b.OutIdx;d.use_xyz&&this.SetZ(c,a,b);if(!d.use_lines||0!==a.WindDelta&& +0!==b.WindDelta){if(a.PolyTyp===b.PolyTyp)if(this.IsEvenOddFillType(a)){var g=a.WindCnt;a.WindCnt=b.WindCnt;b.WindCnt=g}else a.WindCnt=0===a.WindCnt+b.WindDelta?-a.WindCnt:a.WindCnt+b.WindDelta,b.WindCnt=0===b.WindCnt-a.WindDelta?-b.WindCnt:b.WindCnt-a.WindDelta;else this.IsEvenOddFillType(b)?a.WindCnt2=0===a.WindCnt2?1:0:a.WindCnt2+=b.WindDelta,this.IsEvenOddFillType(a)?b.WindCnt2=0===b.WindCnt2?1:0:b.WindCnt2-=a.WindDelta;if(a.PolyTyp===d.PolyType.ptSubject){var h=this.m_SubjFillType;var k=this.m_ClipFillType}else h= +this.m_ClipFillType,k=this.m_SubjFillType;if(b.PolyTyp===d.PolyType.ptSubject){var l=this.m_SubjFillType;g=this.m_ClipFillType}else l=this.m_ClipFillType,g=this.m_SubjFillType;switch(h){case d.PolyFillType.pftPositive:h=a.WindCnt;break;case d.PolyFillType.pftNegative:h=-a.WindCnt;break;default:h=Math.abs(a.WindCnt)}switch(l){case d.PolyFillType.pftPositive:l=b.WindCnt;break;case d.PolyFillType.pftNegative:l=-b.WindCnt;break;default:l=Math.abs(b.WindCnt)}if(e&&f)0!==h&&1!==h||0!==l&&1!==l||a.PolyTyp!== +b.PolyTyp&&this.m_ClipType!==d.ClipType.ctXor?this.AddLocalMaxPoly(a,b,c):(this.AddOutPt(a,c),this.AddOutPt(b,c),d.Clipper.SwapSides(a,b),d.Clipper.SwapPolyIndexes(a,b));else if(e){if(0===l||1===l)this.AddOutPt(a,c),d.Clipper.SwapSides(a,b),d.Clipper.SwapPolyIndexes(a,b)}else if(f){if(0===h||1===h)this.AddOutPt(b,c),d.Clipper.SwapSides(a,b),d.Clipper.SwapPolyIndexes(a,b)}else if(!(0!==h&&1!==h||0!==l&&1!==l)){switch(k){case d.PolyFillType.pftPositive:e=a.WindCnt2;break;case d.PolyFillType.pftNegative:e= +-a.WindCnt2;break;default:e=Math.abs(a.WindCnt2)}switch(g){case d.PolyFillType.pftPositive:f=b.WindCnt2;break;case d.PolyFillType.pftNegative:f=-b.WindCnt2;break;default:f=Math.abs(b.WindCnt2)}if(a.PolyTyp!==b.PolyTyp)this.AddLocalMinPoly(a,b,c);else if(1===h&&1===l)switch(this.m_ClipType){case d.ClipType.ctIntersection:0=e&&0>=f&&this.AddLocalMinPoly(a,b,c);break;case d.ClipType.ctDifference:(a.PolyTyp===d.PolyType.ptClip&&0=e&&0>=f)&&this.AddLocalMinPoly(a,b,c);break;case d.ClipType.ctXor:this.AddLocalMinPoly(a,b,c)}else d.Clipper.SwapSides(a,b)}}else if(0!==a.WindDelta||0!==b.WindDelta)a.PolyTyp===b.PolyTyp&&a.WindDelta!==b.WindDelta&&this.m_ClipType===d.ClipType.ctUnion?0===a.WindDelta?f&&(this.AddOutPt(a,c),e&&(a.OutIdx=-1)):e&&(this.AddOutPt(b,c),f&&(b.OutIdx=-1)):a.PolyTyp!==b.PolyTyp&&(0!==a.WindDelta||1!==Math.abs(b.WindCnt)||this.m_ClipType===d.ClipType.ctUnion&&0!== +b.WindCnt2?0!==b.WindDelta||1!==Math.abs(a.WindCnt)||this.m_ClipType===d.ClipType.ctUnion&&0!==a.WindCnt2||(this.AddOutPt(b,c),f&&(b.OutIdx=-1)):(this.AddOutPt(a,c),e&&(a.OutIdx=-1)))};d.Clipper.prototype.DeleteFromSEL=function(a){var b=a.PrevInSEL,c=a.NextInSEL;if(null!==b||null!==c||a===this.m_SortedEdges)null!==b?b.NextInSEL=c:this.m_SortedEdges=c,null!==c&&(c.PrevInSEL=b),a.NextInSEL=null,a.PrevInSEL=null};d.Clipper.prototype.ProcessHorizontals=function(){for(var a={};this.PopEdgeFromSEL(a);)this.ProcessHorizontal(a.v)}; +d.Clipper.prototype.GetHorzDirection=function(a,b){a.Bot.X=h.Top.X&&(l=null)}else{for(;null!==l.Next&&l.Next.Xp.Curr.X;)0<=a.OutIdx&&!g&&this.AddOutPt(a,new d.IntPoint2(l.X, +a.Bot.Y)),l=l.Prev;if(e===d.Direction.dLeftToRight&&p.Curr.X>c||e===d.Direction.dRightToLeft&&p.Curr.Xe.Top.Y&& +d.ClipperBase.SlopesEqual3(a,e,this.m_UseFullRange)?(t=this.AddOutPt(e,a.Bot),this.AddJoin(n,t,a.Top)):null!==t&&t.Curr.X===a.Bot.X&&t.Curr.Y===a.Bot.Y&&0!==t.WindDelta&&0<=t.OutIdx&&t.Curr.Y>t.Top.Y&&d.ClipperBase.SlopesEqual3(a,t,this.m_UseFullRange)&&(t=this.AddOutPt(t,a.Bot),this.AddJoin(n,t,a.Top)))):this.UpdateEdgeIntoAEL(a):(0<=a.OutIdx&&this.AddOutPt(a,a.Top),this.DeleteFromAEL(a))};d.Clipper.prototype.GetNextInAEL=function(a,b){return b===d.Direction.dLeftToRight?a.NextInAEL:a.PrevInAEL}; +d.Clipper.prototype.IsMinima=function(a){return null!==a&&a.Prev.NextInLML!==a&&a.Next.NextInLML!==a};d.Clipper.prototype.IsMaxima=function(a,b){return null!==a&&a.Top.Y===b&&null===a.NextInLML};d.Clipper.prototype.IsIntermediate=function(a,b){return a.Top.Y===b&&null!==a.NextInLML};d.Clipper.prototype.GetMaximaPair=function(a){return d.IntPoint.op_Equality(a.Next.Top,a.Top)&&null===a.Next.NextInLML?a.Next:d.IntPoint.op_Equality(a.Prev.Top,a.Top)&&null===a.Prev.NextInLML?a.Prev:null};d.Clipper.prototype.GetMaximaPairEx= +function(a){a=this.GetMaximaPair(a);return null===a||a.OutIdx===d.ClipperBase.Skip||a.NextInAEL===a.PrevInAEL&&!d.ClipperBase.IsHorizontal(a)?null:a};d.Clipper.prototype.ProcessIntersections=function(a){if(null===this.m_ActiveEdges)return!0;try{this.BuildIntersectList(a);if(0===this.m_IntersectList.length)return!0;if(1===this.m_IntersectList.length||this.FixupIntersectionOrder())this.ProcessIntersectList();else return!1}catch(b){this.m_SortedEdges=null,this.m_IntersectList.length=0,d.Error("ProcessIntersections error")}this.m_SortedEdges= +null;return!0};d.Clipper.prototype.BuildIntersectList=function(a){if(null!==this.m_ActiveEdges){var b=this.m_ActiveEdges;for(this.m_SortedEdges=b;null!==b;)b.PrevInSEL=b.PrevInAEL,b.NextInSEL=b.NextInAEL,b.Curr.X=d.Clipper.TopX(b,a),b=b.NextInAEL;for(var c=!0;c&&null!==this.m_SortedEdges;){c=!1;for(b=this.m_SortedEdges;null!==b.NextInSEL;){var e=b.NextInSEL,f=new d.IntPoint0;b.Curr.X>e.Curr.X?(this.IntersectPoint(b,e,f),f.Ya?Math.ceil(a-.5):Math.round(a)};J=function(a){return 0>a?Math.ceil(a-.5):Math.floor(a+.5)};K=function(a){return 0>a?-Math.round(Math.abs(a)):Math.round(a)};L=function(a){if(0>a)return a-=.5,-2147483648>a?Math.ceil(a):a|0;a+=.5;return 2147483647b.Top.Y)return c.Y=a.Top.Y,c.X=d.Clipper.TopX(b,a.Top.Y),c.Xa.Curr.Y&&(c.Y=a.Curr.Y,c.X=Math.abs(a.Dx)>Math.abs(b.Dx)?d.Clipper.TopX(b,c.Y):d.Clipper.TopX(a,c.Y))}};d.Clipper.prototype.ProcessEdgesAtTopOfScanbeam=function(a){for(var b,c,e=this.m_ActiveEdges;null!==e;){if(c= +this.IsMaxima(e,a))c=this.GetMaximaPairEx(e),c=null===c||!d.ClipperBase.IsHorizontal(c);if(c)this.StrictlySimple&&this.InsertMaxima(e.Top.X),b=e.PrevInAEL,this.DoMaxima(e),e=null===b?this.m_ActiveEdges:b.NextInAEL;else{this.IsIntermediate(e,a)&&d.ClipperBase.IsHorizontal(e.NextInLML)?(e=this.UpdateEdgeIntoAEL(e),0<=e.OutIdx&&this.AddOutPt(e,e.Bot),this.AddEdgeToSEL(e)):(e.Curr.X=d.Clipper.TopX(e,a),e.Curr.Y=a);d.use_xyz&&(e.Curr.Z=e.Top.Y===a?e.Top.Z:e.Bot.Y===a?e.Bot.Z:0);if(this.StrictlySimple&& +(b=e.PrevInAEL,0<=e.OutIdx&&0!==e.WindDelta&&null!==b&&0<=b.OutIdx&&b.Curr.X===e.Curr.X&&0!==b.WindDelta)){var f=new d.IntPoint1(e.Curr);d.use_xyz&&this.SetZ(f,b,e);c=this.AddOutPt(b,f);b=this.AddOutPt(e,f);this.AddJoin(c,b,f)}e=e.NextInAEL}}this.ProcessHorizontals();this.m_Maxima=null;for(e=this.m_ActiveEdges;null!==e;)this.IsIntermediate(e,a)&&(c=null,0<=e.OutIdx&&(c=this.AddOutPt(e,e.Top)),e=this.UpdateEdgeIntoAEL(e),b=e.PrevInAEL,f=e.NextInAEL,null!==b&&b.Curr.X===e.Bot.X&&b.Curr.Y===e.Bot.Y&& +null!==c&&0<=b.OutIdx&&b.Curr.Y===b.Top.Y&&d.ClipperBase.SlopesEqual5(e.Curr,e.Top,b.Curr,b.Top,this.m_UseFullRange)&&0!==e.WindDelta&&0!==b.WindDelta?(b=this.AddOutPt(ePrev2,e.Bot),this.AddJoin(c,b,e.Top)):null!==f&&f.Curr.X===e.Bot.X&&f.Curr.Y===e.Bot.Y&&null!==c&&0<=f.OutIdx&&f.Curr.Y===f.Top.Y&&d.ClipperBase.SlopesEqual5(e.Curr,e.Top,f.Curr,f.Top,this.m_UseFullRange)&&0!==e.WindDelta&&0!==f.WindDelta&&(b=this.AddOutPt(f,e.Bot),this.AddJoin(c,b,e.Top))),e=e.NextInAEL};d.Clipper.prototype.DoMaxima= +function(a){var b=this.GetMaximaPairEx(a);if(null===b)0<=a.OutIdx&&this.AddOutPt(a,a.Top),this.DeleteFromAEL(a);else{for(var c=a.NextInAEL;null!==c&&c!==b;)this.IntersectEdges(a,c,a.Top),this.SwapPositionsInAEL(a,c),c=a.NextInAEL;-1===a.OutIdx&&-1===b.OutIdx?(this.DeleteFromAEL(a),this.DeleteFromAEL(b)):0<=a.OutIdx&&0<=b.OutIdx?(0<=a.OutIdx&&this.AddLocalMaxPoly(a,b,a.Top),this.DeleteFromAEL(a),this.DeleteFromAEL(b)):d.use_lines&&0===a.WindDelta?(0<=a.OutIdx&&(this.AddOutPt(a,a.Top),a.OutIdx=d.ClipperBase.Unassigned), +this.DeleteFromAEL(a),0<=b.OutIdx&&(this.AddOutPt(b,a.Top),b.OutIdx=d.ClipperBase.Unassigned),this.DeleteFromAEL(b)):d.Error("DoMaxima error")}};d.Clipper.ReversePaths=function(a){for(var b=0,c=a.length;bf)){for(var g=Array(f),h=0;hf||!e.IsOpen&&3>f)){this.FixHoleLinkage(e);var g=new d.PolyNode;a.m_AllPolys.push(g);e.PolyNode=g;g.m_polygon.length=f;e=e.Pts.Prev;for(var h=0;hb.Pt.X?d.Direction.dRightToLeft:d.Direction.dLeftToRight;e=c.Pt.X>e.Pt.X?d.Direction.dRightToLeft:d.Direction.dLeftToRight;if(h===e)return!1;if(h===d.Direction.dLeftToRight){for(;a.Next.Pt.X<=f.X&&a.Next.Pt.X>=a.Pt.X&&a.Next.Pt.Y===f.Y;)a=a.Next;g&&a.Pt.X!==f.X&&(a=a.Next);b=this.DupOutPt(a,!g);d.IntPoint.op_Inequality(b.Pt,f)&&(a=b,a.Pt.X=f.X,a.Pt.Y=f.Y,d.use_xyz&&(a.Pt.Z=f.Z),b=this.DupOutPt(a,!g))}else{for(;a.Next.Pt.X>=f.X&&a.Next.Pt.X<=a.Pt.X&&a.Next.Pt.Y=== +f.Y;)a=a.Next;g||a.Pt.X===f.X||(a=a.Next);b=this.DupOutPt(a,g);d.IntPoint.op_Inequality(b.Pt,f)&&(a=b,a.Pt.X=f.X,a.Pt.Y=f.Y,d.use_xyz&&(a.Pt.Z=f.Z),b=this.DupOutPt(a,g))}if(e===d.Direction.dLeftToRight){for(;c.Next.Pt.X<=f.X&&c.Next.Pt.X>=c.Pt.X&&c.Next.Pt.Y===f.Y;)c=c.Next;g&&c.Pt.X!==f.X&&(c=c.Next);e=this.DupOutPt(c,!g);d.IntPoint.op_Inequality(e.Pt,f)&&(c=e,c.Pt.X=f.X,c.Pt.Y=f.Y,d.use_xyz&&(c.Pt.Z=f.Z),e=this.DupOutPt(c,!g))}else{for(;c.Next.Pt.X>=f.X&&c.Next.Pt.X<=c.Pt.X&&c.Next.Pt.Y===f.Y;)c= +c.Next;g||c.Pt.X===f.X||(c=c.Next);e=this.DupOutPt(c,g);d.IntPoint.op_Inequality(e.Pt,f)&&(c=e,c.Pt.X=f.X,c.Pt.Y=f.Y,d.use_xyz&&(c.Pt.Z=f.Z),e=this.DupOutPt(c,g))}h===d.Direction.dLeftToRight===g?(a.Prev=c,c.Next=a,b.Next=e,e.Prev=b):(a.Next=c,c.Prev=a,b.Prev=e,e.Next=b);return!0};d.Clipper.prototype.JoinPoints=function(a,b,c){var e=a.OutPt1,f;new d.OutPt;var g=a.OutPt2,h;new d.OutPt;if((h=a.OutPt1.Pt.Y===a.OffPt.Y)&&d.IntPoint.op_Equality(a.OffPt,a.OutPt1.Pt)&&d.IntPoint.op_Equality(a.OffPt,a.OutPt2.Pt)){if(b!== +c)return!1;for(f=a.OutPt1.Next;f!==e&&d.IntPoint.op_Equality(f.Pt,a.OffPt);)f=f.Next;f=f.Pt.Y>a.OffPt.Y;for(h=a.OutPt2.Next;h!==g&&d.IntPoint.op_Equality(h.Pt,a.OffPt);)h=h.Next;if(f===h.Pt.Y>a.OffPt.Y)return!1;f?(f=this.DupOutPt(e,!1),h=this.DupOutPt(g,!0),e.Prev=g,g.Next=e,f.Next=h,h.Prev=f):(f=this.DupOutPt(e,!0),h=this.DupOutPt(g,!1),e.Next=g,g.Prev=e,f.Prev=h,h.Next=f);a.OutPt1=e;a.OutPt2=f;return!0}if(h){for(f=e;e.Prev.Pt.Y===e.Pt.Y&&e.Prev!==f&&e.Prev!==g;)e=e.Prev;for(;f.Next.Pt.Y===f.Pt.Y&& +f.Next!==e&&f.Next!==g;)f=f.Next;if(f.Next===e||f.Next===g)return!1;for(h=g;g.Prev.Pt.Y===g.Pt.Y&&g.Prev!==h&&g.Prev!==f;)g=g.Prev;for(;h.Next.Pt.Y===h.Pt.Y&&h.Next!==g&&h.Next!==e;)h=h.Next;if(h.Next===g||h.Next===e)return!1;c={Left:null,Right:null};if(!this.GetOverlap(e.Pt.X,f.Pt.X,g.Pt.X,h.Pt.X,c))return!1;b=c.Left;var k=c.Right;c=new d.IntPoint0;e.Pt.X>=b&&e.Pt.X<=k?(c.X=e.Pt.X,c.Y=e.Pt.Y,d.use_xyz&&(c.Z=e.Pt.Z),b=e.Pt.X>f.Pt.X):g.Pt.X>=b&&g.Pt.X<=k?(c.X=g.Pt.X,c.Y=g.Pt.Y,d.use_xyz&&(c.Z=g.Pt.Z), +b=g.Pt.X>h.Pt.X):f.Pt.X>=b&&f.Pt.X<=k?(c.X=f.Pt.X,c.Y=f.Pt.Y,d.use_xyz&&(c.Z=f.Pt.Z),b=f.Pt.X>e.Pt.X):(c.X=h.Pt.X,c.Y=h.Pt.Y,d.use_xyz&&(c.Z=h.Pt.Z),b=h.Pt.X>g.Pt.X);a.OutPt1=e;a.OutPt2=g;return this.JoinHorz(e,f,g,h,c,b)}for(f=e.Next;d.IntPoint.op_Equality(f.Pt,e.Pt)&&f!==e;)f=f.Next;if(k=f.Pt.Y>e.Pt.Y||!d.ClipperBase.SlopesEqual4(e.Pt,f.Pt,a.OffPt,this.m_UseFullRange)){for(f=e.Prev;d.IntPoint.op_Equality(f.Pt,e.Pt)&&f!==e;)f=f.Prev;if(f.Pt.Y>e.Pt.Y||!d.ClipperBase.SlopesEqual4(e.Pt,f.Pt,a.OffPt, +this.m_UseFullRange))return!1}for(h=g.Next;d.IntPoint.op_Equality(h.Pt,g.Pt)&&h!==g;)h=h.Next;var l=h.Pt.Y>g.Pt.Y||!d.ClipperBase.SlopesEqual4(g.Pt,h.Pt,a.OffPt,this.m_UseFullRange);if(l){for(h=g.Prev;d.IntPoint.op_Equality(h.Pt,g.Pt)&&h!==g;)h=h.Prev;if(h.Pt.Y>g.Pt.Y||!d.ClipperBase.SlopesEqual4(g.Pt,h.Pt,a.OffPt,this.m_UseFullRange))return!1}if(f===e||h===g||f===h||b===c&&k===l)return!1;k?(f=this.DupOutPt(e,!1),h=this.DupOutPt(g,!0),e.Prev=g,g.Next=e,f.Next=h,h.Prev=f):(f=this.DupOutPt(e,!0),h= +this.DupOutPt(g,!1),e.Next=g,g.Prev=e,f.Prev=h,h.Next=f);a.OutPt1=e;a.OutPt2=f;return!0};d.Clipper.GetBounds=function(a){for(var b=0,c=a.length;be.right&&(e.right=a[b][f].X),a[b][f].Ye.bottom&&(e.bottom=a[b][f].Y);return e};d.Clipper.prototype.GetBounds2= +function(a){var b=a,c=new d.IntRect;c.left=a.Pt.X;c.right=a.Pt.X;c.top=a.Pt.Y;c.bottom=a.Pt.Y;for(a=a.Next;a!==b;)a.Pt.Xc.right&&(c.right=a.Pt.X),a.Pt.Yc.bottom&&(c.bottom=a.Pt.Y),a=a.Next;return c};d.Clipper.PointInPolygon=function(a,b){var c=0,e=b.length;if(3>e)return 0;for(var d=b[0],g=1;g<=e;++g){var h=g===e?b[0]:b[g];if(h.Y===a.Y&&(h.X===a.X||d.Y===a.Y&&h.X>a.X===d.X=a.X)if(h.X>a.X)c=1-c; +else{var k=(d.X-a.X)*(h.Y-a.Y)-(h.X-a.X)*(d.Y-a.Y);if(0===k)return-1;0d.Y&&(c=1-c)}else if(h.X>a.X){k=(d.X-a.X)*(h.Y-a.Y)-(h.X-a.X)*(d.Y-a.Y);if(0===k)return-1;0d.Y&&(c=1-c)}d=h}return c};d.Clipper.prototype.PointInPolygon=function(a,b){var c=0,d=b,f=a.X,g=a.Y;var h=b.Pt.X;var k=b.Pt.Y;do{b=b.Next;var l=b.Pt.X,n=b.Pt.Y;if(n===g&&(l===f||k===g&&l>f===h=f)if(l>f)c=1-c;else{h=(h-f)*(n-g)-(l-f)*(k-g);if(0===h)return-1;0k&&(c=1-c)}else if(l>f){h= +(h-f)*(n-g)-(l-f)*(k-g);if(0===h)return-1;0k&&(c=1-c)}h=l;k=n}while(d!==b);return c};d.Clipper.prototype.Poly2ContainsPoly1=function(a,b){var c=a;do{var d=this.PointInPolygon(c.Pt,b);if(0<=d)return 0b)return 0;for(var c=0,d=0,f=b-1;dMath.abs(a.Y-b.Y)?a.X>b.X===a.Xa.X===b.Xb.Y===a.Ya.Y===b.Yc&&(c=0);var g=Array(c);for(f=0;fe)){var f=new d.PolyNode;f.m_jointype=b;f.m_endtype=c;if(c===d.EndType.etClosedLine||c===d.EndType.etClosedPolygon)for(;0f.m_polygon[b].Y||a[h].Y===f.m_polygon[b].Y&&a[h].Xg)&&(this.m_polyNodes.AddChild(f),c===d.EndType.etClosedPolygon))if(0>this.m_lowest.X)this.m_lowest=new d.IntPoint2(this.m_polyNodes.ChildCount()-1,b);else if(a=this.m_polyNodes.Childs()[this.m_lowest.X].m_polygon[this.m_lowest.Y],f.m_polygon[b].Y> +a.Y||f.m_polygon[b].Y===a.Y&&f.m_polygon[b].X=this.ArcTolerance?d.ClipperOffset.def_arc_tolerance:this.ArcTolerance>Math.abs(a)*d.ClipperOffset.def_arc_tolerance?Math.abs(a)*d.ClipperOffset.def_arc_tolerance: +this.ArcTolerance)/Math.abs(a));this.m_sin=Math.sin(d.ClipperOffset.two_pi/f);this.m_cos=Math.cos(d.ClipperOffset.two_pi/f);this.m_StepsPerRad=f/d.ClipperOffset.two_pi;0>a&&(this.m_sin=-this.m_sin);for(c=0;c=a&&(3>g||e.m_endtype!==d.EndType.etClosedPolygon))){this.m_destPoly=[];if(1===g)if(e.m_jointype===d.JoinType.jtRound)for(g=1,e=0,b=1;b<=f;b++){this.m_destPoly.push(new d.IntPoint2(d.ClipperOffset.Round(this.m_srcPoly[0].X+ +g*a),d.ClipperOffset.Round(this.m_srcPoly[0].Y+e*a)));var h=g;g=g*this.m_cos-this.m_sin*e;e=h*this.m_sin+e*this.m_cos}else for(e=g=-1,b=0;4>b;++b)this.m_destPoly.push(new d.IntPoint2(d.ClipperOffset.Round(this.m_srcPoly[0].X+g*a),d.ClipperOffset.Round(this.m_srcPoly[0].Y+e*a))),0>g?g=1:0>e?e=1:g=-1;else{for(b=this.m_normals.length=0;bMath.abs(this.m_sinA*this.m_delta)){if(0this.m_sinA&&(this.m_sinA=-1);if(0> +this.m_sinA*this.m_delta)this.m_destPoly.push(new d.IntPoint2(d.ClipperOffset.Round(this.m_srcPoly[a].X+this.m_normals[b].X*this.m_delta),d.ClipperOffset.Round(this.m_srcPoly[a].Y+this.m_normals[b].Y*this.m_delta))),this.m_destPoly.push(new d.IntPoint1(this.m_srcPoly[a])),this.m_destPoly.push(new d.IntPoint2(d.ClipperOffset.Round(this.m_srcPoly[a].X+this.m_normals[a].X*this.m_delta),d.ClipperOffset.Round(this.m_srcPoly[a].Y+this.m_normals[a].Y*this.m_delta)));else switch(c){case d.JoinType.jtMiter:c= +1+(this.m_normals[a].X*this.m_normals[b].X+this.m_normals[a].Y*this.m_normals[b].Y);c>=this.m_miterLim?this.DoMiter(a,b,c):this.DoSquare(a,b);break;case d.JoinType.jtSquare:this.DoSquare(a,b);break;case d.JoinType.jtRound:this.DoRound(a,b)}return a};d.ClipperOffset.prototype.DoSquare=function(a,b){var c=Math.tan(Math.atan2(this.m_sinA,this.m_normals[b].X*this.m_normals[a].X+this.m_normals[b].Y*this.m_normals[a].Y)/4);this.m_destPoly.push(new d.IntPoint2(d.ClipperOffset.Round(this.m_srcPoly[a].X+this.m_delta* +(this.m_normals[b].X-this.m_normals[b].Y*c)),d.ClipperOffset.Round(this.m_srcPoly[a].Y+this.m_delta*(this.m_normals[b].Y+this.m_normals[b].X*c))));this.m_destPoly.push(new d.IntPoint2(d.ClipperOffset.Round(this.m_srcPoly[a].X+this.m_delta*(this.m_normals[a].X+this.m_normals[a].Y*c)),d.ClipperOffset.Round(this.m_srcPoly[a].Y+this.m_delta*(this.m_normals[a].Y-this.m_normals[a].X*c))))};d.ClipperOffset.prototype.DoMiter=function(a,b,c){c=this.m_delta/c;this.m_destPoly.push(new d.IntPoint2(d.ClipperOffset.Round(this.m_srcPoly[a].X+ +(this.m_normals[b].X+this.m_normals[a].X)*c),d.ClipperOffset.Round(this.m_srcPoly[a].Y+(this.m_normals[b].Y+this.m_normals[a].Y)*c)))};d.ClipperOffset.prototype.DoRound=function(a,b){for(var c=Math.max(d.Cast_Int32(d.ClipperOffset.Round(this.m_StepsPerRad*Math.abs(Math.atan2(this.m_sinA,this.m_normals[b].X*this.m_normals[a].X+this.m_normals[b].Y*this.m_normals[a].Y)))),1),e=this.m_normals[b].X,f=this.m_normals[b].Y,g,h=0;hb)return a;c||(a=[a]);for(var e=a.length,f,g,h,k,l,n,r,p=[],t=0;tf)h=g,p.push(h);else{h=g;k=b*b;l=g[0];for(r=n=1;rb)return d.JS.Clone(a);var c=a[0]instanceof Array;c||(a= +[a]);var e,f,g,h=a.length,k=b*b,l=[];for(e=0;eg;g++){var p=[];r=n.length;if(n[r-1].X!==n[0].X||n[r-1].Y!==n[0].Y){var t=1;n.push({X:n[0].X,Y:n[0].Y});r=n.length}else t=0;var u=[];for(f=0;fg)return 0;b&&(a[g]=a[0],g++);for(;--g;){var h=a[g];var k=h.X;h=h.Y;var l=a[g-1];var n=l.X;l=l.Y;f+=d((k-n)*(k-n)+(h-l)*(h-l))}b&&a.pop();return f/ +c};d.JS.PerimeterOfPaths=function(a,b,c){c||(c=1);for(var e=0,f=0;f { + return seg.map((point) => { + return {X: point[0] + annotationDx - annotation.bbox[0], Y: point[1] + annotationDy - annotation.bbox[1]} + }) + }); + // apparently, we need a deep copy if we pass it to findDifferencePaths/Clipper + const subj_paths2 = JSON.parse(JSON.stringify(subj_paths)); + const subj_paths3 = JSON.parse(JSON.stringify(subj_paths)); + // const subj_paths4 = JSON.parse(JSON.stringify(subj_paths)); + + const drawn_paths = [points.map((point) => { + return {X: point[0], Y: point[1]} + })]; + const drawn_paths2 = [points.map((point) => { + return {X: point[0], Y: point[1]} + })]; + // const drawn_paths3 = [points.map((point) => { + // return {X: point[0], Y: point[1]} + // })]; + const optimal_bbox_paths = [[ + {X: annotationDx, Y: annotationDy}, + {X: annotationDx + annotation.bbox[2], Y: annotationDy}, + {X: annotationDx + annotation.bbox[2], Y: annotationDy + annotation.bbox[3]}, + {X: annotationDx, Y: annotationDy + annotation.bbox[3]}, + ]]; + + // console.log(subj_paths, drawn_paths, optimal_bbox_paths); + + const scale = 100; + let minimalErrorPaths = this.findDifferencePaths(subj_paths, optimal_bbox_paths, scale); + let drawnErrorPaths = this.findDifferencePaths(drawn_paths, subj_paths2, scale, ClipperLib.ClipType.ctDifference); // only error outside of shape + let drawnSuccessPaths = this.findDifferencePaths(subj_paths3, drawn_paths2, scale, ClipperLib.ClipType.ctIntersection); + // let drawnMissPaths = this.findDifferencePaths(subj_paths4, drawn_paths3, scale, ClipperLib.ClipType.ctDifference); + // let drawnSolutionPaths = this.findIntersectionPaths(subj_paths2, drawn_paths, scale); + + // const drawnArea = ClipperLib.JS.AreaOfPolygons(clip_paths) / (100*100)); + const shapeArea = Math.abs(ClipperLib.JS.AreaOfPolygons(subj_paths) / (100*100)); + // const shapeArea = ClipperLib.JS.AreaOfPolygons(subj_paths) / (100*100)); + // const minimalErrorArea = ClipperLib.JS.AreaOfPolygons(minimalErrorPaths) / (100*100); + const successArea = Math.abs(ClipperLib.JS.AreaOfPolygons(drawnSuccessPaths) / (100*100)); + // const missArea = Math.abs(ClipperLib.JS.AreaOfPolygons(drawnMissPaths) / (100*100)); + const minimalErrorArea = Math.abs(ClipperLib.JS.AreaOfPolygons(minimalErrorPaths) / (100*100)); + const drawnErrorArea = Math.abs(ClipperLib.JS.AreaOfPolygons(drawnErrorPaths) / (100*100)); + // const error = ((drawnErrorArea+1)/(minimalErrorArea+1)); + // TODO different? We expected 20% of selection to be error (use minimalErrorArea/drawnArea), it was 25% of error (drawnErrorArea/drawnArea) + // is dat drawnErrorArea/minimalErrorArea + const simpleScore = (successArea / shapeArea);// TODO: Math.pow() for harder punishment of missed areas? + const errorScore = (drawnErrorArea - minimalErrorArea) / shapeArea; // it can get negative, which is what we want for the odd shapes. + const score = simpleScore - Math.min(1, errorScore) / 2; // cap error at 1, and make things easier for the player, so errors count less (/2) + console.log(successArea, shapeArea, simpleScore, errorScore, score); + + + // Scale down coordinates and draw ... + + if(window.location.search == "?debug") { + let shapeEl2 = document.createElementNS('http://www.w3.org/2000/svg', 'path'); + shapeEl2.classList.add('test'); + this.svgEl.appendChild(shapeEl2); + shapeEl2.setAttribute('d', paths2string(minimalErrorPaths, scale)); + shapeEl2.setAttribute('stroke', 'green'); + shapeEl2.setAttribute('stroke-width', '2'); + shapeEl2.setAttribute('fill', 'red'); + let shapeEl = document.createElementNS('http://www.w3.org/2000/svg', 'path'); + shapeEl.classList.add('test'); + this.svgEl.appendChild(shapeEl); + shapeEl.setAttribute('d', paths2string(drawnErrorPaths, scale)); + shapeEl.setAttribute('stroke', 'yellow'); + shapeEl.setAttribute('stroke-width', '2'); + shapeEl.setAttribute('fill', 'orange'); + let shapeEl3 = document.createElementNS('http://www.w3.org/2000/svg', 'path'); + shapeEl3.classList.add('test'); + this.svgEl.appendChild(shapeEl3); + shapeEl3.setAttribute('d', paths2string(drawnSuccessPaths, scale)); + shapeEl3.setAttribute('stroke-width', '2'); + shapeEl3.setAttribute('fill', 'green'); + } + + // Converts Paths to SVG path string + // and scales down the coordinates + function paths2string (paths, scale) { + var svgpath = "", i, j; + if (!scale) scale = 1; + for(i = 0; i < paths.length; i++) { + for(j = 0; j < paths[i].length; j++){ + if (!j) svgpath += "M"; + else svgpath += "L"; + svgpath += (paths[i][j].X / scale) + ", " + (paths[i][j].Y / scale); + } + svgpath += "Z"; + } + if (svgpath=="") svgpath = "M0,0"; + return svgpath; + } + // var paths = [[{"X":10,"Y":10},{"X":110,"Y":10},{"X":110,"Y":110},{"X":10,"Y":110}]]; + // console.log(JSON.stringify(paths)); + // ClipperLib.Clipper.ReversePaths(paths); + // console.log(JSON.stringify(paths)); + } + + findDifferencePaths(subj_paths, clip_paths, scale, overrideClipType) { + let cpr = new ClipperLib.Clipper(); + + ClipperLib.JS.ScaleUpPaths(subj_paths, scale); + ClipperLib.JS.ScaleUpPaths(clip_paths, scale); + + cpr.AddPaths(subj_paths, ClipperLib.PolyType.ptSubject, true); // true means closed path + cpr.AddPaths(clip_paths, ClipperLib.PolyType.ptClip, true); + + let solution_paths = new ClipperLib.Paths(); + // const clipType = ClipperLib.ClipType.ctIntersection; + // const clipType = ClipperLib.ClipType.ctDifference; // we like to know everything that is wrong. + const clipType = overrideClipType ?? ClipperLib.ClipType.ctXor; // we like to know everything that is wrong. + const subject_fillType = ClipperLib.PolyFillType.pftNonZero; + const clip_fillType = ClipperLib.PolyFillType.pftNonZero; + const succeeded = cpr.Execute(clipType, solution_paths, subject_fillType, clip_fillType); + return solution_paths; + } } \ No newline at end of file diff --git a/www/js/svg.js b/www/js/svg.js index ea637ee..9c5da41 100644 --- a/www/js/svg.js +++ b/www/js/svg.js @@ -1,5 +1,8 @@ -function getPathShapeBetweenPoints(p1, p2, corners) { +function getPathShapeBetweenPoints(p1, p2, corners, onlyPoints) { + onlyPoints = typeof onlyPoints == 'undefined' ? false : !!onlyPoints; + console.log('only points',onlyPoints) + let cornerPoints = [/*[p1.x,p1.y]*/]; if(corners == 4){ // draw inbetween p1 & p2. @@ -51,6 +54,9 @@ function getPathShapeBetweenPoints(p1, p2, corners) { } + if( onlyPoints ){ + return cornerPoints; + } // teken punten tussen alle punten let allCornerPoints = [];