private void PlaceBridgedRing(IRing ring, IAtomContainer sharedAtoms, Vector2 sharedAtomsCenter, Vector2 ringCenterVector, double bondLength) { IAtom[] bridgeAtoms = GetBridgeAtoms(sharedAtoms); IAtom bondAtom1 = bridgeAtoms[0]; IAtom bondAtom2 = bridgeAtoms[1]; List <IAtom> otherAtoms = new List <IAtom>(); foreach (IAtom atom in sharedAtoms.Atoms) { if (atom != bondAtom1 && atom != bondAtom2) { otherAtoms.Add(atom); } } bool snap = ring.GetProperty <bool>(SnapHint, false); bool swap = snap ? Det(bondAtom1.Point2D.Value, GeometryUtil.Get2DCenter(otherAtoms), bondAtom2.Point2D.Value) < 0 : Det(bondAtom1.Point2D.Value, GeometryUtil.Get2DCenter(otherAtoms), bondAtom2.Point2D.Value) > 0; if (swap) { IAtom tmp = bondAtom1; bondAtom1 = bondAtom2; bondAtom2 = tmp; } Vector2 bondAtom1Vector = bondAtom1.Point2D.Value; Vector2 bondAtom2Vector = bondAtom2.Point2D.Value; Vector2 midPoint = GetMidPoint(bondAtom1Vector, bondAtom2Vector); Vector2 ringCenter; double radius = GetNativeRingRadius(ring, bondLength); double offset = 0; if (snap) { ringCenter = midPoint; ringCenterVector = GetPerpendicular(bondAtom1Vector, bondAtom2Vector, new Vector2(midPoint.X - sharedAtomsCenter.X, midPoint.Y - sharedAtomsCenter.Y)); offset = 0; foreach (IAtom atom in otherAtoms) { double dist = Vector2.Distance(atom.Point2D.Value, midPoint); if (dist > offset) { offset = dist; } } } else { ringCenter = sharedAtomsCenter; } Vector2.Normalize(ringCenterVector); ringCenterVector = ringCenterVector * (radius - offset); ringCenter += ringCenterVector; bondAtom1Vector -= ringCenter; bondAtom2Vector -= ringCenter; int numUnplaced = ring.RingSize - sharedAtoms.Atoms.Count; double dot = bondAtom2Vector.X * bondAtom1Vector.X + bondAtom2Vector.Y * bondAtom1Vector.Y; double det = bondAtom2Vector.X * bondAtom1Vector.Y - bondAtom2Vector.Y * bondAtom1Vector.X; // theta remain/step double tRemain = Math.Atan2(det, dot); if (tRemain < 0) { tRemain = Math.PI + (Math.PI + tRemain); } double tStep = tRemain / (numUnplaced + 1); Debug.WriteLine($"placeBridgedRing->tRemain: {Vectors.RadianToDegree(tRemain)}"); Debug.WriteLine($"placeBridgedRing->tStep: {Vectors.RadianToDegree(tStep)}"); double startAngle; startAngle = GeometryUtil.GetAngle(bondAtom1.Point2D.Value.X - ringCenter.X, bondAtom1.Point2D.Value.Y - ringCenter.Y); IAtom currentAtom = bondAtom1; IBond currentBond = sharedAtoms.GetConnectedBonds(currentAtom).First(); List <IAtom> atoms = new List <IAtom>(); for (int i = 0; i < ring.Bonds.Count; i++) { currentBond = ring.GetNextBond(currentBond, currentAtom); currentAtom = currentBond.GetOther(currentAtom); if (!sharedAtoms.Contains(currentAtom)) { atoms.Add(currentAtom); } } #if DEBUG Debug.WriteLine($"{nameof(PlaceBridgedRing)}->atomsToPlace: {AtomPlacer.ListNumbers(Molecule, atoms)}"); Debug.WriteLine($"{nameof(PlaceBridgedRing)}->startAngle: {Vectors.RadianToDegree(startAngle)}"); Debug.WriteLine($"{nameof(PlaceBridgedRing)}->tStep: {Vectors.RadianToDegree(tStep)}"); #endif AtomPlacer.PopulatePolygonCorners(atoms, ringCenter, startAngle, -tStep, radius); }