/// <summary> /// Generate an outer glow for the provided rendering element. The glow is defined by the glow /// width and the stroke size. /// </summary> /// <param name="element">rendering element</param> /// <param name="color">color of the glow</param> /// <param name="glowWidth">the width of the glow</param> /// <param name="stroke">the stroke width</param> /// <returns>generated outer glow</returns> internal static IRenderingElement OuterGlow(IRenderingElement element, Color color, double glowWidth, double stroke) { switch (element) { case ElementGroup orgGroup: var newGroup = new ElementGroup(); foreach (var child in orgGroup) { newGroup.Add(OuterGlow(child, color, glowWidth, stroke)); } return(newGroup); case LineElement lineElement: return(new LineElement(lineElement.FirstPoint, lineElement.SecondPoint, stroke + (2 * (glowWidth * stroke)), color)); case GeneralPath org: if (org.Fill) { return(org.Outline(2 * (glowWidth * stroke)).Recolor(color)); } else { return(org.Outline(stroke + (2 * (glowWidth * stroke))).Recolor(color)); } default: throw new ArgumentException($"Cannot generate glow for rendering element,{element.GetType()}"); } }
// public Rectangle PaintReactionSet( // IReactionSet reactionSet, IDrawVisitor drawVisitor) { // // total up the bounding boxes // Rectangle2D totalBounds = CreateRectangle(); // foreach (var reaction in reactionSet.reactions()) { // Rectangle2D modelBounds = BoundsCalculator.CalculateBounds(reaction); // if (totalBounds == null) { // totalBounds = modelBounds; // } else { // totalBounds = totalBounds.CreateUnion(modelBounds); // } // } // // // setup and draw // this.SetupTransformNatural(totalBounds); // ElementGroup diagram = new ElementGroup(); // foreach (var reaction in reactionSet.reactions()) { // diagram.Add(this.GenerateDiagram(reaction)); // } // this.Paint(drawVisitor, diagram); // // // the size of the painted diagram is returned // return this.ConvertToDiagramBounds(totalBounds); // } // // public Rectangle PaintReaction( // IReaction reaction, IDrawVisitor drawVisitor) { // // // calculate the bounds // Rectangle2D modelBounds = BoundsCalculator.CalculateBounds(reaction); // // // setup and draw // this.SetupTransformNatural(modelBounds); // IRenderingElement diagram = this.GenerateDiagram(reaction); // this.Paint(drawVisitor, diagram); // // return this.ConvertToDiagramBounds(modelBounds); // } /// <summary> /// Paint a ChemModel. /// </summary> /// <param name="chemModel"></param> /// <param name="drawVisitor">the visitor that does the drawing</param> /// <param name="bounds">the bounds of the area to paint on.</param> /// <param name="resetCenter">if true, set the modelCenter to the center of the ChemModel's bounds.</param> public void Paint(IChemModel chemModel, IDrawVisitor drawVisitor, Rect bounds, bool resetCenter) { // check for an empty model var moleculeSet = chemModel.MoleculeSet; IReactionSet reactionSet = chemModel.ReactionSet; // nasty, but it seems that reactions can be read in as ChemModels // with BOTH a ReactionSet AND a MoleculeSet... if (moleculeSet == null || reactionSet != null) { if (reactionSet != null) { reactionSetRenderer.Paint(reactionSet, drawVisitor, bounds, resetCenter); } return; } // calculate the total bounding box var modelBounds = BoundsCalculator.CalculateBounds(moleculeSet); this.SetupTransformToFit(bounds, modelBounds, AverageBondLengthCalculator.CalculateAverageBondLength(chemModel), resetCenter); // generate the elements IRenderingElement diagram = moleculeSetRenderer.GenerateDiagram(moleculeSet); // paint it this.Paint(drawVisitor, diagram); }
public IReadOnlyList <IRenderingElement> GetAllSimpleElements(IRenderingElement root) { elements.Clear(); getElementGroups = false; root.Accept(this); return(new List <IRenderingElement>(elements)); }
private IRenderingElement GenerateStereoElement(IBond bond, RendererModel model) { BondStereo stereo = bond.Stereo; WedgeLineElement.WedgeType type = WedgeLineElement.WedgeType.Wedged; BondDirection dir = BondDirection.ToSecond; switch (stereo) { case BondStereo.Down: case BondStereo.DownInverted: type = WedgeLineElement.WedgeType.Dashed; break; case BondStereo.UpOrDown: case BondStereo.UpOrDownInverted: type = WedgeLineElement.WedgeType.Indiff; break; } switch (stereo) { case BondStereo.DownInverted: case BondStereo.UpInverted: case BondStereo.UpOrDownInverted: dir = BondDirection.ToFirst; break; } IRenderingElement base_ = GenerateBondElement(bond, BondOrder.Single, model); return(new WedgeLineElement((LineElement)base_, type, dir, GetColorForBond(bond, model))); }
static IRenderingElement Unbox(IRenderingElement element) { if (element is MarkedElement) { return(((MarkedElement)element).Element()); } return(element); }
/// <summary> /// Markup a molecule with the class <paramref name="mol"/> and optionally the ids/classes /// from it's properties. /// </summary> /// <param name="elem">rendering element</param> /// <param name="mol">molecule</param> /// <returns>the marked element</returns> public static MarkedElement MarkupMol(IRenderingElement elem, IAtomContainer mol) { Debug.Assert(elem != null); var tagElem = MarkupChemObj(elem, mol); tagElem.AddClass("mol"); return(tagElem); }
public void Visit(IRenderingElement element, Transform transform) { var save = transform; this.transform = transform; Visit(element); transform = save; }
public void Main() { IRenderingElement renderingElements = null; #region SvgDrawVisitor visitor = new SvgDrawVisitor(50, 50, Depiction.UnitsMM); visitor.Visit(renderingElements); string svg = visitor.ToString(); #endregion }
public virtual void TestSingleAtom() { IAtomContainer singleAtom = MakeSingleAtom(); // nothing should be made IRenderingElement root = generator.Generate(singleAtom, singleAtom.Atoms[0], model); var elements = elementUtil.GetAllSimpleElements(root); Assert.AreEqual(1, elements.Count); }
/// <summary> /// Given a rendering element, traverse the elements compute required bounds /// to full display all elements. The method searches for <see cref="Bounds"/> /// elements which act to specify the required bounds when adjunct labels /// are considered. /// </summary> /// <param name="element">a rendering element</param> /// <returns>the bounds required (<see cref="Rect.Empty"/> if unspecified)</returns> public virtual Rect GetBounds(IRenderingElement element) { if (element == null) { return(Rect.Empty); } var bounds = new Bounds(element); return(new Rect(bounds.MinX, bounds.MinY, bounds.Width, bounds.Height)); }
/// <summary> /// Markup a bond with the class 'bond' and optionally the ids/classes /// from it's properties. /// </summary> /// <param name="elem">rendering element</param> /// <param name="bond">bond</param> /// <returns>the marked element</returns> public static MarkedElement MarkupBond(IRenderingElement elem, IBond bond) { if (elem == null) { throw new ArgumentNullException(nameof(elem)); } var tagElem = MarkupChemObj(elem, bond); tagElem.AddClass("bond"); return(tagElem); }
/// <summary> /// Markup a atom with the class 'atom' and optionally the ids/classes /// from it's properties. /// </summary> /// <param name="elem">rendering element</param> /// <param name="atom">atom</param> /// <returns>the marked element</returns> public static MarkedElement MarkupAtom(IRenderingElement elem, IAtom atom) { if (elem == null) { return(null); } var tagElem = MarkupChemObj(elem, atom); tagElem.AddClass("atom"); return(tagElem); }
/// <summary> /// Markup a rendering element with the specified classes. /// </summary> /// <param name="elem">rendering element</param> /// <param name="classes">classes</param> /// <returns>the marked element</returns> public static MarkedElement Markup(IRenderingElement elem, params string[] classes) { Debug.Assert(elem != null); var tagElem = new MarkedElement(elem); foreach (var cls in classes) { tagElem.AddClass(cls); } return(tagElem); }
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; } } }
/// <summary> /// Paint a set of molecules. /// </summary> /// <param name="molecules">the <see cref="IChemObjectSet{T}"/> to paint</param> /// <param name="drawVisitor">the visitor that does the drawing</param> /// <param name="bounds">the bounds on the screen</param> /// <param name="resetCenter">if true, set the draw center to be the center of bounds</param> public void Paint(IChemObjectSet <IAtomContainer> molecules, IDrawVisitor drawVisitor, Rect bounds, bool resetCenter) { // total up the bounding boxes var totalBounds = BoundsCalculator.CalculateBounds(molecules); this.SetupTransformToFit(bounds, totalBounds, AverageBondLengthCalculator.CalculateAverageBondLength(molecules), resetCenter); IRenderingElement diagram = this.GenerateDiagram(molecules); this.Paint(drawVisitor, diagram); }
private static MarkedElement MarkupChemObj(IRenderingElement elem, IChemObject chemObj) { Debug.Assert(elem != null); var tagElem = new MarkedElement(elem); if (chemObj != null) { tagElem.Id = chemObj.GetProperty <string>(IdKey); tagElem.AddClass(chemObj.GetProperty <string>(ClassKey)); } return(tagElem); }
/// <inheritdoc/> public Rect Paint(IAtomContainer atomContainer, IDrawVisitor drawVisitor) { // the bounds of the model var modelBounds = BoundsCalculator.CalculateBounds(atomContainer); // setup and draw this.SetupTransformNatural(modelBounds); IRenderingElement diagram = GenerateDiagram(atomContainer); this.Paint(drawVisitor, diagram); return(this.ConvertToDiagramBounds(modelBounds)); }
/// <inheritdoc/> public Rect Paint(IChemObjectSet <IAtomContainer> moleculeSet, IDrawVisitor drawVisitor) { // total up the bounding boxes var totalBounds = BoundsCalculator.CalculateBounds(moleculeSet); // setup and draw this.SetupTransformNatural(totalBounds); IRenderingElement diagram = this.GenerateDiagram(moleculeSet); this.Paint(drawVisitor, diagram); return(this.ConvertToDiagramBounds(totalBounds)); }
public virtual void TestSquare() { IAtomContainer square = MakeSquare(); model.SetKekuleStructure(true); // generate all four atoms IRenderingElement root = generator.Generate(square, model); var elements = elementUtil.GetAllSimpleElements(root); Assert.AreEqual(4, elements.Count); // test that the center is at the origin Assert.AreEqual(new Point(0, 0), Center(elements)); }
/// <summary> /// The target method for paintChemModel, paintReaction, and paintMolecule. /// </summary> /// <param name="drawVisitor">the visitor to draw with</param> /// <param name="diagram">the IRenderingElement tree to render</param> protected virtual void Paint(IDrawVisitor drawVisitor, IRenderingElement diagram) { if (diagram == null) { return; } // cache the diagram for quick-redraw this.cachedDiagram = diagram; fontManager.FontName = rendererModel.GetFontName(); fontManager.FontWeight = rendererModel.GetUsedFontStyle(); drawVisitor.FontManager = this.fontManager; drawVisitor.RendererModel = this.rendererModel; diagram.Accept(drawVisitor, this.transform); }
/// <summary> /// Paint an IChemModel using the IDrawVisitor at a scale determined by the /// bond length in RendererModel. /// </summary> /// <param name="chemModel">the chem model to draw</param> /// <param name="drawVisitor">the visitor used to draw with</param> /// <returns>the rectangular area that the diagram will occupy on screen</returns> public Rect Paint(IChemModel chemModel, IDrawVisitor drawVisitor) { var moleculeSet = chemModel.MoleculeSet; var reactionSet = chemModel.ReactionSet; if (moleculeSet == null && reactionSet != null) { Rect totalBounds = BoundsCalculator.CalculateBounds(reactionSet); this.SetupTransformNatural(totalBounds); IRenderingElement diagram = reactionSetRenderer.GenerateDiagram(reactionSet); this.Paint(drawVisitor, diagram); return(this.ConvertToDiagramBounds(totalBounds)); } if (moleculeSet != null && reactionSet == null) { Rect totalBounds = BoundsCalculator.CalculateBounds(moleculeSet); this.SetupTransformNatural(totalBounds); IRenderingElement diagram = moleculeSetRenderer.GenerateDiagram(moleculeSet); this.Paint(drawVisitor, diagram); return(this.ConvertToDiagramBounds(totalBounds)); } if (moleculeSet != null && reactionSet != null) { var totalBounds = BoundsCalculator.CalculateBounds(chemModel); this.SetupTransformNatural(totalBounds); ElementGroup diagram = new ElementGroup { reactionSetRenderer.GenerateDiagram(reactionSet), moleculeSetRenderer.GenerateDiagram(moleculeSet) }; this.Paint(drawVisitor, diagram); // the size of the painted diagram is returned return(this.ConvertToDiagramBounds(totalBounds)); } return(new Rect(0, 0, 0, 0)); }
public virtual void TestSingleBond() { IAtomContainer container = MakeSingleBond(); model.SetCompactAtom(true); model.SetCompactShape(AtomShapeType.Oval); model.SetShowEndCarbons(true); // generate the single line element IRenderingElement root = generator.Generate(container, model); var elements = elementUtil.GetAllSimpleElements(root); Assert.AreEqual(2, elements.Count); // test that the endpoints are distinct OvalElement ovalA = (OvalElement)elements[0]; OvalElement ovalB = (OvalElement)elements[1]; Assert.AreNotSame(0, Distance(ovalA.Coord, ovalB.Coord)); }
/// <summary> /// Recolor a rendering element after it has been generated. Since rendering elements are /// immutable, the input element remains unmodified. /// </summary> /// <param name="element">the rendering element</param> /// <param name="color">the new color</param> /// <returns>recolored rendering element</returns> private static IRenderingElement Recolor(IRenderingElement element, Color color) { switch (element) { case ElementGroup orgGroup: var newGroup = new ElementGroup(); foreach (var child in orgGroup) { newGroup.Add(Recolor(child, color)); } return(newGroup); case LineElement lineElement: return(new LineElement(lineElement.FirstPoint, lineElement.SecondPoint, lineElement.Width, color)); case GeneralPath generalPath: return(generalPath.Recolor(color)); } throw new ArgumentException($"Cannot highlight rendering element, {element.GetType()}"); }
public void Visit(IRenderingElement element) { if (element is ElementGroup) { if (getElementGroups) { this.elements.Add(element); } ((ElementGroup)element).Visit(this); } else if (element is MarkedElement) { Visit(((MarkedElement)element).Element()); } else if (element is Bounds) { Visit(((Bounds)element).Root); } else { this.elements.Add(element); } }
/// <summary> /// Paint a molecule (an IAtomContainer). /// </summary> /// <param name="atomContainer">the molecule to paint</param> /// <param name="drawVisitor">the visitor that does the drawing</param> /// <param name="bounds">the bounds on the screen</param> /// <param name="resetCenter">if true, set the draw center to be the center of bounds</param> public void Paint(IAtomContainer atomContainer, IDrawVisitor drawVisitor, Rect bounds, bool resetCenter) { if (atomContainer.Bonds.Count > 0 || atomContainer.Atoms.Count == 1) { rendererModel.SetScale( CalculateScaleForBondLength(GeometryUtil.GetBondLengthAverage(atomContainer))); } else if (atomContainer.Atoms.Count > 1) { rendererModel.SetScale( CalculateScaleForBondLength(EstimatedBondLength(atomContainer))); } // the diagram to draw IRenderingElement diagram = GenerateDiagram(atomContainer); // the bounds of the model from 'Bounds' elements // no bounding elements, use the atom coordinates var modelBounds = GetBounds(diagram) ?? BoundsCalculator.CalculateBounds(atomContainer); SetupTransformToFit(bounds, modelBounds, resetCenter); this.Paint(drawVisitor, diagram); }
public abstract void Visit(IRenderingElement element, Transform transform);
public abstract void Visit(IRenderingElement element);
public override void Visit(IRenderingElement element, Transform transform) { }
/// <summary> /// Add the specified element bounds. /// </summary> public void Add(IRenderingElement element) { elements.Add(element); Traverse(element); }
/// <summary> /// An bounding box around the specified element. /// </summary> public Bounds(IRenderingElement element) : this() { Add(element); }