Esempio n. 1
0
        public void useDefaultPlacementWithNoBonds()
        {
            var mock_atom = new Mock <IAtom>(); var atom = mock_atom.Object;

            mock_atom.Setup(n => n.AtomicNumber).Returns(8);
            Assert.AreEqual(Left, HydrogenPositionTools.Position(atom, Array.Empty <IAtom>()));
        }
Esempio n. 2
0
        public void HydrogensAppearBeforeSulfur()
        {
            var mock_atom = new Mock <IAtom>(); var atom = mock_atom.Object;

            mock_atom.Setup(n => n.AtomicNumber).Returns(16);
            Assert.AreEqual(Left, HydrogenPositionTools.UsingDefaultPlacement(atom));
        }
Esempio n. 3
0
        public void HydrogensAppearAfterCarbon()
        {
            var mock_atom = new Mock <IAtom>(); var atom = mock_atom.Object;

            mock_atom.Setup(n => n.AtomicNumber).Returns(6);
            Assert.AreEqual(Right, HydrogenPositionTools.UsingDefaultPlacement(atom));
        }
Esempio n. 4
0
        public void HydrogensAppearBeforeWhenBondIsFromRight()
        {
            var mock_atom1 = new Mock <IAtom>(); var atom1 = mock_atom1.Object;
            var mock_atom2 = new Mock <IAtom>(); var atom2 = mock_atom2.Object;

            mock_atom1.Setup(n => n.Point2D).Returns(new Vector2(0, 0));
            mock_atom2.Setup(n => n.Point2D).Returns(new Vector2(1, 0));
            Assert.AreEqual(Left, HydrogenPositionTools.Position(atom1, new[] { atom2 }));
        }
Esempio n. 5
0
        public void Symmetric()
        {
            // all extents are the same so 'Right' is chosen in preference
            var vectors = new[]
            {
                new Vector2(1, 1), new Vector2(1, -1), new Vector2(-1, 1), new Vector2(-1, -1)
            };

            Assert.AreEqual(Right, HydrogenPositionTools.UsingAngularExtent(vectors));
        }
Esempio n. 6
0
        public void UsingCardinalDirection()
        {
            var mock_atom1 = new Mock <IAtom>(); var atom1 = mock_atom1.Object;
            var mock_atom2 = new Mock <IAtom>(); var atom2 = mock_atom2.Object;
            var mock_atom3 = new Mock <IAtom>(); var atom3 = mock_atom2.Object;

            mock_atom1.Setup(n => n.Point2D).Returns(new Vector2(0, 0));
            mock_atom2.Setup(n => n.Point2D).Returns(new Vector2(1, 1));
            mock_atom3.Setup(n => n.Point2D).Returns(new Vector2(1, -1));
            Assert.AreEqual(Left, HydrogenPositionTools.Position(atom1, new[] { atom2, atom3 }));
        }
Esempio n. 7
0
        public void AngularExtentLeft()
        {
            double theta   = Vectors.DegreeToRadian(120);
            var    vectors = new[]
            {
                new Vector2(1, 0),
                new Vector2(Math.Cos(theta), Math.Sin(theta)),
                new Vector2(Math.Cos(-theta), Math.Sin(-theta)),
            };

            Assert.AreEqual(Left, HydrogenPositionTools.UsingAngularExtent(vectors));
        }
Esempio n. 8
0
        public void LargestExtent()
        {
            // the largest extents here are above and below
            var vectors = new[]
            {
                new Vector2(Math.Cos(Vectors.DegreeToRadian(30)), Math.Sin(Vectors.DegreeToRadian(30))),
                new Vector2(Math.Cos(Vectors.DegreeToRadian(-30)), Math.Sin(Vectors.DegreeToRadian(-30))),
                new Vector2(Math.Cos(Vectors.DegreeToRadian(150)), Math.Sin(Vectors.DegreeToRadian(150))),
                new Vector2(Math.Cos(Vectors.DegreeToRadian(-150)), Math.Sin(Vectors.DegreeToRadian(-150)))
            };

            Assert.AreEqual(Above, HydrogenPositionTools.UsingAngularExtent(vectors));
        }
Esempio n. 9
0
        public void AngularExtentAbove()
        {
            double theta1  = Vectors.DegreeToRadian(30);
            double theta2  = Vectors.DegreeToRadian(150);
            var    vectors = new[]
            {
                new Vector2(0, -1),
                new Vector2(Math.Cos(theta1), Math.Sin(theta1)),
                new Vector2(Math.Cos(theta2), Math.Sin(theta2)),
            };

            Assert.AreEqual(Above, HydrogenPositionTools.UsingAngularExtent(vectors));
        }
Esempio n. 10
0
 public void CardinalDirectionForNorthWestIsRight()
 {
     Assert.AreEqual(Right, HydrogenPositionTools.UsingCardinalDirection(new Vector2(-1, 0)));
 }
Esempio n. 11
0
 public void CardinalDirectionForSouthIsAbove()
 {
     Assert.AreEqual(Above, HydrogenPositionTools.UsingCardinalDirection(new Vector2(0, -1)));
 }
Esempio n. 12
0
 public void CardinalDirectionForSouthEastIsLeft()
 {
     Assert.AreEqual(Left, HydrogenPositionTools.UsingCardinalDirection(new Vector2(1, -1)));
 }
Esempio n. 13
0
 public void CardinalDirectionForNorthIsBelow()
 {
     Assert.AreEqual(Below, HydrogenPositionTools.UsingCardinalDirection(new Vector2(0, 1)));
 }
Esempio n. 14
0
 public void ValueOf()
 {
     Assert.AreEqual(HydrogenPosition.Above, HydrogenPositionTools.Parse("Above"));
 }
Esempio n. 15
0
        /// <summary>
        /// Generate the intermediate <see cref="AtomSymbol"/> instances.
        /// </summary>
        /// <param name="container">structure representation</param>
        /// <param name="symbolRemap">use alternate symbols (used for Sgroup shortcuts)</param>
        /// <param name="visibility">defines whether an atom symbol is displayed</param>
        /// <param name="parameters">render model parameters</param>
        /// <returns>generated atom symbols (can contain <see langword="null"/>)</returns>
        private AtomSymbol[] GenerateAtomSymbols(IAtomContainer container,
                                                 Dictionary <IAtom, string> symbolRemap,
                                                 SymbolVisibility visibility,
                                                 RendererModel parameters,
                                                 ElementGroup annotations,
                                                 Color foreground,
                                                 double stroke,
                                                 StandardDonutGenerator donutGen)
        {
            var scale      = parameters.GetScale();
            var annDist    = parameters.GetAnnotationDistance() * (parameters.GetBondLength() / scale);
            var annScale   = (1 / scale) * parameters.GetAnnotationFontScale();
            var annColor   = parameters.GetAnnotationColor();
            var halfStroke = stroke / 2;

            var symbols = new AtomSymbol[container.Atoms.Count];
            var builder = container.Builder;

            // check if we should annotate attachment point numbers (maxAttach>1)
            // and queue them all up for processing
            var attachPoints = new List <IPseudoAtom>();
            int maxAttach    = 0;

            for (int i = 0; i < container.Atoms.Count; i++)
            {
                var atom = container.Atoms[i];

                if (IsHiddenFully(atom))
                {
                    continue;
                }

                if (atom is IPseudoAtom)
                {
                    var attachNum = ((IPseudoAtom)atom).AttachPointNum;
                    if (attachNum > 0)
                    {
                        attachPoints.Add((IPseudoAtom)atom);
                    }
                    if (attachNum > maxAttach)
                    {
                        maxAttach = attachNum;
                    }
                }

                var remapped     = symbolRemap.ContainsKey(atom);
                var bonds        = container.GetConnectedBonds(atom);
                var neighbors    = container.GetConnectedAtoms(atom);
                var visNeighbors = new List <IAtom>();

                // if a symbol is remapped we only want to consider
                // visible neighbors in the alignment calculation, otherwise
                // we include all neighbors
                foreach (var neighbor in neighbors)
                {
                    if (!remapped || !IsHidden(neighbor))
                    {
                        visNeighbors.Add(neighbor);
                    }
                }

                var auxVectors = new List <Vector2>(1);

                // only generate if the symbol is visible
                if (visibility.Visible(atom, bonds, parameters) || remapped)
                {
                    var hPosition = HydrogenPositionTools.Position(atom, visNeighbors);

                    if (atom.ImplicitHydrogenCount != null && atom.ImplicitHydrogenCount > 0)
                    {
                        auxVectors.Add(hPosition.Vector());
                    }

                    if (remapped)
                    {
                        symbols[i] = atomGenerator.GenerateAbbreviatedSymbol(symbolRemap[atom], hPosition);
                    }
                    else if (donutGen.IsChargeDelocalised(atom))
                    {
                        var charge = atom.FormalCharge;
                        atom.FormalCharge = 0;
                        // can't think of a better way to handle this without API
                        // change to symbol visibility
                        if (atom.AtomicNumber != 6)
                        {
                            symbols[i] = atomGenerator.GenerateSymbol(container, atom, hPosition, parameters);
                        }
                        atom.FormalCharge = charge;
                    }
                    else
                    {
                        symbols[i] = atomGenerator.GenerateSymbol(container, atom, hPosition, parameters);
                    }

                    if (symbols[i] != null)
                    {
                        // defines how the element is aligned on the atom point, when
                        // aligned to the left, the first character 'e.g. Cl' is used.
                        if (visNeighbors.Count < 4)
                        {
                            if (hPosition == HydrogenPosition.Left)
                            {
                                symbols[i] = symbols[i].AlignTo(AtomSymbol.SymbolAlignment.Right);
                            }
                            else
                            {
                                symbols[i] = symbols[i].AlignTo(AtomSymbol.SymbolAlignment.Left);
                            }
                        }

                        var p = atom.Point2D;

                        if (p == null)
                        {
                            throw new ArgumentException("Atom did not have 2D coordinates");
                        }

                        symbols[i] = symbols[i].Resize(1 / scale, 1 / -scale).Center(p.Value.X, p.Value.Y);
                    }
                }

                var label = GetAnnotationLabel(atom);

                if (label != null)
                {
                    // to ensure consistent draw distance we need to adjust the annotation distance
                    // depending on whether we are drawing next to an atom symbol or not.
                    double strokeAdjust = symbols[i] != null ? -halfStroke : 0;

                    var vector     = NewAtomAnnotationVector(atom, bonds, auxVectors);
                    var annOutline = GenerateAnnotation(atom.Point2D.Value, label, vector, annDist + strokeAdjust, annScale, font, emSize, symbols[i]);

                    // the AtomSymbol may migrate during bond generation and therefore the annotation
                    // needs to be tied to the symbol. If no symbol is available the annotation is
                    // fixed and we can add it to the annotation ElementGroup right away.
                    if (symbols[i] != null)
                    {
                        symbols[i] = symbols[i].AddAnnotation(annOutline);
                    }
                    else
                    {
                        annotations.Add(GeneralPath.ShapeOf(annOutline.GetOutline(), annColor));
                    }
                }
            }

            // label attachment points
            if (maxAttach > 1)
            {
                var    attachNumOutlines = new List <TextOutline>();
                double maxRadius         = 0;

                foreach (IPseudoAtom atom in attachPoints)
                {
                    int attachNum = atom.AttachPointNum;

                    // to ensure consistent draw distance we need to adjust the annotation distance
                    // depending on whether we are drawing next to an atom symbol or not.
                    var strokeAdjust = -halfStroke;

                    var vector = NewAttachPointAnnotationVector(
                        atom,
                        container.GetConnectedBonds(atom),
                        new List <Vector2>());

                    var outline = GenerateAnnotation(atom.Point2D.Value,
                                                     attachNum.ToString(),
                                                     vector,
                                                     1.75 * annDist + strokeAdjust,
                                                     annScale,
                                                     new Typeface(font.FontFamily, font.Style, WPF.FontWeights.Bold, font.Stretch),
                                                     emSize,
                                                     null);

                    attachNumOutlines.Add(outline);

                    var w = outline.GetBounds().Width;
                    var h = outline.GetBounds().Height;
                    var r = Math.Sqrt(w * w + h * h) / 2;
                    if (r > maxRadius)
                    {
                        maxRadius = r;
                    }
                }

                foreach (var outline in attachNumOutlines)
                {
                    var group  = new ElementGroup();
                    var radius = 2 * stroke + maxRadius;
                    var shape  = new EllipseGeometry(outline.GetCenter(), radius, radius);
                    var area1  = Geometry.Combine(shape, outline.GetOutline(), GeometryCombineMode.Exclude, Transform.Identity);
                    group.Add(GeneralPath.ShapeOf(area1, foreground));
                    annotations.Add(group);
                }
            }

            return(symbols);
        }