Площадь Polyline и Hatch

Автор Тема: Площадь Polyline и Hatch  (Прочитано 20814 раз)

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

Тема содержит сообщение с Решением. Нажмите здесь чтобы посмотреть его.

Оффлайн AndreyАвтор темы

  • ADN Club
  • Сообщений: 33
  • Карма: 0
Площадь Polyline и Hatch
« : 28-05-2014, 11:48:38 »
Добрый день!
Необходимо получить площади Polyline и Hatch. Вроде ничего сложного, т.к. оба объекта имеют свойства Area.
Но...
Если полилиния не пересекает саму себя, то проблем нет.





Если есть пересечение, то площадь не соответствует значению в Property.





С площадью заливок тоже не понятно. При создании заливки из полилинии - значение Area отсутствует.
Код - C# [Выбрать]
  1. Polyline pl = tr.GetObject(ids[i], OpenMode.ForWrite) as Polyline;
  2. if (!plClosed)
  3.     pl.Closed = true;
  4. ObjectIdCollection acObjIdColl = new ObjectIdCollection();
  5. acObjIdColl.Add(pl.ObjectId);
  6. Hatch acHatch = new Hatch();
  7. acBlkTblRec.AppendEntity(acHatch);
  8. tr.AddNewlyCreatedDBObject(acHatch, true);
  9. acHatch.SetDatabaseDefaults();
  10. acHatch.SetHatchPattern(HatchPatternType.PreDefined, "ANSI31");
  11. acHatch.Associative = false;
  12. acHatch.AppendLoop(HatchLoopTypes.Outermost, acObjIdColl);
  13. acHatch.EvaluateHatch(true);
  14.  





При создании заливки в ручную проблем нет.



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

  • Administrator
  • *****
  • Сообщений: 13830
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: Площадь Polyline и Hatch
« Ответ #1 : 28-05-2014, 12:22:08 »
Если есть пересечение, то площадь не соответствует значению в Property.
Если есть самопересечение, то площадь не имеет смысла. Да и не думаю, что с такими полилиниями имеет смысл работать. Я бы сообщил пользователю, что полилиния некорректная. А на рисунках у тебя вообще как я понял разомкнутые полилинии.
Что касается штриховок, то площадь у них есть и при создании программно.
Нужен полный код, пример полилинии из которой создаешь штриховку (в dwg-файле), версия AutoCAD
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн AndreyАвтор темы

  • ADN Club
  • Сообщений: 33
  • Карма: 0
Re: Площадь Polyline и Hatch
« Ответ #2 : 28-05-2014, 12:51:35 »
Работать с такими полилиниями есть смысл: необходимо получить программу суммирования длин и площадей выбранных полилиний.
Т.к. с area полилиний не получилось решил пробовать через создание штриховок.
Вне зависимости от разомкнутости и самопересечения - поле area даёт точную характеристику.
Версия 2014.
         
Код - C# [Выбрать]
  1.    DocumentCollection acDocMgr = acApp.DocumentManager;
  2.             Document acDoc = acDocMgr.MdiActiveDocument;
  3.             Database acCurDb = acDoc.Database;
  4.             Editor ed = acDoc.Editor;
  5.             int polies = 0;
  6.             double totalArea = 0;
  7.             double totalLength = 0;
  8.             using (DocumentLock docLock = acDoc.LockDocument())
  9.             {
  10.                 using (Transaction tr = acCurDb.TransactionManager.StartTransaction())
  11.                 {
  12.                     BlockTable acBlkTbl = tr.GetObject(acCurDb.BlockTableId, OpenMode.ForRead) as BlockTable;
  13.                     BlockTableRecord acBlkTblRec = tr.GetObject(acBlkTbl[BlockTableRecord.ModelSpace], OpenMode.ForWrite) as BlockTableRecord;
  14.  
  15.                     TypedValue[] filList = new TypedValue[1] { new TypedValue((int)DxfCode.Start, "LWPOLYLINE") };
  16.                     SelectionFilter filter = new SelectionFilter(filList);
  17.                     PromptSelectionOptions opts = new PromptSelectionOptions();
  18.                     opts.MessageForAdding = "Select polylines: ";
  19.                     PromptSelectionResult res = ed.GetSelection(opts, filter);
  20.                      if (res.Status != PromptStatus.OK)
  21.                         return;
  22.                     SelectionSet selSet = res.Value;
  23.                     ObjectId[] ids = selSet.GetObjectIds();
  24.                     for (int i = 0; i < ids.Length; i++)
  25.                     {
  26.                         Polyline pl = tr.GetObject(ids[i], OpenMode.ForWrite) as Polyline;
  27.                         totalLength += pl.Length;
  28.                         bool plClosed = pl.Closed;
  29.  
  30.                         if (!plClosed)
  31.                             pl.Closed = true;
  32.                         ObjectIdCollection acObjIdColl = new ObjectIdCollection();
  33.                         acObjIdColl.Add(pl.ObjectId);
  34.  
  35.                         Hatch acHatch = new Hatch();
  36.                         acBlkTblRec.AppendEntity(acHatch);
  37.                         tr.AddNewlyCreatedDBObject(acHatch, true);
  38.  
  39.                         acHatch.SetDatabaseDefaults();
  40.                         acHatch.SetHatchPattern(HatchPatternType.PreDefined, "ANSI31");
  41.                         acHatch.Associative = false;
  42.                         acHatch.AppendLoop(HatchLoopTypes.Outermost, acObjIdColl);
  43.                         acHatch.EvaluateHatch(true);
  44.                         totalArea += acHatch.Area;
  45.  
  46.                         if (!plClosed)
  47.                             pl.Closed = false;
  48.  
  49.                         pl.Highlight();
  50.                         polies++;
  51.                     }
  52.                     ed.SetImpliedSelection(ids);
  53.                     tr.Commit();
  54.                 }
  55.                 totalLength = Math.Round(totalLength, 4);
  56.                 totalArea = Math.Round(totalArea, 4);
  57.                 ed.WriteMessage("\nPolylines - {0}. Total Length = {1}. Total Area = {2}.",
  58.                            polies.ToString(), totalLength.ToString(), totalArea.ToString());

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

  • Administrator
  • *****
  • Сообщений: 13830
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: Площадь Polyline и Hatch
« Ответ #3 : 28-05-2014, 13:38:05 »
Попробуй без штриховки:
Код - C# [Выбрать]
  1. using System;
  2. using Autodesk.AutoCAD.Runtime;
  3. using Autodesk.AutoCAD.ApplicationServices;
  4. using Autodesk.AutoCAD.DatabaseServices;
  5. using Autodesk.AutoCAD.Geometry;
  6. using Autodesk.AutoCAD.EditorInput;
  7. using Autodesk.AutoCAD.Interop;
  8. using Autodesk.AutoCAD.Interop.Common;
  9. using AcRx = Autodesk.AutoCAD.Runtime;
  10. using AcAp = Autodesk.AutoCAD.ApplicationServices;
  11. using AcDb = Autodesk.AutoCAD.DatabaseServices;
  12. using AcGe = Autodesk.AutoCAD.Geometry;
  13. using AcEd = Autodesk.AutoCAD.EditorInput;
  14. using AcInt = Autodesk.AutoCAD.Interop;
  15. using AcIntCom = Autodesk.AutoCAD.Interop.Common;
  16.  
  17. [assembly: CommandClass(typeof(TestArea.MyCommands))]
  18.  
  19. namespace TestArea
  20. {
  21.   public class MyCommands
  22.   {
  23.     [CommandMethod("TestArea", CommandFlags.Modal | CommandFlags.UsePickSet | CommandFlags.Redraw)]
  24.     public void test()
  25.     {
  26.       DocumentCollection acDocMgr = AcAp.Application.DocumentManager;
  27.       Document acDoc = acDocMgr.MdiActiveDocument;
  28.       Database acCurDb = acDoc.Database;
  29.       Editor ed = acDoc.Editor;
  30.       int polies = 0;
  31.       double totalArea = 0, totalAreaCOM = 0;
  32.       double totalLength = 0;
  33.       ObjectId[] ids;
  34.       using (DocumentLock docLock = acDoc.LockDocument()) {
  35.         using (Transaction tr = acCurDb.TransactionManager.StartTransaction()) {
  36.           TypedValue[] filList = new TypedValue[1] { new TypedValue((int)DxfCode.Start, "LWPOLYLINE") };
  37.           SelectionFilter filter = new SelectionFilter(filList);
  38.           PromptSelectionOptions opts = new PromptSelectionOptions();
  39.           opts.MessageForAdding = "Select polylines: ";
  40.           PromptSelectionResult res = ed.GetSelection(opts, filter);
  41.           if (res.Status != PromptStatus.OK)
  42.             return;
  43.           SelectionSet selSet = res.Value;
  44.           ids = selSet.GetObjectIds();
  45.           for (int i = 0; i < ids.Length; i++) {
  46.             Polyline pl = tr.GetObject(ids[i], OpenMode.ForRead) as Polyline;
  47.             AcIntCom.AcadLWPolyline plCOM = pl.AcadObject as AcIntCom.AcadLWPolyline;
  48.             totalArea += pl.Area;
  49.             totalAreaCOM += plCOM.Area;
  50.             totalLength += pl.Length;
  51.             pl.Highlight();
  52.             polies++;
  53.           }
  54.           tr.Commit();
  55.         }
  56.       }
  57.       ed.SetImpliedSelection(ids);
  58.       totalLength = Math.Round(totalLength, 4);
  59.       totalArea = Math.Round(totalArea, 4);
  60.       ed.WriteMessage("\nPolylines - {0}. Total Length = {1}. Total Area = {2}.  Total Area COM = {3}.",
  61.                  polies.ToString(), totalLength.ToString(), totalArea.ToString(), totalAreaCOM.ToString());
  62.     }
  63.   }
  64. }
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

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

  • Administrator
  • *****
  • Сообщений: 13830
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: Площадь Polyline и Hatch
« Ответ #4 : 28-05-2014, 13:39:57 »
P.S.: Но если ты не будешь сообщать пользователю, что полилиния самопересекающаяся - это будет очень плохо.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн Андрей Бушман

  • ADN Club
  • *****
  • Сообщений: 2000
  • Карма: 163
  • Пишу программки...
    • Блог
  • Skype: Compositum78
Re: Площадь Polyline и Hatch
« Ответ #5 : 28-05-2014, 14:06:35 »
Код - C# [Выбрать]
  1. Document acDoc = acDocMgr.MdiActiveDocument;
  2. Database acCurDb = acDoc.Database;
  3. Editor ed = acDoc.Editor;
Рекомендую взять за правило выполнять проверку MdiActiveDocument на равенство null, прежде чем начинать работать с ним.

Оффлайн AndreyАвтор темы

  • ADN Club
  • Сообщений: 33
  • Карма: 0
Re: Площадь Polyline и Hatch
« Ответ #6 : 28-05-2014, 14:36:40 »
Спасибо, работает! Есть  какая либо документация о разнице объектов NET и COM?
P.S.: Но если ты не будешь сообщать пользователю, что полилиния самопересекающаяся - это будет очень плохо.
В моём случае могут быть контуры одной полилинией

Заливки. Сейчас заметил, что заливки, полученные из MPolygon (по предыдущей теме) тоже получаются без геометрии Area.
Если их создавать как COM
Код - C# [Выбрать]
  1. Hatch h = new Hatch();
  2. AcIntCom.AcadHatch acHatch = h.AcadObject as AcIntCom.AcadHatch;
то как добавлять в транзакцию? Или есть другие способы?

Оффлайн AndreyАвтор темы

  • ADN Club
  • Сообщений: 33
  • Карма: 0
Re: Площадь Polyline и Hatch
« Ответ #7 : 28-05-2014, 14:39:24 »
Рекомендую взять за правило выполнять проверку MdiActiveDocument на равенство null, прежде чем начинать работать с ним.
Буду иметь в виду.

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

  • Administrator
  • *****
  • Сообщений: 13830
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: Площадь Polyline и Hatch
« Ответ #8 : 28-05-2014, 14:43:14 »
Спасибо, работает! Есть  какая либо документация о разнице объектов NET и COM?
Есть документация по AutoCAD AciveX/COM API и есть по AutoCAD .NET API. Это независимые API, но имеют некоторое пересечение по функциональности.
Заливки. Сейчас заметил, что заливки, полученные из MPolygon (по предыдущей теме) тоже получаются без геометрии Area.
Странно, но почему так я предположить не могу.
то как добавлять в транзакцию? Или есть другие способы?
Зачем? По этим обрывкам мыслей и кода я не могу понять что ты собираешься получить в конце.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн AndreyАвтор темы

  • ADN Club
  • Сообщений: 33
  • Карма: 0
Re: Площадь Polyline и Hatch
« Ответ #9 : 28-05-2014, 16:07:53 »
что ты собираешься получить в конце.
Получить надо Hatch из Polyline или MPolygon с геометрией Area
Код
Код - C# [Выбрать]
  1. MPolygon plg = trans.GetObject(id, OpenMode.ForWrite, false) as AcDb.MPolygon;
  2. Hatch acHatch = plg.Hatch.Clone() as Hatch;
  3. BlockTblRec.AppendEntity(acHatch);
  4. trans.AddNewlyCreatedDBObject(acHatch, true);
и
Код - C# [Выбрать]
  1. Polyline pl = tr.GetObject(ids[i], OpenMode.ForWrite) as Polyline;
  2. bool plClosed = pl.Closed;
  3. if (!plClosed)
  4.    pl.Closed = true;
  5. ObjectIdCollection acObjIdColl = new ObjectIdCollection();
  6. acObjIdColl.Add(pl.ObjectId);
  7. Hatch acHatch = new Hatch();
  8. acBlkTblRec.AppendEntity(acHatch);
  9. tr.AddNewlyCreatedDBObject(acHatch, true);
  10. acHatch.SetDatabaseDefaults();
  11. acHatch.SetHatchPattern(HatchPatternType.PreDefined, "ANSI31");
  12. acHatch.Associative = false;
  13. acHatch.AppendLoop(HatchLoopTypes.Outermost, acObjIdColl);
  14. acHatch.EvaluateHatch(true);
Не позволяют этого сделать
Можно ли решить эту задачу с помощью COM? Если да, то каким образом объекты COM подтверждаются в транзакции?

Оффлайн Андрей Бушман

  • ADN Club
  • *****
  • Сообщений: 2000
  • Карма: 163
  • Пишу программки...
    • Блог
  • Skype: Compositum78
Re: Площадь Polyline и Hatch
« Ответ #10 : 28-05-2014, 16:19:44 »
каким образом объекты COM подтверждаются в транзакции?
Несколько раз прочёл, но так и не понял этой фразы.

Оффлайн Дима_

  • ADN Club
  • ****
  • Сообщений: 473
  • Карма: 66
Re: Площадь Polyline и Hatch
« Ответ #11 : 28-05-2014, 16:22:16 »
Если да, то каким образом объекты COM подтверждаются в транзакции?
Никаим - они друг о друге ничего не знают, все "общее"здесь - это COM может объявить о начале и конце отмены - метод Document'а Start/EndUndoMark.

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

  • Administrator
  • *****
  • Сообщений: 13830
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: Площадь Polyline и Hatch
« Ответ #12 : 28-05-2014, 16:44:07 »
Получить надо Hatch из Polyline или MPolygon с геометрией Area
Похоже это в общем случае нереально. Я посмотрел что штриховки (Hatch) достаточно часто не имеют площади. Так что считать тебе придется самостоятельно не полагаясь на свойство Area (ни из AutoCAD .NET API, ни из AutoCAD ActiveX/COM). Во всяком случае если они приводят к exception или значения Hatch.Area и AcadHatch.Area не совпадают.
Алгоритма полного у меня нет, но эти статьи могут помочь:
Периметр штриховки с помощью ObjectARX и .NET API
Как восстановить потерянные границы штриховки?
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн Андрей Бушман

  • ADN Club
  • *****
  • Сообщений: 2000
  • Карма: 163
  • Пишу программки...
    • Блог
  • Skype: Compositum78
Re: Площадь Polyline и Hatch
« Ответ #13 : 28-05-2014, 16:49:15 »
Ещё площади есть у областей (Region).

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

  • Administrator
  • *****
  • Сообщений: 13830
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: Площадь Polyline и Hatch
« Ответ #14 : 28-05-2014, 16:56:59 »
Ещё площади есть у областей (Region).
Насколько мне известно точность вычисления площади у Region значительно ниже, чем у Polyline/Hatch. Относительная погрешность не меньше чем 1e-6. Во всяком случае если мне не изменяет память.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение