/// <summary> /// Constructs an empty, forward reaction. /// </summary> public Reaction() { this.reactants = Builder.NewAtomContainerSet(); this.products = Builder.NewAtomContainerSet(); this.agents = Builder.NewAtomContainerSet(); this.mappings = new List <IMapping>(); direction = ReactionDirection.Forward; }
public virtual void TestSetDirection_IReaction_Direction() { IReaction reaction = (IReaction)NewChemObject(); ReactionDirection direction = ReactionDirection.Bidirectional; reaction.Direction = direction; Assert.AreEqual(direction, reaction.Direction); }
public ReactionDepiction(RendererModel model, List <Bounds> reactants, List <Bounds> products, List <Bounds> agents, Bounds plus, ReactionDirection direction, Dimensions dimensions, IList <Bounds> reactantTitles, IList <Bounds> productTitles, Bounds title, Bounds conditions, Color fgcol) : base(model) { this.model = model; this.dimensions = dimensions; this.title = title; this.fgcol = fgcol; // side components (catalysts, solvents, etc) note we deliberately // swap sideGrid width and height as we to stack agents on top of // each other. By default determineGrid tries to make the grid // wide but we want it tall this.sideComps.AddRange(agents); var sideGrid = Dimensions.DetermineGrid(sideComps.Count); var prelimSideDim = Dimensions.OfGrid(sideComps, yOffsetSide = new double[sideGrid.Width + 1], xOffsetSide = new double[sideGrid.Height + 1]); // build the main components, we add a 'plus' between each molecule foreach (var reactant in reactants) { this.mainComp.Add(reactant); this.mainComp.Add(plus); } // replacing trailing plus with placeholder for arrow if (!reactants.Any()) { this.mainComp.Add(new Bounds()); } else { this.mainComp[this.mainComp.Count - 1] = new Bounds(); } foreach (var product in products) { this.mainComp.Add(product); this.mainComp.Add(plus); } // trailing plus not needed if (products.Any()) { this.mainComp.RemoveAt(this.mainComp.Count - 1); } // add title if supplied, we simply line them up with // the main components and the add them as an extra // row if (reactantTitles.Any() || productTitles.Any()) { if (reactantTitles.Any() && reactantTitles.Count != reactants.Count) { throw new ArgumentException("Number of reactant titles differed from number of reactants"); } if (productTitles.Any() && productTitles.Count != products.Count) { throw new ArgumentException("Number of product titles differed from number of products"); } var mainTitles = new List <Bounds>(); foreach (var reactantTitle in reactantTitles) { mainTitles.Add(reactantTitle); mainTitles.Add(new Bounds()); } if (!reactants.Any()) { mainTitles.Add(new Bounds()); // gap for arrow } foreach (var productTitle in productTitles) { mainTitles.Add(productTitle); mainTitles.Add(new Bounds()); } // remove trailing space for plus if (products.Any()) { mainTitles.RemoveAt(mainTitles.Count - 1); } Trace.Assert(mainTitles.Count == mainComp.Count); this.mainComp.AddRange(mainTitles); this.nRow = 2; this.nCol = mainComp.Count / 2; } else { this.nRow = 1; this.nCol = mainComp.Count; } this.conditions = conditions; // arrow parameters this.arrowIdx = Math.Max(reactants.Count + reactants.Count - 1, 0); this.direction = direction; this.arrowHeight = plus.Height * 2; this.minArrowWidth = 4 * arrowHeight; mainDim = Dimensions.OfGrid(mainComp, yOffsets = new double[nRow + 1], xOffsets = new double[nCol + 1]); double middleRequired = Math.Max(prelimSideDim.width, conditions.Width); // avoid v. small arrows, we take in to account the padding provided by the arrow head height/length if (middleRequired < minArrowWidth - arrowHeight - arrowHeight) { // adjust x-offset so side components are centered double xAdjust = (minArrowWidth - middleRequired) / 2; for (int i = 0; i < xOffsetSide.Length; i++) { xOffsetSide[i] += xAdjust; } // need to recenter agents if (conditions.Width > prelimSideDim.width) { for (int i = 0; i < xOffsetSide.Length; i++) { xOffsetSide[i] += (conditions.Width - prelimSideDim.width) / 2; } } // update side dims this.sideDim = new Dimensions(minArrowWidth, prelimSideDim.height); this.condDim = new Dimensions(minArrowWidth, conditions.Height); } else { // arrow padding for (int i = 0; i < xOffsetSide.Length; i++) { xOffsetSide[i] += arrowHeight; } // need to recenter agents if (conditions.Width > prelimSideDim.width) { for (int i = 0; i < xOffsetSide.Length; i++) { xOffsetSide[i] += (conditions.Width - prelimSideDim.width) / 2; } } this.sideDim = new Dimensions(2 * arrowHeight + middleRequired, prelimSideDim.height); this.condDim = new Dimensions(2 * arrowHeight + middleRequired, conditions.Height); } }