UNPKG

smiles-drawer

Version:

A SMILES drawer and parser. Generate molecular structure depictions in pure JavaScript.

1 lines 107 kB
(function g(d,e,t){function r(i,o){if(!e[i]){if(!d[i]){var s="function"==typeof require&&require;if(!o&&s)return s(i,!0);if(n)return n(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var h=e[i]={exports:{}};d[i][0].call(h.exports,function(t){var e=d[i][1][t];return r(e?e:t)},h,h.exports,g,d,e,t)}return e[i].exports}for(var n="function"==typeof require&&require,i=0;i<t.length;i++)r(t[i]);return r})({1:[function(e,t){"use strict";var n=Math.min,i=Math.max,r=e("./src/Drawer"),a=e("./src/Parser"),o=!!("undefined"!=typeof window&&window.document&&window.document.createElement),l={Version:"1.0.0"};l.Drawer=r,l.Parser=a,l.clean=function(e){return e.replace(/[^A-Za-z0-9@\.\+\-\?!\(\)\[\]\{\}/\\=#\$:\*]/g,"")},l.apply=function(e){for(var t=1<arguments.length&&arguments[1]!==void 0?arguments[1]:"canvas[data-smiles]",n=2<arguments.length&&arguments[2]!==void 0?arguments[2]:"light",a=3<arguments.length&&arguments[3]!==void 0?arguments[3]:null,o=new r(e),s=document.querySelectorAll(t),g=function(){var e=s[d];l.parse(e.getAttribute("data-smiles"),function(t){o.draw(t,e,n,!1)},function(e){a&&a(e)})},d=0;d<s.length;d++)g()},l.parse=function(e,t,n){try{t&&t(a.parse(e))}catch(e){n&&n(e)}},o&&(window.SmilesDrawer=l),Array.prototype.fill||Object.defineProperty(Array.prototype,"fill",{value:function(e){if(null==this)throw new TypeError("this is null or not defined");for(var t=Object(this),r=t.length>>>0,a=arguments[1],o=a>>0,l=0>o?i(r+o,0):n(o,r),s=arguments[2],g=void 0===s?r:s>>0,d=0>g?i(r+g,0):n(g,r);l<d;)t[l]=e,l++;return t}}),t.exports=l},{"./src/Drawer":5,"./src/Parser":10}],2:[function(e,t){"use strict";function n(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}var i="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},r=function(){function e(e,t){for(var n=0,i;n<t.length;n++)i=t[n],i.enumerable=i.enumerable||!1,i.configurable=!0,"value"in i&&(i.writable=!0),Object.defineProperty(e,i.key,i)}return function(t,n,i){return n&&e(t.prototype,n),i&&e(t,i),t}}(),a=function(){function e(){n(this,e)}return r(e,null,[{key:"clone",value:function(t){var n=Array.isArray(t)?[]:{};for(var r in t){var a=t[r];n[r]="function"==typeof a.clone?a.clone():"object"===("undefined"==typeof a?"undefined":i(a))?e.clone(a):a}return n}},{key:"equals",value:function(e,t){if(e.length!==t.length)return!1;for(var n=e.slice().sort(),r=t.slice().sort(),a=0;a<n.length;a++)if(n[a]!==r[a])return!1;return!0}},{key:"print",value:function(e){if(0==e.length)return"";for(var t="(",n=0;n<e.length;n++)t+=e[n].id?e[n].id+", ":e[n]+", ";return t=t.substring(0,t.length-2),t+")"}},{key:"each",value:function(e,t){for(var n=0;n<e.length;n++)t(e[n])}},{key:"get",value:function(e,t,n){for(var r=0;r<e.length;r++)if(e[r][t]==n)return e[r]}},{key:"contains",value:function(e,t){if(!t.property&&!t.func){for(var n=0;n<e.length;n++)if(e[n]==t.value)return!0;}else if(t.func){for(var i=0;i<e.length;i++)if(t.func(e[i]))return!0;}else for(var r=0;r<e.length;r++)if(e[r][t.property]==t.value)return!0;return!1}},{key:"intersection",value:function(e,t){for(var n=[],r=0;r<e.length;r++)for(var i=0;i<t.length;i++)e[r]===t[i]&&n.push(e[r]);return n}},{key:"unique",value:function(e){var t={};return e.filter(function(e){return void 0===t[e]&&(t[e]=!0)})}},{key:"count",value:function(e,t){for(var n=0,r=0;r<e.length;r++)e[r]===t&&n++;return n}},{key:"toggle",value:function(e,t){for(var n=[],r=!1,a=0;a<e.length;a++)e[a]===t?r=!0:n.push(e[a]);return r||n.push(t),n}},{key:"remove",value:function(e,t){for(var n=[],r=0;r<e.length;r++)e[r]!==t&&n.push(e[r]);return n}},{key:"removeUnique",value:function(e,t){var n=e.indexOf(t);return-1<n&&e.splice(n,1),e}},{key:"removeAll",value:function(e,t){return e.filter(function(e){return-1===t.indexOf(e)})}},{key:"merge",value:function(e,t){for(var n=Array(e.length+t.length),r=0;r<e.length;r++)n[r]=e[r];for(var i=0;i<t.length;i++)n[e.length+i]=t[i];return n}},{key:"containsAll",value:function(e,t){for(var n=0,r=0;r<e.length;r++)for(var i=0;i<t.length;i++)e[r]===t[i]&&n++;return n===t.length}},{key:"sortByAtomicNumberDesc",value:function(t){var e=t.map(function(t,e){return{index:e,value:t.atomicNumber.split(".").map(Number)}});return e.sort(function(e,t){for(var n=Math.min(t.value.length,e.value.length),r=0;r<n&&t.value[r]===e.value[r];)r++;return r===n?t.value.length-e.value.length:t.value[r]-e.value[r]}),e.map(function(n){return t[n.index]})}},{key:"deepCopy",value:function(t){for(var n=[],r=0,i;r<t.length;r++)i=t[r],n[r]=i instanceof Array?e.deepCopy(i):i;return n}}]),e}();t.exports=a},{}],3:[function(e,t){"use strict";function n(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}var i=function(){function e(e,t){for(var n=0,i;n<t.length;n++)i=t[n],i.enumerable=i.enumerable||!1,i.configurable=!0,"value"in i&&(i.writable=!0),Object.defineProperty(e,i.key,i)}return function(t,n,i){return n&&e(t.prototype,n),i&&e(t,i),t}}(),r=e("./ArrayHelper"),a=e("./Vertex"),o=e("./Ring"),l=function(){function e(t){var i=1<arguments.length&&void 0!==arguments[1]?arguments[1]:"-";n(this,e),this.element=1===t.length?t.toUpperCase():t,this.drawExplicit=!1,this.ringbonds=[],this.rings=[],this.bondType=i,this.branchBond=null,this.isBridge=!1,this.isBridgeNode=!1,this.originalRings=[],this.bridgedRing=null,this.anchoredRings=[],this.bracket=null,this.plane=0,this.attachedPseudoElements={},this.hasAttachedPseudoElements=!1,this.isDrawn=!0,this.isConnectedToRing=!1,this.neighbouringElements=[],this.isPartOfAromaticRing=t!==this.element,this.bondCount=0,this.chirality="",this.isStereoCenter=!1,this.priority=0,this.mainChain=!1,this.hydrogenDirection="down",this.subtreeDepth=1,this.hasHydrogen=!1}return i(e,[{key:"addNeighbouringElement",value:function(e){this.neighbouringElements.push(e)}},{key:"attachPseudoElement",value:function(e,t){var n=2<arguments.length&&void 0!==arguments[2]?arguments[2]:0,i=3<arguments.length&&void 0!==arguments[3]?arguments[3]:0;null===n&&(n=0),null===i&&(i=0);var r=n+e+i;this.attachedPseudoElements[r]?this.attachedPseudoElements[r].count+=1:this.attachedPseudoElements[r]={element:e,count:1,hydrogenCount:n,previousElement:t,charge:i},this.hasAttachedPseudoElements=!0}},{key:"getAttachedPseudoElements",value:function(){var e={},t=this;return Object.keys(this.attachedPseudoElements).sort().forEach(function(n){e[n]=t.attachedPseudoElements[n]}),e}},{key:"getAttachedPseudoElementsCount",value:function(){return Object.keys(this.attachedPseudoElements).length}},{key:"isHeteroAtom",value:function(){return"C"!==this.element&&"H"!==this.element}},{key:"addAnchoredRing",value:function(e){r.contains(this.anchoredRings,{value:e})||this.anchoredRings.push(e)}},{key:"getRingbondCount",value:function(){return this.ringbonds.length}},{key:"backupRings",value:function(){this.originalRings=Array(this.rings.length);for(var e=0;e<this.rings.length;e++)this.originalRings[e]=this.rings[e]}},{key:"restoreRings",value:function(){this.rings=Array(this.originalRings.length);for(var e=0;e<this.originalRings.length;e++)this.rings[e]=this.originalRings[e]}},{key:"haveCommonRingbond",value:function(e,t){for(var n=0;n<e.ringbonds.length;n++)for(var i=0;i<t.ringbonds.length;i++)if(e.ringbonds[n].id==t.ringbonds[i].id)return!0;return!1}},{key:"neighbouringElementsEqual",value:function(e){if(e.length!==this.neighbouringElements.length)return!1;e.sort(),this.neighbouringElements.sort();for(var t=0;t<this.neighbouringElements.length;t++)if(e[t]!==this.neighbouringElements[t])return!1;return!0}},{key:"getAtomicNumber",value:function(){return e.atomicNumbers[this.element]}},{key:"getMaxBonds",value:function(){return e.maxBonds[this.element]}}],[{key:"maxBonds",get:function(){return{H:1,C:4,N:3,O:2,P:3,S:2,B:3,F:1,I:1,Cl:1,Br:1}}},{key:"atomicNumbers",get:function(){return{H:1,He:2,Li:3,Be:4,B:5,b:5,C:6,c:6,N:7,n:7,O:8,o:8,F:9,Ne:10,Na:11,Mg:12,Al:13,Si:14,P:15,p:15,S:16,s:16,Cl:17,Ar:18,K:19,Ca:20,Sc:21,Ti:22,V:23,Cr:24,Mn:25,Fe:26,Co:27,Ni:28,Cu:29,Zn:30,Ga:31,Ge:32,As:33,Se:34,Br:35,Kr:36,Rb:37,Sr:38,Y:39,Zr:40,Nb:41,Mo:42,Tc:43,Ru:44,Rh:45,Pd:46,Ag:47,Cd:48,In:49,Sn:50,Sb:51,Te:52,I:53,Xe:54,Cs:55,Ba:56,La:57,Ce:58,Pr:59,Nd:60,Pm:61,Sm:62,Eu:63,Gd:64,Tb:65,Dy:66,Ho:67,Er:68,Tm:69,Yb:70,Lu:71,Hf:72,Ta:73,W:74,Re:75,Os:76,Ir:77,Pt:78,Au:79,Hg:80,Tl:81,Pb:82,Bi:83,Po:84,At:85,Rn:86,Fr:87,Ra:88,Ac:89,Th:90,Pa:91,U:92,Np:93,Pu:94,Am:95,Cm:96,Bk:97,Cf:98,Es:99,Fm:100,Md:101,No:102,Lr:103,Rf:104,Db:105,Sg:106,Bh:107,Hs:108,Mt:109,Ds:110,Rg:111,Cn:112,Uut:113,Uuq:114,Uup:115,Uuh:116,Uus:117,Uuo:118}}},{key:"mass",get:function(){return{H:1,He:2,Li:3,Be:4,B:5,b:5,C:6,c:6,N:7,n:7,O:8,o:8,F:9,Ne:10,Na:11,Mg:12,Al:13,Si:14,P:15,p:15,S:16,s:16,Cl:17,Ar:18,K:19,Ca:20,Sc:21,Ti:22,V:23,Cr:24,Mn:25,Fe:26,Co:27,Ni:28,Cu:29,Zn:30,Ga:31,Ge:32,As:33,Se:34,Br:35,Kr:36,Rb:37,Sr:38,Y:39,Zr:40,Nb:41,Mo:42,Tc:43,Ru:44,Rh:45,Pd:46,Ag:47,Cd:48,In:49,Sn:50,Sb:51,Te:52,I:53,Xe:54,Cs:55,Ba:56,La:57,Ce:58,Pr:59,Nd:60,Pm:61,Sm:62,Eu:63,Gd:64,Tb:65,Dy:66,Ho:67,Er:68,Tm:69,Yb:70,Lu:71,Hf:72,Ta:73,W:74,Re:75,Os:76,Ir:77,Pt:78,Au:79,Hg:80,Tl:81,Pb:82,Bi:83,Po:84,At:85,Rn:86,Fr:87,Ra:88,Ac:89,Th:90,Pa:91,U:92,Np:93,Pu:94,Am:95,Cm:96,Bk:97,Cf:98,Es:99,Fm:100,Md:101,No:102,Lr:103,Rf:104,Db:105,Sg:106,Bh:107,Hs:108,Mt:109,Ds:110,Rg:111,Cn:112,Uut:113,Uuq:114,Uup:115,Uuh:116,Uus:117,Uuo:118}}}]),e}();t.exports=l},{"./ArrayHelper":2,"./Ring":11,"./Vertex":15}],4:[function(e,t){"use strict";function n(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}var r=Number.MAX_VALUE,i=function(){function e(e,t){for(var n=0,i;n<t.length;n++)i=t[n],i.enumerable=i.enumerable||!1,i.configurable=!0,"value"in i&&(i.writable=!0),Object.defineProperty(e,i.key,i)}return function(t,n,i){return n&&e(t.prototype,n),i&&e(t,i),t}}(),a=e("./MathHelper"),o=e("./Vector2"),l=e("./Line"),s=e("./Vertex"),g=e("./Ring"),d=function(){function e(t,i,r){n(this,e),this.canvas="string"==typeof t||t instanceof String?document.getElementById(t):t,this.ctx=this.canvas.getContext("2d"),this.colors=i,this.opts=r,this.drawingWidth=0,this.drawingHeight=0,this.offsetX=0,this.offsetY=0,this.fontLarge=this.opts.fontSizeLarge+"pt Helvetica, Arial, sans-serif",this.fontSmall=this.opts.fontSizeSmall+"pt Helvetica, Arial, sans-serif",this.updateSize(this.opts.width,this.opts.height),this.ctx.font=this.fontLarge,this.hydrogenWidth=this.ctx.measureText("H").width,this.halfHydrogenWidth=this.hydrogenWidth/2,this.halfBondThickness=this.opts.bondThickness/2}return i(e,[{key:"updateSize",value:function(e,t){this.devicePixelRatio=window.devicePixelRatio||1,this.backingStoreRatio=this.ctx.webkitBackingStorePixelRatio||this.ctx.mozBackingStorePixelRatio||this.ctx.msBackingStorePixelRatio||this.ctx.oBackingStorePixelRatio||this.ctx.backingStorePixelRatio||1,this.ratio=this.devicePixelRatio/this.backingStoreRatio,1===this.ratio?(this.canvas.width=e*this.ratio,this.canvas.height=t*this.ratio):(this.canvas.width=e*this.ratio,this.canvas.height=t*this.ratio,this.canvas.style.width=e+"px",this.canvas.style.height=t+"px",this.ctx.setTransform(this.ratio,0,0,this.ratio,0,0))}},{key:"setTheme",value:function(e){this.colors=e}},{key:"scale",value:function(e){for(var t=-r,n=-r,a=r,o=r,l=0;l<e.length;l++)if(e[l].value.isDrawn){var i=e[l].position;t<i.x&&(t=i.x),n<i.y&&(n=i.y),a>i.x&&(a=i.x),o>i.y&&(o=i.y)}var s=this.opts.padding;t+=s,n+=s,a-=s,o-=s,this.drawingWidth=t-a,this.drawingHeight=n-o;var g=this.canvas.offsetWidth/this.drawingWidth,d=this.canvas.offsetHeight/this.drawingHeight,u=g<d?g:d;this.ctx.scale(u,u),this.offsetX=-a,this.offsetY=-o,g<d?this.offsetY+=this.canvas.offsetHeight/(2*u)-this.drawingHeight/2:this.offsetX+=this.canvas.offsetWidth/(2*u)-this.drawingWidth/2}},{key:"reset",value:function(){this.ctx.setTransform(1,0,0,1,0,0)}},{key:"getColor",value:function(e){return e=e.toUpperCase(),e in this.colors?this.colors[e]:this.colors.C}},{key:"drawCircle",value:function(e,t,n,i){var r=4<arguments.length&&void 0!==arguments[4]?arguments[4]:!0,o=5<arguments.length&&void 0!==arguments[5]&&arguments[5],l=6<arguments.length&&void 0!==arguments[6]?arguments[6]:"",s=this.ctx,g=this.offsetX,d=this.offsetY;s.save(),s.lineWidth=1.5,s.beginPath(),s.arc(e+g,t+d,n,0,a.twoPI,!0),s.closePath(),o?(r?(s.fillStyle="#f00",s.fill()):(s.strokeStyle="#f00",s.stroke()),this.drawDebugText(e,t,l)):r?(s.fillStyle=i,s.fill()):(s.strokeStyle=i,s.stroke()),s.restore()}},{key:"drawLine",value:function(e){var t=1<arguments.length&&void 0!==arguments[1]&&arguments[1],n=2<arguments.length&&void 0!==arguments[2]?arguments[2]:1,i=this.ctx,a=this.offsetX,o=this.offsetY,s=e.clone().shorten(4),g=s.getLeftVector().clone(),l=s.getRightVector().clone();g.x+=a,g.y+=o,l.x+=a,l.y+=o,t||(i.save(),i.globalCompositeOperation="destination-out",i.beginPath(),i.moveTo(g.x,g.y),i.lineTo(l.x,l.y),i.lineCap="round",i.lineWidth=this.opts.bondThickness+1.2,i.strokeStyle=this.getColor("BACKGROUND"),i.stroke(),i.globalCompositeOperation="source-over",i.restore()),g=e.getLeftVector().clone(),l=e.getRightVector().clone(),g.x+=a,g.y+=o,l.x+=a,l.y+=o,i.save(),i.beginPath(),i.moveTo(g.x,g.y),i.lineTo(l.x,l.y),i.lineCap="round",i.lineWidth=this.opts.bondThickness;var r=this.ctx.createLinearGradient(g.x,g.y,l.x,l.y);r.addColorStop(0.4,this.getColor(e.getLeftElement())||this.getColor("C")),r.addColorStop(0.6,this.getColor(e.getRightElement())||this.getColor("C")),t&&(i.setLineDash([1,1.5]),i.lineWidth=this.opts.bondThickness/1.5),1>n&&(i.globalAlpha=n),i.strokeStyle=r,i.stroke(),i.restore()}},{key:"drawWedge",value:function(e){if(1<arguments.length&&void 0!==arguments[1]?arguments[1]:1,!(isNaN(e.from.x)||isNaN(e.from.y)||isNaN(e.to.x)||isNaN(e.to.y))){var n=this.ctx,i=this.offsetX,a=this.offsetY,s=e.clone().shorten(5),g=s.getLeftVector().clone(),l=s.getRightVector().clone();g.x+=i,g.y+=a,l.x+=i,l.y+=a,g=e.getLeftVector().clone(),l=e.getRightVector().clone(),g.x+=i,g.y+=a,l.x+=i,l.y+=a,n.save();var r=o.normals(g,l);r[0].normalize(),r[1].normalize();var d=e.getRightChiral(),h=g,c=l;d&&(h=l,c=g);var p=o.add(h,o.multiplyScalar(r[0],this.halfBondThickness)),t=o.add(c,o.multiplyScalar(r[0],1.5+this.halfBondThickness)),u=o.add(c,o.multiplyScalar(r[1],1.5+this.halfBondThickness)),v=o.add(h,o.multiplyScalar(r[1],this.halfBondThickness));n.beginPath(),n.moveTo(p.x,p.y),n.lineTo(t.x,t.y),n.lineTo(u.x,u.y),n.lineTo(v.x,v.y);var y=this.ctx.createRadialGradient(l.x,l.y,this.opts.bondLength,l.x,l.y,0);y.addColorStop(0.4,this.getColor(e.getLeftElement())||this.getColor("C")),y.addColorStop(0.6,this.getColor(e.getRightElement())||this.getColor("C")),n.fillStyle=y,n.fill(),n.restore()}}},{key:"drawDashedWedge",value:function(e){if(!(isNaN(e.from.x)||isNaN(e.from.y)||isNaN(e.to.x)||isNaN(e.to.y))){var n=this.ctx,i=this.offsetX,a=this.offsetY,s=e.getLeftVector().clone(),l=e.getRightVector().clone();s.x+=i,s.y+=a,l.x+=i,l.y+=a,n.save();var r=o.normals(s,l);r[0].normalize(),r[1].normalize();var g=e.getRightChiral(),d=e.clone(),u,h,c,p;g?(u=l,h=s,d.shortenRight(1),c=d.getRightVector().clone(),p=d.getLeftVector().clone()):(u=s,h=l,d.shortenLeft(1),c=d.getLeftVector().clone(),p=d.getRightVector().clone()),c.x+=i,c.y+=a,p.x+=i,p.y+=a;var v=o.subtract(h,u).normalize();n.strokeStyle=this.getColor("C"),n.lineCap="round",n.lineWidth=this.opts.bondThickness,n.beginPath();for(var y=e.getLength(),m=1.25/(y/(3*this.opts.bondThickness)),f=!1,b=0;1>b;b+=m){var t=o.multiplyScalar(v,b*y),x=o.add(u,t),k=1.5*b,C=o.multiplyScalar(r[0],k);!f&&0.5<b&&(n.stroke(),n.beginPath(),n.strokeStyle=this.getColor(e.getRightElement())||this.getColor("C"),f=!0),x.subtract(C),n.moveTo(x.x,x.y),x.add(o.multiplyScalar(C,2)),n.lineTo(x.x,x.y)}n.stroke(),n.restore()}}},{key:"drawDebugText",value:function(e,t,n){var i=this.ctx;i.save(),i.font="5px Droid Sans, sans-serif",i.textAlign="start",i.textBaseline="top",i.fillStyle="#ff0000",i.fillText(n,e+this.offsetX,t+this.offsetY),i.restore()}},{key:"drawBall",value:function(e,t,n){var i=this.ctx;i.save(),i.beginPath(),i.arc(e+this.offsetX,t+this.offsetY,this.opts.bondLength/4.5,0,a.twoPI,!1),i.fillStyle=this.getColor(n),i.fill(),i.restore()}},{key:"drawPoint",value:function(e,t,n){var i=this.ctx,r=this.offsetX,o=this.offsetY;i.save(),i.globalCompositeOperation="destination-out",i.beginPath(),i.arc(e+r,t+o,1.5,0,a.twoPI,!0),i.closePath(),i.fill(),i.globalCompositeOperation="source-over",i.beginPath(),i.arc(e+this.offsetX,t+this.offsetY,0.75,0,a.twoPI,!1),i.fillStyle=this.getColor(n),i.fill(),i.restore()}},{key:"drawText",value:function(e,t,n,i,o,l,s,g){var d=8<arguments.length&&void 0!==arguments[8]?arguments[8]:{},u=this.ctx,h=this.offsetX,c=this.offsetY;u.save(),u.textAlign="start",u.textBaseline="alphabetic";var p="",v=0;s&&(p=this.getChargeText(s),u.font=this.fontSmall,v=u.measureText(p).width);var y="0",m=0;0<g&&(y=g.toString(),u.font=this.fontSmall,m=u.measureText(y).width),1===s&&"N"===n&&d.hasOwnProperty("0O")&&d.hasOwnProperty("0O-1")&&(d={"0O":{element:"O",count:2,hydrogenCount:0,previousElement:"C",charge:""}},s=0),u.font=this.fontLarge,u.fillStyle=this.getColor("BACKGROUND");var f=u.measureText(n);f.totalWidth=f.width+v,f.height=parseInt(this.fontLarge,10);var b=f.width>this.opts.fontSizeLarge?f.width:this.opts.fontSizeLarge;b/=1.5,u.globalCompositeOperation="destination-out",u.beginPath(),u.arc(e+h,t+c,b,0,a.twoPI,!0),u.closePath(),u.fill(),u.globalCompositeOperation="source-over";var r=-f.width/2,x=-f.width/2;u.fillStyle=this.getColor(n),u.fillText(n,e+h+r,t+this.opts.halfFontSizeLarge+c),r+=f.width,s&&(u.font=this.fontSmall,u.fillText(p,e+h+r,t-this.opts.fifthFontSizeSmall+c),r+=v),0<g&&(u.font=this.fontSmall,u.fillText(y,e+h+x-m,t-this.opts.fifthFontSizeSmall+c),x-=m),u.font=this.fontLarge;var k=0,C=0;if(1===i){var S=e+h,R=t+c+this.opts.halfFontSizeLarge;k=this.hydrogenWidth,x-=k,"left"===o?S+=x:"right"===o?S+=r:"up"===o&&l?S+=r:"down"===o&&l?S+=r:"up"!==o||l?"down"==o&&!l&&(R+=this.opts.fontSizeLarge+this.opts.quarterFontSizeLarge,S-=this.halfHydrogenWidth):(R-=this.opts.fontSizeLarge+this.opts.quarterFontSizeLarge,S-=this.halfHydrogenWidth),u.fillText("H",S,R),r+=k}else if(1<i){var A=e+h,j=t+c+this.opts.halfFontSizeLarge;k=this.hydrogenWidth,u.font=this.fontSmall,C=u.measureText(i).width,x-=k+C,"left"===o?A+=x:"right"===o?A+=r:"up"===o&&l?A+=r:"down"===o&&l?A+=r:"up"!==o||l?"down"==o&&!l&&(j+=this.opts.fontSizeLarge+this.opts.quarterFontSizeLarge,A-=this.halfHydrogenWidth):(j-=this.opts.fontSizeLarge+this.opts.quarterFontSizeLarge,A-=this.halfHydrogenWidth),u.font=this.fontLarge,u.fillText("H",A,j),u.font=this.fontSmall,u.fillText(i,A+this.halfHydrogenWidth+C,j+this.opts.fifthFontSizeSmall),r+=k+this.halfHydrogenWidth+C}for(var T in d)if(d.hasOwnProperty(T)){var w=0,I=0,P=d[T].element,B=d[T].count,L=d[T].hydrogenCount,E=d[T].charge;u.font=this.fontLarge,1<B&&0<L&&(w=u.measureText("(").width,I=u.measureText(")").width);var D=u.measureText(P).width,N=0,O="",V=0;k=0,0<L&&(k=this.hydrogenWidth),u.font=this.fontSmall,1<B&&(N=u.measureText(B).width),0!==E&&(O=this.getChargeText(E),V=u.measureText(O).width),C=0,1<L&&(C=u.measureText(L).width),u.font=this.fontLarge;var H=e+h,z=t+c+this.opts.halfFontSizeLarge;u.fillStyle=this.getColor(P),0<B&&(x-=N),1<B&&0<L&&("left"===o?(x-=I,u.fillText(")",H+x,z)):(u.fillText("(",H+r,z),r+=w)),"left"===o?(x-=D,u.fillText(P,H+x,z)):(u.fillText(P,H+r,z),r+=D),0<L&&("left"===o?(x-=k+C,u.fillText("H",H+x,z),1<L&&(u.font=this.fontSmall,u.fillText(L,H+x+k,z+this.opts.fifthFontSizeSmall))):(u.fillText("H",H+r,z),r+=k,1<L&&(u.font=this.fontSmall,u.fillText(L,H+r,z+this.opts.fifthFontSizeSmall),r+=C))),u.font=this.fontLarge,1<B&&0<L&&("left"===o?(x-=w,u.fillText("(",H+x,z)):(u.fillText(")",H+r,z),r+=I)),u.font=this.fontSmall,1<B&&("left"===o?u.fillText(B,H+x+w+I+k+C+D,z+this.opts.fifthFontSizeSmall):(u.fillText(B,H+r,z+this.opts.fifthFontSizeSmall),r+=N)),0!==E&&("left"===o?u.fillText(O,H+x+w+I+k+C+D,t-this.opts.fifthFontSizeSmall+c):(u.fillText(O,H+r,t-this.opts.fifthFontSizeSmall+c),r+=V))}u.restore()}},{key:"getChargeText",value:function(e){return 1===e?"+":2===e?"2+":-1===e?"-":-2===e?"2-":""}},{key:"drawDebugPoint",value:function(e,t){var n=2<arguments.length&&void 0!==arguments[2]?arguments[2]:"",i=3<arguments.length&&void 0!==arguments[3]?arguments[3]:"#f00";this.drawCircle(e,t,2,i,!0,!0,n)}},{key:"drawAromaticityRing",value:function(e){var t=this.ctx,n=a.apothemFromSideLength(this.opts.bondLength,e.getSize());t.save(),t.strokeStyle=this.getColor("C"),t.lineWidth=this.opts.bondThickness,t.beginPath(),t.arc(e.center.x+this.offsetX,e.center.y+this.offsetY,n-this.opts.bondSpacing,0,2*Math.PI,!0),t.closePath(),t.stroke(),t.restore()}},{key:"clear",value:function(){this.ctx.clearRect(0,0,this.canvas.offsetWidth,this.canvas.offsetHeight)}}]),e}();t.exports=d},{"./Line":8,"./MathHelper":9,"./Ring":11,"./Vector2":14,"./Vertex":15}],5:[function(e,t){"use strict";function n(e){if(Array.isArray(e)){for(var t=0,n=Array(e.length);t<e.length;t++)n[t]=e[t];return n}return Array.from(e)}function i(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}var r=Math.PI,o=Math.min,a=function(){function e(e,t){for(var n=0,i;n<t.length;n++)i=t[n],i.enumerable=i.enumerable||!1,i.configurable=!0,"value"in i&&(i.writable=!0),Object.defineProperty(e,i.key,i)}return function(t,n,i){return n&&e(t.prototype,n),i&&e(t,i),t}}(),g=e("./MathHelper"),d=e("./ArrayHelper"),l=e("./Vector2"),s=e("./Line"),u=e("./Vertex"),h=e("./Edge"),c=e("./Atom"),p=e("./Ring"),v=e("./RingConnection"),y=e("./CanvasWrapper"),m=e("./Graph"),f=e("./SSSR"),b=function(){function e(t){i(this,e),this.graph=null,this.doubleBondConfigCount=0,this.doubleBondConfig=null,this.ringIdCounter=0,this.ringConnectionIdCounter=0,this.canvasWrapper=null,this.totalOverlapScore=0,this.defaultOptions={width:500,height:500,bondThickness:0.6,bondLength:15,shortBondLength:0.85,bondSpacing:15*0.18,atomVisualization:"default",isomeric:!0,debug:!1,terminalCarbons:!1,explicitHydrogens:!1,overlapSensitivity:0.42,overlapResolutionIterations:1,compactDrawing:!0,fontSizeLarge:5,fontSizeSmall:3,padding:20,themes:{dark:{C:"#fff",O:"#e74c3c",N:"#3498db",F:"#27ae60",CL:"#16a085",BR:"#d35400",I:"#8e44ad",P:"#d35400",S:"#f1c40f",B:"#e67e22",SI:"#e67e22",H:"#fff",BACKGROUND:"#141414"},light:{C:"#222",O:"#e74c3c",N:"#3498db",F:"#27ae60",CL:"#16a085",BR:"#d35400",I:"#8e44ad",P:"#d35400",S:"#f1c40f",B:"#e67e22",SI:"#e67e22",H:"#222",BACKGROUND:"#fff"}}},this.opts=this.extend(!0,this.defaultOptions,t),this.opts.halfBondSpacing=this.opts.bondSpacing/2,this.opts.bondLengthSq=this.opts.bondLength*this.opts.bondLength,this.opts.halfFontSizeLarge=this.opts.fontSizeLarge/2,this.opts.quarterFontSizeLarge=this.opts.fontSizeLarge/4,this.opts.fifthFontSizeSmall=this.opts.fontSizeSmall/5,this.theme=this.opts.themes.dark}return a(e,[{key:"extend",value:function(){var e=this,t={},n=!1,r=0,i=arguments.length;"[object Boolean]"===Object.prototype.toString.call(arguments[0])&&(n=arguments[0],r++);for(var a=function(i){for(var r in i)Object.prototype.hasOwnProperty.call(i,r)&&(t[r]=n&&"[object Object]"===Object.prototype.toString.call(i[r])?e.extend(!0,t[r],i[r]):i[r])},o;r<i;r++)o=arguments[r],a(o);return t}},{key:"draw",value:function(e,t){var n=2<arguments.length&&void 0!==arguments[2]?arguments[2]:"light",r=3<arguments.length&&void 0!==arguments[3]&&arguments[3];if(this.data=e,this.infoOnly=r,this.infoOnly||(this.canvasWrapper=new y(t,this.opts.themes[n],this.opts)),this.ringIdCounter=0,this.ringConnectionIdCounter=0,this.graph=new m(e,this.opts.isomeric),this.rings=[],this.ringConnections=[],this.originalRings=[],this.originalRingConnections=[],this.bridgedRing=!1,this.doubleBondConfigCount=null,this.doubleBondConfig=null,this.initRings(),this.initHydrogens(),!this.infoOnly){this.position(),this.restoreRingInformation(),this.resolvePrimaryOverlaps();var l=this.getOverlapScore();this.totalOverlapScore=this.getOverlapScore().total;for(var s=0;s<this.opts.overlapResolutionIterations;s++)for(var o=0,i;o<this.graph.edges.length;o++)if(i=this.graph.edges[o],this.isEdgeRotatable(i)){var d=this.graph.getTreeDepth(i.sourceId,i.targetId),u=this.graph.getTreeDepth(i.targetId,i.sourceId),h=i.targetId,a=i.sourceId;d>u&&(h=i.sourceId,a=i.targetId);var c=this.getSubtreeOverlapScore(a,h,l.vertexScores);if(c.value>this.opts.overlapSensitivity){var p=this.graph.vertices[h],v=this.graph.vertices[a],f=v.getNeighbours(h);if(1===f.length){var b=this.graph.vertices[f[0]],x=b.position.getRotateAwayFromAngle(p.position,v.position,g.toRad(120));this.rotateSubtree(b.id,v.id,x,v.position);var k=this.getOverlapScore().total;k>this.totalOverlapScore?this.rotateSubtree(b.id,v.id,-x,v.position):this.totalOverlapScore=k}else if(2===f.length){if(0!==v.value.rings.length&&0!==p.value.rings.length)continue;var C=this.graph.vertices[f[0]],S=this.graph.vertices[f[1]];if(1===C.value.rings.length&&1===S.value.rings.length){if(C.value.rings[0]!==S.value.rings[0])continue;}else if(0!==C.value.rings.length||0!==S.value.rings.length)continue;else{var R=C.position.getRotateAwayFromAngle(p.position,v.position,g.toRad(120)),A=S.position.getRotateAwayFromAngle(p.position,v.position,g.toRad(120));this.rotateSubtree(C.id,v.id,R,v.position),this.rotateSubtree(S.id,v.id,A,v.position);var j=this.getOverlapScore().total;j>this.totalOverlapScore?(this.rotateSubtree(C.id,v.id,-R,v.position),this.rotateSubtree(S.id,v.id,-A,v.position)):this.totalOverlapScore=j}}l=this.getOverlapScore()}}this.resolveSecondaryOverlaps(l.scores),this.opts.isomeric&&this.annotateStereochemistry(),this.opts.compactDrawing&&"default"===this.opts.atomVisualization&&this.initPseudoElements(),this.rotateDrawing(),this.canvasWrapper.scale(this.graph.vertices),this.drawEdges(this.opts.debug),this.drawVertices(this.opts.debug),this.canvasWrapper.reset()}}},{key:"edgeRingCount",value:function(e){var t=this.graph.edges[e],n=this.graph.vertices[t.sourceId],i=this.graph.vertices[t.targetId];return o(n.value.rings.length,i.value.rings.length)}},{key:"getBridgedRings",value:function(){for(var e=[],t=0;t<this.rings.length;t++)this.rings[t].isBridged&&e.push(this.rings[t]);return e}},{key:"getFusedRings",value:function(){for(var e=[],t=0;t<this.rings.length;t++)this.rings[t].isFused&&e.push(this.rings[t]);return e}},{key:"getSpiros",value:function(){for(var e=[],t=0;t<this.rings.length;t++)this.rings[t].isSpiro&&e.push(this.rings[t]);return e}},{key:"printRingInfo",value:function(){for(var e="",t=0,n;t<this.rings.length;t++)n=this.rings[t],e+=n.id+";",e+=n.members.length+";",e+=n.neighbours.length+";",e+=n.isSpiro?"true;":"false;",e+=n.isFused?"true;":"false;",e+=n.isBridged?"true;":"false;",e+=n.rings.length+";",e+="\n";return e}},{key:"rotateDrawing",value:function(){for(var e=0,t=0,n=0,r=0,i;r<this.graph.vertices.length;r++)if(i=this.graph.vertices[r],!!i.value.isDrawn)for(var a=r+1,o;a<this.graph.vertices.length;a++)if(o=this.graph.vertices[a],!!o.value.isDrawn){var s=i.position.distanceSq(o.position);s>n&&(n=s,e=r,t=a)}var g=-l.subtract(this.graph.vertices[e].position,this.graph.vertices[t].position).angle();if(!isNaN(g)){var d=g%0.523599;0.2617995>d?g-=d:g+=0.523599-d;for(var r=0;r<this.graph.vertices.length;r++)r!==t&&this.graph.vertices[r].position.rotateAround(g,this.graph.vertices[t].position);for(var r=0;r<this.rings.length;r++)this.rings[r].center.rotateAround(g,this.graph.vertices[t].position)}}},{key:"getTotalOverlapScore",value:function(){return this.totalOverlapScore}},{key:"getRingCount",value:function(){return this.rings.length}},{key:"hasBridgedRing",value:function(){return this.bridgedRing}},{key:"getHeavyAtomCount",value:function(){for(var e=0,t=0;t<this.graph.vertices.length;t++)"H"!==this.graph.vertices[t].value.element&&e++;return e}},{key:"getMolecularFormula",value:function(){for(var t="",n=new Map,e=0,i;e<this.graph.vertices.length;e++)if(i=this.graph.vertices[e].value,n.has(i.element)?n.set(i.element,n.get(i.element)+1):n.set(i.element,1),i.bracket&&!i.bracket.chirality&&(n.has("H")?n.set("H",n.get("H")+i.bracket.hcount):n.set("H",i.bracket.hcount)),!i.bracket){var r=c.maxBonds[i.element]-i.bondCount;i.isPartOfAromaticRing&&r--,n.has("H")?n.set("H",n.get("H")+r):n.set("H",r)}if(n.has("C")){var a=n.get("C");t+="C"+(1<a?a:""),n.delete("C")}if(n.has("H")){var o=n.get("H");t+="H"+(1<o?o:""),n.delete("H")}var l=Object.keys(c.atomicNumbers).sort();return l.map(function(i){if(n.has(i)){var e=n.get(i);t+=i+(1<e?e:"")}}),t}},{key:"getRingbondType",value:function(e,t){if(1>e.value.getRingbondCount()||1>t.value.getRingbondCount())return null;for(var n=0;n<e.value.ringbonds.length;n++)for(var i=0;i<t.value.ringbonds.length;i++)if(e.value.ringbonds[n].id===t.value.ringbonds[i].id)return"-"===e.value.ringbonds[n].bondType?t.value.ringbonds[i].bond:e.value.ringbonds[n].bond;return null}},{key:"initRings",value:function(){for(var e=new Map,t=this.graph.vertices.length-1,i;0<=t;t--)if(i=this.graph.vertices[t],0!==i.value.ringbonds.length)for(var r=0;r<i.value.ringbonds.length;r++){var o=i.value.ringbonds[r].id,l=i.value.ringbonds[r].bond;if(!e.has(o))e.set(o,[i.id,l]);else{var s=i.id,g=e.get(o)[0],d=e.get(o)[1],u=new h(s,g,1);u.setBondType(d||l||"-");var c=this.graph.addEdge(u),y=this.graph.vertices[g];i.addRingbondChild(g,r),i.value.addNeighbouringElement(y.value.element),y.addRingbondChild(s,r),y.value.addNeighbouringElement(i.value.element),i.edges.push(c),y.edges.push(c),e.delete(o)}}var m=f.getRings(this.graph);if(null!==m){for(var t=0;t<m.length;t++)for(var x=[].concat(n(m[t])),k=this.addRing(new p(x)),r=0;r<x.length;r++)this.graph.vertices[x[r]].value.rings.push(k);for(var t=0;t<this.rings.length-1;t++)for(var r=t+1;r<this.rings.length;r++){var C=this.rings[t],a=this.rings[r],b=new v(C,a);0<b.vertices.size&&this.addRingConnection(b)}for(var t=0,S;t<this.rings.length;t++)S=this.rings[t],S.neighbours=v.getNeighbours(this.ringConnections,S.id);for(var t=0,R;t<this.rings.length;t++)R=this.rings[t],this.graph.vertices[R.members[0]].value.addAnchoredRing(R.id);for(this.backupRingInformation();0<this.rings.length;){for(var A=-1,t=0,j;t<this.rings.length;t++)j=this.rings[t],this.isPartOfBridgedRing(j.id)&&!j.isBridged&&(A=j.id);if(-1===A)break;var T=this.getRing(A),w=this.getBridgedRingRings(T.id);this.bridgedRing=!0,this.createBridgedRing(w,T.members[0]);for(var t=0;t<w.length;t++)this.removeRing(w[t])}}}},{key:"initHydrogens",value:function(){if(!this.opts.explicitHydrogens)for(var e=0,t;e<this.graph.vertices.length;e++)if(t=this.graph.vertices[e],"H"===t.value.element){var n=this.graph.vertices[t.neighbours[0]];n.value.hasHydrogen=!0,(!n.value.isStereoCenter||2>n.value.rings.length&&!n.value.bridgedRing||n.value.bridgedRing&&2>n.value.originalRings.length)&&(t.value.isDrawn=!1)}}},{key:"getBridgedRingRings",value:function(e){var t=[],a=this;return function e(o){var r=a.getRing(o);t.push(o);for(var l=0,i;l<r.neighbours.length;l++)i=r.neighbours[l],-1===t.indexOf(i)&&i!==o&&v.isBridge(a.ringConnections,a.graph.vertices,o,i)&&e(i)}(e),d.unique(t)}},{key:"isPartOfBridgedRing",value:function(e){for(var t=0;t<this.ringConnections.length;t++)if(this.ringConnections[t].containsRing(e)&&this.ringConnections[t].isBridge(this.graph.vertices))return!0;return!1}},{key:"createBridgedRing",value:function(e){for(var t=new Set,r=new Set,a=new Set,o=0,i;o<e.length;o++){i=this.getRing(e[o]),i.isPartOfBridged=!0;for(var l=0;l<i.members.length;l++)r.add(i.members[l]);for(var l=0,s;l<i.neighbours.length;l++)s=i.neighbours[l],-1===e.indexOf(s)&&a.add(i.neighbours[l])}var g=new Set,u=!0,h=!1,c;try{for(var v=r[Symbol.iterator](),y;!(u=(y=v.next()).done);u=!0){var m=y.value,f=this.graph.vertices[m],b=d.intersection(e,f.value.rings);1===f.value.rings.length||1===b.length?t.add(f.id):g.add(f.id)}}catch(e){h=!0,c=e}finally{try{!u&&v.return&&v.return()}finally{if(h)throw c}}var x=[],k=!0,C=!1,S;try{for(var R=g[Symbol.iterator](),A;!(k=(A=R.next()).done);k=!0){for(var j=A.value,T=this.graph.vertices[j],w=!1,I=0;I<T.edges.length;I++)1===this.edgeRingCount(T.edges[I])&&(w=!0);w?(T.value.isBridgeNode=!0,t.add(T.id)):(T.value.isBridge=!0,t.add(T.id))}}catch(e){C=!0,S=e}finally{try{!k&&R.return&&R.return()}finally{if(C)throw S}}var P=new p([].concat(n(t)));P.isBridged=!0,P.neighbours=[].concat(n(a));for(var o=0;o<e.length;o++)P.rings.push(this.getRing(e[o]).clone());this.addRing(P);for(var o=0;o<P.members.length;o++)this.graph.vertices[P.members[o]].value.bridgedRing=P.id;for(var o=0,B;o<x.length;o++)B=this.graph.vertices[x[o]],B.value.rings=[];var L=!0,E=!1,D;try{for(var N=t[Symbol.iterator](),O;!(L=(O=N.next()).done);L=!0){var V=O.value,H=this.graph.vertices[V];H.value.rings=d.removeAll(H.value.rings,e),H.value.rings.push(P.id)}}catch(e){E=!0,D=e}finally{try{!L&&N.return&&N.return()}finally{if(E)throw D}}for(var o=0;o<e.length;o++)for(var l=o+1;l<e.length;l++)this.removeRingConnectionsBetween(e[o],e[l]);var z=!0,F=!1,W;try{for(var _=a[Symbol.iterator](),M;!(z=(M=_.next()).done);z=!0){for(var q=M.value,U=this.getRingConnections(q,e),l=0;l<U.length;l++)this.getRingConnection(U[l]).updateOther(P.id,q);this.getRing(q).neighbours.push(P.id)}}catch(e){F=!0,W=e}finally{try{!z&&_.return&&_.return()}finally{if(F)throw W}}return P}},{key:"areVerticesInSameRing",value:function(e,t){for(var n=0;n<e.value.rings.length;n++)for(var i=0;i<t.value.rings.length;i++)if(e.value.rings[n]===t.value.rings[i])return!0;return!1}},{key:"getCommonRings",value:function(e,t){for(var n=[],r=0;r<e.value.rings.length;r++)for(var i=0;i<t.value.rings.length;i++)e.value.rings[r]==t.value.rings[i]&&n.push(e.value.rings[r]);return n}},{key:"getLargestOrAromaticCommonRing",value:function(e,t){for(var n=this.getCommonRings(e,t),r=0,a=null,o=0;o<n.length;o++){var i=this.getRing(n[o]),l=i.getSize();if(i.isBenzeneLike(this.graph.vertices))return i;l>r&&(r=l,a=i)}return a}},{key:"getVerticesAt",value:function(e,t,n){for(var r=[],a=0,i;a<this.graph.vertices.length;a++)if(i=this.graph.vertices[a],i.id!==n&&i.positioned){var o=e.distanceSq(i.position);o<=t*t&&r.push(i.id)}return r}},{key:"getClosestVertex",value:function(e){for(var t=99999,n=null,r=0,i;r<this.graph.vertices.length;r++)if(i=this.graph.vertices[r],i.id!==e.id){var a=e.position.distanceSq(i.position);a<t&&(t=a,n=i)}return n}},{key:"addRing",value:function(e){return e.id=this.ringIdCounter++,this.rings.push(e),e.id}},{key:"removeRing",value:function(e){this.rings=this.rings.filter(function(t){return t.id!==e}),this.ringConnections=this.ringConnections.filter(function(t){return t.firstRingId!==e&&t.secondRingId!==e});for(var t=0,n;t<this.rings.length;t++)n=this.rings[t],n.neighbours=n.neighbours.filter(function(t){return t!==e})}},{key:"getRing",value:function(e){for(var t=0;t<this.rings.length;t++)if(this.rings[t].id==e)return this.rings[t]}},{key:"addRingConnection",value:function(e){return e.id=this.ringConnectionIdCounter++,this.ringConnections.push(e),e.id}},{key:"removeRingConnection",value:function(e){this.ringConnections=this.ringConnections.filter(function(t){return t.id!==e})}},{key:"removeRingConnectionsBetween",value:function(e,t){for(var n=[],r=0,i;r<this.ringConnections.length;r++)i=this.ringConnections[r],(i.firstRingId===e&&i.secondRingId===t||i.firstRingId===t&&i.secondRingId===e)&&n.push(i.id);for(var r=0;r<n.length;r++)this.removeRingConnection(n[r])}},{key:"getRingConnection",value:function(e){for(var t=0;t<this.ringConnections.length;t++)if(this.ringConnections[t].id==e)return this.ringConnections[t]}},{key:"getRingConnections",value:function(e,t){for(var n=[],r=0,i;r<this.ringConnections.length;r++){i=this.ringConnections[r];for(var a=0,o;a<t.length;a++)o=t[a],(i.firstRingId===e&&i.secondRingId===o||i.firstRingId===o&&i.secondRingId===e)&&n.push(i.id)}return n}},{key:"getOverlapScore",value:function(){for(var e=0,t=new Float32Array(this.graph.vertices.length),n=0;n<this.graph.vertices.length;n++)t[n]=0;for(var n=0,r;n<this.graph.vertices.length;n++)for(r=this.graph.vertices.length;--r>n;){var o=this.graph.vertices[n],a=this.graph.vertices[r];if(o.value.isDrawn&&a.value.isDrawn){var s=l.subtract(o.position,a.position).lengthSq();if(s<this.opts.bondLengthSq){var g=(this.opts.bondLength-Math.sqrt(s))/this.opts.bondLength;e+=g,t[n]+=g,t[r]+=g}}}for(var d=[],n=0;n<this.graph.vertices.length;n++)d.push({id:n,score:t[n]});return d.sort(function(e,t){return t.score-e.score}),{total:e,scores:d,vertexScores:t}}},{key:"chooseSide",value:function(e,t,n){for(var r=e.getNeighbours(t.id),a=t.getNeighbours(e.id),o=r.length,l=a.length,s=d.merge(r,a),g=[0,0],u=0,i;u<s.length;u++)i=this.graph.vertices[s[u]].position,i.sameSideAs(e.position,t.position,n[0])?g[0]++:g[1]++;for(var h=[0,0],u=0,c;u<this.graph.vertices.length;u++)c=this.graph.vertices[u].position,c.sameSideAs(e.position,t.position,n[0])?h[0]++:h[1]++;return{totalSideCount:h,totalPosition:h[0]>h[1]?0:1,sideCount:g,position:g[0]>g[1]?0:1,anCount:o,bnCount:l}}},{key:"setRingCenter",value:function(e){for(var t=e.getSize(),n=new l(0,0),r=0;r<t;r++)n.add(this.graph.vertices[e.members[r]].position);e.center=n.divide(t)}},{key:"getSubringCenter",value:function(e,t){for(var n=t.value.originalRings,r=e.center,a=Number.MAX_VALUE,o=0;o<n.length;o++)for(var i=0;i<e.rings.length;i++)n[o]===e.rings[i].id&&e.rings[i].getSize()<a&&(r=e.rings[i].center,a=e.rings[i].getSize());return r}},{key:"drawEdges",value:function(e){var t=this,n=Array(this.graph.edges.length);if(n.fill(!1),this.graph.traverseBF(0,function(r){for(var a=t.graph.getEdges(r.id),o=0,i;o<a.length;o++)i=a[o],n[i]||(n[i]=!0,t.drawEdge(i,e))}),!this.bridgedRing)for(var r=0,i;r<this.rings.length;r++)i=this.rings[r],this.isRingAromatic(i)&&this.canvasWrapper.drawAromaticityRing(i)}},{key:"drawEdge",value:function(e,t){var n=this,i=this.graph.edges[e],r=this.graph.vertices[i.sourceId],o=this.graph.vertices[i.targetId],g=r.value.element,u=o.value.element;if(r.value.isDrawn&&o.value.isDrawn||"default"!==this.opts.atomVisualization){var h=r.position,a=o.position,c=this.getEdgeNormals(i),p=d.clone(c);if(p[0].multiplyScalar(10).add(h),p[1].multiplyScalar(10).add(h),"="===i.bondType||"="===this.getRingbondType(r,o)||i.isPartOfAromaticRing&&this.bridgedRing){var v=this.areVerticesInSameRing(r,o),y=this.chooseSide(r,o,p);if(v){var m=this.getLargestOrAromaticCommonRing(r,o),f=m.center;c[0].multiplyScalar(n.opts.bondSpacing),c[1].multiplyScalar(n.opts.bondSpacing);var b=null;b=f.sameSideAs(r.position,o.position,l.add(h,c[0]))?new s(l.add(h,c[0]),l.add(a,c[0]),g,u):new s(l.add(h,c[1]),l.add(a,c[1]),g,u),b.shorten(this.opts.bondLength-this.opts.shortBondLength*this.opts.bondLength),i.isPartOfAromaticRing?this.canvasWrapper.drawLine(b,!0):this.canvasWrapper.drawLine(b),this.canvasWrapper.drawLine(new s(h,a,g,u))}else if(i.center||r.isTerminal()&&o.isTerminal()){c[0].multiplyScalar(n.opts.halfBondSpacing),c[1].multiplyScalar(n.opts.halfBondSpacing);var x=new s(l.add(h,c[0]),l.add(a,c[0]),g,u),k=new s(l.add(h,c[1]),l.add(a,c[1]),g,u);this.canvasWrapper.drawLine(x),this.canvasWrapper.drawLine(k)}else if(0==y.anCount&&1<y.bnCount||0==y.bnCount&&1<y.anCount){c[0].multiplyScalar(n.opts.halfBondSpacing),c[1].multiplyScalar(n.opts.halfBondSpacing);var C=new s(l.add(h,c[0]),l.add(a,c[0]),g,u),S=new s(l.add(h,c[1]),l.add(a,c[1]),g,u);this.canvasWrapper.drawLine(C),this.canvasWrapper.drawLine(S)}else if(y.sideCount[0]>y.sideCount[1]){c[0].multiplyScalar(n.opts.bondSpacing),c[1].multiplyScalar(n.opts.bondSpacing);var R=new s(l.add(h,c[0]),l.add(a,c[0]),g,u);R.shorten(this.opts.bondLength-this.opts.shortBondLength*this.opts.bondLength),this.canvasWrapper.drawLine(R),this.canvasWrapper.drawLine(new s(h,a,g,u))}else if(y.sideCount[0]<y.sideCount[1]){c[0].multiplyScalar(n.opts.bondSpacing),c[1].multiplyScalar(n.opts.bondSpacing);var A=new s(l.add(h,c[1]),l.add(a,c[1]),g,u);A.shorten(this.opts.bondLength-this.opts.shortBondLength*this.opts.bondLength),this.canvasWrapper.drawLine(A),this.canvasWrapper.drawLine(new s(h,a,g,u))}else if(y.totalSideCount[0]>y.totalSideCount[1]){c[0].multiplyScalar(n.opts.bondSpacing),c[1].multiplyScalar(n.opts.bondSpacing);var j=new s(l.add(h,c[0]),l.add(a,c[0]),g,u);j.shorten(this.opts.bondLength-this.opts.shortBondLength*this.opts.bondLength),this.canvasWrapper.drawLine(j),this.canvasWrapper.drawLine(new s(h,a,g,u))}else if(y.totalSideCount[0]<=y.totalSideCount[1]){c[0].multiplyScalar(n.opts.bondSpacing),c[1].multiplyScalar(n.opts.bondSpacing);var T=new s(l.add(h,c[1]),l.add(a,c[1]),g,u);T.shorten(this.opts.bondLength-this.opts.shortBondLength*this.opts.bondLength),this.canvasWrapper.drawLine(T),this.canvasWrapper.drawLine(new s(h,a,g,u))}else;}else if("#"===i.bondType){c[0].multiplyScalar(n.opts.bondSpacing/1.5),c[1].multiplyScalar(n.opts.bondSpacing/1.5);var w=new s(l.add(h,c[0]),l.add(a,c[0]),g,u),I=new s(l.add(h,c[1]),l.add(a,c[1]),g,u);this.canvasWrapper.drawLine(w),this.canvasWrapper.drawLine(I),this.canvasWrapper.drawLine(new s(h,a,g,u))}else if("."===i.bondType);else{var P=r.value.isStereoCenter,B=o.value.isStereoCenter;"up"===i.wedge?this.canvasWrapper.drawWedge(new s(h,a,g,u,P,B)):"down"===i.wedge?this.canvasWrapper.drawDashedWedge(new s(h,a,g,u,P,B)):this.canvasWrapper.drawLine(new s(h,a,g,u,P,B))}if(t){var L=l.midpoint(h,a);this.canvasWrapper.drawDebugText(L.x,L.y,"e: "+e)}}}},{key:"drawVertices",value:function(e){for(var t=this.graph.vertices.length,t=0;t<this.graph.vertices.length;t++){var n=this.graph.vertices[t],i=n.value,o=0,s=0,g=n.value.bondCount,u=i.element,h=c.maxBonds[u]-g,p=n.getTextDirection(this.graph.vertices),v=(this.opts.terminalCarbons||"C"!==u||i.hasAttachedPseudoElements)&&n.isTerminal(),y="C"===i.element;if(i.bracket&&(h=i.bracket.hcount,o=i.bracket.charge,s=i.bracket.isotope),"allballs"===this.opts.atomVisualization)this.canvasWrapper.drawBall(n.position.x,n.position.y,u);else if(i.isDrawn&&(!y||i.drawExplicit||v||i.hasAttachedPseudoElements)||1===this.graph.vertices.length)"default"===this.opts.atomVisualization?this.canvasWrapper.drawText(n.position.x,n.position.y,u,h,p,v,o,s,i.getAttachedPseudoElements()):"balls"===this.opts.atomVisualization&&this.canvasWrapper.drawBall(n.position.x,n.position.y,u);else if(2===n.getNeighbourCount()&&!0==n.forcePositioned){var m=this.graph.vertices[n.neighbours[0]].position,a=this.graph.vertices[n.neighbours[1]].position,f=l.threePointangle(n.position,m,a);0.1>Math.abs(r-f)&&this.canvasWrapper.drawPoint(n.position.x,n.position.y,u)}if(e){var b="v: "+n.id+" "+d.print(i.ringbonds);this.canvasWrapper.drawDebugText(n.position.x,n.position.y,b)}else;}if(this.opts.debug)for(var t=0,x;t<this.rings.length;t++)x=this.rings[t].center,this.canvasWrapper.drawDebugPoint(x.x,x.y,"r: "+this.rings[t].id)}},{key:"position",value:function(){for(var e=null,t=0;t<this.graph.vertices.length;t++)if(null!==this.graph.vertices[t].value.bridgedRing){e=this.graph.vertices[t];break}for(var t=0;t<this.rings.length;t++)this.rings[t].isBridged&&(e=this.graph.vertices[this.rings[t].members[0]]);0<this.rings.length&&null===e&&(e=this.graph.vertices[this.rings[0].members[0]]),null===e&&(e=this.graph.vertices[0]),this.createNextBond(e,null,0)}},{key:"backupRingInformation",value:function(){this.originalRings=[],this.originalRingConnections=[];for(var e=0;e<this.rings.length;e++)this.originalRings.push(this.rings[e]);for(var e=0;e<this.ringConnections.length;e++)this.originalRingConnections.push(this.ringConnections[e]);for(var e=0;e<this.graph.vertices.length;e++)this.graph.vertices[e].value.backupRings()}},{key:"restoreRingInformation",value:function(){var e=this.getBridgedRings();this.rings=[],this.ringConnections=[];for(var t=0,n;t<e.length;t++){n=e[t];for(var i=0,r;i<n.rings.length;i++)r=n.rings[i],this.originalRings[r.id].center=r.center}for(var t=0;t<this.originalRings.length;t++)this.rings.push(this.originalRings[t]);for(var t=0;t<this.originalRingConnections.length;t++)this.ringConnections.push(this.originalRingConnections[t]);for(var t=0;t<this.graph.vertices.length;t++)this.graph.vertices[t].value.restoreRings()}},{key:"createRing",value:function(e){var t=1<arguments.length&&void 0!==arguments[1]?arguments[1]:null,n=2<arguments.length&&void 0!==arguments[2]?arguments[2]:null,o=3<arguments.length&&void 0!==arguments[3]?arguments[3]:null;if(!e.positioned){t=t?t:new l(0,0);var s=e.getOrderedNeighbours(this.ringConnections),d=n?l.subtract(n.position,t).angle():0,u=g.polyCircumradius(this.opts.bondLength,e.getSize()),h=g.centralAngle(e.getSize());e.centralAngle=h;var c=d,a=this,p=n?n.id:null;if(-1===e.members.indexOf(p)&&(n&&(n.positioned=!1),p=e.members[0]),e.isBridged){this.graph.kkLayout(e.members.slice(),t,n.id,e,this.opts.bondLength),e.positioned=!0,this.setRingCenter(e),t=e.center;for(var y=0;y<e.rings.length;y++)this.setRingCenter(e.rings[y])}else e.eachMember(this.graph.vertices,function(n){var i=a.graph.vertices[n];i.positioned||i.setPosition(t.x+Math.cos(c)*u,t.y+Math.sin(c)*u),c+=h,(!e.isBridged||3>e.rings.length)&&(i.angle=c,i.positioned=!0)},p,o?o.id:null);e.positioned=!0,e.center=t;for(var y=0,i;y<s.length;y++)if(i=this.getRing(s[y].neighbour),!i.positioned){var m=v.getVertices(this.ringConnections,e.id,i.id);if(2===m.length){e.isFused=!0,i.isFused=!0;var f=this.graph.vertices[m[0]],b=this.graph.vertices[m[1]],x=l.midpoint(f.position,b.position),k=l.normals(f.position,b.position);k[0].normalize(),k[1].normalize();var C=g.polyCircumradius(this.opts.bondLength,i.getSize()),r=g.apothem(C,i.getSize());k[0].multiplyScalar(r).add(x),k[1].multiplyScalar(r).add(x);var S=k[0];l.subtract(t,k[1]).lengthSq()>l.subtract(t,k[0]).lengthSq()&&(S=k[1]);var R=l.subtract(f.position,S),A=l.subtract(b.position,S);-1===R.clockwise(A)?!i.positioned&&this.createRing(i,S,f,b):!i.positioned&&this.createRing(i,S,b,f)}else if(1===m.length){e.isSpiro=!0,i.isSpiro=!0;var T=this.graph.vertices[m[0]],w=l.subtract(t,T.position);w.invert(),w.normalize();var I=g.polyCircumradius(this.opts.bondLength,i.getSize());w.multiplyScalar(I),w.add(T.position),i.positioned||this.createRing(i,w,T)}}for(var y=0;y<e.members.length;y++)for(var P=this.graph.vertices[e.members[y]],B=P.neighbours,L=0,j;L<B.length;L++)(j=this.graph.vertices[B[L]],!j.positioned)&&(j.value.isConnectedToRing=!0,this.createNextBond(j,P,0))}}},{key:"rotateSubtree",value:function(e,t,n,r){var a=this;this.graph.traverseTree(e,t,function(e){e.position.rotateAround(n,r);for(var t=0,i;t<e.value.anchoredRings.length;t++)i=a.rings[e.value.anchoredRings[t]],i&&i.center.rotateAround(n,r)})}},{key:"getSubtreeOverlapScore",value:function(e,t,n){var i=this,r=0,a=new l(0,0),o=0;return this.graph.traverseTree(e,t,function(e){if(e.value.isDrawn){var t=n[e.id];t>i.opts.overlapSensitivity&&(r+=t,o++);var l=i.graph.vertices[e.id].position.clone();l.multiplyScalar(t),a.add(l)}}),a.divide(r),{value:r/o,center:a}}},{key:"getCurrentCenterOfMass",value:function(){for(var e=new l(0,0),t=0,n=0,i;n<this.graph.vertices.length;n++)i=this.graph.vertices[n],i.positioned&&(e.add(i.position),t++);return e.divide(t)}},{key:"getCurrentCenterOfMassInNeigbourhood",value:function(e){for(var t=1<arguments.length&&void 0!==arguments[1]?arguments[1]:2*this.opts.bondLength,n=new l(0,0),r=0,a=0,i;a<this.graph.vertices.length;a++)i=this.graph.vertices[a],i.positioned&&e.distanceSq(i.position)<t*t&&(n.add(i.position),r++);return n.divide(r)}},{key:"resolvePrimaryOverlaps",value:function(){for(var e=[],t=Array(this.graph.vertices.length),n=0,i;n<this.rings.length;n++){i=this.rings[n];for(var o=0,l;o<i.members.length;o++)if(l=this.graph.vertices[i.members[o]],!t[l.id]){t[l.id]=!0;var s=this.getNonRingNeighbours(l.id);if(1<s.length){for(var g=[],d=0;d<l.value.rings.length;d++)g.push(l.value.rings[d]);e.push({common:l,rings:g,vertices:s})}else if(1===s.length&&2===l.value.rings.length){for(var u=[],d=0;d<l.value.rings.length;d++)u.push(l.value.rings[d]);e.push({common:l,rings:u,vertices:s})}}}for(var n=0,h;n<e.length;n++)if(h=e[n],2===h.vertices.length){var c=h.vertices[0],a=h.vertices[1];if(!c.value.isDrawn||!a.value.isDrawn)continue;var p=(2*r-this.getRing(h.rings[0]).getAngle())/6;this.rotateSubtree(c.id,h.common.id,p,h.common.position),this.rotateSubtree(a.id,h.common.id,-p,h.common.position);var v=this.getOverlapScore(),y=this.getSubtreeOverlapScore(c.id,h.common.id,v.vertexScores),m=this.getSubtreeOverlapScore(a.id,h.common.id,v.vertexScores),f=y.value+m.value;this.rotateSubtree(c.id,h.common.id,-2*p,h.common.position),this.rotateSubtree(a.id,h.common.id,2*p,h.common.position),v=this.getOverlapScore(),y=this.getSubtreeOverlapScore(c.id,h.common.id,v.vertexScores),m=this.getSubtreeOverlapScore(a.id,h.common.id,v.vertexScores),y.value+m.value>f&&(this.rotateSubtree(c.id,h.common.id,2*p,h.common.position),this.rotateSubtree(a.id,h.common.id,-2*p,h.common.position))}else 1!==h.vertices.length||2!==h.rings.length}},{key:"resolveSecondaryOverlaps",value:function(e){for(var t=0;t<e.length;t++)if(e[t].score>this.opts.overlapSensitivity){var n=this.graph.vertices[e[t].id];if(n.isTerminal()){var i=this.getClosestVertex(n);if(i){var r=null;r=i.isTerminal()?0===i.id?this.graph.vertices[1].position:i.previousPosition:0===i.id?this.graph.vertices[1].position:i.position;var a=0===n.id?this.graph.vertices[1].position:n.previousPosition;n.position.rotateAwayFrom(r,a,g.toRad(20))}}}}},{key:"getLastVertexWithAngle",value:function(e){for(var t=0,n=null;!t&&e;)n=this.graph.vertices[e],t=n.angle,e=n.parentVertexId;return n}},{key:"createNextBond",value:function(e){var t=1<arguments.length&&void 0!==arguments[1]?arguments[1]:null,n=2<arguments.length&&void 0!==arguments[2]?arguments[2]:0,u=3<arguments.length&&void 0!==arguments[3]&&arguments[3],h=4<arguments.length&&void 0!==arguments[4]&&arguments[4];if(!e.positioned||h){var c=!1;if(t){var p=this.graph.getEdge(e.id,t.id);("/"===p.bondType||"\\"===p.bondType)&&1==++this.doubleBondConfigCount%2&&null===this.doubleBondConfig&&(this.doubleBondConfig=p.bondType,c=!0,null===t.parentV