public AtomLabelCharacter(Point position, TtfCharacter character, String colour, char ascii, string parent)
 {
     Position  = position;
     Character = character;
     Colour    = colour;
     Ascii     = ascii;
     Parent    = parent;
 }
Esempio n. 2
0
 public AtomLabelCharacter(Point position, TtfCharacter character, string colour, string parentAtom, string parentMolecule)
 {
     Position       = position;
     Character      = character;
     Colour         = colour;
     ParentAtom     = parentAtom;
     ParentMolecule = parentMolecule;
 }
        public void CreateElementCharacters(Atom atom, Options options)
        {
            string module = $"{_product}.{_class}.{MethodBase.GetCurrentMethod().Name}()";

            //Point atomCentre = new Point((double)atom.X2, (double)atom.Y2);
            string atomLabel = atom.Element.Symbol;
            Rect   labelBounds;

            // Get Charge and Isotope values for use later on
            int iCharge    = atom.FormalCharge ?? 0;
            int iAbsCharge = Math.Abs(iCharge);
            int isoValue   = atom.IsotopeNumber ?? 0;

            // Get Implicit Hydrogen Count for use later on
            int implicitHCount = atom.ImplicitHydrogenCount;

            Point cursorPosition        = atom.Position;
            Point chargeCursorPosition  = atom.Position;
            Point isotopeCursorPosition = atom.Position;

            double lastOffset = 0;

            int bondCount = atom.Bonds.ToList().Count;

            #region Decide if atom label is to be displayed

            bool showLabel = true;
            if (atomLabel == "C")
            {
                if (atom.ShowSymbol.HasValue)
                {
                    showLabel = atom.ShowSymbol.Value;
                }
                else
                {
                    if (atom.IsInRing || bondCount > 1)
                    {
                        showLabel = false;
                    }

                    if (bondCount == 2)
                    {
                        Point p1 = atom.Bonds.ToList()[0].OtherAtom(atom).Position;
                        Point p2 = atom.Bonds.ToList()[1].OtherAtom(atom).Position;

                        double angle1 = Vector.AngleBetween(-(atom.Position - p1), atom.Position - p2);

                        if (Math.Abs(angle1) < 8)
                        {
                            showLabel = true;
                        }
                    }
                }

                // Force on if atom has charge
                if (iAbsCharge > 0)
                {
                    showLabel = true;
                }
                // Force on if atom has isotope value
                if (isoValue > 0)
                {
                    showLabel = true;
                }
            }

            #endregion Decide if atom label is to be displayed

            if (showLabel)
            {
                #region Set Up Atom Colours

                string atomColour = "000000";
                if (options.ColouredAtoms)
                {
                    if (atom.Element.Colour != null)
                    {
                        atomColour = atom.Element.Colour;
                        // Strip out # as OoXml does not use it
                        atomColour = atomColour.Replace("#", "");
                    }
                }

                #endregion Set Up Atom Colours

                #region Step 1 - Measure Bounding Box for all Characters of label

                double xMin = double.MaxValue;
                double yMin = double.MaxValue;
                double xMax = double.MinValue;
                double yMax = double.MinValue;

                Point thisCharacterPosition;
                for (int idx = 0; idx < atomLabel.Length; idx++)
                {
                    char         chr = atomLabel[idx];
                    TtfCharacter c   = _TtfCharacterSet[chr];
                    if (c != null)
                    {
                        thisCharacterPosition = GetCharacterPosition(cursorPosition, c);

                        xMin = Math.Min(xMin, thisCharacterPosition.X);
                        yMin = Math.Min(yMin, thisCharacterPosition.Y);
                        xMax = Math.Max(xMax, thisCharacterPosition.X + OoXmlHelper.ScaleCsTtfToCml(c.Width, _meanBondLength));
                        yMax = Math.Max(yMax, thisCharacterPosition.Y + OoXmlHelper.ScaleCsTtfToCml(c.Height, _meanBondLength));

                        if (idx < atomLabel.Length - 1)
                        {
                            // Move to next Character position
                            cursorPosition.Offset(OoXmlHelper.ScaleCsTtfToCml(c.IncrementX, _meanBondLength), 0);
                        }
                    }
                }

                #endregion Step 1 - Measure Bounding Box for all Characters of label

                #region Step 2 - Reset Cursor such that the text is centered about the atom's co-ordinates

                double width  = xMax - xMin;
                double height = yMax - yMin;
                cursorPosition        = new Point(atom.Position.X - width / 2, atom.Position.Y + height / 2);
                chargeCursorPosition  = new Point(cursorPosition.X, cursorPosition.Y);
                isotopeCursorPosition = new Point(cursorPosition.X, cursorPosition.Y);
                labelBounds           = new Rect(cursorPosition, new Size(width, height));

                #endregion Step 2 - Reset Cursor such that the text is centered about the atom's co-ordinates

                #region Step 3 - Place the characters

                foreach (char chr in atomLabel)
                {
                    TtfCharacter c = _TtfCharacterSet[chr];
                    if (c != null)
                    {
                        thisCharacterPosition = GetCharacterPosition(cursorPosition, c);
                        AtomLabelCharacter alc = new AtomLabelCharacter(thisCharacterPosition, c, atomColour, chr, atom.Path, atom.Parent.Path);
                        _AtomLabelCharacters.Add(alc);

                        // Move to next Character position
                        lastOffset = OoXmlHelper.ScaleCsTtfToCml(c.IncrementX, _meanBondLength);
                        cursorPosition.Offset(OoXmlHelper.ScaleCsTtfToCml(c.IncrementX, _meanBondLength), 0);
                        chargeCursorPosition = new Point(cursorPosition.X, cursorPosition.Y);
                    }
                }

                #endregion Step 3 - Place the characters

                #region Determine NESW

                double        baFromNorth = Vector.AngleBetween(BasicGeometry.ScreenNorth, atom.BalancingVector(true));
                CompassPoints nesw        = CompassPoints.East;

                if (bondCount == 1)
                {
                    nesw = BasicGeometry.SnapTo2EW(baFromNorth);
                }
                else
                {
                    nesw = BasicGeometry.SnapTo4NESW(baFromNorth);
                }

                #endregion Determine NESW

                #region Step 4 - Add Charge if required

                if (iCharge != 0)
                {
                    TtfCharacter hydrogenCharacter = _TtfCharacterSet['H'];

                    char         sign = '.';
                    TtfCharacter chargeSignCharacter = null;
                    if (iCharge >= 1)
                    {
                        sign = '+';
                        chargeSignCharacter = _TtfCharacterSet['+'];
                    }
                    else if (iCharge <= 1)
                    {
                        sign = '-';
                        chargeSignCharacter = _TtfCharacterSet['-'];
                    }

                    if (iAbsCharge > 1)
                    {
                        string digits = iAbsCharge.ToString();
                        // Insert digits
                        foreach (char chr in digits)
                        {
                            TtfCharacter chargeValueCharacter = _TtfCharacterSet[chr];
                            thisCharacterPosition = GetCharacterPosition(chargeCursorPosition, chargeValueCharacter);

                            // Raise the superscript Character
                            thisCharacterPosition.Offset(0, -OoXmlHelper.ScaleCsTtfToCml(chargeValueCharacter.Height * OoXmlHelper.CS_SUPERSCRIPT_RAISE_FACTOR, _meanBondLength));

                            AtomLabelCharacter alcc = new AtomLabelCharacter(thisCharacterPosition, chargeValueCharacter, atomColour, chr, atom.Path, atom.Parent.Path);
                            alcc.IsSmaller   = true;
                            alcc.IsSubScript = true;
                            _AtomLabelCharacters.Add(alcc);

                            // Move to next Character position
                            chargeCursorPosition.Offset(OoXmlHelper.ScaleCsTtfToCml(chargeValueCharacter.IncrementX, _meanBondLength) * OoXmlHelper.SUBSCRIPT_SCALE_FACTOR, 0);
                            cursorPosition.Offset(OoXmlHelper.ScaleCsTtfToCml(chargeValueCharacter.IncrementX, _meanBondLength) * OoXmlHelper.SUBSCRIPT_SCALE_FACTOR, 0);
                        }
                    }

                    // Insert sign at raised position
                    thisCharacterPosition = GetCharacterPosition(chargeCursorPosition, chargeSignCharacter);
                    thisCharacterPosition.Offset(0, -OoXmlHelper.ScaleCsTtfToCml(hydrogenCharacter.Height * OoXmlHelper.CS_SUPERSCRIPT_RAISE_FACTOR, _meanBondLength));
                    thisCharacterPosition.Offset(0, -OoXmlHelper.ScaleCsTtfToCml(chargeSignCharacter.Height / 2 * OoXmlHelper.CS_SUPERSCRIPT_RAISE_FACTOR, _meanBondLength));

                    AtomLabelCharacter alcs = new AtomLabelCharacter(thisCharacterPosition, chargeSignCharacter, atomColour, sign, atom.Path, atom.Parent.Path);
                    alcs.IsSmaller   = true;
                    alcs.IsSubScript = true;
                    _AtomLabelCharacters.Add(alcs);

                    if (iAbsCharge != 0)
                    {
                        cursorPosition.Offset(OoXmlHelper.ScaleCsTtfToCml(chargeSignCharacter.IncrementX, _meanBondLength) * OoXmlHelper.SUBSCRIPT_SCALE_FACTOR, 0);
                    }
                }

                #endregion Step 4 - Add Charge if required

                #region Step 5 - Add Implicit H if required

                if (options.ShowHydrogens && implicitHCount > 0)
                {
                    TtfCharacter hydrogenCharacter      = _TtfCharacterSet['H'];
                    string       numbers                = "012345";
                    TtfCharacter implicitValueCharacter = _TtfCharacterSet[numbers[implicitHCount]];

                    #region Add H

                    if (hydrogenCharacter != null)
                    {
                        switch (nesw)
                        {
                        case CompassPoints.North:
                            if (atom.Bonds.ToList().Count > 1)
                            {
                                cursorPosition.X = labelBounds.X
                                                   + (labelBounds.Width / 2)
                                                   - (OoXmlHelper.ScaleCsTtfToCml(hydrogenCharacter.Width, _meanBondLength) / 2);
                                cursorPosition.Y = cursorPosition.Y
                                                   + OoXmlHelper.ScaleCsTtfToCml(-hydrogenCharacter.Height, _meanBondLength)
                                                   - OoXmlHelper.CHARACTER_VERTICAL_SPACING;
                                if (iCharge > 0)
                                {
                                    if (implicitHCount > 1)
                                    {
                                        cursorPosition.Offset(0,
                                                              OoXmlHelper.ScaleCsTtfToCml(
                                                                  -implicitValueCharacter.Height *
                                                                  OoXmlHelper.SUBSCRIPT_SCALE_FACTOR / 2, _meanBondLength)
                                                              - OoXmlHelper.CHARACTER_VERTICAL_SPACING);
                                    }
                                }
                            }
                            break;

                        case CompassPoints.East:
                            // Leave as is
                            break;

                        case CompassPoints.South:
                            if (atom.Bonds.ToList().Count > 1)
                            {
                                cursorPosition.X = labelBounds.X + (labelBounds.Width / 2)
                                                   - (OoXmlHelper.ScaleCsTtfToCml(hydrogenCharacter.Width, _meanBondLength) / 2);
                                cursorPosition.Y = cursorPosition.Y
                                                   + OoXmlHelper.ScaleCsTtfToCml(hydrogenCharacter.Height, _meanBondLength)
                                                   + OoXmlHelper.CHARACTER_VERTICAL_SPACING;
                            }
                            break;

                        case CompassPoints.West:
                            if (implicitHCount == 1)
                            {
                                if (iAbsCharge == 0)
                                {
                                    cursorPosition.Offset(OoXmlHelper.ScaleCsTtfToCml(-(hydrogenCharacter.IncrementX * 2), _meanBondLength), 0);
                                }
                                else
                                {
                                    cursorPosition.Offset(OoXmlHelper.ScaleCsTtfToCml(-((hydrogenCharacter.IncrementX * 2 + implicitValueCharacter.IncrementX * 1.25)), _meanBondLength), 0);
                                }
                            }
                            else
                            {
                                if (iAbsCharge == 0)
                                {
                                    cursorPosition.Offset(OoXmlHelper.ScaleCsTtfToCml(-(hydrogenCharacter.IncrementX * 2.5), _meanBondLength), 0);
                                }
                                else
                                {
                                    cursorPosition.Offset(OoXmlHelper.ScaleCsTtfToCml(-((hydrogenCharacter.IncrementX * 2 + implicitValueCharacter.IncrementX * 1.25)), _meanBondLength), 0);
                                }
                            }
                            break;
                        }

                        thisCharacterPosition = GetCharacterPosition(cursorPosition, hydrogenCharacter);
                        AtomLabelCharacter alc = new AtomLabelCharacter(thisCharacterPosition, hydrogenCharacter, atomColour, 'H', atom.Path, atom.Parent.Path);
                        _AtomLabelCharacters.Add(alc);

                        // Move to next Character position
                        cursorPosition.Offset(OoXmlHelper.ScaleCsTtfToCml(hydrogenCharacter.IncrementX, _meanBondLength), 0);

                        if (nesw == CompassPoints.East)
                        {
                            chargeCursorPosition = new Point(cursorPosition.X, cursorPosition.Y);
                        }
                        if (nesw == CompassPoints.West)
                        {
                            isotopeCursorPosition = new Point(thisCharacterPosition.X, isotopeCursorPosition.Y);
                        }
                    }

                    #endregion Add H

                    #region Add number

                    if (implicitHCount > 1)
                    {
                        if (implicitValueCharacter != null)
                        {
                            thisCharacterPosition = GetCharacterPosition(cursorPosition, implicitValueCharacter);

                            // Drop the subscript Character
                            thisCharacterPosition.Offset(0, OoXmlHelper.ScaleCsTtfToCml(hydrogenCharacter.Width * OoXmlHelper.SUBSCRIPT_DROP_FACTOR, _meanBondLength));

                            AtomLabelCharacter alc = new AtomLabelCharacter(thisCharacterPosition, implicitValueCharacter, atomColour, numbers[implicitHCount], atom.Path, atom.Parent.Path);
                            alc.IsSmaller   = true;
                            alc.IsSubScript = true;
                            _AtomLabelCharacters.Add(alc);

                            // Move to next Character position
                            cursorPosition.Offset(OoXmlHelper.ScaleCsTtfToCml(implicitValueCharacter.IncrementX, _meanBondLength) * OoXmlHelper.SUBSCRIPT_SCALE_FACTOR, 0);
                        }
                    }

                    #endregion Add number
                }

                #endregion Step 5 - Add Implicit H if required

                #region Step 6 - Add IsoTope Number if required

                if (isoValue > 0)
                {
                    string digits = isoValue.ToString();

                    xMin = double.MaxValue;
                    yMin = double.MaxValue;
                    xMax = double.MinValue;
                    yMax = double.MinValue;

                    Point isoOrigin = isotopeCursorPosition;

                    // Calculate width of digits
                    foreach (char chr in digits)
                    {
                        TtfCharacter c = _TtfCharacterSet[chr];
                        thisCharacterPosition = GetCharacterPosition(isotopeCursorPosition, c);

                        // Raise the superscript Character
                        thisCharacterPosition.Offset(0, -OoXmlHelper.ScaleCsTtfToCml(c.Height * OoXmlHelper.CS_SUPERSCRIPT_RAISE_FACTOR, _meanBondLength));

                        xMin = Math.Min(xMin, thisCharacterPosition.X);
                        yMin = Math.Min(yMin, thisCharacterPosition.Y);
                        xMax = Math.Max(xMax, thisCharacterPosition.X + OoXmlHelper.ScaleCsTtfToCml(c.Width, _meanBondLength));
                        yMax = Math.Max(yMax, thisCharacterPosition.Y + OoXmlHelper.ScaleCsTtfToCml(c.Height, _meanBondLength));

                        // Move to next Character position
                        isotopeCursorPosition.Offset(OoXmlHelper.ScaleCsTtfToCml(c.IncrementX, _meanBondLength) * OoXmlHelper.SUBSCRIPT_SCALE_FACTOR, 0);
                    }

                    // Re-position Isotope Cursor
                    width = xMax - xMin;
                    isotopeCursorPosition = new Point(isoOrigin.X - width, isoOrigin.Y);

                    // Insert digits
                    foreach (char chr in digits)
                    {
                        TtfCharacter c = _TtfCharacterSet[chr];
                        thisCharacterPosition = GetCharacterPosition(isotopeCursorPosition, c);

                        // Raise the superscript Character
                        thisCharacterPosition.Offset(0, -OoXmlHelper.ScaleCsTtfToCml(c.Height * OoXmlHelper.CS_SUPERSCRIPT_RAISE_FACTOR, _meanBondLength));

                        AtomLabelCharacter alcc = new AtomLabelCharacter(thisCharacterPosition, c, atomColour, chr, atom.Path, atom.Parent.Path);
                        alcc.IsSmaller   = true;
                        alcc.IsSubScript = true;
                        _AtomLabelCharacters.Add(alcc);

                        // Move to next Character position
                        isotopeCursorPosition.Offset(OoXmlHelper.ScaleCsTtfToCml(c.IncrementX, _meanBondLength) * OoXmlHelper.SUBSCRIPT_SCALE_FACTOR, 0);
                    }
                }

                #endregion Step 6 - Add IsoTope Number if required

                #region Step 7 - Create Convex Hull

                _convexhHulls.Add(atom.Path, ConvexHull(atom.Path));

                #endregion Step 7 - Create Convex Hull
            }
        }