Сообщество программистов Autodesk в СНГ

ADN Club => AutoCAD .NET API => Тема начата: Дмитрий Загорулькин от 11-10-2013, 11:54:05

Название: Создание пользовательского нестандартного формата листа
Отправлено: Дмитрий Загорулькин от 11-10-2013, 11:54:05
Здравствуйте!
Все примеры по печати, которые нашел в справке и в devblog'ах основаны на использовании уже готовых форматов.
Нашел такой объект, как PlotConfig. Он больше всего напоминает то, что мне нужно. Беда в том, что прочитать можно какие угодно данные, а вот создать свои - не получается.
Вопрос: возможно ли создать нестандартный формат листа средствами NET?
Если на NET невозможно, то есть ли какой-то другой инструмент для этого?
Название: Re: Создание пользовательского нестандартного формата листа
Отправлено: Александр Ривилис от 11-10-2013, 22:37:59
Для создания нестандартного формата листа требуется возможность создания и редактирования pc3/pmp-файлов. Но доступных средств ни в каком из AutoCAD API для этого не существует. Так что я не вижу способа для программного создания нестандартного формата листа.
Впрочем, можешь почитать эти темы:
http://www.theswamp.org/index.php?topic=41529.0
http://www.theswamp.org/index.php?topic=37625.0
Если в двух словах, то pmp и pс3 файлы - это PIA-файлы, которые можно распаковать/изменить/запаковать. Это всё не документировано и может быть изменено в любой момент.
Название: Re: Создание пользовательского нестандартного формата листа
Отправлено: Дмитрий Загорулькин от 12-10-2013, 01:00:20
Да, этот способ я уже пытаюсь приспособить. Думал, может быть есть путь попрямее и попроще.
Было в нем пара непонятных мест, одно из них - назначение битов с 49 по 60 - разъяснилось благодаря указанным Вами ссылкам. Спасибо большое! Буду разбираться дальше. Надеюсь, это нельзя расценить как взлом AutoCAD?
То что нет возможности для создания форматов программно меня удивляет. Есть же утилита по редактированию pc3 в стандартной поставке (pc3exe.exe, pc3edit.dll), можно было бы сделать пару-тройку методов для программного доступа к ней.
Название: Re: Создание пользовательского нестандартного формата листа
Отправлено: Александр Ривилис от 12-10-2013, 02:40:32
Надеюсь, это нельзя расценить как взлом AutoCAD?
Нет. Это вполне законная операция, на уровне адаптации меню. Другое дело, что Autodesk не даёт API для этой операции.
Название: Re: Создание пользовательского нестандартного формата листа
Отправлено: Владимир Шу от 15-10-2014, 17:28:48
Подниму эту тему, какой нибудь практический результат из всего этого получился?
У меня что-то с запаковкой не получается, толь кодировка не та, то ли что то другое, потому и спрашиваю.
Название: Re: Создание пользовательского нестандартного формата листа
Отправлено: Дмитрий Загорулькин от 15-10-2014, 17:48:30
Да, получилось. Уже год как пользуются коллеги. Сейчас работаю над ее усовершенствованием. По сути, все проблемы уже позади, осталось только грамотный интерфейс придумать для работы с пользовательскими форматами.
А с запаковкой я помню намучился прилично. Сейчас уже не вспомню, что у меня не получалось, но бился я долго. Даже уже готов был забросить :)
Кодировка там UTF-8. Но я пробовал делать Default - тоже работало.

Update: UTF-8 не подходит - не распознаются русские буквы.
Название: Re: Создание пользовательского нестандартного формата листа
Отправлено: Владимир Шу от 15-10-2014, 18:31:13
Уже хорошо, в верном направление иду...
Вот тут код с которым вожусь:
https://github.com/BoxaShu/unzip_pc3
Код - C# [Выбрать]
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using System.Threading.Tasks;
  6. using System.IO;
  7. using Ionic.Zlib;
  8.  
  9. namespace unzip_pc3
  10. {
  11.     class Program
  12.     {
  13.         // args[0] - ключ для паковки / распаковки
  14.         //              e - распаковать / extract
  15.         //              c - запаковать / compress
  16.         // args[1] - путь до файла, который будем паковать или распаковывать / path to file
  17.        
  18.         static void Main(string[] args)
  19.         {
  20.             //' на основе вот этого топака : http://www.theswamp.org/index.php?topic=41529.0
  21.  
  22.  
  23.             if(args.Length == 2){
  24.                 // тут распаковываем архивчик
  25.                 if (args[0] == "e")
  26.                 {
  27.                     if(File.Exists(args[1]))
  28.                     {
  29.                         string fileName =  args[1];
  30.                         using (FileStream fs = File.Open(fileName, FileMode.Open, FileAccess.Read))
  31.                         {
  32.                             fs.Seek(60L, SeekOrigin.Begin);
  33.  
  34.                             using (ZlibStream zs = new ZlibStream(fs, CompressionMode.Decompress))
  35.                             {
  36.                                 using (StreamReader sr = new StreamReader(zs))
  37.                                 {
  38.                                     //тут текстово содержание файла
  39.                                     string s = sr.ReadToEnd();
  40.  
  41.                                     using (FileStream fs_out = File.Open(fileName + ".txt", FileMode.Create, FileAccess.ReadWrite))
  42.                                     {
  43.                                         fs_out.Write(Encoding.Default.GetBytes(s), 0, Encoding.Default.GetBytes(s).Length);
  44.                                     }
  45.                                 }
  46.                             }
  47.                         }
  48.                     }
  49.                 }
  50.  
  51.                 // Тут запаковываем все обратно
  52.                 if (args[0] == "c")
  53.                 {
  54.                     if (File.Exists(args[1]))
  55.                     {
  56.                         string fileName = args[1];
  57.                         using (FileStream fs = File.Open(fileName, FileMode.Open, FileAccess.Read))
  58.                         {
  59.                             using (StreamReader sr = new StreamReader(fs))
  60.                             {
  61.                                 String pref_s = "PIAFILEVERSION_2.0,PC3VER1,compress\r\npmzlibcodec";
  62.  
  63.                                 /*
  64.                                 is a good starting point, but contains several errors/lack of information
  65.                                 The header size is 60 No 59
  66.                                 bytes 49->52 = ZlibCodec.Adler32
  67.                                 bytes 53->56 = decompresse stream size
  68.                                 bytes 57->60 = compressed stream size
  69.                                 Эти данные(байты) должны вычеслятся
  70.                                 */
  71.                                 Byte[] ZlibCodec_Adler32 = { 157, 94, 173, 006 };
  72.                                 long decompresse_stream_size = fs.Length;
  73.                                 long compressed_stream_size = fs.Length;
  74.                                 String s = sr.ReadToEnd();
  75.  
  76.                                 using (FileStream fs_out = File.Open(fileName + ".pc3", FileMode.Create, FileAccess.ReadWrite))
  77.                                 {
  78.                                     using (ZlibStream zs = new ZlibStream(fs_out, CompressionMode.Compress,
  79.                                                                              CompressionLevel.BestCompression, false))
  80.                                     {
  81.                                         // тут надо получить размер запакованных данных и сохранить в compressed_stream_size
  82.                                         //но как это сделать пока не знаю
  83.                                         fs_out.Write(Encoding.Default.GetBytes(pref_s), 0, Encoding.Default.GetBytes(pref_s).Length);
  84.                                         fs_out.Write(ZlibCodec_Adler32, 0, 4);
  85.                                         fs_out.Write(BitConverter.GetBytes(decompresse_stream_size), 0, 4);
  86.                                         fs_out.Write(BitConverter.GetBytes(compressed_stream_size), 0, 4);
  87.  
  88.                                         zs.Write(Encoding.Default.GetBytes(s), 0, Encoding.Default.GetBytes(s).Length);
  89.                                     }
  90.                                 }
  91.                             }
  92.                         }
  93.                     }
  94.                 }
  95.              }
  96.         }
  97.     }
  98. }
  99.  
Пока не понял как получить размер запакованных данных..
Но AutoCAD вроде бы проглатывает распакованный и снова запакованный файл.
Если где-то напортачил, поправьте меня пожалуйста.
Название: Re: Создание пользовательского нестандартного формата листа
Отправлено: Дмитрий Загорулькин от 15-10-2014, 18:57:34
Я другой библиотекой пользовался для ZLib - от ComponentAce: http://www.componentace.com/zlib_.NET.htm
Вот есть еще пример разработок, я про него говорил на DWG.RU - https://github.com/Allockse/PiaNO. Опять же, повторюсь, что нашел и поделился со мной этим Алексей (bargool), за что ему спасибо :)
Можно посмотреть, сравнить. Может быть, какие-то идеи почерпнуть. Или просто воспользоваться готовым решением.
Название: Re: Создание пользовательского нестандартного формата листа
Отправлено: Владимир Шу от 15-10-2014, 20:37:34
Спасибо за ссылку на репозитарий, ознакомился =о)
Вот тут все что нужно https://github.com/Allockse/PiaNO/blob/master/Serialization/PiaSerializer.cs
Как увидел код не сильно отличается от моего, вычислять размер запакованного я думал через создание временного файла, в репе это сделано через создание области в памяти... приму на вооружение этот подход.
Смотрю и учусь. Еще раз спасибо.
Название: Re: Создание пользовательского нестандартного формата листа
Отправлено: Дмитрий Загорулькин от 15-10-2014, 22:13:51
Кстати, забавный момент. Вот в коде из поста:
Код - C# [Выбрать]
  1. Byte[] ZlibCodec_Adler32 = { 157, 94, 173, 006 };
А это из гитхабовского кода:
Код - C# [Выбрать]
  1. BitConverter.GetBytes(deflater.Adler).CopyTo(checkSum, 0); // Adler
У меня же в коде уже почти год вот такое:
Код - C# [Выбрать]
  1. bytesLst.AddRange(new byte[] { 255, 255, 255, 255 });
И AutoCAD нормально "кушает" пересобранные файлы :)
Ну не смог я тогда осилить как получить эту контрольную сумму  ::)
А сейчас вот думаю - разбираться с этим или оставить уже как есть? :)
Название: Re: Создание пользовательского нестандартного формата листа
Отправлено: Владимир Шу от 16-10-2014, 09:52:52
Интересно. Посмотрел.
Без текстового заголовка - ругается.
Если размер упакованных данных указать меньше, чем есть на самом деле - ругается (Если больше, не ругается)
На то, что записано в 49-52 байтах AutoCAD ниразу не ругался.
Сейчас туда пишу такой строчкой:
Код - C# [Выбрать]
  1. fs_out.Write(BitConverter.GetBytes(new ZlibCodec(CompressionMode.Compress).Adler32), 0, 4);
ACAD не ругается, хотя по факту в файл пишется: 01 00 00 00
=)))
Название: Re: Создание пользовательского нестандартного формата листа
Отправлено: Дмитрий Загорулькин от 16-10-2014, 10:35:51
На то, что записано в 49-52 байтах AutoCAD ниразу не ругался.
... хотя по факту в файл пишется: 01 00 00 00
У меня вроде были проблемы, когда я произвольные значения записывал. Хотя это было давно, может и путаю уже что-то.
01 00 00 00 - это вроде как начальное значение контрольной суммы. Как я понимаю, надо его извлекать как-то из упаковывающего потока после завершения упаковки. В той библиотеке, которой я пользуюсь, не заложено такой возможности.
Название: Re: Создание пользовательского нестандартного формата листа
Отправлено: German от 04-12-2014, 12:56:13
Update: UTF-8 не подходит - не распознаются русские буквы.
Русский так:
Код - C# [Выбрать]
  1. using (StreamReader sr = new StreamReader(zs, System.Text.Encoding.GetEncoding(1251)))
Название: Re: Создание пользовательского нестандартного формата листа
Отправлено: Дмитрий Загорулькин от 04-12-2014, 13:23:09
Да лучше все-таки, наверное, System.Text.Encoding.Default.
Название: Re: Создание пользовательского нестандартного формата листа
Отправлено: German от 04-12-2014, 13:55:48
А чем лучше? Сам плоттер прописывает себя в pc3 с русским "... Оптимизированный драйвер - HP" и еще в парочке других мест. Пользователь увидит при выборе pc3, в случае System.Text.Encoding.Default, кучу вопросительных знаков.
Или в Windows английской всплывет конкретная проблема с кодировкой?
Название: Re: Создание пользовательского нестандартного формата листа
Отправлено: Дмитрий Загорулькин от 04-12-2014, 14:12:56
Ну я пробовал. У меня в программе уже больше года именно так - проблем нет никаких с русскими символами. Потому как Default в русской Windows - это koi8-r, если мне память не изменяет.
Название: Re: Создание пользовательского нестандартного формата листа
Отправлено: Александр Ривилис от 04-12-2014, 14:59:29
Потому как Default в русской Windows - это koi8-r, если мне память не изменяет.
Неа. Windows-1251 (https://ru.wikipedia.org/wiki/Windows-1251)
Название: Re: Создание пользовательского нестандартного формата листа
Отправлено: Дмитрий Загорулькин от 04-12-2014, 15:07:42
Спасибо! Значит, изменяет :)
Тогда вообще все прозаичнее...
Название: Re: Создание пользовательского нестандартного формата листа
Отправлено: simson43 от 02-11-2018, 21:38:02
Для создания нестандартного формата листа требуется возможность создания и редактирования pc3/pmp-файлов. Но доступных средств ни в каком из AutoCAD API для этого не существует.
все еще не существует?(
Название: Re: Создание пользовательского нестандартного формата листа
Отправлено: Александр Ривилис от 02-11-2018, 21:40:32
Для создания нестандартного формата листа требуется возможность создания и редактирования pc3/pmp-файлов. Но доступных средств ни в каком из AutoCAD API для этого не существует.
все еще не существует?(
Нет и думаю, что существовать никогда не будет внутри AutoCAD API.