Создание пользовательского нестандартного формата листа

Автор Тема: Создание пользовательского нестандартного формата листа  (Прочитано 24314 раз)

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

Оффлайн Дмитрий ЗагорулькинАвтор темы

  • ADN
  • *
  • Сообщений: 2531
  • Карма: 737
Здравствуйте!
Все примеры по печати, которые нашел в справке и в devblog'ах основаны на использовании уже готовых форматов.
Нашел такой объект, как PlotConfig. Он больше всего напоминает то, что мне нужно. Беда в том, что прочитать можно какие угодно данные, а вот создать свои - не получается.
Вопрос: возможно ли создать нестандартный формат листа средствами NET?
Если на NET невозможно, то есть ли какой-то другой инструмент для этого?

Отмечено как Решение Дмитрий Загорулькин 08-10-2014, 14:53:16

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13882
  • Карма: 1787
  • Рыцарь ObjectARX
  • Skype: rivilis
Для создания нестандартного формата листа требуется возможность создания и редактирования 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-файлы, которые можно распаковать/изменить/запаковать. Это всё не документировано и может быть изменено в любой момент.
« Последнее редактирование: 11-10-2013, 22:52:02 от Александр Ривилис »
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн Дмитрий ЗагорулькинАвтор темы

  • ADN
  • *
  • Сообщений: 2531
  • Карма: 737
Да, этот способ я уже пытаюсь приспособить. Думал, может быть есть путь попрямее и попроще.
Было в нем пара непонятных мест, одно из них - назначение битов с 49 по 60 - разъяснилось благодаря указанным Вами ссылкам. Спасибо большое! Буду разбираться дальше. Надеюсь, это нельзя расценить как взлом AutoCAD?
То что нет возможности для создания форматов программно меня удивляет. Есть же утилита по редактированию pc3 в стандартной поставке (pc3exe.exe, pc3edit.dll), можно было бы сделать пару-тройку методов для программного доступа к ней.

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13882
  • Карма: 1787
  • Рыцарь ObjectARX
  • Skype: rivilis
Надеюсь, это нельзя расценить как взлом AutoCAD?
Нет. Это вполне законная операция, на уровне адаптации меню. Другое дело, что Autodesk не даёт API для этой операции.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн Владимир Шу

  • ADN Club
  • *****
  • Сообщений: 624
  • Карма: 158
    • ПГСу Бложик
Подниму эту тему, какой нибудь практический результат из всего этого получился?
У меня что-то с запаковкой не получается, толь кодировка не та, то ли что то другое, потому и спрашиваю.

Оффлайн Дмитрий ЗагорулькинАвтор темы

  • ADN
  • *
  • Сообщений: 2531
  • Карма: 737
Да, получилось. Уже год как пользуются коллеги. Сейчас работаю над ее усовершенствованием. По сути, все проблемы уже позади, осталось только грамотный интерфейс придумать для работы с пользовательскими форматами.
А с запаковкой я помню намучился прилично. Сейчас уже не вспомню, что у меня не получалось, но бился я долго. Даже уже готов был забросить :)
Кодировка там UTF-8. Но я пробовал делать Default - тоже работало.

Update: UTF-8 не подходит - не распознаются русские буквы.
« Последнее редактирование: 16-10-2014, 10:40:52 от Загорулькин Дмитрий »

Оффлайн Владимир Шу

  • ADN Club
  • *****
  • Сообщений: 624
  • Карма: 158
    • ПГСу Бложик
Уже хорошо, в верном направление иду...
Вот тут код с которым вожусь:
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 вроде бы проглатывает распакованный и снова запакованный файл.
Если где-то напортачил, поправьте меня пожалуйста.

Оффлайн Дмитрий ЗагорулькинАвтор темы

  • ADN
  • *
  • Сообщений: 2531
  • Карма: 737
Я другой библиотекой пользовался для ZLib - от ComponentAce: http://www.componentace.com/zlib_.NET.htm
Вот есть еще пример разработок, я про него говорил на DWG.RU - https://github.com/Allockse/PiaNO. Опять же, повторюсь, что нашел и поделился со мной этим Алексей (bargool), за что ему спасибо :)
Можно посмотреть, сравнить. Может быть, какие-то идеи почерпнуть. Или просто воспользоваться готовым решением.

Оффлайн Владимир Шу

  • ADN Club
  • *****
  • Сообщений: 624
  • Карма: 158
    • ПГСу Бложик
Спасибо за ссылку на репозитарий, ознакомился =о)
Вот тут все что нужно https://github.com/Allockse/PiaNO/blob/master/Serialization/PiaSerializer.cs
Как увидел код не сильно отличается от моего, вычислять размер запакованного я думал через создание временного файла, в репе это сделано через создание области в памяти... приму на вооружение этот подход.
Смотрю и учусь. Еще раз спасибо.

Оффлайн Дмитрий ЗагорулькинАвтор темы

  • ADN
  • *
  • Сообщений: 2531
  • Карма: 737
Кстати, забавный момент. Вот в коде из поста:
Код - 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 нормально "кушает" пересобранные файлы :)
Ну не смог я тогда осилить как получить эту контрольную сумму  ::)
А сейчас вот думаю - разбираться с этим или оставить уже как есть? :)

Оффлайн Владимир Шу

  • ADN Club
  • *****
  • Сообщений: 624
  • Карма: 158
    • ПГСу Бложик
Интересно. Посмотрел.
Без текстового заголовка - ругается.
Если размер упакованных данных указать меньше, чем есть на самом деле - ругается (Если больше, не ругается)
На то, что записано в 49-52 байтах AutoCAD ниразу не ругался.
Сейчас туда пишу такой строчкой:
Код - C# [Выбрать]
  1. fs_out.Write(BitConverter.GetBytes(new ZlibCodec(CompressionMode.Compress).Adler32), 0, 4);
ACAD не ругается, хотя по факту в файл пишется: 01 00 00 00
=)))

Оффлайн Дмитрий ЗагорулькинАвтор темы

  • ADN
  • *
  • Сообщений: 2531
  • Карма: 737
На то, что записано в 49-52 байтах AutoCAD ниразу не ругался.
... хотя по факту в файл пишется: 01 00 00 00
У меня вроде были проблемы, когда я произвольные значения записывал. Хотя это было давно, может и путаю уже что-то.
01 00 00 00 - это вроде как начальное значение контрольной суммы. Как я понимаю, надо его извлекать как-то из упаковывающего потока после завершения упаковки. В той библиотеке, которой я пользуюсь, не заложено такой возможности.

Оффлайн German

  • ADN Club
  • **
  • Сообщений: 84
  • Карма: 13
Update: UTF-8 не подходит - не распознаются русские буквы.
Русский так:
Код - C# [Выбрать]
  1. using (StreamReader sr = new StreamReader(zs, System.Text.Encoding.GetEncoding(1251)))

Оффлайн Дмитрий ЗагорулькинАвтор темы

  • ADN
  • *
  • Сообщений: 2531
  • Карма: 737
Да лучше все-таки, наверное, System.Text.Encoding.Default.

Оффлайн German

  • ADN Club
  • **
  • Сообщений: 84
  • Карма: 13
А чем лучше? Сам плоттер прописывает себя в pc3 с русским "... Оптимизированный драйвер - HP" и еще в парочке других мест. Пользователь увидит при выборе pc3, в случае System.Text.Encoding.Default, кучу вопросительных знаков.
Или в Windows английской всплывет конкретная проблема с кодировкой?