Нарисуйте объекты ShapeType.Line во всех направлениях с GemBox.Document - PullRequest
0 голосов
/ 07 декабря 2018

Высокоуровневая бизнес-потребность:

1.) Получение ввода от пользователя для создания данных объекта для построения линий, прямоугольников, text и fields.

2.)Используя input от пользователя, создайте шаблоны документов с помощью GemBox.Document (в настоящее время здесь застряли строки). 3.) Входной рабочий объект объединяет данные в документы template (s) для заполнения полей, сохраняя их как изображение.

Я считаю, что я должен быть в состоянии выяснить # 2 для прямоугольников и текста, так как способ построения объектов похож на то, как Shape работает для GemBox.Document.Тем не менее, объект для Line не тот же, обеспечивая point1 и длину / ширину, а не point1 и point2.

Я классифицирую 3 типа линий ...

1.) Плоский 2.) Положительный шаг 3.) Отрицательный шаг

... Мне удалось выяснить плоскую (без горизонтальной или вертикальной дельты) и положительную высоту (линия сверху слева досправа внизу или его зеркала снизу справа вверху слева), но не удалось определить отрицательный шаг (линия сверху вниз справа налево или его зеркало снизу слева направо вверх).

Объект Shape не будетпозвольте отрицательной длине или отрицательному атрибуту нарисовать его так, как я хочу.Я не мог видеть / выяснить, был ли способ изменить объект линии с помощью поворота / отражения и т. Д.

Я открыт для разных подходов, но мне сказали, что я должен использовать GemBox.Document

namespace GemBoxDocument_LineDemo
{
    using System;
    using MyModels;
    using GemBox.Document;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using GemBox.Document.Drawing;
    using System.IO;
    using System.Reflection;

    public class Program
    {
        //inputs come from a GUI window, we're working with stub/coupon/partial-page/rectangle where w > h
        private const float GUIWIDTH = 425;
        private const float GUIHEIGHT = 200;

        public static void Main(string[] args)
        {
            ComponentInfo.SetLicense("FREE-LIMITED-KEY");

            var gemDoc = new DocumentModel();

            var firstSection = new Section(gemDoc);
            gemDoc.Sections.Add(firstSection);

            var firstParagraph = new Paragraph(gemDoc);
            firstSection.Blocks.Add(firstParagraph);

            var workableWidth = firstSection.PageSetup.PageWidth - (firstSection.PageSetup.PageMargins.Left + firstSection.PageSetup.PageMargins.Right);
            //i think this needs to be -something, or * % of total page since we're partial page
            var workableHeight = firstSection.PageSetup.PageHeight - (firstSection.PageSetup.PageMargins.Top + firstSection.PageSetup.PageMargins.Bottom);

            var widthMultiplier = workableWidth / GUIWIDTH;
            //for now this has been working just fine...
            var heightMultiplier = widthMultiplier;

            //offset of 0 is whole available workable width from GUI, simulating the offset at 50 for instance will show dynamic input shrinks towards center as this increases
            //don't change it too high as it'd create dynamic negative input which isn't possible fron an input perspective. (negative width and/or height)
            var offset = 0;

            var flatOnHorizontalTOPLine = new TemplateItem()
            {
                X = 0 + offset,
                Y = 0 + offset,
                X2 = GUIWIDTH - offset,
                Y2 = 0 + offset,
                Pen = new System.Drawing.Pen(System.Drawing.Color.Black, 1),
                TemplateItemType = TemplateItemType.Line
            };

            var flatOnHorizontalBOTTOMLine = new TemplateItem()
            {
                X = 0 + offset,
                Y = GUIHEIGHT - offset,
                X2 = GUIWIDTH - offset,
                Y2 = GUIHEIGHT - offset,
                Pen = new System.Drawing.Pen(System.Drawing.Color.Black, 1),
                TemplateItemType = TemplateItemType.Line
            };

            var flatOnVerticalLEFTLine = new TemplateItem()
            {
                X = 0 + offset,
                Y = 0 + offset,
                X2 = 0 + offset,
                Y2 = GUIHEIGHT - offset,
                Pen = new System.Drawing.Pen(System.Drawing.Color.Black, 1),
                TemplateItemType = TemplateItemType.Line
            };

            var flatOnVerticalRIGHTLine = new TemplateItem()
            {
                X = GUIWIDTH - offset,
                Y = 0 + offset,
                X2 = GUIWIDTH - offset,
                Y2 = GUIHEIGHT - offset,
                Pen = new System.Drawing.Pen(System.Drawing.Color.Black, 1),
                TemplateItemType = TemplateItemType.Line
            };

            var positivePitchPoint1LessThanPoint2 = new TemplateItem()
            {
                X = 0 + offset,
                Y = 0 + offset,
                X2 = GUIWIDTH - offset,
                Y2 = GUIHEIGHT - offset,
                Pen = new System.Drawing.Pen(System.Drawing.Color.Black, 1),
                TemplateItemType = TemplateItemType.Line
            };

            var positivePitchPoint1GreaterThanPoint2 = new TemplateItem()
            {
                X = 0 + offset,
                Y = 0 + offset,
                X2 = GUIWIDTH - offset,
                Y2 = GUIHEIGHT - offset,
                Pen = new System.Drawing.Pen(System.Drawing.Color.Blue, 1),
                TemplateItemType = TemplateItemType.Line
            };

            //else if (templateItem.X < templateItem.X2 && templateItem.Y > templateItem.Y2)//negative pitch, point 1 below/ToLeft point 2
            var negativePitchPoint1BelowAndToLeftOfPoint2 = new TemplateItem()
            {
                X = 0 + offset,
                Y = GUIHEIGHT - offset,
                X2 = GUIWIDTH - offset,
                Y2 = 0 + offset,
                Pen = new System.Drawing.Pen(System.Drawing.Color.Red, 1),
                TemplateItemType = TemplateItemType.Line
            };

            //else if (templateItem.X > templateItem.X2 && templateItem.Y < templateItem.Y2)//negative pitch, point 1 above/ToRight point 2
            var negativePitchPoint1AboveAndToRightOfPoint2 = new TemplateItem()
            {
                X = GUIWIDTH - offset,
                Y = 0 + offset,
                X2 = 0 + offset,
                Y2 = GUIHEIGHT - offset,
                Pen = new System.Drawing.Pen(System.Drawing.Color.Green, 1),
                TemplateItemType = TemplateItemType.Line
            };

            firstParagraph.Inlines.Add(GetGemboxLineShape(gemDoc, firstSection, flatOnHorizontalTOPLine, heightMultiplier, widthMultiplier));
            firstParagraph.Inlines.Add(GetGemboxLineShape(gemDoc, firstSection, flatOnHorizontalBOTTOMLine, heightMultiplier, widthMultiplier));
            firstParagraph.Inlines.Add(GetGemboxLineShape(gemDoc, firstSection, flatOnVerticalLEFTLine, heightMultiplier, widthMultiplier));
            firstParagraph.Inlines.Add(GetGemboxLineShape(gemDoc, firstSection, flatOnVerticalRIGHTLine, heightMultiplier, widthMultiplier));
            firstParagraph.Inlines.Add(GetGemboxLineShape(gemDoc, firstSection, positivePitchPoint1LessThanPoint2, heightMultiplier, widthMultiplier));
            firstParagraph.Inlines.Add(GetGemboxLineShape(gemDoc, firstSection, positivePitchPoint1GreaterThanPoint2, heightMultiplier, widthMultiplier));

            //cannot figure out these two 'negative pitch' instances...
            firstParagraph.Inlines.Add(GetGemboxLineShape(gemDoc, firstSection, negativePitchPoint1BelowAndToLeftOfPoint2, heightMultiplier, widthMultiplier));
            firstParagraph.Inlines.Add(GetGemboxLineShape(gemDoc, firstSection, negativePitchPoint1AboveAndToRightOfPoint2, heightMultiplier, widthMultiplier));

            gemDoc.Save(Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), $"{Assembly.GetExecutingAssembly().GetName().Name}-{DateTime.Now.ToString("yyyy-MM-dd hhmmss")}.docx"));

            Console.WriteLine("DONE");
            Console.ReadKey();
        }

        public static Shape GetGemboxLineShape(DocumentModel document, Section section, TemplateItem templateItem, double heightMultiplier, double widthMultiplier)
        {
            var verticalTranslation = Math.Abs(templateItem.Y2 - templateItem.Y) * heightMultiplier;
            var horizontalTranslation = Math.Abs(templateItem.X2 - templateItem.X) * widthMultiplier;
            var horizontalAbsolutePosition = 0.0;
            var verticalAbsolutePosition = 0.0;

            if ((templateItem.X < templateItem.X2 && templateItem.Y < templateItem.Y2) ||//positive pitch, point1 < point2
                (templateItem.X == templateItem.X2) || (templateItem.Y == templateItem.Y2))//flat on the horizontal or vertical
            {
                horizontalAbsolutePosition = templateItem.X * widthMultiplier;
                verticalAbsolutePosition = templateItem.Y * heightMultiplier;

                var gemboxLineShape = new Shape(document, ShapeType.Line, GemBox.Document.Layout.Floating(new HorizontalPosition(section.PageSetup.PageMargins.Left + horizontalAbsolutePosition, LengthUnit.Point, HorizontalPositionAnchor.LeftMargin),
                                                                                                          new VerticalPosition(section.PageSetup.PageMargins.Top + verticalAbsolutePosition, LengthUnit.Point, VerticalPositionAnchor.TopMargin),
                                                                                                          new GemBox.Document.Size(horizontalTranslation, verticalTranslation, LengthUnit.Point)));

                gemboxLineShape.Outline.Fill.SetSolid(new GemBox.Document.Color(templateItem.Pen.Color.R, templateItem.Pen.Color.G, templateItem.Pen.Color.B));
                gemboxLineShape.Outline.Width = templateItem.Pen.Width;

                return gemboxLineShape;
            }
            else if (templateItem.X > templateItem.X2 && templateItem.Y > templateItem.Y2)//positive pitch, point1 > point2
            {
                //quickly found out i cannot give a negative width or height to GemBox.Document.Size
                //to account for the mirror of the above condition, AKA drawing the same object but in mirror
                //we just flip-flop the starting point / absolute position and create the shape the same way
                horizontalAbsolutePosition = templateItem.X2 * widthMultiplier;
                verticalAbsolutePosition = templateItem.Y2 * heightMultiplier;

                var gemboxLineShape = new Shape(document, ShapeType.Line, GemBox.Document.Layout.Floating(new HorizontalPosition(section.PageSetup.PageMargins.Left + horizontalAbsolutePosition, LengthUnit.Point, HorizontalPositionAnchor.LeftMargin),
                                                                                                          new VerticalPosition(section.PageSetup.PageMargins.Top + verticalAbsolutePosition, LengthUnit.Point, VerticalPositionAnchor.TopMargin),
                                                                                                          new GemBox.Document.Size(horizontalTranslation, verticalTranslation, LengthUnit.Point)));

                gemboxLineShape.Outline.Fill.SetSolid(new GemBox.Document.Color(templateItem.Pen.Color.R, templateItem.Pen.Color.G, templateItem.Pen.Color.B));
                gemboxLineShape.Outline.Width = templateItem.Pen.Width;

                return gemboxLineShape;
            }
            else if (templateItem.X < templateItem.X2 && templateItem.Y > templateItem.Y2)//negative pitch, point 1 below/ToLeft point 2
            {
                horizontalAbsolutePosition = templateItem.X * widthMultiplier;
                verticalAbsolutePosition = templateItem.Y * heightMultiplier;

                //cannot set negative height for size for it to draw up
                var badLineShape = new Shape(document, ShapeType.Line, GemBox.Document.Layout.Floating(new HorizontalPosition(section.PageSetup.PageMargins.Left + horizontalAbsolutePosition, LengthUnit.Point, HorizontalPositionAnchor.LeftMargin),
                                                                                                       new VerticalPosition(section.PageSetup.PageMargins.Top + verticalAbsolutePosition, LengthUnit.Point, VerticalPositionAnchor.TopMargin),
                                                                                                       new GemBox.Document.Size(horizontalTranslation, verticalTranslation, LengthUnit.Point)));

                badLineShape.Outline.Fill.SetSolid(new GemBox.Document.Color(templateItem.Pen.Color.R, templateItem.Pen.Color.G, templateItem.Pen.Color.B));
                badLineShape.Outline.Width = templateItem.Pen.Width;

                return badLineShape;
            }
            else if (templateItem.X > templateItem.X2 && templateItem.Y < templateItem.Y2)//negative pitch, point 1 above/ToRight point 2
            {
                horizontalAbsolutePosition = templateItem.X * widthMultiplier;
                verticalAbsolutePosition = templateItem.Y * heightMultiplier;

                //cannot set negative width for size for it to draw left
                var badLineShape = new Shape(document, ShapeType.Line, GemBox.Document.Layout.Floating(new HorizontalPosition(section.PageSetup.PageMargins.Left + horizontalAbsolutePosition, LengthUnit.Point, HorizontalPositionAnchor.LeftMargin),
                                                                                                       new VerticalPosition(section.PageSetup.PageMargins.Top + verticalAbsolutePosition, LengthUnit.Point, VerticalPositionAnchor.TopMargin),
                                                                                                       new GemBox.Document.Size(horizontalTranslation, verticalTranslation, LengthUnit.Point)));

                badLineShape.Outline.Fill.SetSolid(new GemBox.Document.Color(templateItem.Pen.Color.R, templateItem.Pen.Color.G, templateItem.Pen.Color.B));
                badLineShape.Outline.Width = templateItem.Pen.Width;

                return badLineShape;
            }
            else
                return null;
        }
    }
}

namespace MyModels
{
    using System.Drawing;

    public enum TemplateItemType { Default, Box, Line, Text, Field }
    public class TemplateItem
    {
        public TemplateItemType TemplateItemType { get; set; }
        public Font Font { get; set; }
        public Pen Pen { get; set; }
        public float X { get; set; }
        public float Y { get; set; }
        public float X2 { get; set; }
        public float Y2 { get; set; }
        public float Width { get; set; }
        public float Height { get; set; }
        public string Text { get; set; }

        public override string ToString()
        {
            switch (this.TemplateItemType)
            {
                case TemplateItemType.Box:
                    return $"<{this.TemplateItemType.ToString("G")}Item> X<{this.X}> Y<{this.Y}> W<{this.Width}> H<{this.Height}>";
                case TemplateItemType.Line:
                    return $"<{this.TemplateItemType.ToString("G")}Item> X1<{this.X}> Y1<{this.Y}> X2<{this.X2}> Y2<{this.Y2}>";
                case TemplateItemType.Text:
                case TemplateItemType.Field:
                    return $"<{this.TemplateItemType.ToString("G")}Item> X<{this.X}> Y<{this.Y}> W<{this.Width}> H<{this.Height}> T<{this.Text}>";
            }

            return string.Empty;
        }
    }
}

Ответы [ 2 ]

0 голосов
/ 12 декабря 2018

Как уже упоминал Mario Z, новая версия с большими исправлениями v1099 позволяет преобразовывать линии, создавая то, что я классифицирую как отрицательную линию тона ... которая теперь позволяет рисовать линии во всех направлениях.

Кажется, что это немного глючит, так как FlipVertical и FlipHorizontal делают одно и то же точное преобразование, когда они не должны.Я также обнаружил небольшую ошибку с настройкой плавающей точки с помощью RightMargin, она не работает так же, как Top / Left (я еще не пробовал играть с Bottom).

public static Shape GetGemboxLineShape(DocumentModel document, Section section, TemplateItem templateItem, double heightMultiplier, double widthMultiplier)
{
    var size = new GemBox.Document.Size(Math.Abs(templateItem.X2 - templateItem.X) * widthMultiplier, Math.Abs(templateItem.Y2 - templateItem.Y) * heightMultiplier, LengthUnit.Point);
    var horizontal = new HorizontalPosition();
    var vertical = new VerticalPosition();
    var requiresNegativeTransform = false;

    if ((templateItem.X < templateItem.X2 && templateItem.Y < templateItem.Y2) ||//positive pitch, point1 < point2
        (templateItem.X == templateItem.X2) || (templateItem.Y == templateItem.Y2))//flat on the horizontal or vertical
    {
        horizontal = new HorizontalPosition(section.PageSetup.PageMargins.Left + (templateItem.X * widthMultiplier), LengthUnit.Point, HorizontalPositionAnchor.LeftMargin);
        vertical = new VerticalPosition(section.PageSetup.PageMargins.Top + (templateItem.Y * heightMultiplier), LengthUnit.Point, VerticalPositionAnchor.TopMargin);
    }
    else if (templateItem.X > templateItem.X2 && templateItem.Y > templateItem.Y2)//positive pitch, point1 > point2
    {
        //quickly found out i cannot give a negative width or height to GemBox.Document.Size
        //to account for the mirror of the above condition, AKA drawing the same object but in mirror
        //we just flip-flop the starting point / absolute position and create the shape the same way
        horizontal = new HorizontalPosition(section.PageSetup.PageMargins.Left + (templateItem.X2 * widthMultiplier), LengthUnit.Point, HorizontalPositionAnchor.LeftMargin);
        vertical = new VerticalPosition(section.PageSetup.PageMargins.Top + (templateItem.Y2 * heightMultiplier), LengthUnit.Point, VerticalPositionAnchor.TopMargin);
    }
    else if (templateItem.X < templateItem.X2 && templateItem.Y > templateItem.Y2)//negative pitch, point 1 below/ToLeft point 2
    {
        //so for ease we're going to pick point2 at the top right and we can use Top/Right margin as our origin instead of Top/Left
        //however, this appears a bit buggy, i would assume i'd need to do -section.PageSetup.PageMargins.Right minus relative (opposite of TopLeft on the X/horizontal)
        //but it appears this wasn't accounted for on the right margin? or i'm not entirely understanding the floating/anchor functionality
        horizontal = new HorizontalPosition(-(templateItem.X2 * widthMultiplier), LengthUnit.Point, HorizontalPositionAnchor.RightMargin);
        vertical = new VerticalPosition(section.PageSetup.PageMargins.Top + (templateItem.Y2 * heightMultiplier), LengthUnit.Point, VerticalPositionAnchor.TopMargin);
        requiresNegativeTransform = true;
    }
    else if (templateItem.X > templateItem.X2 && templateItem.Y < templateItem.Y2)//negative pitch, point 1 above/ToRight point 2
    {
        //opposite of previous in that we're going to pick point1 but everything else will be the same
        horizontal = new HorizontalPosition(-(templateItem.X * widthMultiplier), LengthUnit.Point, HorizontalPositionAnchor.RightMargin);
        vertical = new VerticalPosition(section.PageSetup.PageMargins.Top + (templateItem.Y * heightMultiplier), LengthUnit.Point, VerticalPositionAnchor.TopMargin);
        requiresNegativeTransform = true;
    }
    else
    {
        throw new ArgumentException();
    }

    var gemboxLineShape = new Shape(document, ShapeType.Line, GemBox.Document.Layout.Floating(horizontal, vertical, size));

    gemboxLineShape.Outline.Fill.SetSolid(new GemBox.Document.Color(templateItem.Pen.Color.R, templateItem.Pen.Color.G, templateItem.Pen.Color.B));
    gemboxLineShape.Outline.Width = templateItem.Pen.Width;

    //this appears to solve my problem.... however, similar to right margin appears to be
    //a bit buggy... at least in the sense that FlipVertical and FlipHorizontal should do different transformations but it doesn't
    gemboxLineShape.Layout.Transform.FlipVertical = requiresNegativeTransform;

    return gemboxLineShape;
}
0 голосов
/ 10 декабря 2018

Загрузите текущую последнюю версию исправления ошибки отсюда и попробуйте использовать следующее:

badLineShape.Layout.Transform.FlipVertical = true;

Относительно преобразований FlipVertical и FlipHorizontal, в данном случае (форма линии) они должны быть одинаковыми.

Например, рассмотрим следующее изображение:

Line drawing

Применение к нему преобразования с вертикальным отражением с помощьюНекоторые приложения Photoshop (я использовал Gimp) приводит к следующим результатам:

Line drawing with vertical flip

Применение к нему преобразования горизонтального смещения с помощью некоторого приложения Photoshop (я использовалGimp) приводит к:

Line drawing with horizontal flip

Как вы можете заметить, результирующие изображения одинаковы.

Относительно RightMargin, I 'Я попытаюсь исследовать это дальше.

...