private void NormalizeCoords(Molecule mol, COMPOUND_TYPES type, int id) { if (mol == null) return; //First we get the region we are working in RectangleF region; if (type == COMPOUND_TYPES.Reactant) region = reactantRegions[id]; else if (type == COMPOUND_TYPES.Reagent) region = reagentRegions[0]; //we only ever have one reagent region else region = productRegions[id]; //we get the bounds of the raw copy for initial sizing for the given region mol.Bounds = GetBoundingBox(mol, region); PointF center = new PointF(region.X + region.Width / 2, region.Y + region.Height / 2); //The scale values for x and y are then calculated //We want to keep the same ratio so we get the ratio, find the max sx can be and then calculte sy from that float ratio = mol.Bounds.Width/mol.Bounds.Height; double sx = 40; //region.Width / mol.Bounds.Width-30; double sy = 30; //ratio / sx; foreach (Node atom in mol.Atoms.Values) { double ox = atom.Position.X; double oy = atom.Position.Y; double x = (ox * sx + center.X); double y = (oy * sy + center.Y); atom.Position = new Vector3(x, y, 0); //Finally we go through the bonds and update their nodes, due to some error in copying foreach (Bond bond in mol.Bonds) { if (bond.Node1.ID == atom.ID) bond.Node1 = atom; else if (bond.Node2.ID == atom.ID) bond.Node2 = atom; } //and again go through one more time to calculate the paths foreach (Bond bond in mol.Bonds) { bond.CalculateBoundPath(); } } //We also need to get the new size of the bounding box and get the bounds for each bond mol.Bounds = GetBoundingBox(mol, region); }
private static void WriteBlock(XmlDocument doc, XmlElement pparent, Edit edit, List<int> fileIDs, ObservableCollection<Compound> compounds, COMPOUND_TYPES type) { //First we have a counter to keep track of rc1, rc2 etc int counter = 0; foreach (Compound comp in compounds) { //First we determine what element this will belong to string parentname = string.Empty; switch (type) { case COMPOUND_TYPES.Reactant: parentname = "reactant"; break; case COMPOUND_TYPES.Reagent: parentname = "reagent"; break; case COMPOUND_TYPES.Product: parentname = "product"; break; } XmlElement parent = doc.CreateElement(parentname); //Fileid is generated on the fly XmlElement fileid = doc.CreateElement("fileid"); comp.FileID = GenerateFileID(fileIDs); fileid.InnerText = comp.FileID.ToString(); //Local id is also generated on the fly we simply pass our counter and type XmlElement localid = doc.CreateElement("localid"); localid.InnerText = GenerateLocalID(counter, type); //The name is a copy of our compoud name XmlElement name = doc.CreateElement("name"); name.InnerText = comp.Name; //Copy over ref id XmlElement refid = doc.CreateElement("refid"); refid.InnerText = comp.RefName; //Same for formula XmlElement formula = doc.CreateElement("formula"); formula.InnerText = comp.Formula; //And same for state XmlElement state = doc.CreateElement("state"); state.InnerText = comp.State.ToString(); //density is the same, but it has a temperature <--- NOT DONE XmlElement density = doc.CreateElement("density"); // at temp x density.InnerText = comp.Density.ToString(); //THIS IS NOT COMPLETE; DENSITY EXISTS AT A GIVEN TEMP density.SetAttribute("temp", "25"); XmlElement islimiting = doc.CreateElement("islimiting"); islimiting.InnerText = comp.IsLimiting.ToString(); XmlElement isTarget = doc.CreateElement("istarget"); isTarget.InnerText = comp.IsTarget.ToString(); //The mols have a unit so we look into the dictionary to get the value at whatever unit XmlElement mols = doc.CreateElement("mols"); // unit mols.InnerText = comp.MolsValue.ToString(); mols.SetAttribute("unit", comp.MolsUnit); mols.SetAttribute("unit_power", comp.Mols.Power.ToString()); //The mass is also at a unit so just the same, however some compounds are measured //not in mass but by volume so we check this and output null if thats the case XmlElement mass = doc.CreateElement("mass"); //unit if (comp.MassValue > 0) { mass.InnerText = comp.MassValue.ToString(); mass.SetAttribute("unit", comp.MassUnit); mass.SetAttribute("unit_power", comp.Mass.Power.ToString()); } else { mass.InnerText = "null"; mass.SetAttribute("unit", "mol"); mass.SetAttribute("unit_power", "0"); } //and likewise for the volume, sometimes things are measured by mass and not volume XmlElement volume = doc.CreateElement("volume"); //unit if (comp.VolumeValue > 0) { volume.InnerText = comp.VolumeValue.ToString(); volume.SetAttribute("unit", "l"); volume.SetAttribute("unit_power", comp.Volume.Power.ToString()); } else { volume.InnerText = "null"; volume.SetAttribute("unit", "l"); volume.SetAttribute("unit_power", "0"); } XmlElement solvent = doc.CreateElement("solvent"); if (!string.IsNullOrEmpty(comp.SolventName)) { solvent.InnerText = comp.SolventName; solvent.SetAttribute("conc", comp.Solution.Concentration.Value.ToString()); solvent.SetAttribute("conc_unit", comp.Solution.Concentration.UnitType); solvent.SetAttribute("unit_power", comp.Solution.Concentration.Power.ToString()); } else { solvent.InnerText = "null"; solvent.SetAttribute("conc", "null"); solvent.SetAttribute("conc_unit", "mol/l"); solvent.SetAttribute("unit_power", "0"); } //Now we have to append all of these as children to the parent element given parent.AppendChild(fileid); parent.AppendChild(localid); parent.AppendChild(name); parent.AppendChild(refid); parent.AppendChild(formula); parent.AppendChild(state); parent.AppendChild(density); parent.AppendChild(islimiting); parent.AppendChild(isTarget); parent.AppendChild(mols); parent.AppendChild(mass); parent.AppendChild(volume); parent.AppendChild(solvent); //NOw that we have added all of the elements we add this parent element to our parents parent, giving us the correct format pparent.AppendChild(parent); counter++; } }
private static ObservableCollection<Compound> ReadBlock(XmlNodeList compoundList, COMPOUND_TYPES type) { ObservableCollection<Compound> returnList = new ObservableCollection<Compound>(); foreach (XmlNode node in compoundList) { string localid = string.Empty; string name = string.Empty; string refid = string.Empty; int fileid = 0; //In the files each compound is recognized by a five digit number, so we can attach mol data int state = 0; string formula = string.Empty; float density = 0.0f; Unit mols = new Unit(0, "mol", (int)UNIT_POWERS.none); Unit mass = new Unit(0, "g", (int)UNIT_POWERS.none); Unit volume = new Unit(0, "l", (int)UNIT_POWERS.none); Solution solvent = new Solution("null", new Unit(0, "mol/l", (int)UNIT_POWERS.none)); bool isLimiting = false; bool isTarget = false; foreach (XmlNode inner in node.ChildNodes) { switch (inner.Name) { case "fileid": fileid = int.Parse(inner.InnerText); break; case "localid": localid = inner.InnerText; break; case "name": name = inner.InnerText; break; case "refid": refid = inner.InnerText; break; case "formula": formula = inner.InnerText; break; case "state": string text = inner.InnerText; if (text == "solid") state = 0; if (text == "liquid") state = 1; if (text == "gas") state = 2; if (text == "solvated") state = 3; break; case "islimiting": isLimiting = bool.Parse(inner.InnerText); break; case "istarget": isTarget = bool.Parse(inner.InnerText); break; case "density": if (inner.InnerText == "null") break; density = float.Parse(inner.InnerText); break; case "mols": if(inner.InnerText == "null") break; mols = new Unit(double.Parse(inner.InnerText), inner.Attributes["unit"].Value, int.Parse(inner.Attributes["unit_power"].Value)); break; case "mass": if (inner.InnerText == "null") break; mass = new Unit(double.Parse(inner.InnerText), inner.Attributes["unit"].Value, int.Parse(inner.Attributes["unit_power"].Value)); break; case "volume": if (inner.InnerText == "null") break; volume = new Unit(double.Parse(inner.InnerText), inner.Attributes["unit"].Value, int.Parse(inner.Attributes["unit_power"].Value)); break; case "solvent": if (inner.InnerText == "null") break; solvent = new Solution(inner.InnerText, new Unit(float.Parse(inner.Attributes["conc"].Value), inner.Attributes["conc_unit"].Value, int.Parse(inner.Attributes["unit_power"].Value))); break; } } Compound c = new Compound(name, refid, localid, fileid, (int)type, state, isLimiting, isTarget, formula, density, mols, mass, volume, solvent); Console.WriteLine(c.ToString()); returnList.Add(c); } return returnList; }
//We need to be able to generate an local id for an edit such as rc1 or p1 private static string GenerateLocalID(int counter, COMPOUND_TYPES type) { switch (type) { case COMPOUND_TYPES.Reactant: return "rc" + counter; case COMPOUND_TYPES.Reagent: return "rg" + counter; case COMPOUND_TYPES.Product: return "p" + counter; } return string.Empty; }