예제 #1
0
        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);
        }