/// <summary> /// Gets the geometry of a wedge bond. /// </summary> /// <param name="desc">WedgeBondDescriptor which is populated</param> /// <param name="standardBondLength">Standard bond length as defined by the model</param> /// <param name="standoff">Boundary width between atom label and bond terminus</param> public static void GetWedgeBondGeometry(WedgeBondLayout desc, double standardBondLength, double standoff) { //get the width of the wedge bond's thick end var bondVector = desc.PrincipleVector; var perpVector = bondVector.Perpendicular(); perpVector.Normalize(); perpVector *= standardBondLength * Globals.BondOffsetPercentage; // shrink the bond so it doesn't overlap any AtomVisuals AdjustTerminus(ref desc.Start, desc.End, desc.StartAtomHull, standoff); AdjustTerminus(ref desc.End, desc.Start, desc.EndAtomHull, standoff); //then draw it GetWedgePoints(desc, perpVector); //and pass it back as a Geometry StreamGeometry sg; sg = desc.GetOutline(); sg.Freeze(); desc.DefiningGeometry = sg; }
/// <summary> /// Chamfers or forks the end of a wedge bond under special circumstances /// (one or more incoming single bonds) /// </summary> /// <param name="descriptor"> WedgeBondDescriptor to be populated</param> /// <param name="standardBondLength">Standard bond length as defined by the model</param> /// <param name="otherAtomPoints">List of positions of atoms splaying from the end atom</param> /// <param name="standoff"></param> public static void GetChamferedWedgeGeometry(WedgeBondLayout descriptor, double standardBondLength, List <Point> otherAtomPoints, double standoff) { var bondVector = descriptor.PrincipleVector; //first get an unaltered bond GetWedgeBondGeometry(descriptor, standardBondLength, standoff); var firstEdgeVector = descriptor.FirstCorner - descriptor.Start; var secondEdgeVector = descriptor.SecondCorner - descriptor.Start; //get the two bonds with widest splay var widestPoints = from Point p in otherAtomPoints orderby Math.Abs(Vector.AngleBetween(bondVector, p - descriptor.End)) descending select p; //the scaling factors are what we multiply the bond edge vectors by double firstScalingFactor = 0d; double secondScalingFactor = 0d; //work out the biggest scaling factor for either long edge foreach (var point in widestPoints) { BasicGeometry.IntersectLines(descriptor.Start, descriptor.FirstCorner, descriptor.End, point, out var firstEdgeCut, out var otherBond1Cut); BasicGeometry.IntersectLines(descriptor.Start, descriptor.SecondCorner, descriptor.End, point, out var secondEdgeCut, out var otherBond2Cut); if (otherAtomPoints.Count == 1) { if (firstEdgeCut > firstScalingFactor) { firstScalingFactor = firstEdgeCut; } if (secondEdgeCut > secondScalingFactor) { secondScalingFactor = secondEdgeCut; } } else { if (firstEdgeCut > firstScalingFactor && otherBond1Cut < 1d && otherBond1Cut > 0d) { firstScalingFactor = firstEdgeCut; } if (secondEdgeCut > secondScalingFactor && otherBond2Cut < 1d && otherBond2Cut > 0d) { secondScalingFactor = secondEdgeCut; } } } //and multiply the edges by the scaling factors descriptor.FirstCorner = firstEdgeVector * firstScalingFactor + descriptor.Start; descriptor.SecondCorner = secondEdgeVector * secondScalingFactor + descriptor.Start; descriptor.CappedOff = true; var sg = descriptor.GetOutline(); sg.Freeze(); descriptor.DefiningGeometry = sg; }