Clazz.declarePackage("JM");
Clazz.load(["JM.AtomCollection", "JU.V3"], "JM.BondCollection", ["JU.AU", "$.BS", "$.Measure", "JM.Bond", "$.BondIteratorSelected", "$.BondSet", "$.HBond", "JU.C", "$.Edge"], function(){
var c$ = Clazz.decorateAsClass(function(){
this.bo = null;
this.bondCount = 0;
this.numCached = null;
this.freeBonds = null;
this.molecules = null;
this.moleculeCount = 0;
this.defaultCovalentMad = 0;
this.bsAromaticSingle = null;
this.bsAromaticDouble = null;
this.bsAromatic = null;
this.haveHiddenBonds = false;
this.v1 = null;
this.v2 = null;
this.haveAtropicBonds = false;
Clazz.instantialize(this, arguments);}, JM, "BondCollection", JM.AtomCollection);
Clazz.prepareFields (c$, function(){
this.v1 =  new JU.V3();
this.v2 =  new JU.V3();
});
Clazz.defineMethod(c$, "setupBC", 
function(){
this.bsAromatic =  new JU.BS();
this.numCached =  Clazz.newIntArray (5, 0);
this.freeBonds =  new Array(5);
for (var i = 5; --i > 0; ) this.freeBonds[i] =  new Array(200);

this.setupAC();
});
Clazz.defineMethod(c$, "releaseModelSetBC", 
function(){
this.bo = null;
this.freeBonds = null;
this.releaseModelSetAC();
});
Clazz.defineMethod(c$, "getBondIteratorForType", 
function(bondType, bsAtoms){
return  new JM.BondIteratorSelected(this.bo, this.bondCount, bondType, bsAtoms, this.vwr.getBoolean(603979812));
}, "~N,JU.BS");
Clazz.defineMethod(c$, "getBondIterator", 
function(bsBonds){
return  new JM.BondIteratorSelected(this.bo, this.bondCount, 131071, bsBonds, false);
}, "JU.BS");
Clazz.defineMethod(c$, "getBondColix1", 
function(i){
return JU.C.getColixInherited(this.bo[i].colix, this.bo[i].atom1.colixAtom);
}, "~N");
Clazz.defineMethod(c$, "getBondColix2", 
function(i){
return JU.C.getColixInherited(this.bo[i].colix, this.bo[i].atom2.colixAtom);
}, "~N");
Clazz.defineMethod(c$, "getBondCountInModel", 
function(modelIndex){
var n = 0;
for (var i = this.bondCount; --i >= 0; ) if (this.bo[i] != null && this.bo[i].atom1.mi == modelIndex) n++;

return n;
}, "~N");
Clazz.defineMethod(c$, "getBondsForSelectedAtoms", 
function(bsAtoms, bondSelectionModeOr){
var bs =  new JU.BS();
var n = bsAtoms.cardinality();
switch (n) {
case 0:
return bs;
case 1:
case 2:
var a = this.at[bsAtoms.nextSetBit(0)];
var b = (n == 2 ? this.at[bsAtoms.nextSetBit(a.i + 1)] : null);
if (n == 1 || bondSelectionModeOr) {
for (var i = a.getBondCount(); --i >= 0; ) bs.set(a.bonds[i].index);

if (b != null) for (var i = b.getBondCount(); --i >= 0; ) bs.set(b.bonds[i].index);

} else {
var bond = a.getBond(b);
if (bond != null) bs.set(bond.index);
}return bs;
}
for (var iBond = 0; iBond < this.bondCount; ++iBond) {
var bond = this.bo[iBond];
if (bond == null) continue;
var isSelected1 = bsAtoms.get(bond.atom1.i);
var isSelected2 = bsAtoms.get(bond.atom2.i);
if (bondSelectionModeOr ? isSelected1 || isSelected2 : isSelected1 && isSelected2) bs.set(iBond);
}
return bs;
}, "JU.BS,~B");
Clazz.defineMethod(c$, "bondAtoms", 
function(atom1, atom2, order, mad, bsBonds, energy, addGroup, isNew){
var bond = this.getOrAddBond(atom1, atom2, order, mad, bsBonds, energy, true);
if (isNew) {
bond.order |= 131072;
if (addGroup) {
atom1.group = atom2.group;
atom1.group.addAtoms(atom1.i);
}}return bond;
}, "JM.Atom,JM.Atom,~N,~N,JU.BS,~N,~B,~B");
Clazz.defineMethod(c$, "getOrAddBond", 
function(atom, atomOther, order, mad, bsBonds, energy, overrideBonding){
var i;
if (order == 131071 || order == 65535) order = 1;
if (atom.isBonded(atomOther)) {
i = atom.getBond(atomOther).index;
if (overrideBonding) {
this.bo[i].setOrder(order);
this.bo[i].setMad(mad);
if (Clazz.instanceOf(this.bo[i],"JM.HBond")) (this.bo[i]).energy = energy;
}} else {
if (this.bondCount == this.bo.length) this.bo = JU.AU.arrayCopyObject(this.bo, this.bondCount + 250);
i = this.setBond(this.bondCount++, this.bondMutually(atom, atomOther, order, mad, energy)).index;
}if (bsBonds != null) bsBonds.set(i);
return this.bo[i];
}, "JM.Atom,JM.Atom,~N,~N,JU.BS,~N,~B");
Clazz.defineMethod(c$, "setBond", 
function(index, bond){
return this.bo[bond.index = index] = bond;
}, "~N,JM.Bond");
Clazz.defineMethod(c$, "bondMutually", 
function(atom, atomOther, order, mad, energy){
var bond;
if (JU.Edge.isOrderH(order)) {
bond =  new JM.HBond(atom, atomOther, order, mad, 0, energy);
} else {
bond =  new JM.Bond(atom, atomOther, order, mad, 0);
}this.addBondToAtom(atom, bond);
this.addBondToAtom(atomOther, bond);
return bond;
}, "JM.Atom,JM.Atom,~N,~N,~N");
Clazz.defineMethod(c$, "addBondToAtom", 
function(atom, bond){
if (atom.bonds == null) {
atom.bonds =  new Array(1);
atom.bonds[0] = bond;
} else {
atom.bonds = this.addToBonds(bond, atom.bonds);
}}, "JM.Atom,JM.Bond");
Clazz.defineMethod(c$, "addToBonds", 
function(newBond, oldBonds){
var newBonds;
if (oldBonds == null) {
if (this.numCached[1] > 0) newBonds = this.freeBonds[1][--this.numCached[1]];
 else newBonds =  new Array(1);
newBonds[0] = newBond;
} else {
var oldLength = oldBonds.length;
var newLength = oldLength + 1;
if (newLength < 5 && this.numCached[newLength] > 0) newBonds = this.freeBonds[newLength][--this.numCached[newLength]];
 else newBonds =  new Array(newLength);
newBonds[oldLength] = newBond;
for (var i = oldLength; --i >= 0; ) newBonds[i] = oldBonds[i];

if (oldLength < 5 && this.numCached[oldLength] < 200) this.freeBonds[oldLength][this.numCached[oldLength]++] = oldBonds;
}return newBonds;
}, "JM.Bond,~A");
Clazz.defineMethod(c$, "addHBond", 
function(atom1, atom2, order, energy){
if (this.bondCount == this.bo.length) this.bo = JU.AU.arrayCopyObject(this.bo, this.bondCount + 250);
return this.setBond(this.bondCount++, this.bondMutually(atom1, atom2, order, 1, energy)).index;
}, "JM.Atom,JM.Atom,~N,~N");
Clazz.defineMethod(c$, "deleteAllBonds2", 
function(){
this.vwr.setShapeProperty(1, "reset", null);
for (var i = this.bondCount; --i >= 0; ) {
if (this.bo[i] == null) continue;
this.bo[i].deleteAtomReferences();
this.bo[i] = null;
}
this.bondCount = 0;
});
Clazz.defineMethod(c$, "getDefaultMadFromOrder", 
function(order){
return (JU.Edge.isOrderH(order) ? 1 : order == 32768 ? Clazz.doubleToInt(Math.floor(this.vwr.getFloat(570425406) * 2000)) : this.defaultCovalentMad);
}, "~N");
Clazz.defineMethod(c$, "deleteConnections", 
function(minD, maxD, order, bsA, bsB, isBonds, matchNull){
var minDIsFraction = (minD < 0);
var maxDIsFraction = (maxD < 0);
var isFractional = (minDIsFraction || maxDIsFraction);
minD = this.fixD(minD, minDIsFraction);
maxD = this.fixD(maxD, maxDIsFraction);
var bsDelete =  new JU.BS();
var nDeleted = 0;
var newOrder = order |= 131072;
if (!matchNull && JU.Edge.isOrderH(order)) order = 30720;
var bsBonds;
if (isBonds) {
bsBonds = bsA;
} else {
bsBonds =  new JU.BS();
for (var i = bsA.nextSetBit(0); i >= 0; i = bsA.nextSetBit(i + 1)) {
var a = this.at[i];
if (a.bonds != null) for (var j = a.bonds.length; --j >= 0; ) if (bsB.get(a.getBondedAtomIndex(j))) bsBonds.set(a.bonds[j].index);

}
}for (var i = bsBonds.nextSetBit(0); i < this.bondCount && i >= 0; i = bsBonds.nextSetBit(i + 1)) {
var bond = this.bo[i];
if (bond == null || !this.isInRange(bond.atom1, bond.atom2, minD, maxD, minDIsFraction, maxDIsFraction, isFractional)) continue;
if (matchNull || newOrder == (bond.order & -257 | 131072) || (order & bond.order & 30720) != 0) {
bsDelete.set(i);
nDeleted++;
}}
if (nDeleted > 0) (this).deleteBonds(bsDelete, false);
return  Clazz.newIntArray(-1, [0, nDeleted]);
}, "~N,~N,~N,JU.BS,JU.BS,~B,~B");
Clazz.defineMethod(c$, "fixD", 
function(d, isF){
return (isF ? -d : d * d);
}, "~N,~B");
Clazz.defineMethod(c$, "isInRange", 
function(atom1, atom2, minD, maxD, minFrac, maxfrac, isFractional){
var d2 = atom1.distanceSquared(atom2);
if (isFractional) {
var dAB = Math.sqrt(d2);
var dABcalc = atom1.getBondingRadius() + atom2.getBondingRadius();
return ((minFrac ? dAB >= dABcalc * minD : d2 >= minD) && (maxfrac ? dAB <= dABcalc * maxD : d2 <= maxD));
}return (d2 >= minD && d2 <= maxD);
}, "JM.Atom,JM.Atom,~N,~N,~B,~B,~B");
Clazz.defineMethod(c$, "dBb", 
function(bsBond, isFullModel){
var n = bsBond.cardinality();
if (n == 0) return;
(this).resetMolecules();
var modelIndexLast = -1;
for (var i = bsBond.nextSetBit(0); i >= 0 && i < this.bondCount; i = bsBond.nextSetBit(i + 1)) {
var bond = this.bo[i];
if (bond != null && bsBond.get(i)) {
if (!isFullModel) {
var modelIndex = bond.atom1.mi;
if (modelIndex != modelIndexLast) (this).am[modelIndexLast = modelIndex].resetBoundCount();
}bond.deleteAtomReferences();
this.bo[i] = null;
}}
var sets = this.vwr.getShapeProperty(1, "sets");
if (sets != null) for (var i = 0; i < sets.length; i++) if (sets[i] != null) sets[i].andNot(bsBond);

this.bsAromatic.andNot(bsBond);
}, "JU.BS,~B");
Clazz.defineMethod(c$, "resetAromatic", 
function(){
for (var i = this.bondCount; --i >= 0; ) {
var bond = this.bo[i];
if (bond != null && bond.isAromatic()) bond.setOrder(515);
}
});
Clazz.defineMethod(c$, "assignAromaticBondsBs", 
function(isUserCalculation, bsBonds){
if (!isUserCalculation) this.bsAromatic =  new JU.BS();
this.bsAromaticSingle =  new JU.BS();
this.bsAromaticDouble =  new JU.BS();
var isAll = (bsBonds == null);
var i0 = (isAll ? this.bondCount - 1 : bsBonds.nextSetBit(0));
for (var i = i0; i >= 0; i = (isAll ? i - 1 : bsBonds.nextSetBit(i + 1))) {
var bond = this.bo[i];
if (bond == null) continue;
if (this.bsAromatic.get(i)) bond.setOrder(515);
switch (bond.order & 131071) {
case 515:
if (!this.assignAromaticMustBeSingle(bond.atom1) && !this.assignAromaticMustBeSingle(bond.atom2)) {
this.bsAromatic.set(i);
break;
}bond.order = 513;
case 513:
this.bsAromaticSingle.set(i);
break;
case 514:
this.bsAromaticDouble.set(i);
break;
}
}
var bond;
isAll = (bsBonds == null);
i0 = (isAll ? this.bondCount - 1 : bsBonds.nextSetBit(0));
var bsTest =  new JU.BS();
for (var i = i0; i >= 0; i = (isAll ? i - 1 : bsBonds.nextSetBit(i + 1))) {
bond = this.bo[i];
if (bond == null || !bond.is(515) || this.bsAromaticDouble.get(i) || this.bsAromaticSingle.get(i)) continue;
bsTest.set(i);
if (bond.atom1.getElementNumber() == 8 || bond.atom2.getElementNumber() == 8) {
if (!this.assignAromaticDouble(bond)) this.assignAromaticSingle(bond);
}}
for (var i = bsTest.nextSetBit(0); i >= 0; i = bsTest.nextSetBit(i + 1)) if (!this.assignAromaticDouble(bond = this.bo[i])) this.assignAromaticSingle(bond);

var bsModels =  new JU.BS();
for (var i = i0; i >= 0; i = (isAll ? i - 1 : bsBonds.nextSetBit(i + 1))) {
bond = this.bo[i];
if (bond == null) continue;
if (this.bsAromaticDouble.get(i)) {
if (!bond.is(514)) {
this.bsAromatic.set(i);
bsModels.set(bond.atom1.mi);
bond.setOrder(this.isLinear(bond, this.v1, this.v2) ? 3 : 514);
}} else if (this.bsAromaticSingle.get(i) || bond.isAromatic()) {
if (!bond.is(513)) {
this.bsAromatic.set(i);
bond.setOrder(513);
}}}
var models = (this).am;
for (var i = bsModels.nextSetBit(0); i >= 0; i = bsModels.nextSetBit(i + 1)) if (models[i].isBioModel) models[i].isPdbWithMultipleBonds = true;

this.assignAromaticNandO(bsBonds);
this.bsAromaticSingle = null;
this.bsAromaticDouble = null;
}, "~B,JU.BS");
Clazz.defineMethod(c$, "isLinear", 
function(b, v1, v2){
if (b.order == 3) return true;
if (b.atom1.getCovalentBondCount() != 2 || b.atom2.getCovalentBondCount() != 2) return false;
var edges = b.atom1.getEdges();
for (var i = edges.length; -i >= 0; ) {
if (edges[i] !== b && edges[i].isCovalent()) {
if (JU.Measure.computeAngle(edges[i].getOtherNode(b.atom1), b.atom1, b.atom2, v1, v2, true) < 175) return false;
break;
}}
edges = b.atom2.getEdges();
for (var i = edges.length; -i >= 0; ) {
if (edges[i] !== b && edges[i].isCovalent()) {
if (JU.Measure.computeAngle(edges[i].getOtherNode(b.atom2), b.atom2, b.atom1, v1, v2, true) < 175) return false;
break;
}}
return true;
}, "JM.Bond,JU.V3,JU.V3");
Clazz.defineMethod(c$, "assignAromaticDouble", 
function(bond){
var bondIndex = bond.index;
if (this.bsAromaticSingle.get(bondIndex)) return false;
if (this.bsAromaticDouble.get(bondIndex)) return true;
this.bsAromaticDouble.set(bondIndex);
if (!this.assignAromaticSingleForAtom(bond.atom1, bondIndex) || !this.assignAromaticSingleForAtom(bond.atom2, bondIndex)) {
this.bsAromaticDouble.clear(bondIndex);
return false;
}return true;
}, "JM.Bond");
Clazz.defineMethod(c$, "assignAromaticSingle", 
function(bond){
var bondIndex = bond.index;
if (this.bsAromaticDouble.get(bondIndex)) return false;
if (this.bsAromaticSingle.get(bondIndex)) return true;
this.bsAromaticSingle.set(bondIndex);
if (!this.assignAromaticDoubleForAtom(bond.atom1) || !this.assignAromaticDoubleForAtom(bond.atom2)) {
this.bsAromaticSingle.clear(bondIndex);
return false;
}return true;
}, "JM.Bond");
Clazz.defineMethod(c$, "assignAromaticSingleForAtom", 
function(atom, notBondIndex){
var bonds = atom.bonds;
if (bonds == null) return false;
for (var i = bonds.length; --i >= 0; ) {
var bond = bonds[i];
var bondIndex = bond.index;
if (bondIndex == notBondIndex || !bond.isAromatic() || this.bsAromaticSingle.get(bondIndex)) continue;
if (this.bsAromaticDouble.get(bondIndex) || !this.assignAromaticSingle(bond)) {
return false;
}}
return true;
}, "JM.Atom,~N");
Clazz.defineMethod(c$, "assignAromaticDoubleForAtom", 
function(atom){
var bonds = atom.bonds;
if (bonds == null) return false;
var haveDouble = false;
var lastBond = -1;
for (var i = bonds.length; --i >= 0; ) {
if (this.bsAromaticDouble.get(bonds[i].index)) haveDouble = true;
if (bonds[i].isAromatic()) lastBond = i;
}
for (var i = bonds.length; --i >= 0; ) {
var bond = bonds[i];
var bondIndex = bond.index;
if (!bond.isAromatic() || this.bsAromaticDouble.get(bondIndex) || this.bsAromaticSingle.get(bondIndex)) continue;
if (!haveDouble && this.assignAromaticDouble(bond)) haveDouble = true;
 else if ((haveDouble || i < lastBond) && !this.assignAromaticSingle(bond)) {
return false;
}}
return haveDouble;
}, "JM.Atom");
Clazz.defineMethod(c$, "allowAromaticBond", 
function(b){
if (this.assignAromaticMustBeSingle(b.atom1) || this.assignAromaticMustBeSingle(b.atom2)) return false;
switch (b.getCovalentOrder()) {
case 1:
case 2:
return b.atom1.getCovalentBondCount() <= 3 && b.atom2.getCovalentBondCount() <= 3;
default:
return false;
}
}, "JM.Bond");
Clazz.defineMethod(c$, "assignAromaticMustBeSingle", 
function(atom){
var n = atom.getElementNumber();
switch (n) {
case 6:
case 7:
case 8:
case 16:
break;
default:
return true;
}
var valence = atom.getValenceAromatic(false);
switch (n) {
case 6:
return (valence == 4);
case 7:
return (atom.group.getNitrogenAtom() === atom || valence == 3 && atom.getFormalCharge() < 1);
case 8:
return (atom.group.getCarbonylOxygenAtom() !== atom && valence == 2 && atom.getFormalCharge() < 1);
case 16:
return (atom.group.groupID == 5 || valence == 2 && atom.getFormalCharge() < 1);
}
return false;
}, "JM.Atom");
Clazz.defineMethod(c$, "assignAromaticNandO", 
function(bsSelected){
var bond;
var isAll = (bsSelected == null);
var i0 = (isAll ? this.bondCount - 1 : bsSelected.nextSetBit(0));
for (var i = i0; i >= 0; i = (isAll ? i - 1 : bsSelected.nextSetBit(i + 1))) {
bond = this.bo[i];
if (bond == null || !bond.is(513)) continue;
var atom1;
var atom2 = bond.atom2;
var n1;
var n2 = atom2.getElementNumber();
if (n2 == 7 || n2 == 8) {
n1 = n2;
atom1 = atom2;
atom2 = bond.atom1;
n2 = atom2.getElementNumber();
} else {
atom1 = bond.atom1;
n1 = atom1.getElementNumber();
}if (n1 != 7 && n1 != 8) continue;
var valence = atom1.getValence();
if (valence < 0) continue;
var bondorder = atom1.getCovalentBondCount();
var charge = atom1.getFormalCharge();
switch (n1) {
case 7:
if (valence == 3 && bondorder == 3 && charge < 1 && n2 == 6 && atom2.getValence() == 3) bond.setOrder(514);
break;
case 8:
if (valence == 1 && charge == 0 && (n2 == 14 || n2 == 16)) bond.setOrder(514);
break;
}
}
}, "JU.BS");
Clazz.defineMethod(c$, "getAtomBitsMDb", 
function(tokType, specInfo){
var bs =  new JU.BS();
switch (tokType) {
default:
return this.getAtomBitsMDa(tokType, specInfo, bs);
case 1677721602:
var bsBonds = specInfo;
for (var i = bsBonds.nextSetBit(0); i >= 0; i = bsBonds.nextSetBit(i + 1)) {
if (i < this.bondCount) {
if (this.bo[i] != null) {
bs.set(this.bo[i].atom1.i);
bs.set(this.bo[i].atom2.i);
continue;
}}bsBonds.clear(i);
}
return bs;
case 1073742331:
for (var i = this.bondCount; --i >= 0; ) if (this.bo[i] != null && this.bo[i].isAromatic()) {
bs.set(this.bo[i].atom1.i);
bs.set(this.bo[i].atom2.i);
}
return bs;
}
}, "~N,~O");
Clazz.defineMethod(c$, "removeUnnecessaryBonds", 
function(atom, deleteAtom){
var bs =  new JU.BS();
var bsBonds =  new JU.BS();
var bonds = atom.bonds;
if (bonds == null) return;
for (var i = 0; i < bonds.length; i++) if (bonds[i].isCovalent()) {
var atom2 = bonds[i].getOtherAtom(atom);
if (atom2.getElementNumber() == 1) bs.set(bonds[i].getOtherAtom(atom).i);
} else {
bsBonds.set(bonds[i].index);
}
if (bsBonds.nextSetBit(0) >= 0) (this).deleteBonds(bsBonds, false);
if (deleteAtom) bs.set(atom.i);
if (bs.nextSetBit(0) >= 0) this.vwr.deleteAtoms(bs, false);
}, "JM.Atom,~B");
Clazz.defineMethod(c$, "displayBonds", 
function(bs, isDisplay){
if (!isDisplay) this.haveHiddenBonds = true;
for (var i = bs.nextSetBit(0); i >= 0; i = bs.nextSetBit(i + 1)) if (i < this.bondCount && this.bo[i] != null && this.bo[i].mad != 0) this.bo[i].setShapeVisibility(isDisplay);

}, "JM.BondSet,~B");
Clazz.defineMethod(c$, "getAtomsConnected", 
function(min, max, intType, bs){
var isBonds = Clazz.instanceOf(bs,"JM.BondSet");
var bsResult = (isBonds ?  new JM.BondSet() :  new JU.BS());
var nBonded =  Clazz.newIntArray (this.ac, 0);
var i;
var ishbond = (intType == 30720);
var isall = (intType == 65535);
for (var ibond = 0; ibond < this.bondCount; ibond++) {
var bond = this.bo[ibond];
if (bond != null && (isall || bond.is(intType) || ishbond && bond.isHydrogen())) {
if (isBonds) {
bsResult.set(ibond);
} else {
if (bs.get(bond.atom1.i)) {
nBonded[i = bond.atom2.i]++;
bsResult.set(i);
}if (bs.get(bond.atom2.i)) {
nBonded[i = bond.atom1.i]++;
bsResult.set(i);
}}}}
if (isBonds) return bsResult;
var nonbonded = (min == 0);
for (i = this.ac; --i >= 0; ) {
var n = nBonded[i];
if (this.at[i] == null || n < min || n > max) bsResult.clear(i);
 else if (nonbonded && n == 0) bsResult.set(i);
}
return bsResult;
}, "~N,~N,~N,JU.BS");
Clazz.defineMethod(c$, "addConnectedHAtoms", 
function(atom, bsAtoms){
if (atom.bonds != null) for (var i = atom.bonds.length; --i >= 0; ) {
var atom2 = atom.bonds[i].getOtherAtom(atom);
if (atom2.getElementNumber() == 1) bsAtoms.set(atom2.i);
}
}, "JM.Atom,JU.BS");
});
;//5.0.1-v5 Sun Mar 02 21:12:35 CST 2025
