/// <summary> /// Gets or sets the <see cref="CursorToken"/> that corresponds to a particular point on the compass. /// </summary> /// <param name="compassPoint">the compass point.</param> /// <returns>the <see cref="CursorToken"/> that corresponds to the specified point on the compass, or null.</returns> private CursorToken this[CompassPoints compassPoint] { get { if (!_stretchIndicatorTokens.ContainsKey(compassPoint)) { return(null); } return(_stretchIndicatorTokens[compassPoint]); } set { if (value != null) { _stretchIndicatorTokens[compassPoint] = value; } else { if (_stretchIndicatorTokens.ContainsKey(compassPoint)) { _stretchIndicatorTokens.Remove(compassPoint); } } } }
public void initialize_rover_with_point_and_direction(int x, int y, CompassPoints direction) { var point = new CoordinatesPoint(x, y); var rover = new Rover(point, direction); Assert.AreEqual(rover.GetCoordinatesPoint(), point); Assert.AreEqual(rover.GetCompassPoints(), direction); }
/// <summary> /// Initializes a new instance of the <see cref="Vehicle"/> class. /// </summary> public Vehicle() { // This call is required by the Windows.Forms Form Designer. InitializeComponent(); // TODO: Add any initialization after the InitializeComponent call this.orientation = CompassPoints.north; this.magnitude = 0; }
public Port(Id id, CompassPoints? compassPoint) { if (id == null && compassPoint == null) { throw new ArgumentException("A port must specify either an ID, a compass point, or both."); } this.id = id; this.compassPoint = compassPoint; }
/// <summary> /// Initializes a new instance of the <see cref="Vehicle"/> class. /// </summary> /// <param name="x">The x.</param> /// <param name="y">The y.</param> /// <param name="width">The width.</param> /// <param name="height">The height.</param> public Vehicle(int x, int y, int width, int height) { this.InitializeComponent(); this.Location = new System.Drawing.Point(x, y); this.Width = width; this.Height = height; this.orientation = CompassPoints.north; this.magnitude = 0; }
/// <summary> /// /// </summary> /// <param name="drawingContext"></param> /// <param name="mainAtomMetrics"></param> /// <param name="hMetrics"></param> /// <param name="isoMetrics"></param> /// <param name="defaultHOrientation"></param> /// <returns></returns> private LabelMetrics DrawCharges(DrawingContext drawingContext, AtomTextMetrics mainAtomMetrics, AtomTextMetrics hMetrics, LabelMetrics isoMetrics, CompassPoints defaultHOrientation) { var chargeString = AtomHelpers.GetChargeString(Charge); var chargeText = DrawChargeOrRadical(drawingContext, mainAtomMetrics, hMetrics, isoMetrics, chargeString, Fill, defaultHOrientation); chargeText.TextMetrics.FlattenedPath = chargeText.TextRun.GetOutline(); return(chargeText.TextMetrics); }
/// <summary> /// Measures the dimensions of the atom prior to rendering /// </summary> /// <param name="parentMetrics">Metrics of the parent atom</param> /// <param name="direction">Orientation of the group relative to the parent atom, i.e. NESW</param> /// <returns>AtomTextMetrics object describing placement</returns> public AtomTextMetrics Measure(AtomTextMetrics parentMetrics, CompassPoints direction, float pixelsPerDip) { _subText = null; List <Point> mainOutline; //first, get some initial size measurements _mainText = new GlyphText(Text, SymbolTypeface, _fontSize, pixelsPerDip); _mainText.Premeasure(); //measure up the subscript (if we have one) string subscriptText = AtomHelpers.GetSubText(Count); if (subscriptText != "") { _subText = new SubLabelText(subscriptText, pixelsPerDip); _subText.Premeasure(); } //calculate the center of the H Atom depending on the direction var groupCenter = GetAdjunctCenter(parentMetrics, direction, _mainText.GlyphInfo, _subText?.GlyphInfo); //remeasure the main text _mainText.MeasureAtCenter(groupCenter); mainOutline = _mainText.FlattenedPath; if (_subText != null) //get the offset for the subscript { Vector subscriptOffset = new Vector(_mainText.TextMetrics.TotalBoundingBox.Width + _mainText.TrailingBearing + _subText.LeadingBearing, _subText.TextMetrics.BoundingBox.Height / 2); Point subBottomLeft = _mainText.TextMetrics.TotalBoundingBox.BottomLeft + subscriptOffset; _subText.MeasureAtBottomLeft(subBottomLeft, pixelsPerDip); //merge the total bounding boxes _mainText.Union(_subText); mainOutline.AddRange(_subText.FlattenedPath); } //return the placement metrics for the subscripted atom. AtomTextMetrics result = new AtomTextMetrics { Geocenter = groupCenter, BoundingBox = _mainText.TextMetrics.BoundingBox, TotalBoundingBox = _mainText.TextMetrics.TotalBoundingBox, FlattenedPath = mainOutline }; return(result); }
public void add_rover_to_plateau_get_last_added() { var plateau = new Plate(); plateau.SetSize(5, 5); const CompassPoints direction = CompassPoints.E; var roverPosition = new CoordinatesPoint(1, 2); var rover = new Rover(roverPosition, direction); plateau.AddRover(rover); var lastRover = plateau.GetLastRover(); Assert.AreEqual(rover, lastRover); }
/// <summary> /// Computes the position on a given rectangle that corresponds to the given compass point. /// </summary> /// <param name="compassPoint">the compass point whose position on the rectangle is to be determined.</param> /// <param name="rectangle">the rectangle.</param> /// <returns>the point on the rectangle that corresponds to the given compass point.</returns> private PointF GetCompassPointPosition(CompassPoints compassPoint, RectangleF rectangle) { float top = rectangle.Top; float left = rectangle.Left; float right = rectangle.Right; float bottom = rectangle.Bottom; float centreX = left; if (left != right) { centreX = rectangle.Left + rectangle.Width / 2F; } float centreY = top; if (top != bottom) { centreY = rectangle.Top + rectangle.Height / 2F; } switch (compassPoint) { case CompassPoints.NorthWest: return(new PointF(left, top)); case CompassPoints.NorthEast: return(new PointF(right, top)); case CompassPoints.SouthEast: return(new PointF(right, bottom)); case CompassPoints.SouthWest: return(new PointF(left, bottom)); case CompassPoints.North: return(new PointF(centreX, top)); case CompassPoints.East: return(new PointF(right, centreY)); case CompassPoints.South: return(new PointF(centreX, bottom)); default: //CompassPoints.West: return(new PointF(left, centreY)); } }
/// <summary> /// Offsets the specified orientation. /// </summary> /// <param name="orientation">The orientation.</param> /// <param name="magnitude">The magnitude.</param> public void Offset(CompassPoints orientation, int magnitude) { this.orientation = orientation; this.magnitude = (double)magnitude; switch (orientation) { case CompassPoints.north: this.Location = new Point(this.Location.X, this.Location.Y - (int)this.magnitude); break; case CompassPoints.northeast: this.Location = new Point(this.Location.X + ((int)Math.Round(Math.Sqrt((Math.Pow(this.magnitude, 2)) / 2), 0)), this.Location.Y + (int)-Math.Round((Math.Sqrt((Math.Pow(this.magnitude, 2)) / 2)), 0)); break; case CompassPoints.east: this.Location = new Point(this.Location.X + magnitude, this.Location.Y); break; case CompassPoints.southeast: this.Location = new Point(this.Location.X + (int)Math.Round(Math.Sqrt((Math.Pow(this.magnitude, 2)) / 2), 0), this.Location.Y + (int)Math.Round(Math.Sqrt((Math.Pow(this.magnitude, 2) / 2)), 0)); break; case CompassPoints.south: this.Location = new Point(this.Location.X, this.Location.Y + (magnitude)); break; case CompassPoints.southwest: this.Location = new Point(this.Location.X + (int)-Math.Round(Math.Sqrt(Math.Pow(this.magnitude, 2) / 2), 0), this.Location.Y + (int)Math.Round((Math.Sqrt((Math.Pow(this.magnitude, 2)) / 2)), 0)); break; case CompassPoints.west: this.Location = new Point(this.Location.X - (magnitude), this.Location.Y); break; case CompassPoints.northwest: this.Location = new Point(this.Location.X + (int)-Math.Round(Math.Sqrt((Math.Pow(this.magnitude, 2)) / 2), 0), this.Location.Y + (int)-Math.Round(Math.Sqrt((Math.Pow(this.magnitude, 2)) / 2), 0)); break; default: break; } }
public InnerWallBoard(GamesBoard gb, int colPosition, int rowPosition, CompassPoints wallSide) { for (int c = 0; c < Constants.BOARDCOLSIZE; c++) { for (int r = 0; r < Constants.BOARDROWSIZE; r++) { board[c][r].boardSpace = gb.board[c][r].boardSpace; board[c][r].northWall = gb.board[c][r].northWall; board[c][r].southWall = gb.board[c][r].southWall; board[c][r].westWall = gb.board[c][r].westWall; board[c][r].eastWall = gb.board[c][r].eastWall; } } this.prevDeco = gb; switch (wallSide) { case CompassPoints.NORTH: gb.board[colPosition][rowPosition].northWall = true; board[colPosition][rowPosition].northWall = true; prevDeco.board[colPosition][rowPosition].northWall = true; break; case CompassPoints.SOUTH: gb.board[colPosition][rowPosition].southWall = true; board[colPosition][rowPosition].southWall = true; prevDeco.board[colPosition][rowPosition].southWall = true; break; case CompassPoints.WEST: gb.board[colPosition][rowPosition].westWall = true; board[colPosition][rowPosition].westWall = true; prevDeco.board[colPosition][rowPosition].westWall = true; break; case CompassPoints.EAST: gb.board[colPosition][rowPosition].eastWall = true; board[colPosition][rowPosition].eastWall = true; prevDeco.board[colPosition][rowPosition].eastWall = true; break; default: break; } }
/// <summary> /// Gets the center point of an atom adjunct (like an implicit hydrogen plus subscripts) /// The Adjunct in NH2 is H2 /// </summary> /// <param name="parentMetrics">Metrics of the parent atom</param> /// <param name="direction">NESW direction of the adjunct respective to the atom</param> /// <param name="adjunctGlyphInfo">Initial measurements of the adjunct</param> /// <param name="subscriptInfo">Initial measurements of the subscript (can be null for no subscripts)</param> /// <returns></returns> private static Point GetAdjunctCenter(AtomTextMetrics parentMetrics, CompassPoints direction, GlyphInfo adjunctGlyphInfo, GlyphInfo?subscriptInfo = null) { Point adjunctCenter; double charHeight = (GlyphUtils.GlyphTypeface.Baseline * _fontSize); double adjunctWidth = (parentMetrics.BoundingBox.Width + adjunctGlyphInfo.Width) / 2; switch (direction) { //all addition in this routine is *vector* addition. //We are not adding absolute X and Y values case CompassPoints.East: default: adjunctCenter = parentMetrics.Geocenter + BasicGeometry.ScreenEast * adjunctWidth; break; case CompassPoints.North: adjunctCenter = parentMetrics.Geocenter + BasicGeometry.ScreenNorth * charHeight; break; case CompassPoints.West: if (subscriptInfo != null) { adjunctCenter = parentMetrics.Geocenter + (BasicGeometry.ScreenWest * (adjunctWidth + subscriptInfo.Value.Width)); } else { adjunctCenter = parentMetrics.Geocenter + (BasicGeometry.ScreenWest * (adjunctWidth)); } break; case CompassPoints.South: adjunctCenter = parentMetrics.Geocenter + BasicGeometry.ScreenSouth * charHeight; break; } return(adjunctCenter); }
/// <summary> /// Gets the appropriate <see cref="CursorToken"/> for a given point (in destination coordinates). /// </summary> /// <param name="point">the point (in destination coordinates).</param> /// <returns>a <see cref="CursorToken"/> that is appropriate for the given point, or null.</returns> public override CursorToken GetCursorToken(Point point) { if (_stretchIndicatorTokens.Count == 0) { return(null); } Platform.CheckForNullReference(ControlPoints, "_controlPoints"); int controlPointIndex = ControlPoints.HitTestControlPoint(point); if (controlPointIndex < 0) { return(null); } ControlPoints.CoordinateSystem = CoordinateSystem.Destination; PointF controlPoint = ControlPoints[controlPointIndex]; RectangleF containingRectangle = this.BoundingRectangle; CompassPoints closestCompassPoint = _stretchIndicatorTokens.Keys[0]; float minDistance = DistanceToCompassPoint(controlPoint, containingRectangle, closestCompassPoint); for (int i = 1; i < _stretchIndicatorTokens.Keys.Count; ++i) { CompassPoints compassPoint = _stretchIndicatorTokens.Keys[i]; float distance = DistanceToCompassPoint(controlPoint, containingRectangle, compassPoint); if (distance <= minDistance) { closestCompassPoint = compassPoint; minDistance = distance; } } ControlPoints.ResetCoordinateSystem(); return(_stretchIndicatorTokens[closestCompassPoint]); }
/// <summary> /// Gets or sets the <see cref="CursorToken"/> that corresponds to a particular point on the compass. /// </summary> /// <param name="compassPoint">the compass point.</param> /// <returns>the <see cref="CursorToken"/> that corresponds to the specified point on the compass, or null.</returns> private CursorToken this[CompassPoints compassPoint] { get { if (!_stretchIndicatorTokens.ContainsKey(compassPoint)) return null; return _stretchIndicatorTokens[compassPoint]; } set { if (value != null) { _stretchIndicatorTokens[compassPoint] = value; } else { if (_stretchIndicatorTokens.ContainsKey(compassPoint)) _stretchIndicatorTokens.Remove(compassPoint); } } }
public void move_rover_for_12N(CoordinatesPoint coordinatesPoint, CompassPoints direction, IEnumerable <StringMovement> commands, int cX, int cY, CompassPoints cDirection) { var roverMove = new Rover(coordinatesPoint, cDirection); _plate.SetSize(5, 5); _plate.AddRover(roverMove); roverMove.Move(commands, _plate); var lastRover = _plate.GetLastRover(); Assert.IsNotNull(lastRover); var currentPosition = lastRover.GetCoordinatesPoint(); var currentDirection = lastRover.GetCompassPoints(); Assert.IsNotNull(currentPosition); Assert.IsNotNull(currentDirection); Assert.AreEqual(cX, currentPosition.X); Assert.AreEqual(cY, currentPosition.Y); Assert.AreEqual(cDirection, currentDirection); }
public void Nudge(CompassPoints direction) { var destination = Centre; switch (direction) { case CompassPoints.North: destination = new Point(Centre.X, Centre.Y - _bondLength / 16); break; case CompassPoints.East: destination = new Point(Centre.X + _bondLength / 16, Centre.Y); break; case CompassPoints.South: destination = new Point(Centre.X, Centre.Y + _bondLength / 16); break; case CompassPoints.West: destination = new Point(Centre.X - _bondLength / 16, Centre.Y); break; } AdjustPosition(destination - Centre); }
public void MoveLeft() { switch (_compassPoints) { case CompassPoints.N: _compassPoints = CompassPoints.W; break; case CompassPoints.E: _compassPoints = CompassPoints.N; break; case CompassPoints.S: _compassPoints = CompassPoints.E; break; case CompassPoints.W: _compassPoints = CompassPoints.S; break; default: break; } }
/// <summary> /// Computes the distance from a point to a compass point on the given rectangle. /// </summary> /// <param name="point">a point whose distance from a compass point on the rectangle is to be determined.</param> /// <param name="compassRectangle">the rectangle from which to determine the compass point position.</param> /// <param name="compassPoint">the point on the compass to find the distance to.</param> /// <returns></returns> private float DistanceToCompassPoint(PointF point, RectangleF compassRectangle, CompassPoints compassPoint) { PointF compassPointPosition = GetCompassPointPosition(compassPoint, compassRectangle); return((float)Vector.Distance(point, compassPointPosition)); }
public void CreateElementCharacters(Atom atom, Options options) { string module = $"{_product}.{_class}.{MethodBase.GetCurrentMethod().Name}()"; //Point atomCentre = new Point((double)atom.X2, (double)atom.Y2); string atomLabel = atom.Element.Symbol; Rect labelBounds; // Get Charge and Isotope values for use later on int iCharge = atom.FormalCharge ?? 0; int iAbsCharge = Math.Abs(iCharge); int isoValue = atom.IsotopeNumber ?? 0; // Get Implicit Hydrogen Count for use later on int implicitHCount = atom.ImplicitHydrogenCount; Point cursorPosition = atom.Position; Point chargeCursorPosition = atom.Position; Point isotopeCursorPosition = atom.Position; double lastOffset = 0; int bondCount = atom.Bonds.ToList().Count; #region Decide if atom label is to be displayed bool showLabel = true; if (atomLabel == "C") { if (atom.ShowSymbol.HasValue) { showLabel = atom.ShowSymbol.Value; } else { if (atom.IsInRing || bondCount > 1) { showLabel = false; } if (bondCount == 2) { Point p1 = atom.Bonds.ToList()[0].OtherAtom(atom).Position; Point p2 = atom.Bonds.ToList()[1].OtherAtom(atom).Position; double angle1 = Vector.AngleBetween(-(atom.Position - p1), atom.Position - p2); if (Math.Abs(angle1) < 8) { showLabel = true; } } } // Force on if atom has charge if (iAbsCharge > 0) { showLabel = true; } // Force on if atom has isotope value if (isoValue > 0) { showLabel = true; } } #endregion Decide if atom label is to be displayed if (showLabel) { #region Set Up Atom Colours string atomColour = "000000"; if (options.ColouredAtoms) { if (atom.Element.Colour != null) { atomColour = atom.Element.Colour; // Strip out # as OoXml does not use it atomColour = atomColour.Replace("#", ""); } } #endregion Set Up Atom Colours #region Step 1 - Measure Bounding Box for all Characters of label double xMin = double.MaxValue; double yMin = double.MaxValue; double xMax = double.MinValue; double yMax = double.MinValue; Point thisCharacterPosition; for (int idx = 0; idx < atomLabel.Length; idx++) { char chr = atomLabel[idx]; TtfCharacter c = _TtfCharacterSet[chr]; if (c != null) { thisCharacterPosition = GetCharacterPosition(cursorPosition, c); xMin = Math.Min(xMin, thisCharacterPosition.X); yMin = Math.Min(yMin, thisCharacterPosition.Y); xMax = Math.Max(xMax, thisCharacterPosition.X + OoXmlHelper.ScaleCsTtfToCml(c.Width, _meanBondLength)); yMax = Math.Max(yMax, thisCharacterPosition.Y + OoXmlHelper.ScaleCsTtfToCml(c.Height, _meanBondLength)); if (idx < atomLabel.Length - 1) { // Move to next Character position cursorPosition.Offset(OoXmlHelper.ScaleCsTtfToCml(c.IncrementX, _meanBondLength), 0); } } } #endregion Step 1 - Measure Bounding Box for all Characters of label #region Step 2 - Reset Cursor such that the text is centered about the atom's co-ordinates double width = xMax - xMin; double height = yMax - yMin; cursorPosition = new Point(atom.Position.X - width / 2, atom.Position.Y + height / 2); chargeCursorPosition = new Point(cursorPosition.X, cursorPosition.Y); isotopeCursorPosition = new Point(cursorPosition.X, cursorPosition.Y); labelBounds = new Rect(cursorPosition, new Size(width, height)); #endregion Step 2 - Reset Cursor such that the text is centered about the atom's co-ordinates #region Step 3 - Place the characters foreach (char chr in atomLabel) { TtfCharacter c = _TtfCharacterSet[chr]; if (c != null) { thisCharacterPosition = GetCharacterPosition(cursorPosition, c); AtomLabelCharacter alc = new AtomLabelCharacter(thisCharacterPosition, c, atomColour, chr, atom.Path, atom.Parent.Path); _AtomLabelCharacters.Add(alc); // Move to next Character position lastOffset = OoXmlHelper.ScaleCsTtfToCml(c.IncrementX, _meanBondLength); cursorPosition.Offset(OoXmlHelper.ScaleCsTtfToCml(c.IncrementX, _meanBondLength), 0); chargeCursorPosition = new Point(cursorPosition.X, cursorPosition.Y); } } #endregion Step 3 - Place the characters #region Determine NESW double baFromNorth = Vector.AngleBetween(BasicGeometry.ScreenNorth, atom.BalancingVector(true)); CompassPoints nesw = CompassPoints.East; if (bondCount == 1) { nesw = BasicGeometry.SnapTo2EW(baFromNorth); } else { nesw = BasicGeometry.SnapTo4NESW(baFromNorth); } #endregion Determine NESW #region Step 4 - Add Charge if required if (iCharge != 0) { TtfCharacter hydrogenCharacter = _TtfCharacterSet['H']; char sign = '.'; TtfCharacter chargeSignCharacter = null; if (iCharge >= 1) { sign = '+'; chargeSignCharacter = _TtfCharacterSet['+']; } else if (iCharge <= 1) { sign = '-'; chargeSignCharacter = _TtfCharacterSet['-']; } if (iAbsCharge > 1) { string digits = iAbsCharge.ToString(); // Insert digits foreach (char chr in digits) { TtfCharacter chargeValueCharacter = _TtfCharacterSet[chr]; thisCharacterPosition = GetCharacterPosition(chargeCursorPosition, chargeValueCharacter); // Raise the superscript Character thisCharacterPosition.Offset(0, -OoXmlHelper.ScaleCsTtfToCml(chargeValueCharacter.Height * OoXmlHelper.CS_SUPERSCRIPT_RAISE_FACTOR, _meanBondLength)); AtomLabelCharacter alcc = new AtomLabelCharacter(thisCharacterPosition, chargeValueCharacter, atomColour, chr, atom.Path, atom.Parent.Path); alcc.IsSmaller = true; alcc.IsSubScript = true; _AtomLabelCharacters.Add(alcc); // Move to next Character position chargeCursorPosition.Offset(OoXmlHelper.ScaleCsTtfToCml(chargeValueCharacter.IncrementX, _meanBondLength) * OoXmlHelper.SUBSCRIPT_SCALE_FACTOR, 0); cursorPosition.Offset(OoXmlHelper.ScaleCsTtfToCml(chargeValueCharacter.IncrementX, _meanBondLength) * OoXmlHelper.SUBSCRIPT_SCALE_FACTOR, 0); } } // Insert sign at raised position thisCharacterPosition = GetCharacterPosition(chargeCursorPosition, chargeSignCharacter); thisCharacterPosition.Offset(0, -OoXmlHelper.ScaleCsTtfToCml(hydrogenCharacter.Height * OoXmlHelper.CS_SUPERSCRIPT_RAISE_FACTOR, _meanBondLength)); thisCharacterPosition.Offset(0, -OoXmlHelper.ScaleCsTtfToCml(chargeSignCharacter.Height / 2 * OoXmlHelper.CS_SUPERSCRIPT_RAISE_FACTOR, _meanBondLength)); AtomLabelCharacter alcs = new AtomLabelCharacter(thisCharacterPosition, chargeSignCharacter, atomColour, sign, atom.Path, atom.Parent.Path); alcs.IsSmaller = true; alcs.IsSubScript = true; _AtomLabelCharacters.Add(alcs); if (iAbsCharge != 0) { cursorPosition.Offset(OoXmlHelper.ScaleCsTtfToCml(chargeSignCharacter.IncrementX, _meanBondLength) * OoXmlHelper.SUBSCRIPT_SCALE_FACTOR, 0); } } #endregion Step 4 - Add Charge if required #region Step 5 - Add Implicit H if required if (options.ShowHydrogens && implicitHCount > 0) { TtfCharacter hydrogenCharacter = _TtfCharacterSet['H']; string numbers = "012345"; TtfCharacter implicitValueCharacter = _TtfCharacterSet[numbers[implicitHCount]]; #region Add H if (hydrogenCharacter != null) { switch (nesw) { case CompassPoints.North: if (atom.Bonds.ToList().Count > 1) { cursorPosition.X = labelBounds.X + (labelBounds.Width / 2) - (OoXmlHelper.ScaleCsTtfToCml(hydrogenCharacter.Width, _meanBondLength) / 2); cursorPosition.Y = cursorPosition.Y + OoXmlHelper.ScaleCsTtfToCml(-hydrogenCharacter.Height, _meanBondLength) - OoXmlHelper.CHARACTER_VERTICAL_SPACING; if (iCharge > 0) { if (implicitHCount > 1) { cursorPosition.Offset(0, OoXmlHelper.ScaleCsTtfToCml( -implicitValueCharacter.Height * OoXmlHelper.SUBSCRIPT_SCALE_FACTOR / 2, _meanBondLength) - OoXmlHelper.CHARACTER_VERTICAL_SPACING); } } } break; case CompassPoints.East: // Leave as is break; case CompassPoints.South: if (atom.Bonds.ToList().Count > 1) { cursorPosition.X = labelBounds.X + (labelBounds.Width / 2) - (OoXmlHelper.ScaleCsTtfToCml(hydrogenCharacter.Width, _meanBondLength) / 2); cursorPosition.Y = cursorPosition.Y + OoXmlHelper.ScaleCsTtfToCml(hydrogenCharacter.Height, _meanBondLength) + OoXmlHelper.CHARACTER_VERTICAL_SPACING; } break; case CompassPoints.West: if (implicitHCount == 1) { if (iAbsCharge == 0) { cursorPosition.Offset(OoXmlHelper.ScaleCsTtfToCml(-(hydrogenCharacter.IncrementX * 2), _meanBondLength), 0); } else { cursorPosition.Offset(OoXmlHelper.ScaleCsTtfToCml(-((hydrogenCharacter.IncrementX * 2 + implicitValueCharacter.IncrementX * 1.25)), _meanBondLength), 0); } } else { if (iAbsCharge == 0) { cursorPosition.Offset(OoXmlHelper.ScaleCsTtfToCml(-(hydrogenCharacter.IncrementX * 2.5), _meanBondLength), 0); } else { cursorPosition.Offset(OoXmlHelper.ScaleCsTtfToCml(-((hydrogenCharacter.IncrementX * 2 + implicitValueCharacter.IncrementX * 1.25)), _meanBondLength), 0); } } break; } thisCharacterPosition = GetCharacterPosition(cursorPosition, hydrogenCharacter); AtomLabelCharacter alc = new AtomLabelCharacter(thisCharacterPosition, hydrogenCharacter, atomColour, 'H', atom.Path, atom.Parent.Path); _AtomLabelCharacters.Add(alc); // Move to next Character position cursorPosition.Offset(OoXmlHelper.ScaleCsTtfToCml(hydrogenCharacter.IncrementX, _meanBondLength), 0); if (nesw == CompassPoints.East) { chargeCursorPosition = new Point(cursorPosition.X, cursorPosition.Y); } if (nesw == CompassPoints.West) { isotopeCursorPosition = new Point(thisCharacterPosition.X, isotopeCursorPosition.Y); } } #endregion Add H #region Add number if (implicitHCount > 1) { if (implicitValueCharacter != null) { thisCharacterPosition = GetCharacterPosition(cursorPosition, implicitValueCharacter); // Drop the subscript Character thisCharacterPosition.Offset(0, OoXmlHelper.ScaleCsTtfToCml(hydrogenCharacter.Width * OoXmlHelper.SUBSCRIPT_DROP_FACTOR, _meanBondLength)); AtomLabelCharacter alc = new AtomLabelCharacter(thisCharacterPosition, implicitValueCharacter, atomColour, numbers[implicitHCount], atom.Path, atom.Parent.Path); alc.IsSmaller = true; alc.IsSubScript = true; _AtomLabelCharacters.Add(alc); // Move to next Character position cursorPosition.Offset(OoXmlHelper.ScaleCsTtfToCml(implicitValueCharacter.IncrementX, _meanBondLength) * OoXmlHelper.SUBSCRIPT_SCALE_FACTOR, 0); } } #endregion Add number } #endregion Step 5 - Add Implicit H if required #region Step 6 - Add IsoTope Number if required if (isoValue > 0) { string digits = isoValue.ToString(); xMin = double.MaxValue; yMin = double.MaxValue; xMax = double.MinValue; yMax = double.MinValue; Point isoOrigin = isotopeCursorPosition; // Calculate width of digits foreach (char chr in digits) { TtfCharacter c = _TtfCharacterSet[chr]; thisCharacterPosition = GetCharacterPosition(isotopeCursorPosition, c); // Raise the superscript Character thisCharacterPosition.Offset(0, -OoXmlHelper.ScaleCsTtfToCml(c.Height * OoXmlHelper.CS_SUPERSCRIPT_RAISE_FACTOR, _meanBondLength)); xMin = Math.Min(xMin, thisCharacterPosition.X); yMin = Math.Min(yMin, thisCharacterPosition.Y); xMax = Math.Max(xMax, thisCharacterPosition.X + OoXmlHelper.ScaleCsTtfToCml(c.Width, _meanBondLength)); yMax = Math.Max(yMax, thisCharacterPosition.Y + OoXmlHelper.ScaleCsTtfToCml(c.Height, _meanBondLength)); // Move to next Character position isotopeCursorPosition.Offset(OoXmlHelper.ScaleCsTtfToCml(c.IncrementX, _meanBondLength) * OoXmlHelper.SUBSCRIPT_SCALE_FACTOR, 0); } // Re-position Isotope Cursor width = xMax - xMin; isotopeCursorPosition = new Point(isoOrigin.X - width, isoOrigin.Y); // Insert digits foreach (char chr in digits) { TtfCharacter c = _TtfCharacterSet[chr]; thisCharacterPosition = GetCharacterPosition(isotopeCursorPosition, c); // Raise the superscript Character thisCharacterPosition.Offset(0, -OoXmlHelper.ScaleCsTtfToCml(c.Height * OoXmlHelper.CS_SUPERSCRIPT_RAISE_FACTOR, _meanBondLength)); AtomLabelCharacter alcc = new AtomLabelCharacter(thisCharacterPosition, c, atomColour, chr, atom.Path, atom.Parent.Path); alcc.IsSmaller = true; alcc.IsSubScript = true; _AtomLabelCharacters.Add(alcc); // Move to next Character position isotopeCursorPosition.Offset(OoXmlHelper.ScaleCsTtfToCml(c.IncrementX, _meanBondLength) * OoXmlHelper.SUBSCRIPT_SCALE_FACTOR, 0); } } #endregion Step 6 - Add IsoTope Number if required #region Step 7 - Create Convex Hull _convexhHulls.Add(atom.Path, ConvexHull(atom.Path)); #endregion Step 7 - Create Convex Hull } }
public void CreateFunctionalGroupCharacters(Atom atom, Options options) { FunctionalGroup fg = atom.Element as FunctionalGroup; double baFromNorth = Vector.AngleBetween(BasicGeometry.ScreenNorth, atom.BalancingVector(true)); CompassPoints nesw = BasicGeometry.SnapTo2EW(baFromNorth); bool reverse = nesw == CompassPoints.West; #region Set Up Atom Colours string atomColour = "000000"; if (options.ColouredAtoms) { if (!string.IsNullOrEmpty(fg.Colour)) { atomColour = fg.Colour; // Strip out # as OoXml does not use it atomColour = atomColour.Replace("#", ""); } } #endregion Set Up Atom Colours List <FunctionalGroupTerm> terms = fg.ExpandIntoTerms(reverse); #region Step 1 - Generate the characters and measure Bounding Boxes var cursorPosition = atom.Position; List <AtomLabelCharacter> fgCharacters = new List <AtomLabelCharacter>(); TtfCharacter hydrogenCharacter = _TtfCharacterSet['H']; Rect fgBoundingBox = Rect.Empty; Rect anchorBoundingBox = Rect.Empty; foreach (var term in terms) { foreach (var part in term.Parts) { foreach (char c in part.Text) { Rect bb = AddCharacter(c, part.Type); fgBoundingBox.Union(bb); if (term.IsAnchor) { anchorBoundingBox.Union(bb); } } } } #endregion Step 1 - Generate the characters and measure Bounding Boxes #region Step 2 - Move all characters such that the anchor term is centered on the atom position double offsetX; double offsetY; if (reverse) { offsetX = fgBoundingBox.Width - anchorBoundingBox.Width / 2; offsetY = anchorBoundingBox.Height / 2; } else { offsetX = anchorBoundingBox.Width / 2; offsetY = anchorBoundingBox.Height / 2; } offsetY = offsetY + anchorBoundingBox.Top - atom.Position.Y; foreach (var alc in fgCharacters) { alc.Position = new Point(alc.Position.X - offsetX, alc.Position.Y - offsetY); } #endregion Step 2 - Move all characters such that the anchor term is centered on the atom position #region Step 3 - Transfer characters into main list foreach (var alc in fgCharacters) { _AtomLabelCharacters.Add(alc); } #endregion Step 3 - Transfer characters into main list #region Step 4 - Convex Hull _convexhHulls.Add(atom.Path, ConvexHull(atom.Path)); #endregion Step 4 - Convex Hull // Local Function Rect AddCharacter(char c, FunctionalGroupPartType type) { TtfCharacter ttf = _TtfCharacterSet[c]; var thisCharacterPosition = GetCharacterPosition(cursorPosition, ttf); var alc = new AtomLabelCharacter(thisCharacterPosition, ttf, atomColour, c, atom.Path, atom.Parent.Path); alc.IsSubScript = type == FunctionalGroupPartType.Subscript; alc.IsSuperScript = type == FunctionalGroupPartType.Superscript; alc.IsSmaller = alc.IsSubScript || alc.IsSuperScript; Rect thisBoundingBox; if (alc.IsSmaller) { // Start by assuming it's SubScript thisCharacterPosition.Offset(0, OoXmlHelper.ScaleCsTtfToCml(hydrogenCharacter.Height * OoXmlHelper.SUBSCRIPT_DROP_FACTOR, _meanBondLength)); if (alc.IsSuperScript) { // Shift up by height of H to make it SuperScript thisCharacterPosition.Offset(0, -OoXmlHelper.ScaleCsTtfToCml(hydrogenCharacter.Height, _meanBondLength)); } // Reset the character's position alc.Position = thisCharacterPosition; thisBoundingBox = new Rect(alc.Position, new Size(OoXmlHelper.ScaleCsTtfToCml(alc.Character.Width, _meanBondLength) * OoXmlHelper.SUBSCRIPT_SCALE_FACTOR, OoXmlHelper.ScaleCsTtfToCml(alc.Character.Height, _meanBondLength) * OoXmlHelper.SUBSCRIPT_SCALE_FACTOR)); cursorPosition.Offset(OoXmlHelper.ScaleCsTtfToCml(alc.Character.IncrementX, _meanBondLength) * OoXmlHelper.SUBSCRIPT_SCALE_FACTOR, 0); } else { thisBoundingBox = new Rect(alc.Position, new Size(OoXmlHelper.ScaleCsTtfToCml(alc.Character.Width, _meanBondLength), OoXmlHelper.ScaleCsTtfToCml(alc.Character.Height, _meanBondLength))); cursorPosition.Offset(OoXmlHelper.ScaleCsTtfToCml(alc.Character.IncrementX, _meanBondLength), 0); } fgCharacters.Add(alc); return(thisBoundingBox); } }
/// <summary> /// Computes the position on a given rectangle that corresponds to the given compass point. /// </summary> /// <param name="compassPoint">the compass point whose position on the rectangle is to be determined.</param> /// <param name="rectangle">the rectangle.</param> /// <returns>the point on the rectangle that corresponds to the given compass point.</returns> private PointF GetCompassPointPosition(CompassPoints compassPoint, RectangleF rectangle) { float top = rectangle.Top; float left = rectangle.Left; float right = rectangle.Right; float bottom = rectangle.Bottom; float centreX = left; if (left != right) centreX = rectangle.Left + rectangle.Width / 2F; float centreY = top; if (top != bottom) centreY = rectangle.Top + rectangle.Height / 2F; switch (compassPoint) { case CompassPoints.NorthWest: return new PointF(left, top); case CompassPoints.NorthEast: return new PointF(right, top); case CompassPoints.SouthEast: return new PointF(right, bottom); case CompassPoints.SouthWest: return new PointF(left, bottom); case CompassPoints.North: return new PointF(centreX, top); case CompassPoints.East: return new PointF(right, centreY); case CompassPoints.South: return new PointF(centreX, bottom); default: //CompassPoints.West: return new PointF(left, centreY); } }
public Rover(CoordinatesPoint coordinatesPoint, CompassPoints compassPoints) { _compassPoints = compassPoints; _coordinatesPoint = coordinatesPoint; }
public static double ToDegrees(this CompassPoints cp) { return(45 * (int)cp); }
/// <param name="drawingContext"></param> /// <param name="mainAtomMetrics"> /// </param> /// <param name="hMetrics"> /// </param> /// <param name="isoMetrics"> /// </param> /// <param name="chargeString"></param> /// <param name="fill"></param> /// <param name="defaultHOrientation"></param> /// <returns></returns> /// <summary> /// Draws a charge or radical label at the given point /// </summary> /// <returns></returns> private ChargeLabelText DrawChargeOrRadical(DrawingContext drawingContext, AtomTextMetrics mainAtomMetrics, AtomTextMetrics hMetrics, LabelMetrics isoMetrics, string chargeString, Brush fill, CompassPoints defaultHOrientation) { ChargeLabelText chargeText = new ChargeLabelText(chargeString, PixelsPerDip()); //try to place the charge at 2 o clock to the atom Vector chargeOffset = BasicGeometry.ScreenNorth * GlyphText.SymbolSize * 0.9; RotateUntilClear(mainAtomMetrics, hMetrics, isoMetrics, chargeOffset, chargeText, out var chargeCenter, defaultHOrientation); chargeText.MeasureAtCenter(chargeCenter); chargeText.Fill = fill; chargeText.DrawAtBottomLeft(chargeText.TextMetrics.BoundingBox.BottomLeft, drawingContext); return(chargeText); }
private static void RotateUntilClear(AtomTextMetrics mainAtomMetrics, AtomTextMetrics hMetrics, LabelMetrics isoMetrics, Vector labelOffset, GlyphText labelText, out Point labelCenter, CompassPoints defHOrientation) { Matrix rotator = new Matrix(); double angle = Globals.ClockDirections.II.ToDegrees(); rotator.Rotate(angle); labelOffset = labelOffset * rotator; Rect bb = new Rect(); Rect bb2 = new Rect(); if (hMetrics != null) { bb = hMetrics.TotalBoundingBox; } if (isoMetrics != null) { bb2 = isoMetrics.BoundingBox; } labelCenter = mainAtomMetrics.Geocenter + labelOffset; labelText.MeasureAtCenter(labelCenter); double increment; if (defHOrientation == CompassPoints.East) { increment = -10; } else { increment = 10; } while (labelText.CollidesWith(mainAtomMetrics.TotalBoundingBox, bb, bb2) & Math.Abs(angle - 30) > 0.001) { rotator = new Matrix(); angle += increment; rotator.Rotate(increment); labelOffset = labelOffset * rotator; labelCenter = mainAtomMetrics.Geocenter + labelOffset; labelText.MeasureAtCenter(labelCenter); } }
public void SetRoverCurrentPosition(CoordinatesPoint point, CompassPoints cp) { var rover = new Rover(point, cp); _plate.AddRover(rover); }
public void CreateCharacters(Atom atom, Options options) { string module = $"{_product}.{_class}.{MethodBase.GetCurrentMethod().Name}()"; //Debug.WriteLine("Atom: " + atom.Id + " is " + atom.ElementType); //Point atomCentre = new Point((double)atom.X2, (double)atom.Y2); string atomLabel = atom.Element.Symbol; Rect labelBounds; //Debug Code //atomLabel = "H" + "abcdefHghijklmnopqrstuvwxyz" + "H"; //atomLabel = "ABCHDEFGHIJKLMNOHPQRSHTUVWXYZ"; //atomLabel = "-+H01234567890H+-"; // Get Charge and Isotope valuesfor use later on int iCharge = atom.FormalCharge ?? 0; int iAbsCharge = Math.Abs(iCharge); int isoValue = atom.IsotopeNumber ?? 0; // Get Implicit Hydrogen Count for use later on int implicitHCount = atom.ImplicitHydrogenCount; Point cursorPosition = atom.Position; Point chargeCursorPosition = atom.Position; Point isotopeCursorPosition = atom.Position; double lastOffset = 0; //Debug.WriteLine(" X: " + atom.X2 + " Y: " + atom.Y2 + " Implicit H Count: " + implicitHCount); int ringCount = atom.Rings.Count(); int bondCount = atom.Bonds.Count; //var bv = atom.BalancingVector; //_telemetry.Write(module, "Debugging", $"Atom {atomLabel} [{atom.Id}] at {atom.Position} BalancingVector {bv} [{CoordinateTool.BearingOfVector(bv)}°]"); #region Decide if atom label is to be displayed bool showLabel = true; if (atomLabel == "C") { if (!options.ShowCarbons) { if (ringCount > 0 || bondCount > 1) { showLabel = false; } if (bondCount == 2) { Point p1 = atom.Bonds[0].OtherAtom(atom).Position; Point p2 = atom.Bonds[1].OtherAtom(atom).Position; double angle1 = Vector.AngleBetween(-(atom.Position - p1), atom.Position - p2); if (Math.Abs(angle1) < 8) { showLabel = true; } } // Force on if atom has charge if (iAbsCharge > 0) { showLabel = true; } // Force on if atom has isotope value if (isoValue > 0) { showLabel = true; } } } #endregion Decide if atom label is to be displayed if (showLabel) { #region Set Up Atom Colours string atomColour = "000000"; if (options.ColouredAtoms) { if ((atom.Element as Element).Colour != null) { atomColour = ((Element)atom.Element).Colour; // Strip out # as OoXml does not use it atomColour = atomColour.Replace("#", ""); } } #endregion Set Up Atom Colours #region Step 1 - Measure Bounding Box for all Characters of label double xMin = double.MaxValue; double yMin = double.MaxValue; double xMax = double.MinValue; double yMax = double.MinValue; Point thisCharacterPosition; for (int idx = 0; idx < atomLabel.Length; idx++) { char chr = atomLabel[idx]; TtfCharacter c = m_TtfCharacterSet[chr]; if (c != null) { thisCharacterPosition = GetCharacterPosition(cursorPosition, c); xMin = Math.Min(xMin, thisCharacterPosition.X); yMin = Math.Min(yMin, thisCharacterPosition.Y); xMax = Math.Max(xMax, thisCharacterPosition.X + OoXmlHelper.ScaleCsTtfToCml(c.Width)); yMax = Math.Max(yMax, thisCharacterPosition.Y + OoXmlHelper.ScaleCsTtfToCml(c.Height)); // Uncomment the following to disable offsetting for terminal atoms //if (bonds.Count == 1) //{ // break; //} if (idx < atomLabel.Length - 1) { // Move to next Character position cursorPosition.Offset(OoXmlHelper.ScaleCsTtfToCml(c.IncrementX), 0); } } } #endregion Step 1 - Measure Bounding Box for all Characters of label #region Step 2 - Reset Cursor such that the text is centered about the atom's co-ordinates double width = xMax - xMin; double height = yMax - yMin; cursorPosition = new Point(atom.Position.X - width / 2, atom.Position.Y + height / 2); chargeCursorPosition = new Point(cursorPosition.X, cursorPosition.Y); isotopeCursorPosition = new Point(cursorPosition.X, cursorPosition.Y); labelBounds = new Rect(cursorPosition, new Size(width, height)); //_telemetry.Write(module, "Debugging", $"Atom {atomLabel} [{atom.Id}] Label Bounds {labelBounds}"); #endregion Step 2 - Reset Cursor such that the text is centered about the atom's co-ordinates #region Step 3 - Place the characters foreach (char chr in atomLabel) { TtfCharacter c = m_TtfCharacterSet[chr]; if (c != null) { thisCharacterPosition = GetCharacterPosition(cursorPosition, c); AtomLabelCharacter alc = new AtomLabelCharacter(thisCharacterPosition, c, atomColour, chr, atom.Id); m_AtomLabelCharacters.Add(alc); // Move to next Character position lastOffset = OoXmlHelper.ScaleCsTtfToCml(c.IncrementX); cursorPosition.Offset(OoXmlHelper.ScaleCsTtfToCml(c.IncrementX), 0); chargeCursorPosition = new Point(cursorPosition.X, cursorPosition.Y); } } #endregion Step 3 - Place the characters #region Determine NESW double baFromNorth = Vector.AngleBetween(BasicGeometry.ScreenNorth(), atom.BalancingVector); CompassPoints nesw = CompassPoints.East; if (bondCount == 1) { nesw = BasicGeometry.SnapTo2EW(baFromNorth); } else { nesw = BasicGeometry.SnapTo4NESW(baFromNorth); } #endregion Determine NESW #region Step 4 - Add Implicit H if required if (options.ShowHydrogens && implicitHCount > 0) { TtfCharacter hydrogenCharacter = m_TtfCharacterSet['H']; string numbers = "012345"; TtfCharacter implicitValueCharacter = m_TtfCharacterSet[numbers[implicitHCount]]; #region Add H if (hydrogenCharacter != null) { switch (nesw) { case CompassPoints.North: if (atom.Bonds.Count > 1) { cursorPosition.X = labelBounds.X + (labelBounds.Width / 2) - (OoXmlHelper.ScaleCsTtfToCml(hydrogenCharacter.Width) / 2); cursorPosition.Y = cursorPosition.Y + OoXmlHelper.ScaleCsTtfToCml(-hydrogenCharacter.Height) - OoXmlHelper.CHARACTER_CLIPPING_MARGIN; if (iCharge > 0) { if (implicitHCount > 1) { cursorPosition.Offset(0, OoXmlHelper.ScaleCsTtfToCml(-implicitValueCharacter.Height * OoXmlHelper.SUBSCRIPT_SCALE_FACTOR / 2) - OoXmlHelper.CHARACTER_CLIPPING_MARGIN); } } } break; case CompassPoints.East: // Leave as is break; case CompassPoints.South: if (atom.Bonds.Count > 1) { cursorPosition.X = labelBounds.X + (labelBounds.Width / 2) - (OoXmlHelper.ScaleCsTtfToCml(hydrogenCharacter.Width) / 2); cursorPosition.Y = cursorPosition.Y + OoXmlHelper.ScaleCsTtfToCml(hydrogenCharacter.Height) + OoXmlHelper.CHARACTER_CLIPPING_MARGIN; } break; case CompassPoints.West: if (implicitHCount == 1) { cursorPosition.Offset(OoXmlHelper.ScaleCsTtfToCml(-(hydrogenCharacter.IncrementX * 2)), 0); } else { cursorPosition.Offset(OoXmlHelper.ScaleCsTtfToCml(-(hydrogenCharacter.IncrementX * 2.5)), 0); } break; } //_telemetry.Write(module, "Debugging", $"Adding H at {cursorPosition}"); thisCharacterPosition = GetCharacterPosition(cursorPosition, hydrogenCharacter); AtomLabelCharacter alc = new AtomLabelCharacter(thisCharacterPosition, hydrogenCharacter, atomColour, 'H', atom.Id); m_AtomLabelCharacters.Add(alc); // Move to next Character position cursorPosition.Offset(OoXmlHelper.ScaleCsTtfToCml(hydrogenCharacter.IncrementX), 0); if (nesw == CompassPoints.East) { chargeCursorPosition = new Point(cursorPosition.X, cursorPosition.Y); } if (nesw == CompassPoints.West) { isotopeCursorPosition = new Point(thisCharacterPosition.X, isotopeCursorPosition.Y); } } #endregion Add H #region Add number if (implicitHCount > 1) { if (implicitValueCharacter != null) { thisCharacterPosition = GetCharacterPosition(cursorPosition, implicitValueCharacter); // Drop the subscript Character thisCharacterPosition.Offset(0, OoXmlHelper.ScaleCsTtfToCml(hydrogenCharacter.Width * OoXmlHelper.SUBSCRIPT_DROP_FACTOR)); AtomLabelCharacter alc = new AtomLabelCharacter(thisCharacterPosition, implicitValueCharacter, atomColour, numbers[implicitHCount], atom.Id); alc.IsSubScript = true; m_AtomLabelCharacters.Add(alc); // Move to next Character position cursorPosition.Offset(OoXmlHelper.ScaleCsTtfToCml(implicitValueCharacter.IncrementX) * OoXmlHelper.SUBSCRIPT_SCALE_FACTOR, 0); } } #endregion Add number } #endregion Step 4 - Add Implicit H if required #region Step 5 - Add Charge if required if (iCharge != 0) { TtfCharacter hydrogenCharacter = m_TtfCharacterSet['H']; char sign = '.'; TtfCharacter chargeSignCharacter = null; if (iCharge >= 1) { sign = '+'; chargeSignCharacter = m_TtfCharacterSet['+']; } else if (iCharge <= 1) { sign = '-'; chargeSignCharacter = m_TtfCharacterSet['-']; } if (iAbsCharge > 1) { string digits = iAbsCharge.ToString(); // Insert digits foreach (char chr in digits) { TtfCharacter chargeValueCharacter = m_TtfCharacterSet[chr]; thisCharacterPosition = GetCharacterPosition(chargeCursorPosition, chargeValueCharacter); // Raise the superscript Character thisCharacterPosition.Offset(0, -OoXmlHelper.ScaleCsTtfToCml(chargeValueCharacter.Height * OoXmlHelper.CS_SUPERSCRIPT_RAISE_FACTOR)); AtomLabelCharacter alcc = new AtomLabelCharacter(thisCharacterPosition, chargeValueCharacter, atomColour, chr, atom.Id); alcc.IsSubScript = true; m_AtomLabelCharacters.Add(alcc); // Move to next Character position chargeCursorPosition.Offset(OoXmlHelper.ScaleCsTtfToCml(chargeValueCharacter.IncrementX) * OoXmlHelper.SUBSCRIPT_SCALE_FACTOR, 0); } } // Insert sign at raised position thisCharacterPosition = GetCharacterPosition(chargeCursorPosition, chargeSignCharacter); thisCharacterPosition.Offset(0, -OoXmlHelper.ScaleCsTtfToCml(hydrogenCharacter.Height * OoXmlHelper.CS_SUPERSCRIPT_RAISE_FACTOR)); thisCharacterPosition.Offset(0, -OoXmlHelper.ScaleCsTtfToCml(chargeSignCharacter.Height / 2 * OoXmlHelper.CS_SUPERSCRIPT_RAISE_FACTOR)); AtomLabelCharacter alcs = new AtomLabelCharacter(thisCharacterPosition, chargeSignCharacter, atomColour, sign, atom.Id); alcs.IsSubScript = true; m_AtomLabelCharacters.Add(alcs); } #endregion Step 5 - Add Charge if required #region Step 6 Add IsoTope Number if required if (isoValue > 0) { string digits = isoValue.ToString(); xMin = double.MaxValue; yMin = double.MaxValue; xMax = double.MinValue; yMax = double.MinValue; Point isoOrigin = isotopeCursorPosition; // Calculate width of digits foreach (char chr in digits) { TtfCharacter c = m_TtfCharacterSet[chr]; thisCharacterPosition = GetCharacterPosition(isotopeCursorPosition, c); // Raise the superscript Character thisCharacterPosition.Offset(0, -OoXmlHelper.ScaleCsTtfToCml(c.Height * OoXmlHelper.CS_SUPERSCRIPT_RAISE_FACTOR)); xMin = Math.Min(xMin, thisCharacterPosition.X); yMin = Math.Min(yMin, thisCharacterPosition.Y); xMax = Math.Max(xMax, thisCharacterPosition.X + OoXmlHelper.ScaleCsTtfToCml(c.Width)); yMax = Math.Max(yMax, thisCharacterPosition.Y + OoXmlHelper.ScaleCsTtfToCml(c.Height)); // Move to next Character position isotopeCursorPosition.Offset(OoXmlHelper.ScaleCsTtfToCml(c.IncrementX) * OoXmlHelper.SUBSCRIPT_SCALE_FACTOR, 0); } // Re-position Isotope Cursor width = xMax - xMin; isotopeCursorPosition = new Point(isoOrigin.X - width, isoOrigin.Y); // Insert digits foreach (char chr in digits) { TtfCharacter c = m_TtfCharacterSet[chr]; thisCharacterPosition = GetCharacterPosition(isotopeCursorPosition, c); // Raise the superscript Character thisCharacterPosition.Offset(0, -OoXmlHelper.ScaleCsTtfToCml(c.Height * OoXmlHelper.CS_SUPERSCRIPT_RAISE_FACTOR)); AtomLabelCharacter alcc = new AtomLabelCharacter(thisCharacterPosition, c, atomColour, chr, atom.Id); alcc.IsSubScript = true; m_AtomLabelCharacters.Add(alcc); // Move to next Character position isotopeCursorPosition.Offset(OoXmlHelper.ScaleCsTtfToCml(c.IncrementX) * OoXmlHelper.SUBSCRIPT_SCALE_FACTOR, 0); } } #endregion Step 6 Add IsoTope Number if required } }
/// <summary> /// Computes the distance from a point to a compass point on the given rectangle. /// </summary> /// <param name="point">a point whose distance from a compass point on the rectangle is to be determined.</param> /// <param name="compassRectangle">the rectangle from which to determine the compass point position.</param> /// <param name="compassPoint">the point on the compass to find the distance to.</param> /// <returns></returns> private float DistanceToCompassPoint(PointF point, RectangleF compassRectangle, CompassPoints compassPoint) { PointF compassPointPosition = GetCompassPointPosition(compassPoint, compassRectangle); return (float)Vector.Distance(point, compassPointPosition); }