private Rect MeasureString(string text, Point startPoint) { Rect boundingBox = Rect.Empty; Point cursor = new Point(startPoint.X, startPoint.Y); TtfCharacter i = _TtfCharacterSet['i']; for (int idx = 0; idx < text.Length; idx++) { TtfCharacter c = _TtfCharacterSet['?']; char chr = text[idx]; if (_TtfCharacterSet.ContainsKey(chr)) { c = _TtfCharacterSet[chr]; } if (c != null) { Point position = GetCharacterPosition(cursor, c); Rect thisRect = new Rect(new Point(position.X, position.Y), new Size(OoXmlHelper.ScaleCsTtfToCml(c.Width, _meanBondLength), OoXmlHelper.ScaleCsTtfToCml(c.Height, _meanBondLength))); boundingBox.Union(thisRect); if (idx < text.Length - 1) { // Move to next Character position cursor.Offset(OoXmlHelper.ScaleCsTtfToCml(c.Width + i.Width, _meanBondLength), 0); } } } return(boundingBox); }
public void PlaceString(string text, Point startPoint, string path) { Point cursor = new Point(startPoint.X, startPoint.Y); TtfCharacter i = _TtfCharacterSet['i']; for (int idx = 0; idx < text.Length; idx++) { TtfCharacter c = _TtfCharacterSet['?']; char chr = text[idx]; if (_TtfCharacterSet.ContainsKey(chr)) { c = _TtfCharacterSet[chr]; } if (c != null) { Point position = GetCharacterPosition(cursor, c); AtomLabelCharacter alc = new AtomLabelCharacter(position, c, "000000", chr, path, path); _AtomLabelCharacters.Add(alc); if (idx < text.Length - 1) { // Move to next Character position cursor.Offset(OoXmlHelper.ScaleCsTtfToCml(c.Width + i.Width, _meanBondLength), 0); } } } }
public void AddCharacter(char character, string colour, bool isSubScript = false, bool isSuperScript = false) { Text += character; // Create new AtomLabelCharacter and add to Characters var ttfCharacter = _characterSet[character]; if (ttfCharacter != null) { var isSmaller = isSubScript || isSuperScript; // Get character position as if it's standard size var thisCharacterPosition = GetCharacterPosition(_cursor, ttfCharacter); if (isSmaller) { // Assume that it's SubScript so move it down by drop factor thisCharacterPosition.Offset(0, OoXmlHelper.ScaleCsTtfToCml(_hydrogenCharacter.Height * OoXmlHelper.SUBSCRIPT_DROP_FACTOR, _bondLength)); // If it is SuperScript move it back up by height of 'H' if (isSuperScript) { thisCharacterPosition.Offset(0, -OoXmlHelper.ScaleCsTtfToCml(_hydrogenCharacter.Height, _bondLength)); } } var alc = new AtomLabelCharacter(thisCharacterPosition, ttfCharacter, colour, _atomPath, _parentPath); alc.IsSubScript = isSubScript; alc.IsSuperScript = isSuperScript; alc.IsSmaller = isSmaller; Characters.Add(alc); Size size = new Size(OoXmlHelper.ScaleCsTtfToCml(ttfCharacter.Width, _bondLength), OoXmlHelper.ScaleCsTtfToCml(ttfCharacter.Height, _bondLength)); if (isSmaller) { size.Width *= OoXmlHelper.SUBSCRIPT_SCALE_FACTOR; size.Height *= OoXmlHelper.SUBSCRIPT_SCALE_FACTOR; } Rect thisBoundingBox = new Rect(thisCharacterPosition, size); _boundingBox.Union(thisBoundingBox); // Move to next Character position // We ought to be able to use ttfCharacter.IncrementX, but this does not work with strings such as "Bowl" if (isSmaller) { _cursor.Offset(OoXmlHelper.ScaleCsTtfToCml(ttfCharacter.IncrementX, _bondLength) * OoXmlHelper.SUBSCRIPT_SCALE_FACTOR, 0); } else { _cursor.Offset(OoXmlHelper.ScaleCsTtfToCml(ttfCharacter.IncrementX, _bondLength), 0); } } }
private List <Point> ConvexHull(string atomPath) { List <Point> points = new List <Point>(); var chars = _AtomLabelCharacters.Where(m => m.ParentAtom == atomPath); double margin = OoXmlHelper.CHARACTER_CLIPPING_MARGIN; foreach (var c in chars) { // Top Left -- points.Add(new Point(c.Position.X - margin, c.Position.Y - margin)); if (c.IsSmaller) { // Top Right +- points.Add(new Point(c.Position.X + OoXmlHelper.ScaleCsTtfToCml(c.Character.Width, _meanBondLength) * OoXmlHelper.SUBSCRIPT_SCALE_FACTOR + margin, c.Position.Y - margin)); // Bottom Right ++ points.Add(new Point(c.Position.X + OoXmlHelper.ScaleCsTtfToCml(c.Character.Width, _meanBondLength) * OoXmlHelper.SUBSCRIPT_SCALE_FACTOR + margin, c.Position.Y + OoXmlHelper.ScaleCsTtfToCml(c.Character.Height, _meanBondLength) * OoXmlHelper.SUBSCRIPT_SCALE_FACTOR + margin)); // Bottom Left -+ points.Add(new Point(c.Position.X - margin, c.Position.Y + OoXmlHelper.ScaleCsTtfToCml(c.Character.Height, _meanBondLength) * OoXmlHelper.SUBSCRIPT_SCALE_FACTOR + margin)); } else { // Top Right +- points.Add(new Point(c.Position.X + OoXmlHelper.ScaleCsTtfToCml(c.Character.Width, _meanBondLength) + margin, c.Position.Y - margin)); // Bottom Right ++ points.Add(new Point(c.Position.X + OoXmlHelper.ScaleCsTtfToCml(c.Character.Width, _meanBondLength) + margin, c.Position.Y + OoXmlHelper.ScaleCsTtfToCml(c.Character.Height, _meanBondLength) + margin)); // Bottom Left -+ points.Add(new Point(c.Position.X - margin, c.Position.Y + OoXmlHelper.ScaleCsTtfToCml(c.Character.Height, _meanBondLength) + margin)); } } return(GeometryTool.MakeConvexHull(points)); }
private void DrawWedgeBond(Wpg.WordprocessingGroup wordprocessingGroup, List <Point> points) { UInt32Value id = UInt32Value.FromUInt32((uint)m_ooxmlId++); string atomLabelName = "WedgeBond" + id; Rect cmlExtents = new Rect(points[0], points[points.Count - 1]); for (int i = 0; i < points.Count - 1; i++) { cmlExtents.Union(new Rect(points[i], points[i + 1])); } // Move Extents to have 0,0 Top Left Reference cmlExtents.Offset(-m_canvasExtents.Left, -m_canvasExtents.Top); Int64Value top = OoXmlHelper.ScaleCmlToEmu(cmlExtents.Y); Int64Value left = OoXmlHelper.ScaleCmlToEmu(cmlExtents.X); Int64Value width = OoXmlHelper.ScaleCmlToEmu(cmlExtents.Width); Int64Value height = OoXmlHelper.ScaleCmlToEmu(cmlExtents.Height); Wps.WordprocessingShape shape = new Wps.WordprocessingShape(); Wps.NonVisualDrawingProperties nonVisualDrawingProperties = new Wps.NonVisualDrawingProperties() { Id = id, Name = atomLabelName }; Wps.NonVisualDrawingShapeProperties nonVisualDrawingShapeProperties = new Wps.NonVisualDrawingShapeProperties(); Wps.ShapeProperties shapeProperties = new Wps.ShapeProperties(); A.Transform2D transform2D = new A.Transform2D(); A.Offset offset = new A.Offset { X = left, Y = top }; A.Extents extents = new A.Extents { Cx = width, Cy = height }; transform2D.Append(offset); transform2D.Append(extents); A.CustomGeometry customGeometry = new A.CustomGeometry(); A.AdjustValueList adjustValueList = new A.AdjustValueList(); A.Rectangle rectangle = new A.Rectangle { Left = "l", Top = "t", Right = "r", Bottom = "b" }; A.PathList pathList = new A.PathList(); A.Path path = new A.Path { Width = width, Height = height }; A.MoveTo moveTo = new A.MoveTo(); moveTo.Append(MakePoint(points[0])); path.Append(moveTo); for (int i = 1; i < points.Count; i++) { A.LineTo lineTo = new A.LineTo(); lineTo.Append(MakePoint(points[i])); path.Append(lineTo); } A.CloseShapePath closeShapePath = new A.CloseShapePath(); path.Append(closeShapePath); pathList.Append(path); customGeometry.Append(adjustValueList); customGeometry.Append(rectangle); customGeometry.Append(pathList); // Set shape fill colour A.SolidFill solidFill1 = new A.SolidFill(); A.RgbColorModelHex rgbColorModelHex = new A.RgbColorModelHex { Val = "000000" }; solidFill1.Append(rgbColorModelHex); // Set shape outline colour A.Outline outline = new A.Outline { Width = OoXmlHelper.ACS_LINE_WIDTH_EMUS, CapType = A.LineCapValues.Round }; A.RgbColorModelHex rgbColorModelHex2 = new A.RgbColorModelHex { Val = "000000" }; A.SolidFill solidFill2 = new A.SolidFill(); solidFill2.Append(rgbColorModelHex2); outline.Append(solidFill2); shapeProperties.Append(transform2D); shapeProperties.Append(customGeometry); shapeProperties.Append(solidFill1); shapeProperties.Append(outline); OoXmlHelper.AppendShapeStyle(shape, nonVisualDrawingProperties, nonVisualDrawingShapeProperties, shapeProperties); wordprocessingGroup.Append(shape); // Local Function A.Point MakePoint(Point pp) { pp.Offset(-m_canvasExtents.Left, -m_canvasExtents.Top); pp.Offset(-cmlExtents.Left, -cmlExtents.Top); return(new A.Point { X = $"{OoXmlHelper.ScaleCmlToEmu(pp.X)}", Y = $"{OoXmlHelper.ScaleCmlToEmu(pp.Y)}" }); } }
private void DrawWavyLine(Wpg.WordprocessingGroup wordprocessingGroup, Rect cmlExtents, Point bondStart, Point bondEnd) { UInt32Value id = UInt32Value.FromUInt32((uint)m_ooxmlId++); string bondLineName = "WavyLine" + id; Vector bondVector = bondEnd - bondStart; int noOfWiggles = (int)Math.Ceiling(bondVector.Length / BondOffset()); if (noOfWiggles < 1) { noOfWiggles = 1; } double wiggleLength = bondVector.Length / noOfWiggles; Vector originalWigglePortion = bondVector; originalWigglePortion.Normalize(); originalWigglePortion *= wiggleLength / 2; Matrix toLeft = new Matrix(); toLeft.Rotate(-60); Matrix toRight = new Matrix(); toRight.Rotate(60); Vector leftVector = originalWigglePortion * toLeft; Vector rightVector = originalWigglePortion * toRight; List <Point> allpoints = new List <Point>(); List <List <Point> > allTriangles = new List <List <Point> >(); List <Point> triangle = new List <Point>(); Point lastPoint = bondStart; allpoints.Add(lastPoint); triangle.Add(lastPoint); for (int i = 0; i < noOfWiggles; i++) { Point leftPoint = lastPoint + leftVector; allpoints.Add(leftPoint); triangle.Add(leftPoint); Point midPoint = lastPoint + originalWigglePortion; allpoints.Add(midPoint); triangle.Add(midPoint); allTriangles.Add(triangle); triangle = new List <Point>(); triangle.Add(midPoint); Point rightPoint = lastPoint + originalWigglePortion + rightVector; allpoints.Add(rightPoint); triangle.Add(rightPoint); lastPoint += originalWigglePortion * 2; allpoints.Add(lastPoint); triangle.Add(lastPoint); allTriangles.Add(triangle); triangle = new List <Point>(); triangle.Add(lastPoint); } double minX = double.MaxValue; double maxX = double.MinValue; double minY = double.MaxValue; double maxY = double.MinValue; foreach (Point p in allpoints) { maxX = Math.Max(p.X + cmlExtents.Left, maxX); minX = Math.Min(p.X + cmlExtents.Left, minX); maxY = Math.Max(p.Y + cmlExtents.Top, maxY); minY = Math.Min(p.Y + cmlExtents.Top, minY); } Rect newExtents = new Rect(minX, minY, maxX - minX, maxY - minY); double xOffset = cmlExtents.Left - newExtents.Left; double yOffset = cmlExtents.Top - newExtents.Top; Int64Value width = OoXmlHelper.ScaleCmlToEmu(newExtents.Width); Int64Value height = OoXmlHelper.ScaleCmlToEmu(newExtents.Height); Int64Value top = OoXmlHelper.ScaleCmlToEmu(newExtents.Top); Int64Value left = OoXmlHelper.ScaleCmlToEmu(newExtents.Left); Wps.WordprocessingShape shape = new Wps.WordprocessingShape(); Wps.NonVisualDrawingProperties nonVisualDrawingProperties = new Wps.NonVisualDrawingProperties() { Id = id, Name = bondLineName }; Wps.NonVisualDrawingShapeProperties nonVisualDrawingShapeProperties = new Wps.NonVisualDrawingShapeProperties(); Wps.ShapeProperties shapeProperties = new Wps.ShapeProperties(); A.Transform2D transform2D = new A.Transform2D(); A.Offset offset = new A.Offset { X = left, Y = top }; A.Extents extents = new A.Extents { Cx = width, Cy = height }; transform2D.Append(offset); transform2D.Append(extents); A.CustomGeometry customGeometry = new A.CustomGeometry(); A.AdjustValueList adjustValueList = new A.AdjustValueList(); A.Rectangle rectangle = new A.Rectangle { Left = "l", Top = "t", Right = "r", Bottom = "b" }; A.PathList pathList = new A.PathList(); A.Path path = new A.Path { Width = width, Height = height }; A.MoveTo moveTo = new A.MoveTo(); A.Point point1 = new A.Point { X = OoXmlHelper.ScaleCmlToEmu(bondStart.X + xOffset).ToString(), Y = OoXmlHelper.ScaleCmlToEmu(bondStart.Y + yOffset).ToString() }; moveTo.Append(point1); path.Append(moveTo); // Render as Curves foreach (var tri in allTriangles) { A.CubicBezierCurveTo cubicBezierCurveTo = new A.CubicBezierCurveTo(); foreach (var p in tri) { A.Point point = new A.Point { X = OoXmlHelper.ScaleCmlToEmu(p.X + xOffset).ToString(), Y = OoXmlHelper.ScaleCmlToEmu(p.Y + yOffset).ToString() }; cubicBezierCurveTo.Append(point); } path.Append(cubicBezierCurveTo); } // Render as Straight Lines //foreach (var p in allpoints) //{ // A.LineTo lineTo = new A.LineTo(); // A.Point point = new A.Point { X = OoXmlHelper.ScaleCmlToEmu(p.X + xOffset).ToString(), Y = OoXmlHelper.ScaleCmlToEmu(p.Y + yOffset).ToString() }; // lineTo.Append(point); // path1.Append(lineTo); //} pathList.Append(path); customGeometry.Append(adjustValueList); customGeometry.Append(rectangle); customGeometry.Append(pathList); A.Outline outline = new A.Outline { Width = OoXmlHelper.ACS_LINE_WIDTH_EMUS, CapType = A.LineCapValues.Round }; A.SolidFill solidFill = new A.SolidFill(); A.RgbColorModelHex rgbColorModelHex = new A.RgbColorModelHex { Val = "000000" }; solidFill.Append(rgbColorModelHex); outline.Append(solidFill); shapeProperties.Append(transform2D); shapeProperties.Append(customGeometry); shapeProperties.Append(outline); OoXmlHelper.AppendShapeStyle(shape, nonVisualDrawingProperties, nonVisualDrawingShapeProperties, shapeProperties); wordprocessingGroup.Append(shape); }
private void DrawWavyLine(Wpg.WordprocessingGroup wordprocessingGroup1, Rect extents, Point bondStart, Point bondEnd) { UInt32Value bondLineId = UInt32Value.FromUInt32((uint)m_ooxmlId++); string bondLineName = "WavyLine" + bondLineId; Vector bondVector = bondEnd - bondStart; int noOfWiggles = (int)Math.Ceiling(bondVector.Length / BondOffset()); if (noOfWiggles < 1) { noOfWiggles = 1; } double wiggleLength = bondVector.Length / noOfWiggles; Debug.WriteLine($"v.Length: {bondVector.Length} noOfWiggles: {noOfWiggles}"); Vector originalWigglePortion = bondVector; originalWigglePortion.Normalize(); originalWigglePortion *= wiggleLength / 2; Matrix toLeft = new Matrix(); toLeft.Rotate(-60); Matrix toRight = new Matrix(); toRight.Rotate(60); Vector leftVector = originalWigglePortion * toLeft; Vector rightVector = originalWigglePortion * toRight; List <Point> allpoints = new List <Point>(); List <List <Point> > allTriangles = new List <List <Point> >(); List <Point> triangle = new List <Point>(); Point lastPoint = bondStart; allpoints.Add(lastPoint); triangle.Add(lastPoint); for (int i = 0; i < noOfWiggles; i++) { Point leftPoint = lastPoint + leftVector; allpoints.Add(leftPoint); triangle.Add(leftPoint); Point midPoint = lastPoint + originalWigglePortion; allpoints.Add(midPoint); triangle.Add(midPoint); allTriangles.Add(triangle); triangle = new List <Point>(); triangle.Add(midPoint); Point rightPoint = lastPoint + originalWigglePortion + rightVector; allpoints.Add(rightPoint); triangle.Add(rightPoint); lastPoint += originalWigglePortion * 2; allpoints.Add(lastPoint); triangle.Add(lastPoint); allTriangles.Add(triangle); triangle = new List <Point>(); triangle.Add(lastPoint); } double minX = double.MaxValue; double maxX = double.MinValue; double minY = double.MaxValue; double maxY = double.MinValue; foreach (Point p in allpoints) { maxX = Math.Max(p.X + extents.Left, maxX); minX = Math.Min(p.X + extents.Left, minX); maxY = Math.Max(p.Y + extents.Top, maxY); minY = Math.Min(p.Y + extents.Top, minY); } Rect newExtents = new Rect(minX, minY, maxX - minX, maxY - minY); double xOffset = extents.Left - newExtents.Left; double yOffset = extents.Top - newExtents.Top; Int64Value width = OoXmlHelper.ScaleCmlToEmu(newExtents.Width); Int64Value height = OoXmlHelper.ScaleCmlToEmu(newExtents.Height); Int64Value top = OoXmlHelper.ScaleCmlToEmu(newExtents.Top); Int64Value left = OoXmlHelper.ScaleCmlToEmu(newExtents.Left); Wps.WordprocessingShape wordprocessingShape1 = new Wps.WordprocessingShape(); Wps.NonVisualDrawingProperties nonVisualDrawingProperties1 = new Wps.NonVisualDrawingProperties() { Id = bondLineId, Name = bondLineName }; Wps.NonVisualDrawingShapeProperties nonVisualDrawingShapeProperties1 = new Wps.NonVisualDrawingShapeProperties(); Wps.ShapeProperties shapeProperties1 = new Wps.ShapeProperties(); A.Transform2D transform2D1 = new A.Transform2D(); A.Offset offset2 = new A.Offset() { X = left, Y = top }; A.Extents extents2 = new A.Extents() { Cx = width, Cy = height }; transform2D1.Append(offset2); transform2D1.Append(extents2); A.CustomGeometry customGeometry1 = new A.CustomGeometry(); A.AdjustValueList adjustValueList1 = new A.AdjustValueList(); A.Rectangle rectangle1 = new A.Rectangle() { Left = "l", Top = "t", Right = "r", Bottom = "b" }; A.PathList pathList1 = new A.PathList(); A.Path path1 = new A.Path() { Width = width, Height = height }; A.MoveTo moveTo1 = new A.MoveTo(); A.Point point1 = new A.Point() { X = OoXmlHelper.ScaleCmlToEmu(bondStart.X + xOffset).ToString(), Y = OoXmlHelper.ScaleCmlToEmu(bondStart.Y + yOffset).ToString() }; moveTo1.Append(point1); path1.Append(moveTo1); //Curves foreach (var tri in allTriangles) { A.CubicBezierCurveTo cubicBezierCurveTo = new A.CubicBezierCurveTo(); foreach (var p in tri) { A.Point point = new A.Point() { X = OoXmlHelper.ScaleCmlToEmu(p.X + xOffset).ToString(), Y = OoXmlHelper.ScaleCmlToEmu(p.Y + yOffset).ToString() }; cubicBezierCurveTo.Append(point); } path1.Append(cubicBezierCurveTo); } //// Straight Lines //foreach (var p in allpoints) //{ // A.LineTo lineTo = new A.LineTo(); // A.Point point = new A.Point() { X = OoXmlHelper.ScaleCmlToEmu(p.X + xOffset).ToString(), Y = OoXmlHelper.ScaleCmlToEmu(p.Y + yOffset).ToString() }; // lineTo.Append(point); // path1.Append(lineTo); //} pathList1.Append(path1); customGeometry1.Append(adjustValueList1); customGeometry1.Append(rectangle1); customGeometry1.Append(pathList1); A.Outline outline1 = new A.Outline() { Width = 9525, CapType = A.LineCapValues.Round }; A.SolidFill solidFill1 = new A.SolidFill(); A.RgbColorModelHex rgbColorModelHex1 = new A.RgbColorModelHex() { Val = "000000" }; A.Alpha alpha1 = new A.Alpha() { Val = new Int32Value() { InnerText = "100%" } }; rgbColorModelHex1.Append(alpha1); solidFill1.Append(rgbColorModelHex1); outline1.Append(solidFill1); shapeProperties1.Append(transform2D1); shapeProperties1.Append(customGeometry1); shapeProperties1.Append(outline1); Wps.ShapeStyle shapeStyle1 = new Wps.ShapeStyle(); A.LineReference lineReference1 = new A.LineReference() { Index = (UInt32Value)0U }; A.FillReference fillReference1 = new A.FillReference() { Index = (UInt32Value)0U }; A.EffectReference effectReference1 = new A.EffectReference() { Index = (UInt32Value)0U }; A.FontReference fontReference1 = new A.FontReference() { Index = A.FontCollectionIndexValues.Minor }; shapeStyle1.Append(lineReference1); shapeStyle1.Append(fillReference1); shapeStyle1.Append(effectReference1); shapeStyle1.Append(fontReference1); Wps.TextBodyProperties textBodyProperties1 = new Wps.TextBodyProperties(); wordprocessingShape1.Append(nonVisualDrawingProperties1); wordprocessingShape1.Append(nonVisualDrawingShapeProperties1); wordprocessingShape1.Append(shapeProperties1); wordprocessingShape1.Append(shapeStyle1); wordprocessingShape1.Append(textBodyProperties1); wordprocessingGroup1.Append(wordprocessingShape1); }
private void DrawDashedLine(Wpg.WordprocessingGroup wordprocessingGroup1, Rect extents, Point bondStart, Point bondEnd) { UInt32Value bondLineId = UInt32Value.FromUInt32((uint)m_ooxmlId++); string bondLineName = "DashedBondLine" + bondLineId; Int64Value width = OoXmlHelper.ScaleCmlToEmu(extents.Width); Int64Value height = OoXmlHelper.ScaleCmlToEmu(extents.Height); Int64Value top = OoXmlHelper.ScaleCmlToEmu(extents.Top); Int64Value left = OoXmlHelper.ScaleCmlToEmu(extents.Left); Wps.WordprocessingShape wordprocessingShape1 = new Wps.WordprocessingShape(); Wps.NonVisualDrawingProperties nonVisualDrawingProperties1 = new Wps.NonVisualDrawingProperties() { Id = bondLineId, Name = bondLineName }; Wps.NonVisualDrawingShapeProperties nonVisualDrawingShapeProperties1 = new Wps.NonVisualDrawingShapeProperties(); Wps.ShapeProperties shapeProperties1 = new Wps.ShapeProperties(); A.Transform2D transform2D1 = new A.Transform2D(); A.Offset offset2 = new A.Offset() { X = left, Y = top }; A.Extents extents2 = new A.Extents() { Cx = width, Cy = height }; transform2D1.Append(offset2); transform2D1.Append(extents2); A.CustomGeometry customGeometry1 = new A.CustomGeometry(); A.AdjustValueList adjustValueList1 = new A.AdjustValueList(); A.Rectangle rectangle1 = new A.Rectangle() { Left = "l", Top = "t", Right = "r", Bottom = "b" }; A.PathList pathList1 = new A.PathList(); A.Path path1 = new A.Path() { Width = width, Height = height }; A.MoveTo moveTo1 = new A.MoveTo(); A.Point point1 = new A.Point() { X = OoXmlHelper.ScaleCmlToEmu(bondStart.X).ToString(), Y = OoXmlHelper.ScaleCmlToEmu(bondStart.Y).ToString() }; moveTo1.Append(point1); A.LineTo lineTo1 = new A.LineTo(); A.Point point2 = new A.Point() { X = OoXmlHelper.ScaleCmlToEmu(bondEnd.X).ToString(), Y = OoXmlHelper.ScaleCmlToEmu(bondEnd.Y).ToString() }; lineTo1.Append(point2); path1.Append(moveTo1); path1.Append(lineTo1); pathList1.Append(path1); customGeometry1.Append(adjustValueList1); customGeometry1.Append(rectangle1); customGeometry1.Append(pathList1); A.Outline outline1 = new A.Outline() { Width = 9525, CapType = A.LineCapValues.Round }; A.SolidFill solidFill1 = new A.SolidFill(); A.PresetDash presetDash1 = new A.PresetDash() { Val = A.PresetLineDashValues.LargeDash }; A.RgbColorModelHex rgbColorModelHex1 = new A.RgbColorModelHex() { Val = "000000" }; A.Alpha alpha1 = new A.Alpha() { Val = new Int32Value() { InnerText = "100%" } }; rgbColorModelHex1.Append(alpha1); solidFill1.Append(rgbColorModelHex1); outline1.Append(solidFill1); outline1.Append(presetDash1); shapeProperties1.Append(transform2D1); shapeProperties1.Append(customGeometry1); shapeProperties1.Append(outline1); Wps.ShapeStyle shapeStyle1 = new Wps.ShapeStyle(); A.LineReference lineReference1 = new A.LineReference() { Index = (UInt32Value)0U }; A.FillReference fillReference1 = new A.FillReference() { Index = (UInt32Value)0U }; A.EffectReference effectReference1 = new A.EffectReference() { Index = (UInt32Value)0U }; A.FontReference fontReference1 = new A.FontReference() { Index = A.FontCollectionIndexValues.Minor }; shapeStyle1.Append(lineReference1); shapeStyle1.Append(fillReference1); shapeStyle1.Append(effectReference1); shapeStyle1.Append(fontReference1); Wps.TextBodyProperties textBodyProperties1 = new Wps.TextBodyProperties(); wordprocessingShape1.Append(nonVisualDrawingProperties1); wordprocessingShape1.Append(nonVisualDrawingShapeProperties1); wordprocessingShape1.Append(shapeProperties1); wordprocessingShape1.Append(shapeStyle1); wordprocessingShape1.Append(textBodyProperties1); wordprocessingGroup1.Append(wordprocessingShape1); }
private void DrawFilledTriangle(Wpg.WordprocessingGroup wordprocessingGroup1, List <Point> points) { UInt32Value atomLabelId = UInt32Value.FromUInt32((uint)m_ooxmlId++); string atomLabelName = "WedgeBond" + atomLabelId; double minX = double.MaxValue; double maxX = double.MinValue; double minY = double.MaxValue; double maxY = double.MinValue; foreach (Point p in points) { maxX = Math.Max(p.X, maxX); minX = Math.Min(p.X, minX); maxY = Math.Max(p.Y, maxY); minY = Math.Min(p.Y, minY); } Rect extents = new Rect(minX, minY, maxX - minX, maxY - minY); // Create modifyable Points Point p0 = new Point(points[0].X, points[0].Y); Point p1 = new Point(points[1].X, points[1].Y); Point p2 = new Point(points[2].X, points[2].Y); // Move Points to have 0,0 Top Left Reference within the drawing canvas p0.Offset(-m_canvasExtents.Left, -m_canvasExtents.Top); p1.Offset(-m_canvasExtents.Left, -m_canvasExtents.Top); p2.Offset(-m_canvasExtents.Left, -m_canvasExtents.Top); // Move shape's extents to correct place in drawing canvas extents.Offset(-m_canvasExtents.Left, -m_canvasExtents.Top); // Move points again to put them inside the shape's extents p0.Offset(-extents.Left, -extents.Top); p1.Offset(-extents.Left, -extents.Top); p2.Offset(-extents.Left, -extents.Top); Int64Value top = OoXmlHelper.ScaleCmlToEmu(extents.Y); Int64Value left = OoXmlHelper.ScaleCmlToEmu(extents.X); Int64Value width = OoXmlHelper.ScaleCmlToEmu(extents.Width); Int64Value height = OoXmlHelper.ScaleCmlToEmu(extents.Height); Wps.WordprocessingShape wordprocessingShape10 = new Wps.WordprocessingShape(); Wps.NonVisualDrawingProperties nonVisualDrawingProperties10 = new Wps.NonVisualDrawingProperties() { Id = atomLabelId, Name = atomLabelName }; Wps.NonVisualDrawingShapeProperties nonVisualDrawingShapeProperties10 = new Wps.NonVisualDrawingShapeProperties(); Wps.ShapeProperties shapeProperties10 = new Wps.ShapeProperties(); A.Transform2D transform2D10 = new A.Transform2D(); A.Offset offset11 = new A.Offset() { X = left, Y = top }; A.Extents extents11 = new A.Extents() { Cx = width, Cy = height }; transform2D10.Append(offset11); transform2D10.Append(extents11); A.CustomGeometry customGeometry10 = new A.CustomGeometry(); A.AdjustValueList adjustValueList10 = new A.AdjustValueList(); A.Rectangle rectangle10 = new A.Rectangle() { Left = "l", Top = "t", Right = "r", Bottom = "b" }; A.PathList pathList10 = new A.PathList(); A.Path path10 = new A.Path() { Width = width, Height = height }; string xCoOrdinate = OoXmlHelper.ScaleCmlToEmu(p0.X).ToString(); string yCoOrdinate = OoXmlHelper.ScaleCmlToEmu(p0.Y).ToString(); A.MoveTo moveTo10 = new A.MoveTo(); A.Point point19 = new A.Point() { X = xCoOrdinate, Y = yCoOrdinate }; moveTo10.Append(point19); path10.Append(moveTo10); xCoOrdinate = OoXmlHelper.ScaleCmlToEmu(p1.X).ToString(); yCoOrdinate = OoXmlHelper.ScaleCmlToEmu(p1.Y).ToString(); A.LineTo lineTo10 = new A.LineTo(); A.Point point20 = new A.Point() { X = xCoOrdinate, Y = yCoOrdinate }; lineTo10.Append(point20); path10.Append(lineTo10); xCoOrdinate = OoXmlHelper.ScaleCmlToEmu(p2.X).ToString(); yCoOrdinate = OoXmlHelper.ScaleCmlToEmu(p2.Y).ToString(); A.LineTo lineTo19 = new A.LineTo(); A.Point point29 = new A.Point() { X = xCoOrdinate, Y = yCoOrdinate }; lineTo19.Append(point29); path10.Append(lineTo19); A.CloseShapePath closeShapePath1 = new A.CloseShapePath(); path10.Append(closeShapePath1); pathList10.Append(path10); customGeometry10.Append(adjustValueList10); customGeometry10.Append(rectangle10); customGeometry10.Append(pathList10); A.SolidFill solidFill10 = new A.SolidFill(); A.RgbColorModelHex rgbColorModelHex10 = new A.RgbColorModelHex() { Val = "000000" }; A.Alpha alpha10 = new A.Alpha() { Val = new Int32Value() { InnerText = "100%" } }; rgbColorModelHex10.Append(alpha10); solidFill10.Append(rgbColorModelHex10); shapeProperties10.Append(transform2D10); shapeProperties10.Append(customGeometry10); shapeProperties10.Append(solidFill10); Wps.ShapeStyle shapeStyle10 = new Wps.ShapeStyle(); A.LineReference lineReference10 = new A.LineReference() { Index = (UInt32Value)0U }; A.FillReference fillReference10 = new A.FillReference() { Index = (UInt32Value)0U }; A.EffectReference effectReference10 = new A.EffectReference() { Index = (UInt32Value)0U }; A.FontReference fontReference10 = new A.FontReference() { Index = A.FontCollectionIndexValues.Minor }; shapeStyle10.Append(lineReference10); shapeStyle10.Append(fillReference10); shapeStyle10.Append(effectReference10); shapeStyle10.Append(fontReference10); Wps.TextBodyProperties textBodyProperties10 = new Wps.TextBodyProperties(); wordprocessingShape10.Append(nonVisualDrawingProperties10); wordprocessingShape10.Append(nonVisualDrawingShapeProperties10); wordprocessingShape10.Append(shapeProperties10); wordprocessingShape10.Append(shapeStyle10); wordprocessingShape10.Append(textBodyProperties10); wordprocessingGroup1.Append(wordprocessingShape10); }
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 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 } }
public void DrawCharacter(Wpg.WordprocessingGroup wordprocessingGroup, AtomLabelCharacter alc) { Point characterPosition = new Point(alc.Position.X, alc.Position.Y); characterPosition.Offset(-_canvasExtents.Left, -_canvasExtents.Top); UInt32Value id = UInt32Value.FromUInt32((uint)_ooxmlId++); string atomLabelName = "Atom " + alc.ParentAtom; Int64Value width = OoXmlHelper.ScaleCsTtfToEmu(alc.Character.Width, _meanBondLength); Int64Value height = OoXmlHelper.ScaleCsTtfToEmu(alc.Character.Height, _meanBondLength); if (alc.IsSmaller) { width = OoXmlHelper.ScaleCsTtfSubScriptToEmu(alc.Character.Width, _meanBondLength); height = OoXmlHelper.ScaleCsTtfSubScriptToEmu(alc.Character.Height, _meanBondLength); } Int64Value top = OoXmlHelper.ScaleCmlToEmu(characterPosition.Y); Int64Value left = OoXmlHelper.ScaleCmlToEmu(characterPosition.X); // Set variable true to show bounding box of (every) character if (_options.ShowCharacterBoundingBoxes) { Rect boundingBox = new Rect(new Point(left, top), new Size(width, height)); DrawCharacterBox(wordprocessingGroup, boundingBox, "00ff00", 0.25); } Wps.WordprocessingShape shape = new Wps.WordprocessingShape(); Wps.NonVisualDrawingProperties nonVisualDrawingProperties = new Wps.NonVisualDrawingProperties() { Id = id, Name = atomLabelName }; Wps.NonVisualDrawingShapeProperties nonVisualDrawingShapeProperties = new Wps.NonVisualDrawingShapeProperties(); Wps.ShapeProperties shapeProperties = new Wps.ShapeProperties(); A.Transform2D transform2D = new A.Transform2D(); A.Offset offset = new A.Offset { X = left, Y = top }; A.Extents extents = new A.Extents { Cx = width, Cy = height }; transform2D.Append(offset); transform2D.Append(extents); A.CustomGeometry geometry = new A.CustomGeometry(); A.AdjustValueList adjustValueList = new A.AdjustValueList(); A.Rectangle rectangle = new A.Rectangle { Left = "l", Top = "t", Right = "r", Bottom = "b" }; A.PathList pathList = new A.PathList(); A.Path path = new A.Path { Width = width, Height = height }; foreach (TtfContour contour in alc.Character.Contours) { int i = 0; while (i < contour.Points.Count) { TtfPoint thisPoint = contour.Points[i]; TtfPoint nextPoint = null; if (i < contour.Points.Count - 1) { nextPoint = contour.Points[i + 1]; } switch (thisPoint.Type) { case TtfPoint.PointType.Start: A.MoveTo moveTo = new A.MoveTo(); if (alc.IsSmaller) { A.Point point = MakeSubscriptPoint(thisPoint); moveTo.Append(point); path.Append(moveTo); } else { A.Point point = MakeNormalPoint(thisPoint); moveTo.Append(point); path.Append(moveTo); } i++; break; case TtfPoint.PointType.Line: A.LineTo lineTo = new A.LineTo(); if (alc.IsSmaller) { A.Point point = MakeSubscriptPoint(thisPoint); lineTo.Append(point); path.Append(lineTo); } else { A.Point point = MakeNormalPoint(thisPoint); lineTo.Append(point); path.Append(lineTo); } i++; break; case TtfPoint.PointType.CurveOff: A.QuadraticBezierCurveTo quadraticBezierCurveTo = new A.QuadraticBezierCurveTo(); if (alc.IsSmaller) { A.Point pointA = MakeSubscriptPoint(thisPoint); A.Point pointB = MakeSubscriptPoint(nextPoint); quadraticBezierCurveTo.Append(pointA); quadraticBezierCurveTo.Append(pointB); path.Append(quadraticBezierCurveTo); } else { A.Point pointA = MakeNormalPoint(thisPoint); A.Point pointB = MakeNormalPoint(nextPoint); quadraticBezierCurveTo.Append(pointA); quadraticBezierCurveTo.Append(pointB); path.Append(quadraticBezierCurveTo); } i++; i++; break; case TtfPoint.PointType.CurveOn: // Should never get here ! i++; break; } } A.CloseShapePath closeShapePath = new A.CloseShapePath(); path.Append(closeShapePath); } pathList.Append(path); geometry.Append(adjustValueList); geometry.Append(rectangle); geometry.Append(pathList); A.SolidFill solidFill = new A.SolidFill(); // Set Colour A.RgbColorModelHex rgbColorModelHex = new A.RgbColorModelHex { Val = alc.Colour }; solidFill.Append(rgbColorModelHex); shapeProperties.Append(transform2D); shapeProperties.Append(geometry); shapeProperties.Append(solidFill); OoXmlHelper.AppendShapeStyle(shape, nonVisualDrawingProperties, nonVisualDrawingShapeProperties, shapeProperties); wordprocessingGroup.Append(shape); // Local Functions A.Point MakeSubscriptPoint(TtfPoint ttfPoint) { A.Point pp = new A.Point { X = $"{OoXmlHelper.ScaleCsTtfSubScriptToEmu(ttfPoint.X - alc.Character.OriginX, _meanBondLength)}", Y = $"{OoXmlHelper.ScaleCsTtfSubScriptToEmu(alc.Character.Height + ttfPoint.Y - (alc.Character.Height + alc.Character.OriginY), _meanBondLength)}" }; return(pp); } A.Point MakeNormalPoint(TtfPoint ttfPoint) { A.Point pp = new A.Point { X = $"{OoXmlHelper.ScaleCsTtfToEmu(ttfPoint.X - alc.Character.OriginX, _meanBondLength)}", Y = $"{OoXmlHelper.ScaleCsTtfToEmu(alc.Character.Height + ttfPoint.Y - (alc.Character.Height + alc.Character.OriginY), _meanBondLength)}" }; return(pp); } }
private void DrawCharacterBox(Wpg.WordprocessingGroup wordprocessingGroup, Rect boxExtents, string colour, double points) { UInt32Value id = UInt32Value.FromUInt32((uint)_ooxmlId++); string bondLineName = "char-diag-box-" + id; Int64Value width = (Int64Value)boxExtents.Width; Int64Value height = (Int64Value)boxExtents.Height; Int64Value top = (Int64Value)boxExtents.Top; Int64Value left = (Int64Value)boxExtents.Left; Wps.WordprocessingShape shape = new Wps.WordprocessingShape(); Wps.NonVisualDrawingProperties nonVisualDrawingProperties = new Wps.NonVisualDrawingProperties() { Id = id, Name = bondLineName }; Wps.NonVisualDrawingShapeProperties nonVisualDrawingShapeProperties = new Wps.NonVisualDrawingShapeProperties(); Wps.ShapeProperties shapeProperties = new Wps.ShapeProperties(); A.Transform2D transform2D = new A.Transform2D(); A.Offset offset = new A.Offset { X = left, Y = top }; A.Extents extents = new A.Extents { Cx = width, Cy = height }; transform2D.Append(offset); transform2D.Append(extents); A.CustomGeometry customGeometry = new A.CustomGeometry(); A.AdjustValueList adjustValueList = new A.AdjustValueList(); A.Rectangle rectangle = new A.Rectangle { Left = "l", Top = "t", Right = "r", Bottom = "b" }; A.PathList pathList = new A.PathList(); A.Path path = new A.Path { Width = width, Height = height }; // Starting Point A.MoveTo moveTo = new A.MoveTo(); A.Point point1 = new A.Point { X = "0", Y = "0" }; moveTo.Append(point1); // Mid Point A.LineTo lineTo1 = new A.LineTo(); A.Point point2 = new A.Point { X = boxExtents.Width.ToString("0"), Y = "0" }; lineTo1.Append(point2); // Mid Point A.LineTo lineTo2 = new A.LineTo(); A.Point point3 = new A.Point { X = boxExtents.Width.ToString("0"), Y = boxExtents.Height.ToString("0") }; lineTo2.Append(point3); // Last Point A.LineTo lineTo3 = new A.LineTo(); A.Point point4 = new A.Point { X = "0", Y = boxExtents.Height.ToString("0") }; lineTo3.Append(point4); // Back to Start Point A.LineTo lineTo4 = new A.LineTo(); A.Point point5 = new A.Point { X = "0", Y = "0" }; lineTo4.Append(point5); path.Append(moveTo); path.Append(lineTo1); path.Append(lineTo2); path.Append(lineTo3); path.Append(lineTo4); pathList.Append(path); customGeometry.Append(adjustValueList); customGeometry.Append(rectangle); customGeometry.Append(pathList); Int32Value emus = (Int32Value)(points * OoXmlHelper.EMUS_PER_WORD_POINT); A.Outline outline = new A.Outline { Width = emus, CapType = A.LineCapValues.Round }; A.SolidFill solidFill = new A.SolidFill(); A.RgbColorModelHex rgbColorModelHex = new A.RgbColorModelHex { Val = colour }; solidFill.Append(rgbColorModelHex); outline.Append(solidFill); shapeProperties.Append(transform2D); shapeProperties.Append(customGeometry); shapeProperties.Append(outline); OoXmlHelper.AppendShapeStyle(shape, nonVisualDrawingProperties, nonVisualDrawingShapeProperties, shapeProperties); wordprocessingGroup.Append(shape); }
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); } }
private Point GetCharacterPosition(Point cursorPosition, TtfCharacter character) { // Add the (negative) OriginY to raise the character by it return(new Point(cursorPosition.X, cursorPosition.Y + OoXmlHelper.ScaleCsTtfToCml(character.OriginY, _meanBondLength))); }
private void DrawDashedLine(Wpg.WordprocessingGroup wordprocessingGroup, Rect cmlExtents, Point bondStart, Point bondEnd, string colour = "000000") { UInt32Value id = UInt32Value.FromUInt32((uint)m_ooxmlId++); string bondLineName = "DashedBondLine" + id; Int64Value width = OoXmlHelper.ScaleCmlToEmu(cmlExtents.Width); Int64Value height = OoXmlHelper.ScaleCmlToEmu(cmlExtents.Height); Int64Value top = OoXmlHelper.ScaleCmlToEmu(cmlExtents.Top); Int64Value left = OoXmlHelper.ScaleCmlToEmu(cmlExtents.Left); Wps.WordprocessingShape shape = new Wps.WordprocessingShape(); Wps.NonVisualDrawingProperties nonVisualDrawingProperties = new Wps.NonVisualDrawingProperties() { Id = id, Name = bondLineName }; Wps.NonVisualDrawingShapeProperties nonVisualDrawingShapeProperties = new Wps.NonVisualDrawingShapeProperties(); Wps.ShapeProperties shapeProperties = new Wps.ShapeProperties(); A.Transform2D transform2D = new A.Transform2D(); A.Offset offset = new A.Offset { X = left, Y = top }; A.Extents extents = new A.Extents { Cx = width, Cy = height }; transform2D.Append(offset); transform2D.Append(extents); A.CustomGeometry customGeometry = new A.CustomGeometry(); A.AdjustValueList adjustValueList = new A.AdjustValueList(); A.Rectangle rectangle = new A.Rectangle { Left = "l", Top = "t", Right = "r", Bottom = "b" }; A.PathList pathList = new A.PathList(); A.Path path = new A.Path { Width = width, Height = height }; A.MoveTo moveTo = new A.MoveTo(); A.Point point1 = new A.Point { X = OoXmlHelper.ScaleCmlToEmu(bondStart.X).ToString(), Y = OoXmlHelper.ScaleCmlToEmu(bondStart.Y).ToString() }; moveTo.Append(point1); A.LineTo lineTo = new A.LineTo(); A.Point point2 = new A.Point { X = OoXmlHelper.ScaleCmlToEmu(bondEnd.X).ToString(), Y = OoXmlHelper.ScaleCmlToEmu(bondEnd.Y).ToString() }; lineTo.Append(point2); path.Append(moveTo); path.Append(lineTo); pathList.Append(path); customGeometry.Append(adjustValueList); customGeometry.Append(rectangle); customGeometry.Append(pathList); A.Outline outline = new A.Outline { Width = OoXmlHelper.ACS_LINE_WIDTH_EMUS, CapType = A.LineCapValues.Round }; A.SolidFill solidFill = new A.SolidFill(); A.PresetDash presetDash = new A.PresetDash() { Val = A.PresetLineDashValues.SystemDash }; A.RgbColorModelHex rgbColorModelHex = new A.RgbColorModelHex { Val = colour }; solidFill.Append(rgbColorModelHex); outline.Append(solidFill); outline.Append(presetDash); shapeProperties.Append(transform2D); shapeProperties.Append(customGeometry); shapeProperties.Append(outline); OoXmlHelper.AppendShapeStyle(shape, nonVisualDrawingProperties, nonVisualDrawingShapeProperties, shapeProperties); wordprocessingGroup.Append(shape); }
private void DrawShape(Wpg.WordprocessingGroup wordprocessingGroup, Rect cmlExtents, A.ShapeTypeValues shape, string colour) { UInt32Value id = UInt32Value.FromUInt32((uint)m_ooxmlId++); string bondLineName = "shape" + id; Int64Value width = OoXmlHelper.ScaleCmlToEmu(cmlExtents.Width); Int64Value height = OoXmlHelper.ScaleCmlToEmu(cmlExtents.Height); Int64Value top = OoXmlHelper.ScaleCmlToEmu(cmlExtents.Top); Int64Value left = OoXmlHelper.ScaleCmlToEmu(cmlExtents.Left); Point location = new Point(left, top); Size size = new Size(width, height); location.Offset(OoXmlHelper.ScaleCmlToEmu(-m_canvasExtents.Left), OoXmlHelper.ScaleCmlToEmu(-m_canvasExtents.Top)); Rect boundingBox = new Rect(location, size); width = (Int64Value)boundingBox.Width; height = (Int64Value)boundingBox.Height; top = (Int64Value)boundingBox.Top; left = (Int64Value)boundingBox.Left; A.PresetGeometry presetGeometry = null; A.Extents extents = new A.Extents { Cx = width, Cy = height }; presetGeometry = new A.PresetGeometry() { Preset = shape }; Wps.WordprocessingShape wordprocessingShape = new Wps.WordprocessingShape(); Wps.NonVisualDrawingProperties nonVisualDrawingProperties = new Wps.NonVisualDrawingProperties() { Id = id, Name = bondLineName }; Wps.NonVisualDrawingShapeProperties nonVisualDrawingShapeProperties = new Wps.NonVisualDrawingShapeProperties(); Wps.ShapeProperties shapeProperties = new Wps.ShapeProperties(); A.Transform2D transform2D = new A.Transform2D(); A.Offset offset = new A.Offset { X = left, Y = top }; transform2D.Append(offset); transform2D.Append(extents); A.AdjustValueList adjustValueList = new A.AdjustValueList(); presetGeometry.Append(adjustValueList); A.SolidFill solidFill = new A.SolidFill(); A.RgbColorModelHex rgbColorModelHex = new A.RgbColorModelHex { Val = colour }; solidFill.Append(rgbColorModelHex); shapeProperties.Append(transform2D); shapeProperties.Append(presetGeometry); shapeProperties.Append(solidFill); OoXmlHelper.AppendShapeStyle(wordprocessingShape, nonVisualDrawingProperties, nonVisualDrawingShapeProperties, shapeProperties); wordprocessingGroup.Append(wordprocessingShape); }
// Add the (negative) OriginY to raise the character by it private Point GetCharacterPosition(Point cursorPosition, TtfCharacter character) => new Point(cursorPosition.X, cursorPosition.Y + OoXmlHelper.ScaleCsTtfToCml(character.OriginY, _bondLength));
private Point GetCharacterPosition(Point cursorPosition, TtfCharacter character) { // Add the (negative) OriginY to raise the character by it return(new Point(cursorPosition.X, cursorPosition.Y + OoXmlHelper.ScaleCsTtfToCml(character.OriginY))); // return new Point(cursorPosition.X, cursorPosition.Y + OoXmlHelper.ScaleCsTtfToCml(character.Height) - OoXmlHelper.ScaleCsTtfToCml(character.Height - character.OriginY)); }
public void DrawCharacter(Wpg.WordprocessingGroup wordprocessingGroup1, AtomLabelCharacter alc) { Point characterPosition = new Point(alc.Position.X, alc.Position.Y); characterPosition.Offset(-_canvasExtents.Left, -_canvasExtents.Top); UInt32Value atomLabelId = UInt32Value.FromUInt32((uint)_ooxmlId++); string atomLabelName = "AtomLabel" + atomLabelId; Int64Value width = OoXmlHelper.ScaleCsTtfToEmu(alc.Character.Width); Int64Value height = OoXmlHelper.ScaleCsTtfToEmu(alc.Character.Height); if (alc.IsSubScript) { width = OoXmlHelper.ScaleCsTtfSubScriptToEmu(alc.Character.Width); height = OoXmlHelper.ScaleCsTtfSubScriptToEmu(alc.Character.Height); } Int64Value top = OoXmlHelper.ScaleCmlToEmu(characterPosition.Y); Int64Value left = OoXmlHelper.ScaleCmlToEmu(characterPosition.X); // Set variable true to show bounding box of (every) character if (_options.ShowCharacterBoundingBoxes) { Rect boundingBox = new Rect(new Point(left, top), new Size(width, height)); DrawCharacterBox(wordprocessingGroup1, boundingBox, "00ff00", 10); } Wps.WordprocessingShape wordprocessingShape10 = new Wps.WordprocessingShape(); Wps.NonVisualDrawingProperties nonVisualDrawingProperties10 = new Wps.NonVisualDrawingProperties() { Id = atomLabelId, Name = atomLabelName }; Wps.NonVisualDrawingShapeProperties nonVisualDrawingShapeProperties10 = new Wps.NonVisualDrawingShapeProperties(); Wps.ShapeProperties shapeProperties10 = new Wps.ShapeProperties(); A.Transform2D transform2D10 = new A.Transform2D(); A.Offset offset11 = new A.Offset() { X = left, Y = top }; A.Extents extents11 = new A.Extents() { Cx = width, Cy = height }; transform2D10.Append(offset11); transform2D10.Append(extents11); A.CustomGeometry customGeometry10 = new A.CustomGeometry(); A.AdjustValueList adjustValueList10 = new A.AdjustValueList(); A.Rectangle rectangle10 = new A.Rectangle() { Left = "l", Top = "t", Right = "r", Bottom = "b" }; A.PathList pathList10 = new A.PathList(); A.Path path10 = new A.Path() { Width = width, Height = height }; foreach (TtfContour contour in alc.Character.Contours) { int i = 0; while (i < contour.Points.Count) { TtfPoint thisPoint = contour.Points[i]; TtfPoint nextPoint = null; if (i < contour.Points.Count - 1) { nextPoint = contour.Points[i + 1]; } switch (thisPoint.Type) { case TtfPoint.PointType.Start: A.MoveTo moveTo1 = new A.MoveTo(); if (alc.IsSubScript) { A.Point point1 = new A.Point() { X = OoXmlHelper.ScaleCsTtfSubScriptToEmu(thisPoint.X - alc.Character.OriginX).ToString(), Y = OoXmlHelper.ScaleCsTtfSubScriptToEmu(alc.Character.Height + thisPoint.Y - (alc.Character.Height + alc.Character.OriginY)).ToString() }; moveTo1.Append(point1); path10.Append(moveTo1); } else { A.Point point1 = new A.Point() { X = OoXmlHelper.ScaleCsTtfToEmu(thisPoint.X - alc.Character.OriginX).ToString(), Y = OoXmlHelper.ScaleCsTtfToEmu(alc.Character.Height + thisPoint.Y - (alc.Character.Height + alc.Character.OriginY)).ToString() }; moveTo1.Append(point1); path10.Append(moveTo1); } i++; break; case TtfPoint.PointType.Line: A.LineTo lineTo1 = new A.LineTo(); if (alc.IsSubScript) { A.Point point2 = new A.Point() { X = OoXmlHelper.ScaleCsTtfSubScriptToEmu(thisPoint.X - alc.Character.OriginX).ToString(), Y = OoXmlHelper.ScaleCsTtfSubScriptToEmu(alc.Character.Height + thisPoint.Y - (alc.Character.Height + alc.Character.OriginY)).ToString() }; lineTo1.Append(point2); path10.Append(lineTo1); } else { A.Point point2 = new A.Point() { X = OoXmlHelper.ScaleCsTtfToEmu(thisPoint.X - alc.Character.OriginX).ToString(), Y = OoXmlHelper.ScaleCsTtfToEmu(alc.Character.Height + thisPoint.Y - (alc.Character.Height + alc.Character.OriginY)).ToString() }; lineTo1.Append(point2); path10.Append(lineTo1); } i++; break; case TtfPoint.PointType.CurveOff: A.QuadraticBezierCurveTo quadraticBezierCurveTo13 = new A.QuadraticBezierCurveTo(); if (alc.IsSubScript) { A.Point point3 = new A.Point() { X = OoXmlHelper.ScaleCsTtfSubScriptToEmu(thisPoint.X - alc.Character.OriginX).ToString(), Y = OoXmlHelper.ScaleCsTtfSubScriptToEmu(alc.Character.Height + thisPoint.Y - (alc.Character.Height + alc.Character.OriginY)).ToString() }; A.Point point4 = new A.Point() { X = OoXmlHelper.ScaleCsTtfSubScriptToEmu(nextPoint.X - alc.Character.OriginX).ToString(), Y = OoXmlHelper.ScaleCsTtfSubScriptToEmu(alc.Character.Height + nextPoint.Y - (alc.Character.Height + alc.Character.OriginY)).ToString() }; quadraticBezierCurveTo13.Append(point3); quadraticBezierCurveTo13.Append(point4); path10.Append(quadraticBezierCurveTo13); } else { A.Point point3 = new A.Point() { X = OoXmlHelper.ScaleCsTtfToEmu(thisPoint.X - alc.Character.OriginX).ToString(), Y = OoXmlHelper.ScaleCsTtfToEmu(alc.Character.Height + thisPoint.Y - (alc.Character.Height + alc.Character.OriginY)).ToString() }; A.Point point4 = new A.Point() { X = OoXmlHelper.ScaleCsTtfToEmu(nextPoint.X - alc.Character.OriginX).ToString(), Y = OoXmlHelper.ScaleCsTtfToEmu(alc.Character.Height + nextPoint.Y - (alc.Character.Height + alc.Character.OriginY)).ToString() }; quadraticBezierCurveTo13.Append(point3); quadraticBezierCurveTo13.Append(point4); path10.Append(quadraticBezierCurveTo13); } i++; i++; break; case TtfPoint.PointType.CurveOn: // Should never get here ! i++; break; } } A.CloseShapePath closeShapePath1 = new A.CloseShapePath(); path10.Append(closeShapePath1); } pathList10.Append(path10); customGeometry10.Append(adjustValueList10); customGeometry10.Append(rectangle10); customGeometry10.Append(pathList10); A.SolidFill solidFill10 = new A.SolidFill(); // Set Colour A.RgbColorModelHex rgbColorModelHex10 = new A.RgbColorModelHex() { Val = alc.Colour }; solidFill10.Append(rgbColorModelHex10); shapeProperties10.Append(transform2D10); shapeProperties10.Append(customGeometry10); shapeProperties10.Append(solidFill10); Wps.ShapeStyle shapeStyle10 = new Wps.ShapeStyle(); A.LineReference lineReference10 = new A.LineReference() { Index = (UInt32Value)0U }; A.FillReference fillReference10 = new A.FillReference() { Index = (UInt32Value)0U }; A.EffectReference effectReference10 = new A.EffectReference() { Index = (UInt32Value)0U }; A.FontReference fontReference10 = new A.FontReference() { Index = A.FontCollectionIndexValues.Minor }; shapeStyle10.Append(lineReference10); shapeStyle10.Append(fillReference10); shapeStyle10.Append(effectReference10); shapeStyle10.Append(fontReference10); Wps.TextBodyProperties textBodyProperties10 = new Wps.TextBodyProperties(); wordprocessingShape10.Append(nonVisualDrawingProperties10); wordprocessingShape10.Append(nonVisualDrawingShapeProperties10); wordprocessingShape10.Append(shapeProperties10); wordprocessingShape10.Append(shapeStyle10); wordprocessingShape10.Append(textBodyProperties10); wordprocessingGroup1.Append(wordprocessingShape10); }