Generate rendering elements for a bond, without ring elements but
considering the type of the bond (single, double, triple).

@param bond the bond to use when generating elements
@param model the renderer model
@return one or more rendering elements
339107
public IRenderingElement generateBondElement(IBond bond, RendererModel model) {
        return generateBondElement(bond, bond.getOrder(), model);
    }
1367916
@Override
    public DescriptorValue calculate(IBond bond, IAtomContainer atomContainer) {
        double value = 0;
        // FIXME: for now I'll cache a few modified atomic properties, and restore them at the end of this method
        String originalAtomtypeName1 = bond.getBegin().getAtomTypeName();
        Integer originalNeighborCount1 = bond.getBegin().getFormalNeighbourCount();
        IAtomType.Hybridization originalHybridization1 = bond.getBegin().getHybridization();
        Integer originalValency1 = bond.getBegin().getValency();
        String originalAtomtypeName2 = bond.getEnd().getAtomTypeName();
        Integer originalNeighborCount2 = bond.getEnd().getFormalNeighbourCount();
        IAtomType.Hybridization originalHybridization2 = bond.getEnd().getHybridization();
        Integer originalValency2 = bond.getEnd().getValency();
        Double originalBondOrderSum1 = bond.getBegin().getBondOrderSum();
        Order originalMaxBondOrder1 = bond.getBegin().getMaxBondOrder();
        Double originalBondOrderSum2 = bond.getEnd().getBondOrderSum();
        Order originalMaxBondOrder2 = bond.getEnd().getMaxBondOrder();

        if (!isCachedAtomContainer(atomContainer)) {
            try {
                AtomContainerManipulator.percieveAtomTypesAndConfigureAtoms(atomContainer);
                LonePairElectronChecker lpcheck = new LonePairElectronChecker();
                lpcheck.saturate(atomContainer);
            } catch (CDKException e) {
                return getDummyDescriptorValue(e);
            }

        }
        if (!bond.getOrder().equals(IBond.Order.SINGLE)) {
            try {
                value = IonizationPotentialTool.predictIP(atomContainer, bond);
            } catch (CDKException e) {
                return getDummyDescriptorValue(e);
            }
        }
        bond.getBegin().setAtomTypeName(originalAtomtypeName1);
        bond.getBegin().setHybridization(originalHybridization1);
        bond.getBegin().setValency(originalValency1);
        bond.getBegin().setFormalNeighbourCount(originalNeighborCount1);
        bond.getEnd().setAtomTypeName(originalAtomtypeName2);
        bond.getEnd().setHybridization(originalHybridization2);
        bond.getEnd().setValency(originalValency2);
        bond.getEnd().setFormalNeighbourCount(originalNeighborCount2);
        bond.getBegin().setMaxBondOrder(originalMaxBondOrder1);
        bond.getBegin().setBondOrderSum(originalBondOrderSum1);
        bond.getEnd().setMaxBondOrder(originalMaxBondOrder2);
        bond.getEnd().setBondOrderSum(originalBondOrderSum2);

        return new DescriptorValue(getSpecification(), getParameterNames(), getParameters(), new DoubleResult(value),
                DESCRIPTOR_NAMES);
    }
342346
public static IBond deref(IBond bond) {
        while (bond instanceof BondRef)
            bond = ((BondRef) bond).deref();
        return bond;
    }
550055
public static MarkedElement markupBond(IRenderingElement elem, IBond bond) {
        assert elem != null;
        MarkedElement tagElem = markupChemObj(elem, bond);
        tagElem.aggClass("bond");
        return tagElem;
    }
944628
public List<String> getChainIds() {

		List<String> chains = new ArrayList<String>(getSubunitCount());

		// Loop through all subunits in the clusters and fill Lists
		for (int c = 0; c < clusters.size(); c++) {
			for (int s = 0; s < clusters.get(c).size(); s++)
				chains.add(clusters.get(c).getSubunits().get(s).getName());
		}

		return chains;
	}

	/**
	 * This method is provisional and should only be used for coloring Subunits.
	 * A new coloring schema has to be implemented to allow the coloring of
	 * Subunits, without implying one Subunit = one Chain.
	 *
	 * @return A List of the Model number of each Subunit
	 */
	public List<Integer> getModelNumbers() {

		List<Integer> models = new ArrayList<Integer>(getSubunitCount());

		// Loop through all subunits in the clusters and fill Lists
		for (int c = 0; c < clusters.size(); c++) {
			for (int s = 0; s < clusters.get(c).size(); s++) {

				Atom[] atoms = clusters.get(c).getAlignedAtomsSubunit(s);

				// TODO guess them chain and model (very ugly)
				Chain chain = atoms[0].getGroup().getChain();

				int model = 0;
				for (int m = 0; m < chain.getStructure().nrModels(); m++) {
					if (chain.getStructure().getModel(m).contains(chain)) {
						model = m;
						break;
					}
				}
				models.add(model);
			}
		}
		return models;
	}

	public int getSubunitCount() {
		run();
		if (centers == null) {
			return 0;
		}
		return centers.size();
	}

	public List<Integer> getFolds() {
		return folds;
	}

	public int getCalphaCount() {
		int count = 0;
		for (Point3d[] trace : caCoords) {
			count += trace.length;
		}
		return count;
	}

	public int getLargestSubunit() {
		int index = -1;
		int maxLength = 0;
		for (int i = 0; i < caCoords.size(); i++) {
			int length = caCoords.get(i).length;
			if (length > maxLength) {
				index = i;
			}
		}
		return index;
	}

	public List<Point3d> getCenters() {
		run();
		return centers;
	}

	public List<Vector3d> getUnitVectors() {
		run();
		return unitVectors;
	}

	public List<Point3d> getOriginalCenters() {
		run();
		return originalCenters;
	}

	public Point3d getCentroid() {
		run();
		return centroid;
	}

	public MomentsOfInertia getMomentsOfInertia() {
		run();
		return momentsOfInertia;
	}

	private void run() {
		if (centers.size() > 0) {
			return;
		}
		calcOriginalCenters();
		calcCentroid();
		calcCenters();
		calcMomentsOfIntertia();
	}

	private void calcOriginalCenters() {
		for (Point3d[] trace : caCoords) {
			Point3d com = CalcPoint.centroid(trace);
			originalCenters.add(com);
		}
	}

	private void calcCentroid() {
		Point3d[] orig = originalCenters.toArray(new Point3d[originalCenters
				.size()]);
		centroid = CalcPoint.centroid(orig);
	}

	private void calcCenters() {
		for (Point3d p : originalCenters) {
			Point3d c = new Point3d(p);
			c.sub(centroid);
			centers.add(c);
			Vector3d v = new Vector3d(c);
			v.normalize();
			unitVectors.add(v);
		}
	}

	public Point3d getLowerBound() {
		Point3d lower = new Point3d();
		for (Point3d p : centers) {
			if (p.x < lower.x) {
				lower.x = p.x;
			}
			if (p.y < lower.y) {
				lower.y = p.y;
			}
			if (p.z < lower.z) {
				lower.z = p.z;
			}
		}
		return lower;
	}

	public Point3d getUpperBound() {
		Point3d upper = new Point3d();
		for (Point3d p : centers) {
			if (p.x > upper.x) {
				upper.x = p.x;
			}
			if (p.y > upper.y) {
				upper.y = p.y;
			}
			if (p.z > upper.z) {
				upper.z = p.z;
			}
		}
		return upper;
	}

	private void calcMomentsOfIntertia() {
		for (Point3d[] trace : caCoords) {
			for (Point3d p : trace) {
				momentsOfInertia.addPoint(p, 1.0f);
			}
		}
	}

}
1338833
public static double getBondLengthMedian(final IAtomContainer container) {
        if (container.getBondCount() == 0) throw new IllegalArgumentException("Container has no bonds.");
        int nBonds = 0;
        double[] lengths = new double[container.getBondCount()];
        for (int i = 0; i < container.getBondCount(); i++) {
            final IBond bond = container.getBond(i);
            final IAtom atom1 = bond.getBegin();
            final IAtom atom2 = bond.getEnd();
            Point2d p1 = atom1.getPoint2d();
            Point2d p2 = atom2.getPoint2d();
            if (p1 == null || p2 == null)
                throw new IllegalArgumentException("An atom has no 2D coordinates.");
            if (p1.x != p2.x || p1.y != p2.y)
                lengths[nBonds++] = p1.distance(p2);
        }
        Arrays.sort(lengths, 0, nBonds);
        return lengths[nBonds / 2];
    }
987004
@Override
    public double calculateScaleForBondLength(double modelBondLength) {
        if (Double.isNaN(modelBondLength) || modelBondLength == 0) {
            return DEFAULT_SCALE;
        } else {
            return rendererModel.getParameter(BondLength.class).getValue() / modelBondLength;
        }
    }
619231
protected String getBondSymbol(IBond bond) {
        String bondSymbol = "";
        if (bond.getOrder() == IBond.Order.SINGLE) {
            if (isSP2Bond(bond)) {
                bondSymbol = ":";
            } else {
                bondSymbol = "-";
            }
        } else if (bond.getOrder() == IBond.Order.DOUBLE) {
            if (isSP2Bond(bond)) {
                bondSymbol = ":";
            } else {
                bondSymbol = "=";
            }
        } else if (bond.getOrder() == IBond.Order.TRIPLE) {
            bondSymbol = "#";
        } else if (bond.getOrder() == IBond.Order.QUADRUPLE) {
            bondSymbol = "*";
        }
        return bondSymbol;
    }
1269169
public IRenderingElement generateDiagram(T object) {
        ElementGroup diagram = new ElementGroup();
        for (IGenerator<T> generator : this.generators) {
            diagram.add(generator.generate(object, this.rendererModel));
        }
        return diagram;
    }
1269110
public static Set<IBond> findMappedBonds(IReaction reaction) {
        Set<IBond> mapped = new HashSet<>();

        // first we collect the occurrance of mapped bonds from reacants then products
        Set<IntTuple> mappedReactantBonds = new HashSet<>();
        Set<IntTuple> mappedProductBonds  = new HashSet<>();
        for (IAtomContainer reactant : reaction.getReactants().atomContainers()) {
            for (IBond bond : reactant.bonds()) {
                Integer begidx = bond.getBegin().getProperty(CDKConstants.ATOM_ATOM_MAPPING);
                Integer endidx = bond.getEnd().getProperty(CDKConstants.ATOM_ATOM_MAPPING);
                if (begidx != null && endidx != null)
                    mappedReactantBonds.add(new IntTuple(begidx, endidx));
            }
        }
        // fail fast
        if (mappedReactantBonds.isEmpty())
            return Collections.emptySet();

        for (IAtomContainer product : reaction.getProducts().atomContainers()) {
            for (IBond bond : product.bonds()) {
                Integer begidx = bond.getBegin().getProperty(CDKConstants.ATOM_ATOM_MAPPING);
                Integer endidx = bond.getEnd().getProperty(CDKConstants.ATOM_ATOM_MAPPING);
                if (begidx != null && endidx != null)
                    mappedProductBonds.add(new IntTuple(begidx, endidx));
            }
        }
        // fail fast
        if (mappedProductBonds.isEmpty())
            return Collections.emptySet();

        // repeat above but now store any that are different or unmapped as being mapped
        for (IAtomContainer reactant : reaction.getReactants().atomContainers()) {
            for (IBond bond : reactant.bonds()) {
                Integer begidx = bond.getBegin().getProperty(CDKConstants.ATOM_ATOM_MAPPING);
                Integer endidx = bond.getEnd().getProperty(CDKConstants.ATOM_ATOM_MAPPING);
                if (begidx != null && endidx != null && mappedProductBonds.contains(new IntTuple(begidx, endidx)))
                    mapped.add(bond);
            }
        }
        for (IAtomContainer product : reaction.getProducts().atomContainers()) {
            for (IBond bond : product.bonds()) {
                Integer begidx = bond.getBegin().getProperty(CDKConstants.ATOM_ATOM_MAPPING);
                Integer endidx = bond.getEnd().getProperty(CDKConstants.ATOM_ATOM_MAPPING);
                if (begidx != null && endidx != null && mappedReactantBonds.contains(new IntTuple(begidx, endidx)))
                    mapped.add(bond);
            }
        }
        return mapped;
    }
54275
public static double calculateAverageBondLength(IChemModel model) {

        // empty models have to have a scale
        IAtomContainerSet moleculeSet = model.getMoleculeSet();
        if (moleculeSet == null) {
            IReactionSet reactionSet = model.getReactionSet();
            if (reactionSet != null) {
                return calculateAverageBondLength(reactionSet);
            }
            return 0.0;
        }

        return calculateAverageBondLength(moleculeSet);
    }
143791
public Blacklist generateBlacklist(Model model)
	{
		Blacklist blacklist = new Blacklist();

		// populate the blacklist

		for (SmallMoleculeReference smr : model.getObjects(SmallMoleculeReference.class))
		{
			String name = smr.getDisplayName();
			if (name == null) continue;
			name = name.toLowerCase();

			if (knownNames.containsKey(name))
			{
				blacklist.addEntry(smr.getUri(), 1, knownNames.get(name));

				for (SimplePhysicalEntity spe : smr.getEntityReferenceOf())
				{
					blacklist.addEntry(spe.getUri(), 1, knownNames.get(name));
				}
			}
		}

		return blacklist;
	}
183765
public boolean cyclic(IBond bond) {
        // XXX: linear search - but okay for now
        int u = container.indexOf(bond.getBegin());
        int v = container.indexOf(bond.getEnd());
        if (u < 0 || v < 0) throw new NoSuchElementException("atoms of the bond are not found in the container");
        return searcher.cyclic(u, v);
    }
544625
@Override
    public IRingSet getRings(IBond bond) {
        IRingSet rings = bond.getBuilder().newInstance(IRingSet.class);
        Ring ring;
        for (int i = 0; i < getAtomContainerCount(); i++) {
            ring = (Ring) getAtomContainer(i);
            if (ring.contains(bond)) {
                rings.addAtomContainer(ring);
            }
        }
        return rings;
    }
535105
public void elementDecl(String name, String model) throws SAXException {
		if (preserveDTD) {
			// e.g. <!ELEMENT Hello (#PCDATA)>
			// --> name == Hello && model == (#PCDATA) <--
			docTypeText += "<!ELEMENT " + name + " " + model + "> ";
		}
	}
990638
public AtomSymbolElement generateElement(IAtom atom, int alignment, RendererModel model) {
        String text;
        if (atom instanceof IPseudoAtom) {
            text = ((IPseudoAtom) atom).getLabel();
        } else {
            text = atom.getSymbol();
        }
        return new AtomSymbolElement(atom.getPoint2d().x, atom.getPoint2d().y, text, atom.getFormalCharge(),
                atom.getImplicitHydrogenCount(), alignment, getAtomColor(atom, model));
    }
4313
public Blacklist generateBlacklist(Model model)
	{
		ChemicalNameNormalizer normalizer = new ChemicalNameNormalizer(model);
		SIFSearcher searcher = new SIFSearcher(new Fetcher(normalizer), SIFEnum.USED_TO_PRODUCE);

		Set<SIFInteraction> sifs = searcher.searchSIF(model);

		// read interactions into maps

		Map<String, Set<String>> upstrMap = new HashMap<String, Set<String>>();
		Map<String, Set<String>> dwstrMap = new HashMap<String, Set<String>>();
		Map<String, Set<String>> neighMap = new HashMap<String, Set<String>>();

		for (SIFInteraction sif : sifs)
		{
			String source = sif.sourceID;
			String target = sif.targetID;

			if (!neighMap.containsKey(source)) neighMap.put(source, new HashSet<String>());
			if (!neighMap.containsKey(target)) neighMap.put(target, new HashSet<String>());
			if (!dwstrMap.containsKey(source)) dwstrMap.put(source, new HashSet<String>());
			if (!dwstrMap.containsKey(target)) dwstrMap.put(target, new HashSet<String>());
			if (!upstrMap.containsKey(source)) upstrMap.put(source, new HashSet<String>());
			if (!upstrMap.containsKey(target)) upstrMap.put(target, new HashSet<String>());

			neighMap.get(source).add(target);
			neighMap.get(target).add(source);
			dwstrMap.get(source).add(target);
			upstrMap.get(target).add(source);
		}

		// remove intersection of upstream and downstream

		for (String name : neighMap.keySet())
		{
			if (!upstrMap.containsKey(name) || !dwstrMap.containsKey(name)) continue;

			Set<String> upstr = upstrMap.get(name);
			Set<String> dwstr = dwstrMap.get(name);

			Set<String> temp = new HashSet<String>(upstr);
			upstr.removeAll(dwstr);
			dwstr.removeAll(temp);
		}


		Blacklist blacklist = new Blacklist();

		// populate the blacklist

		for (SmallMoleculeReference smr : model.getObjects(SmallMoleculeReference.class))
		{
			String name = normalizer.getName(smr);

			int neighSize = neighMap.containsKey(name) ? neighMap.get(name).size() : 0;
			int upstrOnly = upstrMap.containsKey(name) ? upstrMap.get(name).size() : 0;
			int dwstrOnly = dwstrMap.containsKey(name) ? dwstrMap.get(name).size() : 0;

//			if (neighSize > 30) System.out.println(name + "\t" + neighSize + "\t" + upstrOnly + "\t" + dwstrOnly);

			if (decider.isUbique(neighSize, upstrOnly, dwstrOnly))
			{
				blacklist.addEntry(smr.getUri(),
					decider.getScore(neighSize, upstrOnly, dwstrOnly),
					decider.getContext(neighSize, upstrOnly, dwstrOnly));
			}
		}

		return blacklist;
	}