in packages/ketcher-core/src/application/render/renderers/sequence/SequenceRenderer.ts [196:312]
private static showBonds(chainsCollection: ChainsCollection) {
const handledMonomersToAttachmentPoints: Map<
BaseMonomer,
Set<AttachmentPointName>
> = new Map();
chainsCollection.chains.forEach((chain) => {
chain.subChains.forEach((subChain) => {
subChain.nodes.forEach((node) => {
if (node instanceof EmptySequenceNode) {
return;
}
node.monomers.forEach((monomer) => {
if (!handledMonomersToAttachmentPoints.has(monomer)) {
handledMonomersToAttachmentPoints.set(monomer, new Set());
}
monomer.forEachBond((polymerBond, attachmentPointName) => {
const handledAttachmentPoints =
handledMonomersToAttachmentPoints.get(
monomer,
) as Set<AttachmentPointName>;
if (polymerBond instanceof MonomerToAtomBond) {
const bondRenderer = new MonomerToAtomBondSequenceRenderer(
polymerBond,
node,
);
bondRenderer.show();
polymerBond.setRenderer(bondRenderer);
handledAttachmentPoints.add(attachmentPointName);
return;
}
if (!subChain.bonds.includes(polymerBond)) {
subChain.bonds.push(polymerBond);
}
if (!polymerBond.isSideChainConnection) {
polymerBond.setRenderer(
new BackBoneBondSequenceRenderer(polymerBond),
);
return;
}
if (handledAttachmentPoints.has(attachmentPointName)) {
return;
}
const anotherMonomer = polymerBond.getAnotherEntity(
monomer,
) as BaseMonomer;
// Skip handling side chains for sugar(R3) + base(R1) connections.
if (
(monomer instanceof Sugar &&
getRnaBaseFromSugar(monomer) === anotherMonomer) ||
(anotherMonomer instanceof Sugar &&
getRnaBaseFromSugar(anotherMonomer) === monomer)
) {
return;
}
let bondRenderer;
// If side connection comes from rna base then take connected sugar and draw side connection from it
// because for rna we display only one letter instead of three
const connectedSugarToBase = getSugarFromRnaBase(anotherMonomer);
if (
isRnaBaseOrAmbiguousRnaBase(anotherMonomer) &&
connectedSugarToBase
) {
bondRenderer = new PolymerBondSequenceRenderer(
new PolymerBond(monomer, connectedSugarToBase),
);
} else {
bondRenderer = new PolymerBondSequenceRenderer(polymerBond);
}
bondRenderer.show();
polymerBond.setRenderer(bondRenderer);
handledAttachmentPoints.add(attachmentPointName);
if (!handledMonomersToAttachmentPoints.get(anotherMonomer)) {
handledMonomersToAttachmentPoints.set(
anotherMonomer,
new Set(),
);
}
const anotherMonomerHandledAttachmentPoints =
handledMonomersToAttachmentPoints.get(
anotherMonomer,
) as Set<AttachmentPointName>;
anotherMonomerHandledAttachmentPoints.add(
anotherMonomer?.getAttachmentPointByBond(
polymerBond,
) as AttachmentPointName,
);
});
});
});
});
if (chain.isCyclic) {
const polymerBond = chain.firstMonomer?.attachmentPointsToBonds
.R1 as PolymerBond;
const bondRenderer = new PolymerBondSequenceRenderer(
polymerBond,
chain.firstNode,
chain.lastNonEmptyNode,
);
bondRenderer.show();
polymerBond.setRenderer(bondRenderer);
}
});
}