private void Traverse(IRenderingElement newElement) { var stack = new Deque <IRenderingElement>(); stack.Push(newElement); while (stack.Any()) { var element = stack.Poll(); switch (element) { case Bounds e: Add(e); break; case GeneralPath e: Add(e); break; case LineElement lineElem: var vec = lineElem.SecondPoint - lineElem.FirstPoint; var ortho = new WPF::Vector(-vec.Y, vec.X); ortho.Normalize(); vec.Normalize(); ortho *= lineElem.Width / 2; // stroke width vec *= lineElem.Width / 2; // stroke rounded also makes line longer Add(lineElem.FirstPoint - vec + ortho); Add(lineElem.SecondPoint + vec + ortho); Add(lineElem.FirstPoint - vec - ortho); Add(lineElem.SecondPoint + vec - ortho); break; case OvalElement oval: Add(new Point(oval.Coord.X - oval.Radius, oval.Coord.Y)); Add(new Point(oval.Coord.X + oval.Radius, oval.Coord.Y)); Add(new Point(oval.Coord.X, oval.Coord.Y - oval.Radius)); Add(new Point(oval.Coord.X, oval.Coord.Y + oval.Radius)); break; case ElementGroup elementGroup: stack.AddRange(elementGroup); break; case MarkedElement e: stack.Add(e.Element()); break; default: // ignored from bounds calculation, we don't really // care but log we skipped it Trace.TraceWarning($"{element.GetType()} not included in bounds calculation"); break; } } }
/// <inheritdoc/> public IRenderingElement Generate(IAtomContainer container, RendererModel model) { ElementGroup group = new ElementGroup(); // TODO : put into RendererModel const double SCREEN_RADIUS = 1.0; // separation between centers const double SCREEN_SEPARATION = 2.5; Color RADICAL_COLOR = WPF.Media.Colors.Black; // XXX : is this the best option? double ATOM_RADIUS = model.GetAtomRadius(); double scale = model.GetScale(); double modelAtomRadius = ATOM_RADIUS / scale; double modelPointRadius = SCREEN_RADIUS / scale; double modelSeparation = SCREEN_SEPARATION / scale; foreach (var lonePair in container.LonePairs) { IAtom atom = lonePair.Atom; Vector2 point = atom.Point2D.Value; int align = GeometryUtil.GetBestAlignmentForLabelXY(container, atom); var center = ToPoint(point); var diff = new WPF::Vector(); if (align == 1) { center.X += modelAtomRadius; diff.Y += modelSeparation; } else if (align == -1) { center.X -= modelAtomRadius; diff.Y += modelSeparation; } else if (align == 2) { center.Y -= modelAtomRadius; diff.X += modelSeparation; } else if (align == -2) { center.Y += modelAtomRadius; diff.X += modelSeparation; } group.Add(new OvalElement(center + diff, modelPointRadius, true, RADICAL_COLOR)); group.Add(new OvalElement(center - diff, modelPointRadius, true, RADICAL_COLOR)); } return(group); }
/// <summary> /// Convert a WPF point to a <see cref="NCDK.Numerics.Vector2"/>. /// </summary> /// <param name="vector">WPF point</param> /// <returns><see cref="NCDK.Numerics.Vector2"/> point</returns> public static Vector2 ToVector2(WPF::Vector vector) => new Vector2(vector.X, vector.Y);
public static WPF::Vector NewPerpendicularVector(WPF::Vector vector) { return(new WPF::Vector(-vector.Y, vector.X)); }