private void BeautifyLines(Atom atom, string bondId) { if ((Element)atom.Element == Globals.PeriodicTable.C) { if (atom.Bonds.Count == 3) { bool isInRing = atom.Rings.Count != 0; List <BondLine> lines = _bondLines.Where(bl => bl.ParentBond.Equals(bondId)).ToList(); if (lines.Any()) { List <Bond> otherBonds; if (isInRing) { otherBonds = atom.Bonds.Where(b => !b.Id.Equals(bondId)).ToList(); } else { otherBonds = atom.Bonds.Where(b => !b.Id.Equals(bondId) && b.OrderValue == 1).ToList(); } if (lines.Count == 2 && otherBonds.Count == 2) { BondLine line1 = _bondLines.First(bl => bl.ParentBond.Equals(otherBonds[0].Id)); BondLine line2 = _bondLines.First(bl => bl.ParentBond.Equals(otherBonds[1].Id)); TrimLines(lines, line1, line2, isInRing); } } } } }
private void TrimLines(List <BondLine> mainPair, BondLine line1, BondLine line2, bool isInRing) { // Only two of these calls are expected to do anything if (!TrimLine(mainPair[0], line1, isInRing)) { TrimLine(mainPair[0], line2, isInRing); } if (!TrimLine(mainPair[1], line1, isInRing)) { TrimLine(mainPair[1], line2, isInRing); } }
private bool TrimLine(BondLine leftOrRight, BondLine line, bool isInRing) { bool dummy; bool intersect; Point intersection; // Make a longer version of the line Point startLonger = new Point(leftOrRight.Start.X, leftOrRight.Start.Y); Point endLonger = new Point(leftOrRight.End.X, leftOrRight.End.Y); CoordinateTool.AdjustLineAboutMidpoint(ref startLonger, ref endLonger, _medianBondLength / 5); // See if they intersect at one end CoordinateTool.FindIntersection(startLonger, endLonger, line.Start, line.End, out dummy, out intersect, out intersection); // If they intersect update the main line if (intersect) { double l1 = CoordinateTool.DistanceBetween(intersection, leftOrRight.Start); double l2 = CoordinateTool.DistanceBetween(intersection, leftOrRight.End); if (l1 > l2) { leftOrRight.End = new Point(intersection.X, intersection.Y); } else { leftOrRight.Start = new Point(intersection.X, intersection.Y); } if (!isInRing) { l1 = CoordinateTool.DistanceBetween(intersection, line.Start); l2 = CoordinateTool.DistanceBetween(intersection, line.End); if (l1 > l2) { line.End = new Point(intersection.X, intersection.Y); } else { line.Start = new Point(intersection.X, intersection.Y); } } } return(intersect); }
private void ShrinkBondLinesPass2(Progress pb) { // so that they do not overlap label characters if (_atomLabelCharacters.Count > 1) { pb.Show(); } pb.Message = "Clipping Bond Lines - Pass 2"; pb.Value = 0; pb.Maximum = _atomLabelCharacters.Count; foreach (AtomLabelCharacter alc in _atomLabelCharacters) { pb.Increment(1); double width = OoXmlHelper.ScaleCsTtfToCml(alc.Character.Width); double height = OoXmlHelper.ScaleCsTtfToCml(alc.Character.Height); if (alc.IsSubScript) { // Shrink bounding box width = width * OoXmlHelper.SUBSCRIPT_SCALE_FACTOR; height = height * OoXmlHelper.SUBSCRIPT_SCALE_FACTOR; } // Create rectangle of the bounding box with a suitable clipping margin Rect cbb = new Rect(alc.Position.X - OoXmlHelper.CHARACTER_CLIPPING_MARGIN, alc.Position.Y - OoXmlHelper.CHARACTER_CLIPPING_MARGIN, width + (OoXmlHelper.CHARACTER_CLIPPING_MARGIN * 2), height + (OoXmlHelper.CHARACTER_CLIPPING_MARGIN * 2)); //Debug.WriteLine("Character: " + alc.Ascii + " Rectangle: " + a); // Just in case we end up splitting a line into two List <BondLine> extraBondLines = new List <BondLine>(); // Select Lines which may require trimming // By using LINQ to implement the following SQL // Where (L.Right Between Cbb.Left And Cbb.Right) // Or (L.Left Between Cbb.Left And Cbb.Right) // Or (L.Top Between Cbb.Top And Cbb.Botton) // Or (L.Bottom Between Cbb.Top And Cbb.Botton) var targeted = from l in _bondLines where (cbb.Left <= l.BoundingBox.Right & l.BoundingBox.Right <= cbb.Right) | (cbb.Left <= l.BoundingBox.Left & l.BoundingBox.Left <= cbb.Right) | (cbb.Top <= l.BoundingBox.Top & l.BoundingBox.Top <= cbb.Bottom) | (cbb.Top <= l.BoundingBox.Bottom & l.BoundingBox.Bottom <= cbb.Bottom) select l; foreach (BondLine bl in targeted) { //pb.Increment(1); Point start = new Point(bl.Start.X, bl.Start.Y); Point end = new Point(bl.End.X, bl.End.Y); //Debug.WriteLine(" Line From: " + start + " To: " + end); int attempts = 0; if (CohenSutherland.ClipLine(cbb, ref start, ref end, out attempts)) { //Debug.WriteLine(" Clipped Line Start Point: " + start); //Debug.WriteLine(" Clipped Line End Point: " + end); bool bClipped = false; if (Math.Abs(bl.Start.X - start.X) < EPSILON && Math.Abs(bl.Start.Y - start.Y) < EPSILON) { bl.Start = new Point(end.X, end.Y); bClipped = true; } if (Math.Abs(bl.End.X - end.X) < EPSILON && Math.Abs(bl.End.Y - end.Y) < EPSILON) { bl.End = new Point(start.X, start.Y); bClipped = true; } if (!bClipped) { // Line was clipped at both ends; // 1. Generate new line BondLine extraLine = new BondLine(new Point(end.X, end.Y), new Point(bl.End.X, bl.End.Y), bl.Type, bl.ParentBond, bl.ParentMolecule, bl.StartAtomId, bl.EndAtomId); extraBondLines.Add(extraLine); // 2. Trim existing line bl.End = new Point(start.X, start.Y); } } if (attempts >= 15) { Debug.WriteLine("Clipping failed !"); } } // Add any extra lines generated by this character into the List of Bond Lines foreach (BondLine bl in extraBondLines) { _bondLines.Add(bl); } } }
public void DrawBondLines(Graphics g) { List <Bond> starts = new List <Bond>(); foreach (Bond b in drawnBonds) { if (b.ChainType != ChainType.None && b.IsStart) { starts.Add(b); } } foreach (Bond start in starts) { if (start.ChainType.IsDistributed()) { Bond curBond = start; while (curBond.Next != null) { Bond nextBond = curBond.Next; PointF p0 = bondPoints[curBond.GetHandleHash(curBond.ChainType.GetOppositeAttachment())]; PointF p1 = bondPoints[nextBond.GetHandleHash()]; float difX = p1.X - p0.X; float difY = p1.Y - p0.Y; float dist = (float)Math.Sqrt(difX * difX + difY * difY); float normX = difX * (1f / dist) * 5; float normY = difY * (1f / dist) * 5; PointF[] pts = new PointF[squiggleCount + 1]; pts[0] = p0; pts[pts.Length - 1] = p1; for (int i = 1; i < pts.Length - 1; i++) { int sign = i % 2 == 0 ? 1 : -1; pts[i] = new PointF( p0.X + difX * i / squiggleCount + normY * sign, p0.Y + difY * i / squiggleCount + normX * sign); } PointF midPoint = p0.MidPoint(p1); //g.DrawLine(Pens.Green, p0, p1); g.DrawCurve(Pens.Green, pts); curBond = nextBond; } } else if (start.ChainType.IsAligned()) { Bond curBond = start; Bond lastBond = curBond.GetLast(); PointF pStart = bondPoints[curBond.GetHandleHash()]; PointF pEnd = bondPoints[lastBond.GetHandleHash()]; BondLine bl = new BondLine(pStart, pEnd, curBond.BondType, curBond.SourceAttachment); do { PointF p0 = bondPoints[curBond.GetHandleHash()]; float xb = p0.X + bl.offset.X; float yb = p0.Y + bl.offset.Y; PointF p0b = new PointF(xb, yb); g.DrawLine(Pens.Red, p0, p0b); curBond = curBond.Next; }while (curBond != null && !curBond.IsStart); // joining line g.DrawLine( Pens.Red, pStart.X + bl.offset.X, pStart.Y + bl.offset.Y, pEnd.X + bl.offset.X, pEnd.Y + bl.offset.Y); } } drawnBonds.Clear(); bondLines.Clear(); bondPoints.Clear(); }