Экспрот в jpg каждого листа многолистового чертежа

Автор sim68, 25.07.18, 08:20:46

« назад - далее »

0 Пользователи и 1 гость просматривают эту тему.

sim68

Добрый день! Есть многолистовые чертежи, помеченные в штампе, например, как A3*3
Каким образом посредством API можно сконвертировать по отдельности каждый из листов такого чертежа в jpg ?
Конвертацию чертежей в jpg из одного листа делать умею, а как справиться с вышеуказанной задачей ?

Олеся_Орен

Цитата: sim68 от 25.07.18, 08:20:46
Добрый день! Есть многолистовые чертежи, помеченные в штампе, например, как A3*3
Каким образом посредством API можно сконвертировать по отдельности каждый из листов такого чертежа в jpg ?
Конвертацию чертежей в jpg из одного листа делать умею, а как справиться с вышеуказанной задачей ?
Точно также. Просто у вас для каждого листа создастся отдельный рисунок.

Lotos82

Олеся, Олеся...
Мужчину интересует как это реализовать программными средствами на языке С...))))

sim68

Цитата: Олеся_Орен от 25.07.18, 11:16:16
Точно также. Просто у вас для каждого листа создастся отдельный рисунок.

Да,Олеся, Lotos правильно отметил, эту задачу мне необходимо решить средствами API

На сегодня экспорт в jpg для однолиствого чертежа делается так:

                if (kompas == null)
                {
                    Type t = Type.GetTypeFromProgID("KOMPAS.Application.5");
                    kompas = (KompasObject)Activator.CreateInstance(t);
                }

                if (kompas != null)
                {
                    kompas.Visible = true;
                    kompas.ActivateControllerAPI();
                    iApi7 = (IApplication)kompas.ksGetApplication7();
                    iApi7.HideMessage = ksHideMessageEnum.ksHideMessageYes;
                }

                RasterFormatParam iRastFormatParam = null;
                ksDocument2D doc = null;
                SpcDocument spec = null;
               
                if (fileInfo.Extension.ToLower() == ".cdw") 
                {
                    // Получение объекта спецификации из файла чертежа
                    doc = (ksDocument2D)kompas.Document2D();
                    doc.ksOpenDocument(fileInfo.FullName, true);
                    iRastFormatParam = (RasterFormatParam)doc.RasterFormatParam();
                }
                }
                else
                {
                    // Получение объекта спецификации из файла спецификации
                    spec = (SpcDocument)kompas.SpcDocument();
                    spec.ksOpenDocument(fileInfo.FullName, 0);
                    iRastFormatParam = (RasterFormatParam)spec.RasterFormatParam();
                }

                iRastFormatParam.Init();
                iRastFormatParam.format = 2;    // JPG
                iRastFormatParam.colorType = 0;
                iRastFormatParam.extResolution = 300;
                iRastFormatParam.extScale = 1;
                iRastFormatParam.greyScale = false;
                iRastFormatParam.colorBPP = 24;
                iRastFormatParam.multiPageOutput = true;
                iRastFormatParam.onlyThinLine = true;
                iRastFormatParam.rangeIndex = 0;

                if (fileInfo.Extension.ToLower() == ".cdw")
                {
                    doc.SaveAsToRasterFormat(m_fileName, iRastFormatParam);
                    doc.ksCloseDocument();
                }
                else
                {
                    spec.SaveAsToRasterFormat(m_fileName, iRastFormatParam);
                    spec.ksCloseDocument();
                }

      -- Далее следует найденный на этом форуме код по чтению формата чертежа (A2,A3,A4...)
      
      -- И здесь была строка по чтению кол-ва листов документа

      int _countPages = doc.ksGetDocumentPagesCount();

      -- НО здесь всегда выдается одно значение = 1
      -- т.е. по моему предположению подобным образом можно было бы получить количество листов многолистового чертежа , перебрать каждый из них и сконвертировать в jpg файл, но... (((  количество листов всегда выдается равное 1.

      -- следующая часть кода работает - она нужна для чтения формата листа в чертеже, но, повторюсь - всегда только для всего только для чертежа на одном листе(A3,A4...). Тип чертежа A3*3 в этом случае вообще не определяется (строка _format.GetHashCode().ToString() не возвращает ничего)

                if (iApi7.ActiveDocument != null)
                {
                    LayoutSheet _lSheet = iApi7.ActiveDocument.LayoutSheets.get_ItemByNumber(1);  // здесь 1 - номер листа документа
                    // обращаемся к искомому объекту SheetFormat в котром и хранятся все данные о листе
                    // формат, ориентация, кратность, высота, ширина,
                    SheetFormat _shFormat = _lSheet.Format;
                    // получаем формат в ввиде перечисления
                    ksDocumentFormatEnum _format = _shFormat.Format;

          // Формат листа:
          string _format = "А" + _format.GetHashCode().ToString();
                }


                kompas.Quit();
                kompas = null;

   Т.е. если бы можно было как-то получить доступ ко всем листам многолистового документа и перебрать каждый из них - задача была бы решена. Вопрос - как ?

pr0100


Цитата: sim68 от 25.07.18, 12:15:00
   Т.е. если бы можно было как-то получить доступ ко всем листам многолистового документа и перебрать каждый из них - задача была бы решена. Вопрос - как ?
Здесь посмотрите
http://forum.ascon.ru/index.php/topic,28102.msg211969.html#msg211969

#programmer

iApi7.ActiveDocument.LayoutSheets


У LayoutSheets есть свойство Count - количество листов документа.
В справке этого нет почему-то....

sim68

Цитата: pr0100 от 25.07.18, 12:48:05
Здесь посмотрите
http://forum.ascon.ru/index.php/topic,28102.msg211969.html#msg211969

спасибо, полностью рабочий пример, но как перевожу на c#, аналогичные методы выдают в трехлистовом чертеже кол-во листов равное единице. То же самое касается метода (спасибо,#programmer) IApi7.ActiveDocument.LayoutSheets.Count - тоже выдает кол-во листов = 1.
Хотя макрос по вышеуказанной ссылке при загрузке тестируемого файла правильно определяет кол-во листов = 3 (для A3*3)
Доходит до смешного, но видимо что-то я делаю не так, вот код (по аналогии с примером макроса). Может кто подскажет, в чем моя ошибка ?  (обрабатываемый сборочный чертеж (.cdw) загружается по пути fileInfo.FullName, чертеж из трех листов A3*3)

                 Kompas6API5.Application _kompas = new Kompas6API5.Application();
                _kompas.Visible = true;
                KompasAPI7.IApplication kompas7 = (IApplication)_kompas.ksGetApplication7();
                KompasAPI7.Documents doc7 = kompas7.Documents;
                var item = doc7.Open(fileInfo.FullName, true, true);  // после этого действия на панели инструментов появляется открытый в Компасе чертеж

                if (item.DocumentType == DocumentTypeEnum.ksDocumentDrawing)  // правильно определяется тип документа
                {
                    // и вот здесь хоть тресни возвращает кол-во листов = 1
                    KompasAPI7.LayoutSheets DrawPar = item.LayoutSheets;
                    MessageBox.Show(DrawPar.Count.ToString());    //  результат = 1
                }
                // такой же результат выдает метод (#programmer)
                MessageBox.Show(kompas7.ActiveDocument.LayoutSheets.Count.ToString());  // = 1

               // пробовал еще так:
               ksDocument2D doc = (ksDocument2D)kompas.Document2D();
               doc.ksOpenDocument(fileInfo.FullName, true);
               int _countPages = doc.ksGetDocumentPagesCount();    // снова результат = 1
               

               Если этот же самый файл прогнать через вышеуказанный макрос на VB, он правильно определяет кол-во листов = 3

Дмитрий22

25.07.18, 18:37:24 #7 Последнее редактирование: 25.07.18, 18:57:03 от Дмитрий22
 У меня все работает как надо:
   
// Получаем интерфейс активного документа 2D в API5
  doc2D = (ksDocument2D)kompas.ActiveDocument2D();
   if (doc2D == null)
    return;
  MessageBox.Show(doc2D.ksGetDocumentPagesCount().ToString(), "Количество листов", MessageBoxButtons.OK, MessageBoxIcon.Asterisk);

Если нужно листы перевести в картинки, то я пользуюсь не jpg, а tiff. У этого формата есть настройка сохранять каждый лист в отдельный файл.
За кратность формата отвечает свойство iStandartSheet.multiply.
+ Благодарностей: 1

sim68

Дмитрий, огромное спасибо за подсказку
"За кратность формата отвечает свойство iStandartSheet.multiply."  - совсем упустил этот момент, и я похоже подменил понятия лист и кратность, теперь формат A3*3 читается как надо - 1 лист A3 с кратностью 3.
И вы написали фразу :
"Если нужно листы перевести в картинки, то я пользуюсь не jpg, а tiff. У этого формата есть настройка сохранять каждый лист в отдельный файл."
Можете пояснить где при экспорте указывается эта настройка? Моя задача состоит в том, чтобы сконвертировать вот этот один чертеж A3*3 в три отдельных листа A3 (для последующей печати каждого листа из прикладной программы).
Я,как описывал в начале,делаю так:
    doc = (ksDocument2D)kompas.Document2D();
    doc.ksOpenDocument(fileInfo.FullName, true);
    iRastFormatParam = (RasterFormatParam)doc.RasterFormatParam();

И далее для опции iRastFormatParam.format если указать значение = 4, то будет именно формат tif - но где включить настройку разбивки по листам ?
И возможно ли при таком подходе заставить сконвертировать один исходный лист чертежа A3*3 на 3 отдельных листа (A3) .tif ?

Дмитрий22

Если Вы при конвертации в tiff будете пользоваться опцией iRastFormatParam.multiPageOutput, то команда SaveAsToRasterFormat сама будет сохранять листы чертежа в отдельные файлы. Не путайте  А3х3 -это не 3 отдельных листа, это лист в 3 раза длиннее стандартного. Он будет сохранен в отдельный файл. Как разбить формат А3х3 на 3 отдельных картинки не знаю, так же не знаю, зачем это нужно.

sim68

Дмитрий, спасибо за пояснение. Последний штрих как сказать - может кто-нибудь подскажет идею ....
Зачем всё это нужно. Есть прикладная программа, в которой для каждого изделия выстраивается структура в вид "дерева" со всеми сборками, подсборками, деталями, спецификациями, сборочным чертежами (с кучей сопутствующей информацией(с нормами времени на изготовление деталей, тарифами и т.д. и т.п.)). И необходимо, чтобы по нажатии одной кнопки, распечатывалась целиком вся документаций на изделие согласно выстроенной иерархии. И что важно - чтобы распечатывалось в реальных размерах - т.е. если в Компасе сборочный чертеж определен как A3*3, то из приложения он должен быть распечатан (как и из Компаса) - на трех листах A3.
Осталось сделать последний нерешенный момент - как печатать вот эти 'длинные' чертежи.
За любые подсказки буду очень благодарен

За печать отвечает интерфейс IPrintJob, т.ч. разбирайтесь с ним.

DesignЯR

Сделайте ваш чертеж не на одном листе А3х3, а на трех листах А3, а для каждого листа создайте и примените оформление рамки как вам надо.

sim68

Цитата: DesignЯR от 26.07.18, 19:30:08
Сделайте ваш чертеж не на одном листе А3х3, а на трех листах А3, а для каждого листа создайте и примените оформление рамки как вам надо.
Я ограничен тем, что уже существуют большие рабочие архивы документации и конструкторы переделывать в них уже ничего не станут - имеем дел с тем что есть. Сейчас идет процесс загрузки пакетов чертежей изделий в базу данных (в отдельной папке выстраивается целиком структура изделия и заливается в базу, чего нет добавляется вручную) Попутно идет конвертация чертежей в jpg-файлы.
Похоже то что мне подходит - это интерфейс печати  IPrintJob (спасибо Sabahs  за подсказку) - разбираюсь с ним.
Jpg-файлы (посмотрю по подсказке в сторону tif) для однолистовых обычных чертежей мне всё-равно придется сохранить, поскольку при их печати необходимо производить еще и дуплексную печать - на обороте распечатывать дополнительную информацию.
Поэтому, повторюсь, на сегодня мне кажется подходящее решение - интерфейс  IPrintJob

sim68

Цитата: DesignЯR от 26.07.18, 19:30:08
Сделайте ваш чертеж не на одном листе А3х3, а на трех листах А3, а для каждого листа создайте и примените оформление рамки как вам надо.
Вот если бы посредством API можно было разбить чертеж A3*3 (это конечно, пример)  на три отдельных листа A3 (как это, видимо, делает Компас при печати)- это было бы очень хорошо

DesignЯR

Задумка и была в том, чтобы при помощи ILayoutSheets переделать оригинал в  трехлистовой чертеж и применить к листам свои оформления. Оказалось что оформление рамок читать из фрагмента нельзя : либо прямоугольники - либо ничего.Поэтому. Для первых двух листов выбираем стиль оформления №15 - "Без оформления". Для третьего листа создаем новый стиль без обоих рамок и применяем свой новый штамп. Этот штамп также создаем на основе стандартного, но редактируем его и сдвигаем таблицу и боковые штампы, потому что привязка идет ко внутренней рамке - а так как её нет, то нужно изменить привязку.Такой штамп подхватит данные из чертежа оригинала. Можно отрисовать штамп и библиотекой как таблицу или макроэлемент, но тогда придется и данные сначала читать из оригинального чертежа, а потом отрисовывать(при редактировании впоследствии потеряются - если особо не заморачиваться с кодом). Рамка рисуется на новом виде, который по окончании блокируется от редактирования. Во вложении (то что получается если сделать все процедуры вручную) - скрин самого чертежа и "Сохранить как..."  =>   *.JPG. Сохранение в jpg реализовываете либо в своей библиотеке сразу, либо потом из существующей библиотеки сделаете пакетом.
Через IPrintJob, если я правильно понял, вы либо сохраните в PDF(если установлен pdf принтер), либо просто сможете распечатать. jpg потом придется делать из pdf.

sim68

Цитата: DesignЯR от 26.07.18, 19:30:08
Сделайте ваш чертеж не на одном листе А3х3, а на трех листах А3, а для каждого листа создайте и примените оформление рамки как вам надо.

А как посредством API однолистовой чертеж с кратностью 3 переделать в  трехлистовой чертеж ?

DesignЯR

В архиве исходник. Файл со стилем оформления должен находиться рядом с файлом библиотеки, или нужно будет вносить изменения в код. Код для тех кто не любит архивы

using Kompas6API5;
using System;
using System.IO;
using Microsoft.Win32;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Windows.Forms;
using KAPITypes;
using KompasAPI7;
using Kompas6Constants;
using reference = System.Int32;

namespace A3x3_Saver
{
    // Класс Step1 - Самая простая библиотека на C#
    [ClassInterface(ClassInterfaceType.AutoDual)]
    public class Step1
    {
        // Имя библиотеки
        [return: MarshalAs(UnmanagedType.BStr)]
        public string GetLibraryName()  {  return "Сохранение А3x3 в 3xA3";    }

        public KompasObject Kompas;
        public  string NewLibName = "A3x3_stamp.LYT";
        public string NewLibPath;
        public FileInfo LibraryFileInfo;
        public ILayoutSheets LayoutSheets;
        public IKompasDocument2D KompasDocument2D;
        public IKompasDocument KompasDocument;
        public IApplication KompasAPI;

        public KompasObject kompas;
        public ksDocument2D doc;

       

        // Головная функция библиотеки
        public void ExternalRunCommand([In] short command, [In] short mode, [In, MarshalAs(UnmanagedType.IDispatch)] object kompas_)
        {
            Kompas = (KompasObject)kompas_;
            KompasAPI = (IApplication)Kompas.ksGetApplication7();
            KompasDocument = KompasAPI.ActiveDocument;
            KompasDocument2D = (IKompasDocument2D)KompasAPI.ActiveDocument;

            LayoutSheets = KompasDocument.LayoutSheets;// ksM("Получены Листы");

            //библиотека оформлений находится в папке с библиотекой
            LibraryFileInfo = new FileInfo(Assembly.GetExecutingAssembly().Location);
            NewLibPath = LibraryFileInfo.DirectoryName + @"\" + NewLibName;
         

            //Добавляем два листа к существующему
            LayoutSheets.Add();
            LayoutSheets.Add();
            //получаем лист 1 и задаем ему новые параметры формата и оформления
            ILayoutSheet LayoutSheet1 = LayoutSheets.ItemByNumber[1];// ksM("Получен Лист 1");
            ISheetFormat SheetFormat1 = LayoutSheet1.Format;// ksM("Получен Формат листа");
            LayoutSheet1.LayoutLibraryFileName = "";
            LayoutSheet1.LayoutStyleNumber = 0;
            SheetFormat1.Format = ksDocumentFormatEnum.ksFormatA3;// ksM("Назначен формат А3");
            SheetFormat1.FormatMultiplicity = 1;// ksM("Кратность чертежа 1");
            SheetFormat1.VerticalOrientation = false;// ksM("Горизонтальная ориентация");
            LayoutSheet1.Update();

            //добавляем второй лист
            ILayoutSheet LayoutSheet2 = LayoutSheets.ItemByNumber[2];// ksM("Получен Лист 1");
            ISheetFormat SheetFormat2 = LayoutSheet2.Format;// ksM("Получен Формат листа");
            LayoutSheet2.LayoutLibraryFileName = "";
            LayoutSheet2.LayoutStyleNumber = 0;
            SheetFormat2.Format = ksDocumentFormatEnum.ksFormatA3;// ksM("Назначен формат А3");
            SheetFormat2.FormatMultiplicity = 1;// ksM("Кратность чертежа 1");
            SheetFormat2.VerticalOrientation = false;// ksM("Горизонтальная ориентация");
            LayoutSheet2.Update();


            //добавляем третий лист
            ILayoutSheet LayoutSheet3 = LayoutSheets.ItemByNumber[3];// ksM("Получен Лист 1");
            ISheetFormat SheetFormat3 = LayoutSheet3.Format;// ksM("Получен Формат листа");
            LayoutSheet3.LayoutLibraryFileName = NewLibPath;
            LayoutSheet3.LayoutStyleNumber = 3;
            SheetFormat3.Format = ksDocumentFormatEnum.ksFormatA3;// ksM("Назначен формат А3");
            SheetFormat3.FormatMultiplicity = 1;// ksM("Кратность чертежа 1");
            SheetFormat3.VerticalOrientation = false;// ksM("Горизонтальная ориентация");
            LayoutSheet3.Update();

            //получаем АПИ5 документ чтобы потом можно было в нем рисовать
            doc = (Document2D)Kompas.ActiveDocument2D();
         
            //получаем менеджер видов и слоев
            IViewsAndLayersManager ViewsAndLayersManager = KompasDocument2D.ViewsAndLayersManager;
            IViews Views = ViewsAndLayersManager.Views;// ksM("Получены виды");
                     
            //получаем текущий вид
            IView CurView = Views.ActiveView;
            //Создаем новый вид для рамки
            IView NewView = Views.Add(LtViewType.vt_Normal);
            NewView.Name = "Рамка чертежа";
            //NewView.Color = 33023;//цвет надо подбирать
            NewView.Scale = 1;
            NewView.Current = true;
            NewView.Update();
            //Создаем слой для рамки, чтобы его потом залочить
            ILayers Layers = NewView.Layers;
            Layers.Add();
            ILayer Layer = Layers.Layer[Layers.Count-1];
            Layer.Name = "Слой с рамкой чертежа";
            Layer.Background = true;
           
            Layer.Current = true;
            Layer.Update();


            //рисуем рамку
            doc.ksLineSeg(0, 0, 1260, 0, 2);
              doc.ksLineSeg(0, 0, 0, 297, 2);
              doc.ksLineSeg(0, 297, 1260,297, 2);
              doc.ksLineSeg(1260, 0, 1260, 297,2);
            doc.ksLineSeg(20, 5, 1255, 5, 1);
            doc.ksLineSeg(20, 5, 20, 292, 1);
            doc.ksLineSeg(20, 292, 1255, 292, 1);
            doc.ksLineSeg(1255, 5, 1255, 292, 1);
            //блокируем слой с рамкой
            Layers.Layer[0].Current = true;
            Layers.Layer[0].Update();
            Layers.Layer[Layers.Count - 1].Background = true;
            Layers.Layer[Layers.Count - 1].Update();
       
            //возвращаемся в исходный вид
            CurView.Current = true;
            CurView.Update();
        }
        public  void ksM(string text)
        {
            Kompas.ksMessage(text);
        }

        #region COM Registration
        // Эта функция выполняется при регистрации класса для COM
        // Она добавляет в ветку реестра компонента раздел Kompas_Library,
        // который сигнализирует о том, что класс является приложением Компас,
        // а также заменяет имя InprocServer32 на полное, с указанием пути.
        // Все это делается для того, чтобы иметь возможность подключить
        // библиотеку на вкладке ActiveX.
        [ComRegisterFunction]
        public static void RegisterKompasLib(Type t)
        {
            try
            {
                RegistryKey regKey = Registry.LocalMachine;
                string keyName = @"SOFTWARE\Classes\CLSID\{" + t.GUID.ToString() + "}";
                regKey = regKey.OpenSubKey(keyName, true);
                regKey.CreateSubKey("Kompas_Library");
                regKey = regKey.OpenSubKey("InprocServer32", true);
                regKey.SetValue(null, System.Environment.GetFolderPath(Environment.SpecialFolder.System) + @"\mscoree.dll");
                regKey.Close();
            }
            catch (Exception ex)
            {
               
                MessageBox.Show(string.Format("При регистрации класса для COM-Interop произошла ошибка:\n{0}", ex));
            }
        }

        // Эта функция удаляет раздел Kompas_Library из реестра
        [ComUnregisterFunction]
        public static void UnregisterKompasLib(Type t)
        {
            RegistryKey regKey = Registry.LocalMachine;
            string keyName = @"SOFTWARE\Classes\CLSID\{" + t.GUID.ToString() + "}";
            RegistryKey subKey = regKey.OpenSubKey(keyName, true);
            subKey.DeleteSubKey("Kompas_Library");
            subKey.Close();
        }
        #endregion
    }
}



Надеюсь объяснять как сохранить в растр, организовать цикл и выбор файлов не нужно?
+ Благодарностей: 2

sim68

Цитата: DesignЯR от 01.08.18, 12:56:43
В архиве исходник. Файл со стилем оформления должен находиться рядом с файлом библиотеки, или нужно будет вносить изменения в код.
DesignЯR, очень благодарен за готовый пример ! Я попробовал через него (вставил в свою программу этот блок) прогнать чертеж A3х3 и вот какой результат у меня получился - исходный чертеж и полученные jpg-файлы в архиве
Экспорт я выполнял так:
фрагмент кода после вашей разбивки на листы
//возвращаемся в исходный вид
                            CurView.Current = true;
                            CurView.Update();

// добавленный фрагмент кода для экспорта
// к этому моменту функция doc.ksGetDocumentPagesCount() возвращает 3 листа
          RasterFormatParam iRastFormatParam = (RasterFormatParam)doc.RasterFormatParam();
          iRastFormatParam.Init();
          iRastFormatParam.format = 2;    // 4 - TIF  (2 - JPG)
          iRastFormatParam.colorType = 0;
          iRastFormatParam.extResolution = 150;
          iRastFormatParam.extScale = 1;
          iRastFormatParam.greyScale = false;
          iRastFormatParam.colorBPP = 24;
          iRastFormatParam.multiPageOutput = true;
          iRastFormatParam.onlyThinLine = false;
          iRastFormatParam.rangeIndex = 0;

          doc.SaveAsToRasterFormat(m_fileName, iRastFormatParam);     // m_fileName - имя выходного файла
          doc.ksCloseDocument();

По итогу получается 3 jpg-файла, но на первом листе получается наложение, а последний пустой
Быть может из-за того, что на сборочном чертеже еще присутствует спецификация ?

ТрындецЪ

А3х3 это 3 шт А3 в вертикальной ориентации.