Exemple #1
0
        public void AlignToRight()
        {
            TextOutline outline = new TextOutline("Cl", font, emSize);
            AtomSymbol  symbol  = new AtomSymbol(outline, Array.Empty <TextOutline>());

            AssertCloseTo(outline.GetLastGlyphCenter(), symbol.AlignTo(Right).GetAlignmentCenter(), 0.01);
        }
Exemple #2
0
        /// <summary>
        /// Generate an annotation 'label' for an atom (located at 'basePoint'). The label is offset from
        /// the basePoint by the provided 'distance' and 'direction'.
        /// </summary>
        /// <param name="basePoint">the relative (0,0) reference</param>
        /// <param name="label">the annotation text</param>
        /// <param name="direction">the direction along which the label is laid out</param>
        /// <param name="distance">the distance along the direct to travel</param>
        /// <param name="scale">the font scale of the label</param>
        /// <param name="font">the font to use</param>
        /// <param name="symbol">the atom symbol to avoid overlap with</param>
        /// <returns>the position text outline for the annotation</returns>
        internal static TextOutline GenerateAnnotation(Vector2 basePoint, string label, Vector2 direction, double distance, double scale, Typeface font, double emSize, AtomSymbol symbol)
        {
            var italicHint = label.StartsWith(ItalicDisplayPrefix);

            label = italicHint ? label.Substring(ItalicDisplayPrefix.Length) : label;
            var annFont    = italicHint ? new Typeface(font.FontFamily, WPF.FontStyles.Italic, font.Weight, font.Stretch) : font;
            var annOutline = new TextOutline(label, annFont, emSize).Resize(scale, -scale);

            // align to the first or last character of the annotation depending on the direction
            var center = direction.X > 0.3 ? annOutline.GetFirstGlyphCenter() : direction.X < -0.3 ? annOutline.GetLastGlyphCenter() : annOutline.GetCenter();

            // Avoid atom symbol
            if (symbol != null)
            {
                var intersect = symbol.GetConvexHull().Intersect(VecmathUtil.ToPoint(basePoint), VecmathUtil.ToPoint(VecmathUtil.Sum(basePoint, direction)));
                // intersect should never be null be check against this
                if (intersect != null)
                {
                    basePoint = VecmathUtil.ToVector(intersect);
                }
            }

            direction *= distance;
            direction += basePoint;

            // move to position
            return(annOutline.Translate(direction.X - center.X, direction.Y - center.Y));
        }
Exemple #3
0
        private static TextOutline LeftAlign(TextOutline outline)
        {
            var center = outline.GetCenter();
            var first  = outline.GetFirstGlyphCenter();

            return(outline.Translate(center.X - first.X, center.Y - first.Y));
        }
Exemple #4
0
        [TestMethod()]  // Font bounds vary between systems
        public void UntransformedCenter()
        {
            TextOutline clOutline = new TextOutline("Cl", font, emSize);
            var         center    = clOutline.GetCenter();

            Assert.AreEqual(5.62, center.X, 0.01);
            Assert.AreEqual(-4.47, center.Y, 0.01);
        }
Exemple #5
0
        public void TestGetLastGlyphCenter()
        {
            TextOutline original = new TextOutline("Cl", font, emSize);
            var         oCenter  = original.GetCenter();
            var         tCenter  = original.GetLastGlyphCenter();

            Assert.IsTrue(tCenter.X > oCenter.X);
        }
 /// <summary>
 /// Internal constructor with required attributes.
 /// </summary>
 /// <param name="font">the font to depict symbols with</param>
 /// <param name="adjunctSpacing">the spacing between adjuncts and the element symbol as fraction of 'H'  width</param>
 /// <param name="scriptSize">the size of</param>
 private StandardAtomGenerator(Typeface font, double emSize, double adjunctSpacing, double scriptSize)
 {
     this.font                 = font;
     this.emSize               = emSize;
     this.scriptSize           = scriptSize;
     this.defaultHydrogenLabel = new TextOutline("H", font, emSize);
     this.padding              = adjunctSpacing * defaultHydrogenLabel.GetBounds().Width;
 }
        /// <summary>
        /// Position the mass label relative to the element label. The mass adjunct is position to the
        /// top left of the element label.
        /// </summary>
        /// <param name="massLabel">mass label outline</param>
        /// <param name="elementLabel">element label outline</param>
        /// <returns>positioned mass label</returns>
        public TextOutline PositionMassLabel(TextOutline massLabel, TextOutline elementLabel)
        {
            var elementBounds = elementLabel.GetBounds();
            var massBounds    = massLabel.GetBounds();

            return(massLabel.Translate((elementBounds.Left - padding) - massBounds.Right,
                                       (elementBounds.Top - (massBounds.Height / 2)) - massBounds.Top));
        }
        public TextOutline PositionAfter(TextOutline before, TextOutline after)
        {
            var fixedBounds   = before.GetBounds();
            var movableBounds = after.GetBounds();

            after = after.Translate((fixedBounds.Right + padding) - movableBounds.Left, 0);
            return(after);
        }
Exemple #9
0
 /// <summary>
 /// Internal constructor provides the attributes.
 /// </summary>
 /// <param name="element">the element label</param>
 /// <param name="adjuncts">the adjunct labels</param>
 /// <param name="alignment">left, center, or right alignment</param>
 /// <param name="hull">convex hull</param>
 private AtomSymbol(TextOutline element, IList <TextOutline> adjuncts, IList <TextOutline> annotationAdjuncts, SymbolAlignment alignment, ConvexHull hull)
 {
     this.element            = element;
     this.adjuncts           = adjuncts;
     this.annotationAdjuncts = annotationAdjuncts;
     this.alignment          = alignment;
     this.hull = hull;
 }
Exemple #10
0
 /// <summary>
 /// Create a new atom symbol with the specified adjuncts.
 /// </summary>
 /// <param name="element">the element symbol (e.g. 'N' in 'NH4+')</param>
 /// <param name="adjuncts">the adjuncts</param>
 public AtomSymbol(TextOutline element, IList <TextOutline> adjuncts)
 {
     this.element            = element;
     this.adjuncts           = adjuncts;
     this.annotationAdjuncts = new List <TextOutline>();
     this.alignment          = SymbolAlignment.Center;
     this.hull = ConvexHull.OfShapes(GetOutlines());
 }
Exemple #11
0
        public void FirstAndLastCenterIsTheSameForSingleLetterOutline()
        {
            TextOutline oOutline    = new TextOutline("O", font, emSize);
            var         firstCenter = oOutline.GetFirstGlyphCenter();
            var         lastCenter  = oOutline.GetLastGlyphCenter();

            Assert.AreEqual(lastCenter.X, firstCenter.X, 0.01);
            Assert.AreEqual(lastCenter.Y, firstCenter.Y, 0.01);
        }
Exemple #12
0
        public void ResizeMaintainsCenter()
        {
            TextOutline clOutline = new TextOutline("Cl", font, emSize);
            var         orgCenter = clOutline.GetCenter();
            var         newCenter = clOutline.Resize(21, 5).GetCenter();

            Assert.AreEqual(newCenter.X, orgCenter.X, 0.01);
            Assert.AreEqual(newCenter.Y, orgCenter.Y, 0.01);
        }
Exemple #13
0
        public TextOutline PositionSuperscript(TextOutline label, TextOutline superscript)
        {
            var labelBounds       = label.GetBounds();
            var superscriptBounds = superscript.GetBounds();

            superscript = superscript.Translate((labelBounds.Right + padding) - superscriptBounds.Left,
                                                (labelBounds.Top - (superscriptBounds.Height / 2)) - superscriptBounds.Top);
            return(superscript);
        }
Exemple #14
0
        /// <summary>
        /// Positions an outline in the subscript position relative to another 'primary' label.
        /// </summary>
        /// <param name="label">a label outline</param>
        /// <param name="subscript">the label outline to position as subscript</param>
        /// <returns>positioned subscript outline</returns>
        public TextOutline PositionSubscript(TextOutline label, TextOutline subscript)
        {
            var hydrogenBounds      = label.GetBounds();
            var hydrogenCountBounds = subscript.GetBounds();

            subscript = subscript.Translate((hydrogenBounds.Right + padding) - hydrogenCountBounds.Left,
                                            (hydrogenBounds.Bottom + (hydrogenCountBounds.Height / 2)) - hydrogenCountBounds.Bottom);
            return(subscript);
        }
Exemple #15
0
        /// <summary>
        /// Include a new annotation adjunct in the atom symbol.
        /// </summary>
        /// <param name="annotation">the new annotation adjunct</param>
        /// <returns>a new AtomSymbol instance including the annotation adjunct</returns>
        public AtomSymbol AddAnnotation(TextOutline annotation)
        {
            List <TextOutline> newAnnotations = new List <TextOutline>(annotationAdjuncts)
            {
                annotation
            };

            return(new AtomSymbol(element, adjuncts, newAnnotations, alignment, hull));
        }
Exemple #16
0
        public void TransformedCenter()
        {
            TextOutline original    = new TextOutline("Cl", font, emSize);
            TextOutline transformed = original.Translate(0, -5);
            var         oCenter     = original.GetCenter();
            var         tCenter     = transformed.GetCenter();

            Assert.AreEqual(oCenter.X, tCenter.X, 0.01);
            Assert.AreEqual(oCenter.Y - 5, tCenter.Y, 0.01);
        }
Exemple #17
0
        public void TestToString()
        {
            TextOutline outline = new TextOutline("Cl", font, emSize);
            var         bounds  = outline.GetBounds();

            Assert.AreEqual(
                "Cl [x=" + ToString(bounds.X) + ", y=" + ToString(bounds.Y)
                + ", w=" + ToString(bounds.Width) + ", h=" + ToString(bounds.Height) + "]",
                outline.ToString());
        }
Exemple #18
0
        [TestMethod(), Ignore()] // Font bounds vary between systems
        public void UntransformedBounds()
        {
            TextOutline clOutline = new TextOutline("Cl", font, emSize);
            var         bounds    = clOutline.GetBounds();

            Assert.AreEqual(0.67, bounds.X, 0.01);
            Assert.AreEqual(-9.12, bounds.Y, 0.01);
            Assert.AreEqual(9.90, bounds.Width, 0.01);
            Assert.AreEqual(9.28, bounds.Height, 0.01);
        }
        public void PositionMassLabel()
        {
            var mass       = new TextOutline("15", font, emSize);
            var positioned = atomGenerator.PositionMassLabel(mass, element);

            var elementBounds = element.GetBounds();
            var massBounds    = positioned.GetBounds();

            Assert.IsTrue(massBounds.Right < elementBounds.Left);
            Assert.AreEqual(elementBounds.Top, massBounds.CenterY(), 0.01);
        }
        public void PositionHydrogenCount()
        {
            var hydrogenCount = new TextOutline("2", font, emSize);
            var positioned    = atomGenerator.PositionSubscript(hydrogen, hydrogenCount);

            var hydrogenBounds      = hydrogen.GetBounds();
            var hydrogenCountBounds = positioned.GetBounds();

            Assert.IsTrue(hydrogenCountBounds.Left > hydrogenBounds.Left);
            Assert.AreEqual(hydrogenBounds.Bottom, hydrogenCountBounds.CenterY(), 0.01);
        }
Exemple #21
0
        public void BoundsTransformedWithYTranslation()
        {
            TextOutline original    = new TextOutline("Cl", font, emSize);
            TextOutline transformed = original.Translate(0, -5);
            var         oBounds     = original.GetBounds();
            var         tBounds     = transformed.GetBounds();

            Assert.AreEqual(oBounds.X, tBounds.X, 0.01);
            Assert.AreEqual(oBounds.Y - 5, tBounds.Y, 0.01);
            Assert.AreEqual(oBounds.Width, tBounds.Width, 0.01);
            Assert.AreEqual(oBounds.Height, tBounds.Height, 0.01);
        }
Exemple #22
0
        public void TestGetOutlines()
        {
            TextOutline outline       = new TextOutline("Cl", font, emSize);
            AtomSymbol  symbol        = new AtomSymbol(outline, Array.Empty <TextOutline>());
            var         outlineBounds = outline.GetOutline().Bounds;
            var         symbolBounds  = symbol.GetOutlines()[0].Bounds;

            Assert.AreEqual(symbolBounds.X, outlineBounds.X, 0.01);
            Assert.AreEqual(symbolBounds.Y, outlineBounds.Y, 0.01);
            Assert.AreEqual(symbolBounds.Left, outlineBounds.Left, 0.01);
            Assert.AreEqual(symbolBounds.Bottom, outlineBounds.Bottom, 0.01);
        }
        public void PositionOfChargeWhenHydrogensAreBelow()
        {
            var charge     = new TextOutline("+", font, emSize);
            var positioned = atomGenerator.PositionChargeLabel(1, HydrogenPosition.Below, charge, element,
                                                               hydrogen.Translate(0, 5));

            var elementBounds = element.GetBounds();
            var chargeBounds  = positioned.GetBounds();

            Assert.IsTrue(chargeBounds.Left > elementBounds.Left);
            Assert.AreEqual(elementBounds.Top, chargeBounds.CenterY(), 0.01);
        }
Exemple #24
0
        public void ResizeModifiesBounds()
        {
            TextOutline original    = new TextOutline("Cl", font, emSize);
            TextOutline transformed = original.Resize(2, 2);
            var         oBounds     = original.GetBounds();
            var         tBounds     = transformed.GetBounds();

            Assert.AreEqual(oBounds.X - oBounds.Width / 2, tBounds.X, 0.01);
            Assert.AreEqual(oBounds.Y - oBounds.Height / 2, tBounds.Y, 0.01);
            Assert.AreEqual(oBounds.Width * 2, tBounds.Width, 0.01);
            Assert.AreEqual(oBounds.Height * 2, tBounds.Height, 0.01);
        }
Exemple #25
0
        public void TestGetOutlinesWithAdjunct()
        {
            TextOutline outline       = new TextOutline("Cl", font, emSize);
            TextOutline adjunct       = new TextOutline("H", font, emSize);
            AtomSymbol  symbol        = new AtomSymbol(outline, new[] { adjunct });
            var         outlineBounds = adjunct.GetOutline().Bounds;
            var         symbolBounds  = symbol.GetOutlines()[1].Bounds;

            Assert.AreEqual(symbolBounds.X, outlineBounds.X, 0.01);
            Assert.AreEqual(symbolBounds.Y, outlineBounds.Y, 0.01);
            Assert.AreEqual(symbolBounds.Left, outlineBounds.Left, 0.01);
            Assert.AreEqual(symbolBounds.Bottom, outlineBounds.Bottom, 0.01);
        }
Exemple #26
0
        public void TestTranslate()
        {
            TextOutline outline     = new TextOutline("Cl", font, emSize);
            AtomSymbol  symbol      = new AtomSymbol(outline, Array.Empty <TextOutline>());
            AtomSymbol  transformed = symbol.Translate(4, 2);
            var         orgBounds   = symbol.GetOutlines()[0].Bounds;
            var         newBounds   = transformed.GetOutlines()[0].Bounds;

            Assert.AreEqual(orgBounds.X + 4, newBounds.X, 0.01);
            Assert.AreEqual(orgBounds.Y + 2, newBounds.Y, 0.01);
            Assert.AreEqual(orgBounds.Right + 4, newBounds.Right, 0.01);
            Assert.AreEqual(orgBounds.Bottom + 2, newBounds.Bottom, 0.01);
        }
Exemple #27
0
        public void TestResize()
        {
            TextOutline outline     = new TextOutline("Cl", font, emSize);
            AtomSymbol  symbol      = new AtomSymbol(outline, Array.Empty <TextOutline>());
            AtomSymbol  transformed = symbol.Resize(2, 2);
            var         orgBounds   = outline.GetBounds();
            var         newBounds   = transformed.GetOutlines()[0].Bounds;

            Assert.AreEqual(orgBounds.Left - orgBounds.Width / 2, newBounds.Left, 0.01);
            Assert.AreEqual(orgBounds.Top - orgBounds.Height / 2, newBounds.Top, 0.01);
            Assert.AreEqual(orgBounds.Right + orgBounds.Width / 2, newBounds.Right, 0.01);
            Assert.AreEqual(orgBounds.Bottom + orgBounds.Height / 2, newBounds.Bottom, 0.01);
        }
        public void PositionOfChargeWhenOneHydrogenIsAbove()
        {
            // hydrogen is arbitrarily moved to ensure x/y are different from the element
            var charge        = new TextOutline("+", font, emSize);
            var localHydrogen = hydrogen.Translate(10, 10);
            var positioned    = atomGenerator.PositionChargeLabel(1, HydrogenPosition.Above, charge, element,
                                                                  localHydrogen);

            var elementBounds = element.GetBounds();
            var chargeBounds  = positioned.GetBounds();

            Assert.IsTrue(chargeBounds.Left > elementBounds.Left);
            Assert.AreEqual(elementBounds.Top, chargeBounds.CenterY(), 0.01);
        }
Exemple #29
0
        /// <summary>
        /// Generate an atom symbol for a periodic element with the specified number of hydrogens, ionic
        /// charge, mass,
        /// </summary>
        /// <param name="number">atomic number</param>
        /// <param name="hydrogens">labelled hydrogen count</param>
        /// <param name="mass">atomic mass</param>
        /// <param name="charge">ionic formal charge</param>
        /// <param name="unpaired">number of unpaired electrons</param>
        /// <param name="position">placement of hydrogen</param>
        /// <returns>laid out atom symbol</returns>
        public AtomSymbol GeneratePeriodicSymbol(int number, int hydrogens, int mass, int charge, int unpaired, HydrogenPosition position)
        {
            var element = number == 0
                        ? new TextOutline("*", font, emSize)
                        : new TextOutline(ChemicalElement.Of(number).Symbol, font, emSize);
            var hydrogenAdjunct = defaultHydrogenLabel;

            // the hydrogen count, charge, and mass adjuncts are script size
            var hydrogenCount = new TextOutline(hydrogens.ToString(), font, emSize).Resize(scriptSize, scriptSize);
            var chargeAdjunct = new TextOutline(ChargeAdjunctText(charge, unpaired), font, emSize).Resize(scriptSize, scriptSize);
            var massAdjunct   = new TextOutline(mass.ToString(), font, emSize).Resize(scriptSize, scriptSize);

            // position each adjunct relative to the element label and each other
            hydrogenAdjunct = PositionHydrogenLabel(position, element, hydrogenAdjunct);
            hydrogenCount   = PositionSubscript(hydrogenAdjunct, hydrogenCount);
            chargeAdjunct   = PositionChargeLabel(hydrogens, position, chargeAdjunct, element, hydrogenAdjunct);
            massAdjunct     = PositionMassLabel(massAdjunct, element);

            // when the hydrogen label is positioned to the left we may need to nudge it
            // over to account for the hydrogen count and/or the mass adjunct colliding
            // with the element label
            if (position == HydrogenPosition.Left)
            {
                var nudgeX = HydrogenXDodge(hydrogens, mass, element, hydrogenAdjunct, hydrogenCount, massAdjunct);
                hydrogenAdjunct = hydrogenAdjunct.Translate(nudgeX, 0);
                hydrogenCount   = hydrogenCount.Translate(nudgeX, 0);
            }

            var adjuncts = new List <TextOutline>(4);

            if (hydrogens > 0)
            {
                adjuncts.Add(hydrogenAdjunct);
            }
            if (hydrogens > 1)
            {
                adjuncts.Add(hydrogenCount);
            }
            if (charge != 0 || unpaired > 0)
            {
                adjuncts.Add(chargeAdjunct);
            }
            if (mass > 0)
            {
                adjuncts.Add(massAdjunct);
            }

            return(new AtomSymbol(element, adjuncts));
        }
Exemple #30
0
        public void TestGetConvexHull()
        {
            TextOutline outline     = new TextOutline("Cl", font, emSize);
            AtomSymbol  symbol      = new AtomSymbol(outline, Array.Empty <TextOutline>());
            ConvexHull  outlineHull = ConvexHull.OfShape(outline.GetOutline());
            ConvexHull  symbolHull  = symbol.GetConvexHull();

            var outlineBounds = outlineHull.Outline.Bounds;
            var symbolBounds  = symbolHull.Outline.Bounds;

            Assert.AreEqual(symbolBounds.X, outlineBounds.X, 0.01);
            Assert.AreEqual(symbolBounds.Y, outlineBounds.Y, 0.01);
            Assert.AreEqual(symbolBounds.Left, outlineBounds.Left, 0.01);
            Assert.AreEqual(symbolBounds.Bottom, outlineBounds.Bottom, 0.01);
        }