Exemplo n.º 1
0
        /// <summary>
        ///  Returns the geometry of a wedge bond.  Hatch bonds use the same geometry
        ///     but a different brush.
        /// </summary>
        /// <param name="desc">Descriptor defining the bond shape</param>
        /// <param name="perp">perpendicular vector to the bond</param>
        public static void GetWedgePoints(WedgeBondLayout desc, Vector perp)
        {
            desc.FirstCorner = desc.End + perp;

            desc.SecondCorner = desc.End - perp;

            desc.Boundary.AddRange(new[] { desc.Start, desc.FirstCorner, desc.SecondCorner });
        }
Exemplo n.º 2
0
        /// <summary>
        /// Gets the geometry of a wedge bond.
        /// </summary>
        /// <param name="desc">WedgeBondDescriptor which is populated</param>
        /// <param name="standardBondLength">Standard bond length as defined by the model</param>
        /// <param name="standoff">Boundary width between atom label and bond terminus</param>
        public static void GetWedgeBondGeometry(WedgeBondLayout desc, double standardBondLength, double standoff)
        {
            //get the width of the wedge bond's thick end
            var bondVector = desc.PrincipleVector;
            var perpVector = bondVector.Perpendicular();

            perpVector.Normalize();
            perpVector *= standardBondLength * Globals.BondOffsetPercentage;

            // shrink the bond so it doesn't overlap any AtomVisuals
            AdjustTerminus(ref desc.Start, desc.End, desc.StartAtomHull, standoff);
            AdjustTerminus(ref desc.End, desc.Start, desc.EndAtomHull, standoff);

            //then draw it
            GetWedgePoints(desc, perpVector);
            //and pass it back as a Geometry
            StreamGeometry sg;

            sg = desc.GetOutline();
            sg.Freeze();
            desc.DefiningGeometry = sg;
        }
Exemplo n.º 3
0
        public static BondLayout GetBondDescriptor(AtomVisual startAtomVisual, AtomVisual endAtomVisual,
                                                   double modelXamlBondLength, Globals.BondStereo parentStereo,
                                                   Point startAtomPosition, Point endAtomPosition,
                                                   double?parentOrderValue, Globals.BondDirection parentPlacement,
                                                   Point?centroid, Point?secondaryCentroid)
        {
            if (parentStereo == Globals.BondStereo.Wedge || parentStereo == Globals.BondStereo.Hatch)
            {
                WedgeBondLayout wbd = new WedgeBondLayout()
                {
                    Start           = startAtomPosition,
                    End             = endAtomPosition,
                    StartAtomVisual = startAtomVisual,
                    EndAtomVisual   = endAtomVisual
                };

                var  endAtom    = endAtomVisual.ParentAtom;
                var  otherBonds = endAtom.Bonds.Except(new[] { startAtomVisual.ParentAtom.BondBetween(endAtom) }).ToList();
                Bond bond       = null;
                if (otherBonds.Any())
                {
                    bond = otherBonds.ToArray()[0];
                }

                bool chamferBond = (otherBonds.Any() &&
                                    (endAtom.Element as Element) == Globals.PeriodicTable.C &&
                                    endAtom.SymbolText == "" &&
                                    bond.Order == Globals.OrderSingle);
                if (!chamferBond)
                {
                    wbd.CappedOff = false;
                    BondGeometry.GetWedgeBondGeometry(wbd, modelXamlBondLength);
                }
                else
                {
                    var nonHPs = (from b in otherBonds
                                  select b.OtherAtom(endAtom).Position).ToList();
                    if (nonHPs.Any())
                    {
                        wbd.CappedOff = true;
                        BondGeometry.GetChamferedWedgeGeometry(wbd, modelXamlBondLength, nonHPs);
                    }
                    else
                    {
                        wbd.CappedOff = false;
                        BondGeometry.GetWedgeBondGeometry(wbd, modelXamlBondLength);
                    }
                }

                return(wbd);
            }

            //wavy bond
            if (parentStereo == Globals.BondStereo.Indeterminate && parentOrderValue == 1.0)
            {
                BondLayout sbd = new BondLayout
                {
                    Start           = startAtomPosition,
                    End             = endAtomPosition,
                    StartAtomVisual = startAtomVisual,
                    EndAtomVisual   = endAtomVisual
                };
                BondGeometry.GetWavyBondGeometry(sbd, modelXamlBondLength);
                return(sbd);
            }

            switch (parentOrderValue)
            {
            //indeterminate double
            case 2 when parentStereo == Globals.BondStereo.Indeterminate:
                DoubleBondLayout dbd = new DoubleBondLayout()
                {
                    StartAtomVisual = startAtomVisual,
                    EndAtomVisual   = endAtomVisual,
                    Start           = startAtomPosition,
                    End             = endAtomPosition
                };
                BondGeometry.GetCrossedDoubleGeometry(dbd, modelXamlBondLength);
                return(dbd);

            //partial or undefined bonds
            case 0:
            case 0.5:
            case 1.0:
                BondLayout sbd = new BondLayout
                {
                    Start           = startAtomPosition,
                    End             = endAtomPosition,
                    StartAtomVisual = startAtomVisual,
                    EndAtomVisual   = endAtomVisual
                };

                BondGeometry.GetSingleBondGeometry(sbd);
                return(sbd);

            //double bond & 1.5 bond
            case 1.5:
            case 2:
                DoubleBondLayout dbd2 = new DoubleBondLayout()
                {
                    StartAtomVisual   = startAtomVisual,
                    EndAtomVisual     = endAtomVisual,
                    Start             = startAtomPosition,
                    End               = endAtomPosition,
                    Placement         = parentPlacement,
                    PrimaryCentroid   = centroid,
                    SecondaryCentroid = secondaryCentroid
                };

                BondGeometry.GetDoubleBondGeometry(dbd2, modelXamlBondLength);
                return(dbd2);

            //triple and 2.5 bond
            case 2.5:
            case 3:
                TripleBondLayout tbd = new TripleBondLayout()
                {
                    StartAtomVisual   = startAtomVisual,
                    EndAtomVisual     = endAtomVisual,
                    Start             = startAtomPosition,
                    End               = endAtomPosition,
                    Placement         = parentPlacement,
                    PrimaryCentroid   = centroid,
                    SecondaryCentroid = secondaryCentroid
                };
                BondGeometry.GetTripleBondGeometry(tbd, modelXamlBondLength);
                return(tbd);

            default:
                return(null);
            }
        }
Exemplo n.º 4
0
        /// <summary>
        /// Chamfers or forks the end of a wedge bond under special circumstances
        /// (one or more incoming single bonds)
        /// </summary>
        /// <param name="descriptor"> WedgeBondDescriptor to be populated</param>
        /// <param name="standardBondLength">Standard bond length as defined by the model</param>
        /// <param name="otherAtomPoints">List of positions of atoms splaying from the end atom</param>
        /// <param name="standoff"></param>
        public static void GetChamferedWedgeGeometry(WedgeBondLayout descriptor,
                                                     double standardBondLength,
                                                     List <Point> otherAtomPoints, double standoff)
        {
            var bondVector = descriptor.PrincipleVector;

            //first get an unaltered bond
            GetWedgeBondGeometry(descriptor, standardBondLength, standoff);

            var firstEdgeVector  = descriptor.FirstCorner - descriptor.Start;
            var secondEdgeVector = descriptor.SecondCorner - descriptor.Start;

            //get the two bonds with widest splay

            var widestPoints = from Point p in otherAtomPoints
                               orderby Math.Abs(Vector.AngleBetween(bondVector, p - descriptor.End)) descending
                               select p;

            //the scaling factors are what we multiply the bond edge vectors by
            double firstScalingFactor  = 0d;
            double secondScalingFactor = 0d;

            //work out the biggest scaling factor for either long edge
            foreach (var point in widestPoints)
            {
                BasicGeometry.IntersectLines(descriptor.Start,
                                             descriptor.FirstCorner,
                                             descriptor.End,
                                             point, out var firstEdgeCut, out var otherBond1Cut);
                BasicGeometry.IntersectLines(descriptor.Start,
                                             descriptor.SecondCorner,
                                             descriptor.End,
                                             point, out var secondEdgeCut, out var otherBond2Cut);
                if (otherAtomPoints.Count == 1)
                {
                    if (firstEdgeCut > firstScalingFactor)
                    {
                        firstScalingFactor = firstEdgeCut;
                    }
                    if (secondEdgeCut > secondScalingFactor)
                    {
                        secondScalingFactor = secondEdgeCut;
                    }
                }
                else
                {
                    if (firstEdgeCut > firstScalingFactor && otherBond1Cut < 1d && otherBond1Cut > 0d)
                    {
                        firstScalingFactor = firstEdgeCut;
                    }
                    if (secondEdgeCut > secondScalingFactor && otherBond2Cut < 1d && otherBond2Cut > 0d)
                    {
                        secondScalingFactor = secondEdgeCut;
                    }
                }
            }

            //and multiply the edges by the scaling factors
            descriptor.FirstCorner  = firstEdgeVector * firstScalingFactor + descriptor.Start;
            descriptor.SecondCorner = secondEdgeVector * secondScalingFactor + descriptor.Start;

            descriptor.CappedOff = true;

            var sg = descriptor.GetOutline();

            sg.Freeze();
            descriptor.DefiningGeometry = sg;
        }
Exemplo n.º 5
0
        public static BondLayout GetBondDescriptor(AtomVisual startAtomVisual, AtomVisual endAtomVisual,
                                                   double modelXamlBondLength, Globals.BondStereo parentStereo,
                                                   Point startAtomPosition, Point endAtomPosition,
                                                   double?parentOrderValue, Globals.BondDirection parentPlacement,
                                                   Point?centroid, Point?secondaryCentroid, double standoff)
        {
            List <Point> startAtomHull = new List <Point>();
            List <Point> endAtomHull   = new List <Point>();

            if (startAtomVisual.ParentAtom.SymbolText != "" || startAtomVisual.ShowAllCarbons)
            {
                startAtomHull = startAtomVisual.Hull;
            }
            if (endAtomVisual.ParentAtom.SymbolText != "" || endAtomVisual.ShowAllCarbons)
            {
                endAtomHull = endAtomVisual.Hull;
            }
            if ((parentStereo == Globals.BondStereo.Wedge || parentStereo == Globals.BondStereo.Hatch) &&
                parentOrderValue == 1)
            {
                WedgeBondLayout wbd = new WedgeBondLayout
                {
                    Start         = startAtomPosition,
                    End           = endAtomPosition,
                    StartAtomHull = startAtomHull,
                    EndAtomHull   = endAtomHull
                };

                var endAtom    = endAtomVisual.ParentAtom;
                var otherBonds = endAtom.Bonds.Except(new[] { startAtomVisual.ParentAtom.BondBetween(endAtom) }).ToList();

                Bond bond    = null;
                bool oblique = true;
                if (otherBonds.Any())
                {
                    bond = otherBonds.ToArray()[0];
                    Vector wedgevector = wbd.End - wbd.Start;
                    foreach (Bond b in otherBonds)
                    {
                        Atom   otherAtom = b.OtherAtom(endAtom);
                        Vector v         = wbd.End - otherAtom.Position;
                        double angle     = System.Math.Abs(Vector.AngleBetween(wedgevector, v));

                        if (angle < 109.5 || angle > 130.5)
                        {
                            oblique = false;
                            break;
                        }
                    }
                }

                bool chamferBond = otherBonds.Any() &&
                                   oblique &&
                                   (endAtom.Element as Element) == Globals.PeriodicTable.C &&
                                   endAtom.SymbolText == "" &&
                                   bond.Order == Globals.OrderSingle;
                if (!chamferBond)
                {
                    wbd.CappedOff = false;
                    BondGeometry.GetWedgeBondGeometry(wbd, modelXamlBondLength, standoff);
                }
                else
                {
                    var nonHPs = (from b in otherBonds
                                  select b.OtherAtom(endAtom).Position).ToList();
                    if (nonHPs.Any())
                    {
                        wbd.CappedOff = true;
                        BondGeometry.GetChamferedWedgeGeometry(wbd, modelXamlBondLength, nonHPs, standoff);
                    }
                    else
                    {
                        wbd.CappedOff = false;
                        BondGeometry.GetWedgeBondGeometry(wbd, modelXamlBondLength, standoff);
                    }
                }

                return(wbd);
            }

            //wavy bond
            if (parentStereo == Globals.BondStereo.Indeterminate && parentOrderValue == 1.0)
            {
                BondLayout sbd = new BondLayout
                {
                    Start         = startAtomPosition,
                    End           = endAtomPosition,
                    StartAtomHull = startAtomHull,
                    EndAtomHull   = endAtomHull
                };
                BondGeometry.GetWavyBondGeometry(sbd, modelXamlBondLength, standoff);
                return(sbd);
            }

            switch (parentOrderValue)
            {
            //indeterminate double
            case 2 when parentStereo == Globals.BondStereo.Indeterminate:
                DoubleBondLayout dbd = new DoubleBondLayout()
                {
                    StartAtomHull          = startAtomHull,
                    EndAtomHull            = endAtomHull,
                    Start                  = startAtomPosition,
                    End                    = endAtomPosition,
                    StartNeigbourPositions = (from Atom a in startAtomVisual.ParentAtom.NeighboursExcept(endAtomVisual.ParentAtom)
                                              select a.Position).ToList(),
                    EndNeighbourPositions = (from Atom a in endAtomVisual.ParentAtom.NeighboursExcept(startAtomVisual.ParentAtom)
                                             select a.Position).ToList()
                };
                BondGeometry.GetCrossedDoubleGeometry(dbd, modelXamlBondLength, standoff);
                return(dbd);

            //partial or undefined bonds
            case 0:
            case 0.5:
            case 1.0:
                BondLayout sbd = new BondLayout
                {
                    Start         = startAtomPosition,
                    End           = endAtomPosition,
                    StartAtomHull = startAtomHull,
                    EndAtomHull   = endAtomHull
                };

                BondGeometry.GetSingleBondGeometry(sbd, standoff);
                return(sbd);

            //double bond & 1.5 bond
            case 1.5:
            case 2:
                DoubleBondLayout dbd2 = new DoubleBondLayout()
                {
                    StartAtomHull          = startAtomHull,
                    EndAtomHull            = endAtomHull,
                    Start                  = startAtomPosition,
                    End                    = endAtomPosition,
                    Placement              = parentPlacement,
                    PrimaryCentroid        = centroid,
                    SecondaryCentroid      = secondaryCentroid,
                    StartNeigbourPositions = (from Atom a in startAtomVisual.ParentAtom.NeighboursExcept(endAtomVisual.ParentAtom)
                                              select a.Position).ToList(),
                    EndNeighbourPositions = (from Atom a in endAtomVisual.ParentAtom.NeighboursExcept(startAtomVisual.ParentAtom)
                                             select a.Position).ToList()
                };

                BondGeometry.GetDoubleBondGeometry(dbd2, modelXamlBondLength, standoff);
                return(dbd2);

            //triple and 2.5 bond
            case 2.5:
            case 3:
                TripleBondLayout tbd = new TripleBondLayout()
                {
                    StartAtomHull     = startAtomHull,
                    EndAtomHull       = endAtomHull,
                    Start             = startAtomPosition,
                    End               = endAtomPosition,
                    Placement         = parentPlacement,
                    PrimaryCentroid   = centroid,
                    SecondaryCentroid = secondaryCentroid
                };
                BondGeometry.GetTripleBondGeometry(tbd, modelXamlBondLength, standoff);
                return(tbd);

            default:
                return(null);
            }
        }