AutoCAD .NET API: Рассечение штриховки.

Автор Тема: AutoCAD .NET API: Рассечение штриховки.  (Прочитано 9461 раз)

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

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

  • ADN OPEN
  • **
  • Сообщений: 95
  • Карма: 11
Этот код позволяет разрезать штриховку кажущимся пересечением, образованным замкнутым контуром, то есть тем, который визуально отображается на мониторе, плоскости штриховки и контура могут не совпадать, главное что бы было визуальное их пересечение. Для создания кода использовалось достаточно много кода с этого сайта.
« Последнее редактирование: 13-03-2023, 22:55:11 от Александр Ривилис »

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

  • ADN OPEN
  • **
  • Сообщений: 95
  • Карма: 11
Re: AutoCAD .NET API: Рассечение штриховки.
« Ответ #1 : 13-03-2023, 22:16:28 »
Ух блин, видимо какое то ограничение на длину сообщений. в предварительном просмотре все было нормально, а тут обрезало, надо делить на куски, как отредактировать не вижу :(

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

  • ADN OPEN
  • **
  • Сообщений: 95
  • Карма: 11
Re: AutoCAD .NET API: Рассечение штриховки.
« Ответ #2 : 13-03-2023, 22:23:41 »
Первая часть кода

Код - C# [Выбрать]
  1. using Autodesk.AutoCAD.ApplicationServices;
  2. using Autodesk.AutoCAD.DatabaseServices;
  3. using Autodesk.AutoCAD.EditorInput;
  4. using Autodesk.AutoCAD.Geometry;
  5. using Autodesk.AutoCAD.Runtime;
  6. using System;
  7. using System.Collections.Generic;
  8. using System.Reflection;
  9.  
  10. namespace Trim_objects
  11. {
  12.     public class CurHatch
  13.     {    
  14.         [CommandMethod("cut_hatch")]
  15.         public void c_hatch()
  16.         {
  17.             ObjectId plId = GetObjectId(new List<string> { "acdbpolyline", "acdbcircle" }, "Выберите замкнутый секущий контур");
  18.             if (plId == ObjectId.Null ) return;
  19.             ObjectId hId = GetObjectId(new List<string> { "acdbhatch" }, "Выберите разрезаемую штриховку");
  20.             if (hId == ObjectId.Null) return;
  21.             CutHatch(plId, hId);
  22.         }
  23.         /// <summary>
  24.         /// Основная команда, режет штриховку возвращает списко ObjectId полученных штриховок
  25.         /// </summary>
  26.         /// <param name="plId">ObjectId разрезающего контура</param>
  27.         /// <param name="hId">ObjectId разрезаемой штриховки</param>
  28.         public List<ObjectId> CutHatch(ObjectId plId, ObjectId hId)
  29.         {    
  30.             List<ObjectId> result = new List<ObjectId>();
  31.             //работаем сразу в транзокции и таблице так как частенько придется что-то доставать или что-то записывать
  32.             using (Transaction tr = HostApplicationServices.WorkingDatabase.TransactionManager.StartTransaction())
  33.             {
  34.                 using (BlockTableRecord ms = tr.GetObject(HostApplicationServices.WorkingDatabase.CurrentSpaceId, OpenMode.ForWrite, false, true) as BlockTableRecord)
  35.                 {
  36.                     using (Hatch hatch = tr.GetObject(hId, OpenMode.ForWrite, false, true) as Hatch)
  37.                     {
  38.                         //получаем план штриховки
  39.                         Plane plane = hatch.GetPlane();
  40.                         //получаем вектор текущего вида
  41.                         Vector3d vector = GetViewVector();
  42.                         //проверяем на самопересечение и замкнутость
  43.                         using (Curve pl1 = tr.GetObject(plId, OpenMode.ForRead, false, true) as Curve)
  44.                         using (Curve pl = pl1.GetProjectedCurve(plane, vector))
  45.                         using (Curve3d pl3d = pl.GetGeCurve())
  46.                         using (CurveCurveIntersector3d cuin = new CurveCurveIntersector3d(pl3d, pl3d, vector))
  47.                         {
  48.                             if (cuin.NumberOfIntersectionPoints > 0 | !pl3d.IsClosed())
  49.                             {
  50.                                 tr.Commit(); return new List<ObjectId> { ObjectId.Null };
  51.                             }
  52.                         }
  53.                         //получаем лупы из штриховки
  54.                         List<HatchLoop> loops = new List<HatchLoop>();
  55.                         for (int i = hatch.NumberOfLoops - 1; i >= 0; i--)
  56.                         {
  57.                             loops.Add(hatch.GetLoopAt(i));
  58.                         }
  59.                         //создаем кривые в чертеже для каждого лупа и записываем их в списки
  60.                         List<ObjectId> LoopCurve = new List<ObjectId>();
  61.                         foreach (HatchLoop loop in loops)
  62.                         {
  63.                             //получаем куски лупа
  64.                             LoopCurve.AddRange(GetCurveFromLoop(loop, plane, hatch));
  65.                         }
  66.                         //список удаляемых кривых лупов
  67.                         List<ObjectId> erList = new List<ObjectId>();
  68.                         //список добавляемых кривых в лупы
  69.                         List<ObjectId> addList = new List<ObjectId>();
  70.                         //список секущих точек
  71.                         List<Point3d> sPoints = new List<Point3d>();
  72.                         //разрезаем все контура в штриховке проекцией контура (которые контур рассекает)
  73.                         foreach (ObjectId id in LoopCurve)
  74.                         {
  75.                             //получаем кривую
  76.                             using (Curve cur = tr.GetObject(id, OpenMode.ForWrite, false, true) as Curve)
  77.                             {
  78.                                 //получаем точки пересечения
  79.                                 List<Point3d> points = IntersectPoints(plId, ObjectId.Null, null, cur.Clone() as Curve, plane, vector, false);
  80.                                 //если точки есть то разрезаем кривую, добавляем куски в список и удаляем разрезанную
  81.                                 if (points.Count > 0)
  82.                                 {
  83.                                     sPoints.AddRange(points);
  84.                                     using (Point3dCollection collection = new Point3dCollection())
  85.                                     {
  86.                                         foreach (Point3d point in points) collection.Add(point);
  87.                                         using (DBObjectCollection objects = cur.GetSplitCurves(collection))
  88.                                         {
  89.                                             foreach (Object obj in objects)
  90.                                             {
  91.                                                 using (Curve curve = obj as Curve)
  92.                                                 {
  93.                                                     if (curve != null)
  94.                                                     {
  95.                                                         addList.Add(ms.AppendEntity(curve));
  96.                                                         tr.AddNewlyCreatedDBObject(curve, true);
  97.                                                     }
  98.                                                 }
  99.                                             }
  100.                                         }
  101.                                     }
  102.                                     cur.Erase();
  103.                                     erList.Add(id);
  104.                                 }
  105.                             }
  106.                         }
  107.                         //если пересечений не было значит штриховку можно не трогать
  108.                         if (erList.Count == 0)
  109.                         {
  110.                             DeleteObj(LoopCurve);
  111.                             tr.Commit();
  112.                             return new List<ObjectId> { ObjectId.Null };
  113.                         }
  114.                         //если были то обновляем список кривых в лупах
  115.                         foreach (ObjectId id in erList) LoopCurve.Remove(id);
  116.                         LoopCurve.AddRange(addList);
  117.                         //создаем списки распределения кривых (других по идее быть не должно)
  118.                         //внутри
  119.                         List<Curve> inner = new List<Curve>();
  120.                         //снаружи
  121.                         List<Curve> outer = new List<Curve>();
  122.                         //создаем список с кусками пересекающей кривой, которые будем добавлять в лупы
  123.                         List<ObjectId> kontPartLstId = new List<ObjectId>();
  124.                         List<Curve> kontPartLst = new List<Curve>();
  125.                         List<Curve> kontPartLstCopy = new List<Curve>();
  126.                         //получаем контур в виде проекции на плоскость штриховки                    
  127.                         using (Curve pl1 = tr.GetObject(plId, OpenMode.ForRead, false, true) as Curve)
  128.                         using (Curve pl = pl1.GetProjectedCurve(plane, vector))
  129.                         {
  130.                             //распределяем куски лупов по спискам
  131.                             foreach (ObjectId id in LoopCurve)
  132.                             {
  133.                                 Curve c = tr.GetObject(id, OpenMode.ForRead, false, true) as Curve;
  134.                                 //после всех манипуляций тут должны быть только результаты 1 - 5
  135.                                 //если встретится что-то другое то скорее всего произошла какая-то ошибка и просто прекращаем
  136.                                 //если все нормально то все кривые распределятся по спискам кроме номера 3
  137.                                 //он просто игнорируется и никуда не идет, его заменят если что части контура
  138.                                 int res = PartIn(pl, c, plane, vector);
  139.                                 if (res == 0 | res == 6)
  140.                                 {
  141.                                     DeleteObj(LoopCurve);
  142.                                     tr.Commit();
  143.                                     return new List<ObjectId> { ObjectId.Null };
  144.                                 }
  145.                                 if (res == 1 | res == 4)
  146.                                 {
  147.                                     inner.Add(c);
  148.                                     continue;
  149.                                 }
  150.                                 if (res == 2 | res == 5)
  151.                                 {
  152.                                     outer.Add(c);
  153.                                     continue;
  154.                                 }
  155.                                 if (res == 3) continue;
  156.                             }
  157.                             //ищем куски разрезающей кривой
  158.                             //сортируем точки по разрезающей кривой
  159.                             sPoints = SortPoint(sPoints, pl);
  160.                             using (Point3dCollection collection = new Point3dCollection())
  161.                             {
  162.                                 foreach (Point3d point in sPoints) collection.Add(point);
  163.                                 using (DBObjectCollection objects = pl.GetSplitCurves(collection))
  164.                                 {
  165.                                     foreach (Object obj in objects)
  166.                                     {
  167.                                         using (Curve curve = obj as Curve)
  168.                                         {
  169.                                             if (curve != null)
  170.                                             {
  171.                                                 //проверяем находится ли кусок контура внутри штриховки
  172.                                                 int res = CurveInCurves(curve, LoopCurve, plane, vector, null);
  173.                                                 //если ошибка
  174.                                                 if (res == 0)
  175.                                                 {
  176.                                                     DeleteObj(LoopCurve);
  177.                                                     DeleteObj(kontPartLstId);
  178.                                                     tr.Commit();
  179.                                                     return new List<ObjectId> { ObjectId.Null };
  180.                                                 }
  181.                                                 //если внутри то добавляем на модель и в список
  182.                                                 if (res == 1)
  183.                                                 {
  184.                                                     kontPartLstId.Add(ms.AppendEntity(curve));
  185.                                                     tr.AddNewlyCreatedDBObject(curve, true);
  186.                                                 }
  187.                                             }
  188.                                         }
  189.                                     }
  190.                                 }
  191.                             }
  192.                             //получаем куски контура как кривые и создаем 2 списка для тех областей что внутри и для тех что снаружи
  193.                             List<ObjectId> nkontPartLstId = new List<ObjectId>();
  194.                             foreach (ObjectId objectId in kontPartLstId)
  195.                             {
  196.                                 Curve curve = tr.GetObject(objectId, OpenMode.ForRead, false, true) as Curve;
  197.                                 kontPartLst.Add(curve);
  198.                                 //добавляем копию на модель и в список
  199.                                 Curve curveCopy = curve.Clone() as Curve;
  200.                                 nkontPartLstId.Add(ms.AppendEntity(curveCopy));
  201.                                 tr.AddNewlyCreatedDBObject(curveCopy, true);
  202.                                 kontPartLstCopy.Add(curveCopy);
  203.                             }
  204.                             //добавляем ObjectId копий в общий список для последующего удаления
  205.                             kontPartLstId.AddRange(nkontPartLstId);
  206.                             //анализируем списки и составляем из кусков новые лупы
  207.                             inner.AddRange(kontPartLstCopy);
  208.                             List<List<ObjectId>> loopsId = GetNewLoops(inner);
  209.                             if (loopsId != null) result.Add(NewHatch(tr, ms, loopsId, hatch));
  210.                             else
  211.                             {
  212.                                 DeleteObj(LoopCurve);
  213.                                 DeleteObj(kontPartLstId);
  214.                                 tr.Commit();
  215.                                 return new List<ObjectId> { ObjectId.Null };
  216.                             }
  217.                             outer.AddRange(kontPartLst);
  218.                             loopsId = GetNewLoops(outer);
  219.                             if (loopsId != null) result.Add(NewHatch(tr, ms, loopsId, hatch));
  220.                             else
  221.                             {
  222.                                 DeleteObj(LoopCurve);
  223.                                 DeleteObj(kontPartLstId);
  224.                                 tr.Commit();
  225.                                 return new List<ObjectId> { ObjectId.Null };
  226.                             }
  227.                         }
  228.                         hatch.Erase();
  229.                     }
  230.                 }                
  231.                 tr.Commit();
  232.             }
  233.             return result;
  234.         }
  235.         /// <summary>
  236.         /// создает новые лупы из списка кусков путем объединения в замкнутые контуры
  237.         /// возвращает список со списками ObjectId, объекты в которых образуют замкнутый контур
  238.         /// </summary>
  239.         /// <param name="cur"></param>
  240.         /// <returns></returns>
  241.         private List<List<ObjectId>> GetNewLoops(List<Curve> cur)
  242.         {
  243.             List<List<ObjectId>> loopsId = new List<List<ObjectId>>();            
  244.             int stop = 0;            
  245.             while (cur.Count > 0)
  246.             {
  247.                 //на всякий случай выход из цикла
  248.                 stop++;
  249.                 if (stop > 2000)
  250.                 {
  251.                    return null;                    
  252.                 }
  253.                 //создаем список контуров лупа
  254.                 List<ObjectId> loop = new List<ObjectId>();
  255.                 //проверяем списки и составляем лупы, пока все не очистим    
  256.                 //берем первую кривую
  257.                 Curve curve = cur[0];
  258.                 loop.Add(curve.Id);
  259.                 cur.RemoveAt(0);
  260.                 //если она замкнута это готовый луп
  261.                 //добавляем в список готовых лупов удаляем из списка обрабатываемых и переходим к следующему
  262.                 if (curve.Closed == true | curve.StartPoint.Equals(curve.EndPoint))
  263.                 {
  264.                     loopsId.Add(loop);                    
  265.                     continue;
  266.                 }
  267.                 else
  268.                 {                  
  269.                     //получаем концы кривой
  270.                     Point3d k1 = curve.StartPoint;
  271.                     Point3d k2 = curve.EndPoint;
  272.                     //проходим по объектам пока не замкнем контур
  273.                     int stop2 = 0;
  274.                     while (!k1.Equals(k2))
  275.                     {
  276.                         //на всякий случай выход из цикла
  277.                         stop2++;
  278.                         if (stop2 > 2000)
  279.                         {
  280.                             return null;
  281.                         }        
  282.                         //проходим по контурам
  283.                         for (int i = 0; i < cur.Count; i++)
  284.                         {
  285.                             if (k1.Equals(cur[i].StartPoint))
  286.                             {
  287.                                 loop.Add(cur[i].Id);                                
  288.                                 k1 = cur[i].EndPoint;
  289.                                 cur.RemoveAt(i);
  290.                                 if (k1.Equals(k2))
  291.                                 {
  292.                                     loopsId.Add(loop);
  293.                                     break;
  294.                                 }                                    
  295.                                 continue;
  296.                             }
  297.                             if (k1.Equals(cur[i].EndPoint))
  298.                             {
  299.                                 loop.Add(cur[i].Id);                                
  300.                                 k1 = cur[i].StartPoint;
  301.                                 cur.RemoveAt(i);
  302.                                 if (k1.Equals(k2))
  303.                                 {
  304.                                     loopsId.Add(loop);
  305.                                     break;
  306.                                 }
  307.                                 continue;
  308.                             }
  309.                             if (k2.Equals(cur[i].StartPoint))
  310.                             {
  311.                                 loop.Add(cur[i].Id);                                
  312.                                 k2 = cur[i].EndPoint;
  313.                                 cur.RemoveAt(i);
  314.                                 if (k1.Equals(k2))
  315.                                 {
  316.                                     loopsId.Add(loop);
  317.                                     break;
  318.                                 }
  319.                                 continue;
  320.                             }
  321.                             if (k2.Equals(cur[i].EndPoint))
  322.                             {
  323.                                 loop.Add(cur[i].Id);                                
  324.                                 k2 = cur[i].StartPoint;
  325.                                 cur.RemoveAt(i);
  326.                                 if (k1.Equals(k2))
  327.                                 {
  328.                                     loopsId.Add(loop);
  329.                                     break;
  330.                                 }                              
  331.                             }                          
  332.                         }                        
  333.                     }                    
  334.                 }
  335.             }
  336.             return loopsId;
  337.         }        
  338.         /// <summary>
  339.         /// возвращает точку центра кривой
  340.         /// </summary>
  341.         /// <param name="ob"></param>
  342.         /// <returns></returns>
  343.         private Point3d GetCentr(Curve ob)
  344.         {
  345.             return ob.GetPointAtDist((ob.GetDistanceAtParameter(ob.StartParam) + ob.GetDistanceAtParameter(ob.EndParam)) / 2);
  346.         }
  347.         /// <summary>
  348.         /// строит штриховку из списка лупов в виде списков ObjecrId элементов используя как шаблон другую штриховку
  349.         /// возвращает ObjectId построенной штриховки если удалось
  350.         /// </summary>
  351.         /// <param name="tr"></param>
  352.         /// <param name="ms"></param>
  353.         /// <param name="loopsId"></param>
  354.         /// <param name="hatch"></param>
  355.         /// <returns></returns>
  356.         private ObjectId NewHatch(Transaction tr, BlockTableRecord ms, List<List<ObjectId>> loopsId, Hatch hatch)
  357.         {
  358.             ObjectId result = ObjectId.Null;
  359.             //переменная для фиксации результата
  360.             bool del = false;
  361.             using (Hatch h = new Hatch())
  362.             {
  363.                 using (Transaction tr2 = HostApplicationServices.WorkingDatabase.TransactionManager.StartTransaction())
  364.                 {
  365.                     result = ms.AppendEntity(h);
  366.                     tr2.AddNewlyCreatedDBObject(h, true);
  367.                     tr2.Commit();
  368.                 }
  369.                 //создаем новую штриховку
  370.                 h.Normal = hatch.Normal;
  371.                 h.Origin = hatch.Origin;  
  372.                 h.Elevation = hatch.Elevation;
  373.                 h.SetDatabaseDefaults();
  374.                 h.VisualStyleId = hatch.VisualStyleId;
  375.                 h.Color = hatch.Color;
  376.                 //тут все сложно, что бы все масштабы корректно отобразились
  377.                 //после их установки надо прописать h.SetHatchPattern(HatchPatternType.PreDefined, hatch.PatternName);
  378.                 //но если перед их установкой не прописать h.SetHatchPattern(hatch.PatternType, hatch.PatternName);
  379.                 //то угол штриховки установить не получится так как видимо базовый тип не предусматривает установки угла, выдает исключение
  380.                 h.SetHatchPattern(hatch.PatternType, hatch.PatternName);
  381.                 h.PatternAngle = hatch.PatternAngle;
  382.                 h.PatternScale = hatch.PatternScale;                              
  383.                 h.PatternDouble = hatch.PatternDouble;
  384.                 h.SetHatchPattern(HatchPatternType.PreDefined, hatch.PatternName);        
  385.                 h.Layer = hatch.Layer;
  386.                 h.Linetype = hatch.Linetype;
  387.                 h.LineWeight = hatch.LineWeight;
  388.                 h.LinetypeScale = hatch.LinetypeScale;
  389.                 h.Transparency = hatch.Transparency;                              
  390.                 //проходим по всем лупам в списке
  391.                 foreach (List<ObjectId> loopId in loopsId)
  392.                 {
  393.                     if (loopId.Count == 0) continue;
  394.                     //если ошибок не было то вставляем луп
  395.                     if (!del)
  396.                     {
  397.                         //создаем из списка коллекцию
  398.                         using (ObjectIdCollection lId = new ObjectIdCollection())
  399.                         {
  400.                             foreach (ObjectId curId in loopId) lId.Add(curId);
  401.                             //пробуем добавить коллекцию в штриховку
  402.                             try
  403.                             {
  404.                                 h.AppendLoop(HatchLoopTypes.Default, lId);
  405.                             }
  406.                             catch
  407.                             {
  408.                                 //если не удалось то удаляем штриховку и возвращаем ObjectId.Null
  409.                                 del = true;
  410.                             }
  411.                         }
  412.                     }
  413.                     //удаляем куски лупа
  414.                     foreach (ObjectId curId in loopId)
  415.                         using (Curve cur = tr.GetObject(curId, OpenMode.ForWrite, false, true) as Curve)
  416.                             cur.Erase();                    
  417.                 }              
  418.                 //если произошла какая-то ошибка то удаляем штриховку
  419.                 if (del)
  420.                 {
  421.                     h.Erase();
  422.                     return ObjectId.Null;
  423.                 }                  
  424.             }
  425.             return result;
  426.         }        
  427.         /// <summary>
  428.         /// возвращает вектор текущего вида в wcs
  429.         /// </summary>
  430.         /// <returns></returns>
  431.         private Vector3d GetViewVector()
  432.         {
  433.             if (System.Convert.ToInt32(Application.GetSystemVariable("WORLDUCS")) == 0)
  434.             {
  435.                 //если установлена ucs то получаем вектор из преобразованной точки
  436.                 Point3d vpoint = (Point3d)Application.GetSystemVariable("VIEWDIR");
  437.                 return vpoint.GetAsVector().TransformBy(Application.DocumentManager.MdiActiveDocument.Editor.CurrentUserCoordinateSystem).GetNormal();
  438.             }
  439.             else
  440.             {
  441.                 Point3d vpoint = (Point3d)Application.GetSystemVariable("VIEWDIR");
  442.                 return vpoint.GetAsVector().GetNormal();
  443.             }
  444.         }
  445.         /// <summary>
  446.         /// сортирует точки находящиеся на кривой от начала кривой к концу
  447.         /// </summary>
  448.         /// <param name="result">список точек</param>
  449.         /// <param name="curve">кривая</param>
  450.         /// <returns></returns>
  451.         private List<Point3d> SortPoint(List<Point3d> result, Curve curve)
  452.         {
  453.             if (result.Count > 1)
  454.             {
  455.                 List<Point3d> sorted_coll = new List<Point3d>();
  456.                 while (result.Count > 0)
  457.                 {
  458.                     Point3d? minPoint = null;
  459.                     double? min = null;
  460.                     for (int i = 0; i < result.Count; i++)
  461.                     {
  462.                         double dist = curve.GetDistAtPoint(result[i]);
  463.                         if (minPoint == null)
  464.                         {
  465.                             minPoint = result[i];
  466.                             min = dist;
  467.                         }
  468.                         else
  469.                         {
  470.                             if (dist < min.Value)
  471.                             {
  472.                                 minPoint = result[i];
  473.                                 min = dist;
  474.                             }
  475.                         }
  476.                     }
  477.                     result.Remove(minPoint.Value);
  478.                     sorted_coll.Add(minPoint.Value);
  479.                 }
  480.                 foreach (Point3d coll in sorted_coll)
  481.                 {
  482.                     result.Add(coll);
  483.                 }
  484.             }
  485.             return result;
  486.         }

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

  • ADN OPEN
  • **
  • Сообщений: 95
  • Карма: 11
Re: AutoCAD .NET API: Рассечение штриховки.
« Ответ #3 : 13-03-2023, 22:25:08 »
Вторая часть кода

Код - C# [Выбрать]
  1. /// <summary>
  2.         /// возвращает список точек пересечения кривых на плане по вектору
  3.         /// Использовались части кода от Александра Ривилиса
  4.         /// </summary>
  5.         /// <param name="bCurId">ObjectId секущей кривой</param>
  6.         /// <param name="iCurId">ObjectId пересекаемой кривой </param>
  7.         /// <param name="bCur">секущая кривая</param>
  8.         /// <param name="iCur">пересекаемая кривая</param>
  9.         /// <param name="iBlock">Блок если пересекаемая кривая находится в блоке</param>
  10.         /// <param name="plane">план на котором ищутся пересечения</param>
  11.         /// <param name="vector">направление проецирования на план</param>
  12.         /// <param name="firstLast">возвращать точки пересечения на концах пересекаемой линии?</param>
  13.         /// <returns>список точек пересечения на пересекаемой кривой</returns>
  14.         private List<Point3d> IntersectPoints(ObjectId bCurId, ObjectId iCurId, Curve bCur, Curve iCur, Plane plane, Vector3d vector, bool firstLast)
  15.         {
  16.             List<Point3d> result = new List<Point3d>();
  17.             //если кривых нет то останавливаем
  18.             if ((bCurId == ObjectId.Null & bCur == null) | (iCurId == ObjectId.Null & iCur == null)) return result;
  19.             //если кривые заданы через ObjectId то получаем
  20.             if (bCur == null | iCur == null)
  21.             {
  22.                 using (Transaction tr = HostApplicationServices.WorkingDatabase.TransactionManager.StartTransaction())
  23.                 {
  24.                     if (bCur == null)
  25.                     {
  26.                         bCur = tr.GetObject(bCurId, OpenMode.ForRead, false, true) as Curve;
  27.                     }
  28.                     if (iCur == null)
  29.                     {
  30.                         iCur = tr.GetObject(iCurId, OpenMode.ForRead, false, true) as Curve;
  31.                     }
  32.                     tr.Commit();
  33.                 }
  34.             }
  35.             //если вдруг что-то пошло не так и кривые мы все таки не получили то прекращаем
  36.             if (bCur == null | iCur == null) return result;            
  37.             //получаем проекции кривых на плоскость
  38.             using (Curve bCurPr = bCur.GetProjectedCurve(plane, vector))
  39.             using (Curve iCurPr = iCur.GetProjectedCurve(plane, vector))
  40.             {
  41.                 //проверяем что проекции имеют длину
  42.                 if ((bCurPr.GetDistanceAtParameter(bCurPr.StartParam) + bCurPr.GetDistanceAtParameter(bCurPr.EndParam)) == 0) return result;
  43.                 if ((iCurPr.GetDistanceAtParameter(iCurPr.StartParam) + iCurPr.GetDistanceAtParameter(iCurPr.EndParam)) == 0) return result;
  44.                 //получаем Curve3d
  45.                 using (Curve3d bCurPr3d = bCurPr.GetGeCurve())
  46.                 using (Curve3d iCurPr3d = iCurPr.GetGeCurve())
  47.                 {
  48.                     //получаем точки пересечения кривых
  49.                     using (CurveCurveIntersector3d cInt = new CurveCurveIntersector3d(bCurPr3d, iCurPr3d, vector))
  50.                     {
  51.                         //если пересечения есть
  52.                         if (cInt.NumberOfIntersectionPoints > 0)
  53.                         {
  54.                             //получаем непроецированную кривую как Curve3d
  55.                             using (Curve3d iCur3d = iCur.GetGeCurve())
  56.                             {
  57.                                 //проходим по пересечениям
  58.                                 for (int i = 0; i < cInt.NumberOfIntersectionPoints; i++)
  59.                                 {
  60.                                     //если касание пропускаем
  61.                                     if (cInt.IsTangential(i)) continue;
  62.                                     //получаем точку пересечения
  63.                                     Point3d point = cInt.GetIntersectionPoint(i);
  64.                                     //если это точка начала или конца и она не нужна то пропускаем
  65.                                     if (!firstLast)
  66.                                     {
  67.                                         if ((i == 0 | i == (cInt.NumberOfIntersectionPoints - 1)) & (point.Equals(iCurPr3d.StartPoint) | point.Equals(iCurPr3d.EndPoint))) continue;
  68.                                     }
  69.                                     //строим линию из этой точки и ищем реальную точку на непроецированной кривой
  70.                                     using (Line3d line = new Line3d(point, vector))
  71.                                     {
  72.                                         //получаем точки пересечения линии и непроецированной кривой
  73.                                         using (CurveCurveIntersector3d cits = new CurveCurveIntersector3d(iCur3d, line, vector))
  74.                                         {
  75.                                             if (cits.NumberOfIntersectionPoints > 0)
  76.                                             {
  77.                                                 for (int j = 0; j < cits.NumberOfIntersectionPoints; j++)
  78.                                                 {
  79.                                                     //если этой точки нет в списке то добавляем в список
  80.                                                     if (!result.Contains(cits.GetIntersectionPoint(j))) result.Add(cits.GetIntersectionPoint(j));
  81.                                                 }                                                    
  82.                                             }
  83.                                         }
  84.                                     }
  85.                                 }
  86.                             }
  87.                         }
  88.                     }
  89.                 }
  90.             }        
  91.             //возвращаем отсортированные точки
  92.             return SortPoint(result, iCur);
  93.         }
  94.         /// <summary>
  95.         /// Возвращает ObjectId кривых в лупе отрисованных в текущем пространстве
  96.         /// (немного доработанная функция от Александра Ривилиса)
  97.         /// </summary>
  98.         /// <param name="loop"></param>
  99.         /// <param name="plane"></param>
  100.         /// <param name="iBlock"></param>
  101.         /// <returns></returns>
  102.         private List<ObjectId> GetCurveFromLoop(HatchLoop loop, Plane plane, Hatch hatch)
  103.         {
  104.             List<ObjectId> result = new List<ObjectId>();
  105.             using (Transaction tr = HostApplicationServices.WorkingDatabase.TransactionManager.StartTransaction())
  106.             {                
  107.                 using (BlockTableRecord ms = tr.GetObject(HostApplicationServices.WorkingDatabase.CurrentSpaceId, OpenMode.ForWrite, false, true) as BlockTableRecord)
  108.                 {
  109.                     if (loop.IsPolyline)
  110.                     {
  111.                         using (Polyline poly = new Polyline())
  112.                         {
  113.                             int iVertex = 0;
  114.                             foreach (BulgeVertex bv in loop.Polyline)
  115.                             {
  116.                                 poly.AddVertexAt(iVertex++, bv.Vertex, bv.Bulge, 0.0, 0.0);
  117.                             }
  118.                             poly.Normal = hatch.Normal;
  119.                             poly.Elevation = hatch.Elevation;                            
  120.                             result.Add(ms.AppendEntity(poly));
  121.                             tr.AddNewlyCreatedDBObject(poly, true);
  122.                         }
  123.                     }
  124.                     else
  125.                     {
  126.                         foreach (Curve2d cv in loop.Curves)
  127.                         {
  128.                             LineSegment2d line2d = cv as LineSegment2d;
  129.                             CircularArc2d arc2d = cv as CircularArc2d;
  130.                             EllipticalArc2d ellipse2d = cv as EllipticalArc2d;
  131.                             NurbCurve2d spline2d = cv as NurbCurve2d;
  132.                             if (line2d != null)
  133.                             {
  134.                                 using (Line ent = new Line())
  135.                                 {
  136.                                     ent.StartPoint = new Point3d(plane, line2d.StartPoint);
  137.                                     ent.EndPoint = new Point3d(plane, line2d.EndPoint);
  138.                                     result.Add(ms.AppendEntity(ent));
  139.                                     tr.AddNewlyCreatedDBObject(ent, true);
  140.                                 }
  141.                             }
  142.                             else if (arc2d != null)
  143.                             {
  144.                                 if (arc2d.IsClosed() || Math.Abs(arc2d.EndAngle - arc2d.StartAngle) < 1e-5)
  145.                                 {
  146.                                     using (Circle ent = new Circle(new Point3d(plane, arc2d.Center), plane.Normal, arc2d.Radius))
  147.                                     {
  148.                                         result.Add(ms.AppendEntity(ent));
  149.                                         tr.AddNewlyCreatedDBObject(ent, true);
  150.                                     }
  151.                                 }
  152.                                 else
  153.                                 {
  154.                                     if (arc2d.IsClockWise)
  155.                                     {
  156.                                         arc2d = arc2d.GetReverseParameterCurve() as CircularArc2d;
  157.                                     }
  158.                                     double angle = new Vector3d(plane, arc2d.ReferenceVector).AngleOnPlane(plane);
  159.                                     double startAngle = arc2d.StartAngle + angle;
  160.                                     double endAngle = arc2d.EndAngle + angle;
  161.                                     using (Arc ent = new Arc(new Point3d(plane, arc2d.Center), plane.Normal, arc2d.Radius, startAngle, endAngle))
  162.                                     {
  163.                                         result.Add(ms.AppendEntity(ent));
  164.                                         tr.AddNewlyCreatedDBObject(ent, true);
  165.                                     }
  166.                                 }
  167.                             }
  168.                             else if (ellipse2d != null)
  169.                             {
  170.                                 //-------------------------------------------------------------------------------------------
  171.                                 // Bug: Can not assign StartParam and EndParam of Ellipse:
  172.                                 // Ellipse ent = new Ellipse(new Point3d(plane, e2d.Center), plane.Normal,
  173.                                 //      new Vector3d(plane,e2d.MajorAxis) * e2d.MajorRadius,
  174.                                 //      e2d.MinorRadius / e2d.MajorRadius, e2d.StartAngle, e2d.EndAngle);
  175.                                 // ent.StartParam = e2d.StartAngle;
  176.                                 // ent.EndParam = e2d.EndAngle;
  177.                                 // error CS0200: Property or indexer 'Autodesk.AutoCAD.DatabaseServices.Curve.StartParam' cannot be assigned to -- it is read only
  178.                                 // error CS0200: Property or indexer 'Autodesk.AutoCAD.DatabaseServices.Curve.EndParam' cannot be assigned to -- it is read only
  179.                                 //---------------------------------------------------------------------------------------------
  180.                                 // Workaround is using Reflection
  181.                                 //
  182.                                 using (Ellipse ent = new Ellipse(new Point3d(plane, ellipse2d.Center), plane.Normal,
  183.                                      new Vector3d(plane, ellipse2d.MajorAxis) * ellipse2d.MajorRadius,
  184.                                      ellipse2d.MinorRadius / ellipse2d.MajorRadius, ellipse2d.StartAngle, ellipse2d.EndAngle))
  185.                                 {
  186.                                     ent.GetType().InvokeMember("StartParam", BindingFlags.SetProperty, null,
  187.                                       ent, new object[] { ellipse2d.StartAngle });
  188.                                     ent.GetType().InvokeMember("EndParam", BindingFlags.SetProperty, null,
  189.                                       ent, new object[] { ellipse2d.EndAngle });
  190.                                     result.Add(ms.AppendEntity(ent));
  191.                                     tr.AddNewlyCreatedDBObject(ent, true);
  192.                                 }
  193.  
  194.                             }
  195.                             else if (spline2d != null)
  196.                             {
  197.                                 if (spline2d.HasFitData)
  198.                                 {
  199.                                     NurbCurve2dFitData n2fd = spline2d.FitData;
  200.                                     using (Point3dCollection p3ds = new Point3dCollection())
  201.                                     {
  202.                                         foreach (Point2d p in n2fd.FitPoints) p3ds.Add(new Point3d(plane, p));
  203.                                         using (Spline ent = new Spline(p3ds, new Vector3d(plane, n2fd.StartTangent), new Vector3d(plane, n2fd.EndTangent),
  204.                                           /* n2fd.KnotParam, */  n2fd.Degree, n2fd.FitTolerance.EqualPoint))
  205.                                         {
  206.                                             result.Add(ms.AppendEntity(ent));
  207.                                             tr.AddNewlyCreatedDBObject(ent, true);
  208.                                         }
  209.                                     }
  210.                                 }
  211.                                 else
  212.                                 {
  213.                                     NurbCurve2dData n2fd = spline2d.DefinitionData;
  214.                                     using (Point3dCollection p3ds = new Point3dCollection())
  215.                                     {
  216.                                         DoubleCollection knots = new DoubleCollection(n2fd.Knots.Count);
  217.                                         foreach (Point2d p in n2fd.ControlPoints) p3ds.Add(new Point3d(plane, p));
  218.                                         foreach (double k in n2fd.Knots) knots.Add(k);
  219.                                         double period = 0;
  220.                                         using (Spline ent = new Spline(n2fd.Degree, n2fd.Rational,
  221.                                                  spline2d.IsClosed(), spline2d.IsPeriodic(out period),
  222.                                                  p3ds, knots, n2fd.Weights, n2fd.Knots.Tolerance, n2fd.Knots.Tolerance))
  223.                                         {
  224.                                             result.Add(ms.AppendEntity(ent));
  225.                                             tr.AddNewlyCreatedDBObject(ent, true);
  226.                                         }
  227.                                     }
  228.                                 }
  229.                             }
  230.                         }
  231.                     }
  232.                 }
  233.                 tr.Commit();
  234.             }
  235.             return result;
  236.         }
  237.         /// <summary>
  238.         /// выбор объекта на чертеже и возврат его ObjectId
  239.         /// </summary>
  240.         /// <param name="objTypes">список с типами допущенных для выбора объектов, пустой лист любого объекта</param>
  241.         /// <param name="soob">Выводимое сообщение при выборе</param>
  242.         /// <returns></returns>
  243.         private ObjectId GetObjectId(List<string> objTypes, string soob)
  244.         {
  245.             //повторяем пока не выбран нужный объект
  246.             while (true)
  247.             {
  248.                 //Выбираем объект на чертеже
  249.                 PromptEntityResult entRes = Application.DocumentManager.MdiActiveDocument.Editor.GetEntity("\n" + soob);
  250.                 //Если объект не выбран то прекращаем программу
  251.                 if (entRes.Status == PromptStatus.Cancel)
  252.                 {
  253.                     return ObjectId.Null;
  254.                 }
  255.                 //проверка на тип объекта если выбранный объект корректен то выходим из цикла выбора
  256.                 if (objTypes.Count == 0) return entRes.ObjectId;
  257.                 foreach (string objType in objTypes)
  258.                     if (entRes.ObjectId.ObjectClass.Name.ToLower().Equals(objType.ToLower()))
  259.                         return entRes.ObjectId;              
  260.             }
  261.         }      
  262.         /// <summary>
  263.         /// используется что бы определить положение объекта относительно других кривых
  264.         /// даст точный результат если объекты из списка образуют замкнутый контур
  265.         /// </summary>
  266.         /// <param name="cur">элемент который проверяется (кривая или точка)</param>
  267.         /// <param name="curvesId">список ObjectId кривых</param>
  268.         /// <param name="plane"></param>
  269.         /// <param name="vector"></param>
  270.         /// <param name="kontur">кривая если нужно передать уже открытую</param>
  271.         /// <returns>
  272.         /// 0 - ошибка исходных данных
  273.         /// 1 - внутри кривых
  274.         /// 2 - снаружи кривых
  275.         /// </returns>
  276.         private int CurveInCurves(Object cur, List<ObjectId> curvesId, Plane plane, Vector3d vector, Curve kontur)
  277.         {
  278.             if ((curvesId.Count == 0 & kontur == null) | cur == null ) return 0;
  279.             //счетчик общего числа пересечений
  280.             //создаем список точек что бы не задваивать пересечения
  281.             //если вдруг точка пересечения попадет в стык между двумя кривыми
  282.             //встречается часто если сечется прямоугольником так как вектор параллелен оси
  283.             List<Point3d> points = new List<Point3d>();
  284.             using (Transaction tr = HostApplicationServices.WorkingDatabase.TransactionManager.StartTransaction())
  285.             {
  286.                 //строим луч из центра кривой в плане штриховки
  287.                 using (Ray ray = new Ray())
  288.                 {                    
  289.                     //создаем луч из центра кривой
  290.                     if (cur is Curve) ray.BasePoint = GetCentr(cur as Curve);
  291.                     if (cur is Point3d) ray.BasePoint = (Point3d)cur;
  292.                     ray.UnitDir = plane.Normal.GetPerpendicularVector();                    
  293.                     //проходим по всем кривым и ищем пересечения
  294.                     using (Curve3d ray3d = ray.GetGeCurve())
  295.                     {
  296.                         List<Curve> curves = new List<Curve>();
  297.                         foreach (ObjectId id in curvesId) curves.Add(tr.GetObject(id, OpenMode.ForRead, false, true) as Curve);                      
  298.                         if (kontur != null) curves.Add(kontur);
  299.                         foreach (Curve curve in curves)
  300.                         {
  301.                             using (Curve3d loopCur3d = curve.GetGeCurve())
  302.                             using (CurveCurveIntersector3d cuin = new CurveCurveIntersector3d(ray3d, loopCur3d, vector))
  303.                             {
  304.                                 if (cuin.NumberOfIntersectionPoints > 0)
  305.                                 {
  306.                                     //ищем число пересечений не считая касательных                                        
  307.                                     for (int i = 0; i < cuin.NumberOfIntersectionPoints; i++)
  308.                                         if (cuin.IsTransversal(i))                                        
  309.                                         {
  310.                                             if (!points.Contains(cuin.GetIntersectionPoint(i)))
  311.                                             {
  312.                                                 points.Add(cuin.GetIntersectionPoint(i));                                              
  313.                                             }
  314.                                         }  
  315.                                 }
  316.                             }
  317.                         }
  318.                     }
  319.                 }
  320.                 tr.Commit();
  321.             }
  322.             //если число пересечений нечетное то точка изнутри, если четное или ноль то снаружи
  323.             if (points.Count % 2 != 0) return 1;          
  324.             else return 2;  
  325.         }
  326.         /// <summary>
  327.         /// удаляет объекты из списка по id
  328.         /// </summary>
  329.         /// <param name="ids"></param>
  330.         private void DeleteObj(List<ObjectId> ids)
  331.         {
  332.             using (Transaction tr = HostApplicationServices.WorkingDatabase.TransactionManager.StartTransaction())
  333.             {
  334.                 foreach (ObjectId id in ids)
  335.                 {
  336.                     using (Entity c = tr.GetObject(id, OpenMode.ForWrite, false, true) as Entity)
  337.                     {
  338.                         c.Erase();
  339.                     }
  340.                 }
  341.                 tr.Commit();
  342.             }
  343.         }
  344.         /// <summary>
  345.         /// проверяет положение кривой part относительно кривой kontur
  346.         /// </summary>
  347.         /// <param name="kontur"></param>
  348.         /// <param name="part"></param>
  349.         /// <param name="iBlock"></param>
  350.         /// <returns>
  351.         /// 0 - ошибка исходных данных
  352.         /// 1 - внутри
  353.         /// 2 - снаружи
  354.         /// 3 - на границе    
  355.         /// 4 - внутри и касается контура
  356.         /// 5 - снаружи и касается контура
  357.         /// 6 - пересекает контур            
  358.         /// </returns>
  359.         private int PartIn(Curve kontur, Curve part, Plane plane, Vector3d vector)
  360.         {
  361.             if (kontur == null | part == null) return 0;
  362.             //внутри контура
  363.             bool into = false;
  364.             //снаружи контура
  365.             bool outer = false;
  366.             //на границе контура
  367.             bool g = false;
  368.             //создаем список из трех точек
  369.             List<Point3d> points = new List<Point3d>
  370.             {
  371.                 part.StartPoint,
  372.                 part.EndPoint,
  373.                 GetCentr(part)
  374.             };
  375.             //проверяем на пересечение
  376.             List<Point3d> per = IntersectPoints(ObjectId.Null, ObjectId.Null, kontur.Clone() as Curve, part.Clone() as Curve, plane, vector, false);
  377.             if (per.Count > 0) return 6;
  378.             foreach (Point3d point in points)
  379.             {
  380.                 //проверяем на нахождение на контуре
  381.                 //если проекция точки на контур совпадает с точкой то она на контуре
  382.                 if (kontur.GetClosestPointTo(point, false).Equals(point))
  383.                 {
  384.                     g = true;
  385.                     continue;
  386.                 }
  387.                 //если не на границе то пользуемся определением положения через луч
  388.                 int res = CurveInCurves(point, new List<ObjectId>(), plane, vector, kontur);                
  389.                 if (res == 1) into = true;
  390.                 if (res == 2) outer = true;
  391.             }                          
  392.             //точки только внутри
  393.             if (into & !outer & !g)
  394.             {
  395.                 return 1;
  396.             }
  397.             //точки только снаружи
  398.             if (!into & outer & !g)
  399.             {
  400.                 return 2;
  401.             }
  402.             //точки только на границe
  403.             if (!into & !outer & g)
  404.             {
  405.                 return 3;
  406.             }
  407.             //точки внутри и на границе
  408.             if (into & !outer & g)
  409.             {
  410.                 return 4;
  411.             }
  412.             //точки снаружи и на границе
  413.             if (!into & outer & g)
  414.             {
  415.                 return 5;
  416.             }
  417.             return 6;
  418.         }
  419.     }
  420. }

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

  • ADN OPEN
  • **
  • Сообщений: 95
  • Карма: 11
Re: AutoCAD .NET API: Рассечение штриховки.
« Ответ #4 : 22-03-2023, 12:58:12 »
Потестировав этот вариант разрезания нашел нестандартное поведение получившихся элементов. Разрезанные этим методом штриховки невозможно разделить встроенным методом "Отдельные штриховки". Есть к у кого какие мысли, может быть я что-то не учел при создании новой штриховки?

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

  • ADN OPEN
  • **
  • Сообщений: 95
  • Карма: 11
Re: AutoCAD .NET API: Рассечение штриховки.
« Ответ #5 : 24-03-2023, 21:46:47 »
Разобрался, все зависит от типа петли, если использовать default то штриховка корректно отображается только если тип островков стоит нормальный, соответственно не работает свойство площади штриховки и ее невозможно разделить на отдельные.
Для корректного отображения штриховки нужно использовать минимум 3 типа, в зависимости от количества вложений петель, к тому же петли подразделяются на 2 глобальных типа, обычные и HatchLoopTypes.Textbox(визуально убирают штриховку внутри контура но это сокрытие не влияет на площадь).
Протестировав варианты петель обнаружились такие типы
Обычные
1 - Наружный контур HatchLoopTypes.External
2 - Внутренний контур - внутри наружного HatchLoopTypes.Outermost (если он касается наружного имеет двойной тип + HatchLoopTypes.External )
3 - Контура внутри внутреннего контура обозначаются как HatchLoopTypes.Default
Текстбоксы
1 - снаружи или снаружи и касается внешнего контура или пересекает внешний контур HatchLoopTypes.Textbox | HatchLoopTypes.External
2 - внутри относительно внешнего контура, пересекает второй контур или его касается HatchLoopTypes.Textbox | HatchLoopTypes.Outermost
3 - внутри и касается внешнего контура HatchLoopTypes.Textbox | HatchLoopTypes.Outermost  | HatchLoopTypes.External
 при переходе в глубину вложения контуров уже идет зависимость от номера вложения для глубины больше 2
4 - текст внутри четного контура - HatchLoopTypes.Textbox | HatchLoopTypes.TextIsland
5 - текст внутри нечетного контура или внутри четного контура но его касается или его пересекает  - HatchLoopTypes.Textbox

Для реализации всех этих элементов были изменены следующие функции
1 основной код
Код - C# [Выбрать]
  1.         public List<ObjectId> CutHatch(ObjectId plId, ObjectId hId)
  2.         {    
  3.             List<ObjectId> result = new List<ObjectId>();
  4.             //работаем сразу в транзокции и таблице так как частенько придется что-то доставать или что-то записывать
  5.             using (Transaction tr = HostApplicationServices.WorkingDatabase.TransactionManager.StartTransaction())
  6.             {
  7.                 using (BlockTableRecord ms = tr.GetObject(HostApplicationServices.WorkingDatabase.CurrentSpaceId, OpenMode.ForWrite, false, true) as BlockTableRecord)
  8.                 {
  9.                     using (Hatch hatch = tr.GetObject(hId, OpenMode.ForWrite, false, true) as Hatch)
  10.                     {
  11.                         //получаем план штриховки
  12.                         Plane plane = hatch.GetPlane();
  13.                         //получаем вектор текущего вида
  14.                         Vector3d vector = GetViewVector();
  15.                         //проверяем на самопересечение и замкнутость
  16.                         using (Curve pl1 = tr.GetObject(plId, OpenMode.ForRead, false, true) as Curve)
  17.                         using (Curve pl = pl1.GetProjectedCurve(plane, vector))
  18.                         using (Curve3d pl3d = pl.GetGeCurve())
  19.                         using (CurveCurveIntersector3d cuin = new CurveCurveIntersector3d(pl3d, pl3d, vector))
  20.                         {
  21.                             if (cuin.NumberOfIntersectionPoints > 0 | !pl3d.IsClosed())
  22.                             {
  23.                                 tr.Commit(); return new List<ObjectId> { ObjectId.Null };
  24.                             }
  25.                         }
  26.                         //получаем петли из штриховки
  27.                         //List<HatchLoop> loops = new List<HatchLoop>();                      
  28.                         //создаем кривые в чертеже для каждого петли и записываем их в списки
  29.                         //список обычных петель
  30.                         List<ObjectId> loopCurve = new List<ObjectId>();
  31.                         //список текстбоксовых петель
  32.                         List<List<ObjectId>> textLoopCurve = new List<List<ObjectId>>();                        
  33.                         for (int i = hatch.NumberOfLoops - 1; i >= 0; i--)
  34.                         {
  35.                             HatchLoopTypes sdfds = hatch.LoopTypeAt(i);
  36.                             //получаем куски петли
  37.                             List<ObjectId> objectIds = GetCurveFromLoop(hatch.GetLoopAt(i), plane, hatch);                            
  38.                             if (hatch.LoopTypeAt(i).Equals(HatchLoopTypes.Textbox) |
  39.                                 hatch.LoopTypeAt(i).Equals(HatchLoopTypes.TextIsland | HatchLoopTypes.Textbox) |
  40.                                 hatch.LoopTypeAt(i).Equals(HatchLoopTypes.Textbox | HatchLoopTypes.Outermost) |
  41.                                 hatch.LoopTypeAt(i).Equals(HatchLoopTypes.Textbox | HatchLoopTypes.External) |
  42.                                 hatch.LoopTypeAt(i).Equals(HatchLoopTypes.Textbox | HatchLoopTypes.Outermost | HatchLoopTypes.External)
  43.                                 ) textLoopCurve.Add(objectIds);
  44.                             else loopCurve.AddRange(objectIds);
  45.                         }
  46.                         //return new List<ObjectId> { ObjectId.Null };
  47.                         //список секущих точек
  48.                         List<Point3d> sPoints = new List<Point3d>();
  49.                         //разрезаем все контура в штриховке проекцией контура (которые контур рассекает)                        
  50.                         //список удаляемых кривых петель
  51.                         List<ObjectId> erList = new List<ObjectId>();
  52.                         //список добавляемых кривых в петли
  53.                         List<ObjectId> addList = new List<ObjectId>();
  54.                         foreach (ObjectId id in loopCurve)
  55.                         {
  56.                             //получаем кривую
  57.                             using (Curve cur = tr.GetObject(id, OpenMode.ForWrite, false, true) as Curve)
  58.                             {
  59.                                 //получаем точки пересечения
  60.                                 List<Point3d> points = IntersectPoints(plId, ObjectId.Null, null, cur.Clone() as Curve, plane, vector, false);
  61.                                 //если точки есть то разрезаем кривую, добавляем куски в список и удаляем разрезанную
  62.                                 if (points.Count > 0)
  63.                                 {
  64.                                     sPoints.AddRange(points);
  65.                                     using (Point3dCollection collection = new Point3dCollection())
  66.                                     {
  67.                                         foreach (Point3d point in points) collection.Add(point);
  68.                                         using (DBObjectCollection objects = cur.GetSplitCurves(collection))
  69.                                         {
  70.                                             foreach (Object obj in objects)
  71.                                             {
  72.                                                 using (Curve curve = obj as Curve)
  73.                                                 {
  74.                                                     if (curve != null)
  75.                                                     {
  76.                                                         addList.Add(ms.AppendEntity(curve));
  77.                                                         tr.AddNewlyCreatedDBObject(curve, true);
  78.                                                     }
  79.                                                 }
  80.                                             }
  81.                                         }
  82.                                     }
  83.                                     cur.Erase();
  84.                                     erList.Add(id);
  85.                                 }
  86.                             }
  87.                         }
  88.                         //если были то обновляем список кривых в петлих
  89.                         foreach (ObjectId id in erList) loopCurve.Remove(id);
  90.                         loopCurve.AddRange(addList);
  91.                         //создаем списки распределения кривых (других по идее быть не должно)
  92.                         //внутри
  93.                         List<Curve> inner = new List<Curve>();
  94.                         //снаружи
  95.                         List<Curve> outer = new List<Curve>();
  96.                         //создаем список с кусками пересекающей кривой, которые будем добавлять в петли
  97.                         List<ObjectId> kontPartLstId = new List<ObjectId>();
  98.                         List<Curve> kontPartLst = new List<Curve>();
  99.                         List<Curve> kontPartLstCopy = new List<Curve>();
  100.                         //получаем контур в виде проекции на плоскость штриховки                    
  101.                         using (Curve pl1 = tr.GetObject(plId, OpenMode.ForRead, false, true) as Curve)
  102.                         using (Curve pl = pl1.GetProjectedCurve(plane, vector))
  103.                         {
  104.                             //распределяем куски петель по спискам
  105.                             foreach (ObjectId id in loopCurve)
  106.                             {
  107.                                 Curve c = tr.GetObject(id, OpenMode.ForRead, false, true) as Curve;
  108.                                 //после всех манипляций тут должны быть только результаты 1 - 5
  109.                                 //если встретится что-то другое то скорее всего произошла какая-то ошибка и просто прекращаем
  110.                                 //если все нормально то все кривые распределятся по спискам кроме номера 3
  111.                                 //он просто игнорируется и никуда не идет, его заменят если что части контура
  112.                                 int res = PartIn(pl, c, plane, vector);
  113.                                 if (res == 0 | res == 6)
  114.                                 {
  115.                                     DeleteObj(loopCurve);
  116.                                     tr.Commit();
  117.                                     return new List<ObjectId> { ObjectId.Null };
  118.                                 }
  119.                                 if (res == 1 | res == 4)
  120.                                 {
  121.                                     inner.Add(c);
  122.                                     continue;
  123.                                 }
  124.                                 if (res == 2 | res == 5)
  125.                                 {
  126.                                     outer.Add(c);
  127.                                     continue;
  128.                                 }
  129.                                 if (res == 3) continue;
  130.                             }
  131.                             //ищем куски разрезающей кривой
  132.                             //сортируем точки по разрезающей кривой
  133.                             sPoints = SortPoint(sPoints, pl);                            
  134.                             using (Point3dCollection collection = new Point3dCollection())
  135.                             {
  136.                                 if (sPoints.Count > 0)
  137.                                 {
  138.                                     foreach (Point3d point in sPoints) collection.Add(point);
  139.                                     using (DBObjectCollection objects = pl.GetSplitCurves(collection))
  140.                                     {
  141.                                         foreach (Object obj in objects)
  142.                                         {
  143.                                             using (Curve curve = obj as Curve)
  144.                                             {
  145.                                                 if (curve != null)
  146.                                                 {
  147.                                                     //проверяем находится ли кусок контура внутри штриховки
  148.                                                     int res = CurveInCurves(curve, loopCurve, plane, vector, null);
  149.                                                     //если ошибка
  150.                                                     if (res == 0)
  151.                                                     {
  152.                                                         DeleteObj(loopCurve);
  153.                                                         DeleteObj(kontPartLstId);
  154.                                                         tr.Commit();
  155.                                                         return new List<ObjectId> { ObjectId.Null };
  156.                                                     }
  157.                                                     //если внутри то добавляем на модель и в список
  158.                                                     if (res == 1 | res == 4)
  159.                                                     {
  160.                                                         kontPartLstId.Add(ms.AppendEntity(curve));
  161.                                                         tr.AddNewlyCreatedDBObject(curve, true);
  162.                                                     }
  163.                                                 }
  164.                                             }
  165.                                         }
  166.                                     }
  167.                                 }
  168.                             }
  169.                             //получаем куски контура как кривые и создаем 2 списка для тех областей что внутри и для тех что снаружи
  170.                             List<ObjectId> nkontPartLstId = new List<ObjectId>();
  171.                             foreach (ObjectId objectId in kontPartLstId)
  172.                             {
  173.                                 Curve curve = tr.GetObject(objectId, OpenMode.ForRead, false, true) as Curve;
  174.                                 kontPartLst.Add(curve);
  175.                                 //добавляем копию на модель и в список
  176.                                 Curve curveCopy = curve.Clone() as Curve;
  177.                                 nkontPartLstId.Add(ms.AppendEntity(curveCopy));
  178.                                 tr.AddNewlyCreatedDBObject(curveCopy, true);
  179.                                 kontPartLstCopy.Add(curveCopy);
  180.                             }
  181.                             //добавляем ObjectId копий в общий список для последующего удаления
  182.                             kontPartLstId.AddRange(nkontPartLstId);
  183.                             //анализируем списки и составляем из кусков новые петли
  184.                             inner.AddRange(kontPartLstCopy);
  185.                             List<List<ObjectId>> loopsId = GetNewLoops(inner);
  186.                             List<(List<ObjectId>, HatchLoopTypes)> loopsIdAndType = GetLoopsType(loopsId, plane, vector);
  187.                             for (int i = (hatch.NumberOfLoops - 1); i >= 0; i--) hatch.RemoveLoopAt(i);  
  188.                             if (loopsId != null) result.Add(NewHatch(tr, ms, loopsIdAndType, hatch, textLoopCurve));
  189.                             else
  190.                             {
  191.                                 DeleteObj(loopCurve);
  192.                                 DeleteObj(kontPartLstId);
  193.                                 tr.Commit();
  194.                                 return new List<ObjectId> { ObjectId.Null };
  195.                             }
  196.                             outer.AddRange(kontPartLst);
  197.                             loopsId = GetNewLoops(outer);
  198.                             loopsIdAndType = GetLoopsType(loopsId, plane, vector);
  199.                             if (loopsId != null) result.Add(NewHatch(tr, ms, loopsIdAndType, hatch, textLoopCurve));
  200.                             else
  201.                             {
  202.                                 DeleteObj(loopCurve);
  203.                                 DeleteObj(kontPartLstId);
  204.                                 tr.Commit();
  205.                                 return new List<ObjectId> { ObjectId.Null };
  206.                             }
  207.                             DeleteObj(kontPartLstId);
  208.                             DeleteObj(nkontPartLstId);
  209.                         }
  210.                         foreach (List<ObjectId> ids in textLoopCurve) DeleteObj(ids);
  211.                         DeleteObj(loopCurve);                        
  212.                         hatch.Erase();
  213.                     }
  214.                 }                
  215.                 tr.Commit();
  216.             }
  217.             return result;
  218.         }

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

  • ADN OPEN
  • **
  • Сообщений: 95
  • Карма: 11
Re: AutoCAD .NET API: Рассечение штриховки.
« Ответ #6 : 24-03-2023, 21:55:56 »
2 - функция определения положения точки или кривой относительно группы кривых

Код - C# [Выбрать]
  1.    /// <summary>
  2.         /// используется что бы определить положение объекта относительно элементов петли
  3.         /// даст точный результат если объекты из списка обзаруют замкнутый контур
  4.         /// </summary>
  5.         /// <param name="cur"></param>
  6.         /// <param name="loopIds"></param>
  7.         /// <param name="plane"></param>
  8.         /// <param name="vector"></param>
  9.         /// <param name="kontur"></param>
  10.         /// <returns>
  11.         /// 0 - ошибка исходных данных
  12.         /// 1 - внутри петли
  13.         /// 2 - снаружи петли
  14.         /// 3 - пересекает петлю
  15.         /// 4 - касается петли и внутри
  16.         /// 5 - касается петли и снаружи
  17.         /// 6 - если точка лежит на контуре
  18.         /// </returns>
  19.         private int CurveInCurves(Object cur, List<ObjectId> loopIds, Plane plane, Vector3d vector, Curve kontur)
  20.         {
  21.             if ((loopIds.Count == 0 & kontur == null) | cur == null ) return 0;
  22.             //проверяем на пересечение
  23.             bool kas = false;
  24.             using (Transaction tr = HostApplicationServices.WorkingDatabase.TransactionManager.StartTransaction())
  25.             {
  26.                 if (cur is Curve)
  27.                 {
  28.                     Curve curCur = cur as Curve;
  29.                     using (Curve3d cur3d = curCur.GetGeCurve())
  30.                     {
  31.                         foreach (ObjectId loopId in loopIds)
  32.                         {
  33.                             using (Curve curve = tr.GetObject(loopId, OpenMode.ForRead, false, true) as Curve)
  34.                             {
  35.                                 if (curve != null)
  36.                                 {
  37.                                     using (Curve3d curve3d = curve.GetGeCurve())
  38.                                     using (CurveCurveIntersector3d cuin = new CurveCurveIntersector3d(curve3d, cur3d, vector))
  39.                                     {
  40.                                         if (cuin.NumberOfIntersectionPoints > 0)
  41.                                         {
  42.                                             for (int i = 0; i < cuin.NumberOfIntersectionPoints; i++)
  43.                                             {
  44.                                                 if (cuin.IsTransversal(i))
  45.                                                 {
  46.                                                     if (cuin.GetIntersectionPoint(i).Equals(cur3d.StartPoint) | cuin.GetIntersectionPoint(i).Equals(cur3d.EndPoint))
  47.                                                     {
  48.                                                         kas = true;
  49.                                                     }
  50.                                                     else
  51.                                                     {
  52.                                                         tr.Commit();
  53.                                                         return 3;
  54.                                                     }                                                  
  55.                                                 }
  56.                                                 else
  57.                                                 {
  58.                                                     kas = true;
  59.                                                 }
  60.                                             }
  61.                                         }
  62.                                     }
  63.                                 }
  64.                             }
  65.                         }
  66.                     }
  67.                 }
  68.                 if (cur is Point3d)
  69.                 {
  70.                     foreach (ObjectId loopId in loopIds)
  71.                     {
  72.                         using (Curve curve = tr.GetObject(loopId, OpenMode.ForRead, false, true) as Curve)
  73.                         {
  74.                             if (curve != null)
  75.                                 if (curve.GetClosestPointTo((Point3d)cur, false).DistanceTo((Point3d)cur) == 0)
  76.                                 {
  77.                                     tr.Commit();
  78.                                     return 5;
  79.                                 }
  80.                         }
  81.                     }
  82.  
  83.                 }
  84.                 tr.Commit();
  85.             }              
  86.             //счетчик общего числа пересечений
  87.             //создаем список точек что бы не задваивать пересечения
  88.             //если вдруг точка пересечения попадет в стык между двумя кривыми
  89.             //встречается часто если сечется прямоугольником так как вектор параллелен оси
  90.             List<Point3d> points = new List<Point3d>();            
  91.             using (Transaction tr = HostApplicationServices.WorkingDatabase.TransactionManager.StartTransaction())
  92.             {
  93.                 //строим луч из центра кривой в плане штриховки
  94.                 using (Ray ray = new Ray())
  95.                 {                    
  96.                     //создаем луч из центра кривой
  97.                     if (cur is Curve) ray.BasePoint = GetCentr(cur as Curve);
  98.                     if (cur is Point3d) ray.BasePoint = (Point3d)cur;
  99.                     ray.UnitDir = plane.Normal.GetPerpendicularVector();                    
  100.                     //проходим по всем кривым и ищем пересечения                  
  101.                     using (Curve3d ray3d = ray.GetGeCurve())
  102.                     {
  103.                         List<Curve> curves = new List<Curve>();
  104.                         foreach (ObjectId id in loopIds) curves.Add(tr.GetObject(id, OpenMode.ForRead, false, true) as Curve);                      
  105.                         if (kontur != null) curves.Add(kontur);
  106.                         foreach (Curve curve in curves)
  107.                         {
  108.                             using (Curve3d loopCur3d = curve.GetGeCurve())
  109.                             using (CurveCurveIntersector3d cuin = new CurveCurveIntersector3d(ray3d, loopCur3d, vector))
  110.                             {
  111.                                 if (cuin.NumberOfIntersectionPoints > 0)
  112.                                 {
  113.                                     //ищем число пересечений не считая касательных                                        
  114.                                     for (int i = 0; i < cuin.NumberOfIntersectionPoints; i++)
  115.                                         if (cuin.IsTransversal(i))                                        
  116.                                         {
  117.                                             if (!points.Contains(cuin.GetIntersectionPoint(i)))
  118.                                             {
  119.                                                 points.Add(cuin.GetIntersectionPoint(i));                                              
  120.                                             }
  121.                                         }  
  122.                                 }
  123.                             }
  124.                         }
  125.                     }
  126.                 }
  127.                 tr.Commit();
  128.             }
  129.             //если число пересечений нечетное то точка изнутри, если четное или ноль то снаружи
  130.             if (points.Count % 2 != 0)
  131.             {
  132.                 if (kas) return 4;
  133.                 else return 1;
  134.             }                          
  135.             else
  136.             {
  137.                 if (kas) return 5;
  138.                 else return 2;
  139.             }
  140.         }
3 изменена функция отрисовки новой штриховки, теперь учитывает типы петель

Код - C# [Выбрать]
  1.         private ObjectId NewHatch(Transaction tr, BlockTableRecord ms, List<(List<ObjectId>, HatchLoopTypes)> loopsIdAndType, Hatch hatch, List<List<ObjectId>> textLoopCurve)
  2.         {
  3.             ObjectId result = ObjectId.Null;
  4.             //переменная для фиксации результата
  5.             bool del = false;
  6.             using (Hatch h = hatch.Clone() as Hatch)
  7.             {
  8.                 using (Transaction tr2 = HostApplicationServices.WorkingDatabase.TransactionManager.StartTransaction())
  9.                 {
  10.                     result = ms.AppendEntity(h);
  11.                     tr2.AddNewlyCreatedDBObject(h, true);
  12.                     tr2.Commit();
  13.                 }
  14.                 //проходим по всем loop в списке
  15.                 for (int i = 0; i < loopsIdAndType.Count; i++)
  16.                 {
  17.                     List<ObjectId> loopId = loopsIdAndType[i].Item1;
  18.                     if (loopId.Count == 0) continue;
  19.                     //если ошибок не было то вставляем петлю
  20.                     if (!del)
  21.                     {
  22.                         //создаем из списка коллекцию
  23.                         using (ObjectIdCollection lId = new ObjectIdCollection())
  24.                         {
  25.                             //добавляем в коллекцию куски loop
  26.                             foreach (ObjectId curId in loopId) lId.Add(curId);
  27.                             //пробуем добавить коллекцию в штриховку
  28.                             try
  29.                             {
  30.                                 h.AppendLoop(loopsIdAndType[i].Item2, lId);
  31.                             }
  32.                             catch
  33.                             {
  34.                                 //если не удалось то удаляем штриховку и возвращаем ObjectId.Null
  35.                                 del = true;
  36.                             }
  37.                         }
  38.                     }                                      
  39.                 }
  40.                 //теперь требуется определить новую глубину вложения каждого тексбокса
  41.                 //глубина определяется положением текстбокса относительно всех петель
  42.                 // 1 петля - внешний контур External
  43.                 // 2 петля - внутренний контур Outermost
  44.                 // остальные петли идут как Default
  45.                 //в отличии от обычных петель которые друг с другом не пересекаются (еси есть пересечения они объединяются в одну петлю)
  46.                 //типы положения текстбоксов
  47.                 // 1 - текстбокс снаружи или снаружи и касается внешнего контура или пересекает внешний контур +External
  48.                 // 2 - внутри относительно внешнего контура, пересекает второй контур или его касается +Outermost
  49.                 // 3 - внутри и касается внешнего контура +Outermost +External
  50.                 //при переходе в глубину вложения контуров уже идет зависимость от номера вложения для уровней больше 2
  51.                 // 4 - текст внутри четного контура +TextIsland
  52.                 // 5 - текст внутри четного контура но его касается или его пересекает - ничего                
  53.                 for (int i = 0; i < textLoopCurve.Count; i++)
  54.                 {
  55.                     List<ObjectId> loopId = textLoopCurve[i];
  56.                     if (loopId.Count == 0) continue;
  57.                     //если ошибок не было то вставляем петлю
  58.                     if (!del)
  59.                     {
  60.                         //создаем из списка коллекцию
  61.                         using (ObjectIdCollection lId = new ObjectIdCollection())
  62.                         {
  63.                             //добавляем в коллекцию куски loop
  64.                             foreach (ObjectId curId in loopId) lId.Add(curId);
  65.                             //определяем место текстовой петли относительно обычных
  66.                             if (loopsIdAndType.Count > 0)
  67.                             {
  68.                                 //тип текстбокс штриховки
  69.                                 int vType = 1;
  70.                                 //полный уровень вложения
  71.                                 int into = 100000;                                
  72.                                 //проходим по кускам петли и определяем уровень вложения
  73.                                 foreach (ObjectId curLoopId in lId)
  74.                                 {
  75.                                     bool stop = false;
  76.                                     using (Curve c = tr.GetObject(curLoopId, OpenMode.ForRead, false, true) as Curve)
  77.                                     {
  78.                                         int curinto = 0;
  79.                                         //проходим по всем не текстбокс петлям
  80.                                         foreach ((List<ObjectId>, HatchLoopTypes) vloopId in loopsIdAndType)
  81.                                         {
  82.                                             int res = CurveInCurves(c, vloopId.Item1, hatch.GetPlane(), GetViewVector(), null);
  83.                                             //определяем уровень вложения
  84.                                             if (res == 1)
  85.                                             {
  86.                                                 curinto++;
  87.                                                 continue;
  88.                                             }
  89.                                             if (res == 3)
  90.                                             {
  91.                                                 //если пересекает внешний контур
  92.                                                 if (vloopId.Item2 == HatchLoopTypes.External)
  93.                                                 {
  94.                                                     vType = 1;
  95.                                                     stop = true;
  96.                                                     break;
  97.                                                 }
  98.                                                 //если пересекает внутренний контур
  99.                                                 if (vloopId.Item2 == HatchLoopTypes.Outermost | vloopId.Item2 == (HatchLoopTypes.Outermost | HatchLoopTypes.External))
  100.                                                 {
  101.                                                     vType = 2;                                                                                                    
  102.                                                 }                                                
  103.                                             }
  104.                                             if (res == 4)
  105.                                             {
  106.                                                 //если пересекает внешний контур
  107.                                                 if (vloopId.Item2 == HatchLoopTypes.External)
  108.                                                 {
  109.                                                     vType = 3;
  110.                                                     stop = true;
  111.                                                     break;
  112.                                                 }                                                
  113.                                             }
  114.                                         }
  115.                                         if (into > curinto) into = curinto;
  116.                                         if (stop) break;                                        
  117.                                     }
  118.                                 }
  119.                                 if (vType == 1 & into > 0)
  120.                                 {
  121.                                     if (into == 1) vType = 2;
  122.                                     if (into % 2 != 0) vType = 4;
  123.                                     else vType = 5;
  124.                                 }
  125.                                 //пробуем добавить коллекцию в штриховку
  126.                                 try
  127.                                 {
  128.                                     //устанаваливаем loop в зависимости от глубины вложения
  129.                                     switch (vType)
  130.                                     {
  131.                                         case 1: h.AppendLoop(HatchLoopTypes.External | HatchLoopTypes.Textbox, lId); break;
  132.                                         case 2: h.AppendLoop(HatchLoopTypes.Outermost | HatchLoopTypes.Textbox, lId); break;
  133.                                         case 3: h.AppendLoop(HatchLoopTypes.External | HatchLoopTypes.Outermost | HatchLoopTypes.Textbox, lId); break;
  134.                                         case 4: h.AppendLoop(HatchLoopTypes.TextIsland | HatchLoopTypes.Textbox, lId); break;
  135.                                         case 5: h.AppendLoop(HatchLoopTypes.Textbox, lId); break;
  136.                                     }
  137.                                 }
  138.                                 catch
  139.                                 {
  140.                                     //если не удалось то удаляем штриховку и возвращаем ObjectId.Null
  141.                                     del = true;
  142.                                 }
  143.                             }
  144.                         }
  145.                     }
  146.                 }
  147.                 //если произошла какая-то ошибка то удаляем штриховку
  148.                 if (del)
  149.                 {
  150.                     h.Erase();
  151.                     return ObjectId.Null;
  152.                 }                  
  153.             }
  154.             return result;
  155.         }  
4 добавлена новая функция, определяет тип петли
Код - C# [Выбрать]
  1. private List<(List<ObjectId>, HatchLoopTypes)> GetLoopsType(List<List<ObjectId>> loopsId, Plane plane, Vector3d vector)
  2.         {
  3.             List<(List<ObjectId>, HatchLoopTypes)> result = new List<(List<ObjectId>, HatchLoopTypes)>();
  4.             if (loopsId == null) return result;
  5.             using (Transaction tr = HostApplicationServices.WorkingDatabase.TransactionManager.StartTransaction())
  6.             {
  7.  
  8.                 for (int i = 0; i < loopsId.Count; i++)
  9.                 {
  10.                     //касание внешнего контура
  11.                     bool exout = false;
  12.                     List<ObjectId> loopId = loopsId[i];
  13.                     if (loopId.Count == 0) continue;
  14.                     //переменная для определения уровня вложения
  15.                     int into = 0;    
  16.                     //если loop больше одного определяем тип этого loop
  17.                     if (loopsId.Count > 1)
  18.                     {
  19.                         //берем за основу один из элементов loop
  20.                         using (Curve c = tr.GetObject(loopId[0], OpenMode.ForRead, false, true) as Curve)
  21.                         {
  22.                             //проходим по всем loop кроме текущего и проверяем где находится элемент относительно них
  23.                             foreach (List<ObjectId> vloopId in loopsId)
  24.                             {
  25.                                 if (vloopId.Equals(loopId)) continue;
  26.                                 int res = CurveInCurves(c, vloopId, plane, vector, null);
  27.                                 //если элемент внутри одного из loop (возврат от проверки - 1)
  28.                                 if (res == 1) into++;
  29.                                 if (res == 4)
  30.                                 {
  31.                                     exout = true;
  32.                                     into++;
  33.                                 }                                    
  34.                                 //все вложения больше 1 это default
  35.                                 if (into > 1) break;
  36.                             }
  37.                         }
  38.                     }
  39.                     //устанаваливаем loop в зависимости от глубины вложения
  40.                     switch (into)
  41.                     {
  42.                         case 0: result.Add((loopId, HatchLoopTypes.External)); break;
  43.                         case 1:
  44.                             {
  45.                                 if (exout) result.Add((loopId, HatchLoopTypes.Outermost | HatchLoopTypes.External));
  46.                                 else result.Add((loopId, HatchLoopTypes.Outermost));
  47.                                 break;
  48.                             }  
  49.                         default: result.Add((loopId, HatchLoopTypes.Default)); break;
  50.                     }
  51.                 }
  52.                 tr.Commit();
  53.             }
  54.             return result;
  55.         }
  56.