Выбор точки вставка объекта относительно других объектов (нумерация вершин)

Автор Тема: Выбор точки вставка объекта относительно других объектов (нумерация вершин)  (Прочитано 8617 раз)

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

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

  • ADN OPEN
  • Сообщений: 25
  • Карма: 3
Доброго времени суток! Имеется задача пронумеровать вершины всех выделенных полилиний в порядке возрастания, по порядку выделения полилиний с заданным размером шрифта и дистанцией отскока. Отскок должен быть во внешнюю сторону замкнутой полилинии. При этом если вершины дублируются в одном месте или стоят рядом (идёт наложение) - номер следующей вершины не проставляется. Моя логика вкратце: делаю offset полилинии наружу, нумерую вершины по его местоположению; паралельно делаю клон с масштабированием, на случай если оффсет съест какие-либо вершины. Далее провожу линии из вершин в разные стороны и таким образом нахожу, чтобы место для вершины не пересекалось с собственной полилиней и с другими объектами. Если место не находится - выводится сообщение в консоль (в этом месте я бы мог ещё дальше прописывать множественные условия по пересечениям, отклонения, удалениям дистанции и т.п). Вобщем нумерует оно в итоге коряво. Может существует какая-либо функция API для этого? Как думаете, решаемая задача?
Прикладываю свой код и пример чертежа. Желаемый результат видим, он в слое !numeratsiya. То что делает мой код находится в слое my-num.

Код - C# [Выбрать]
  1. using System;
  2. using Autodesk.AutoCAD.ApplicationServices;
  3. using Autodesk.AutoCAD.DatabaseServices;
  4. using Autodesk.AutoCAD.EditorInput;
  5. using Autodesk.AutoCAD.Runtime;
  6. using Autodesk.AutoCAD.Geometry;
  7. using Platform = Autodesk.AutoCAD;
  8. using PlatformDb = Autodesk.AutoCAD;
  9. [assembly: CommandClass(typeof(testtool.PolyNum))]
  10. namespace testtool
  11. {
  12.     public class PolyNum
  13.     {
  14.         [CommandMethod("enumtest")]
  15.         static public void enumer()
  16.         {
  17.             ObjectIdCollection mtexts = new ObjectIdCollection();
  18.             Document doc = Platform.ApplicationServices.Application.DocumentManager.MdiActiveDocument;
  19.             Database db = doc.Database;
  20.             Editor ed = doc.Editor;
  21.             int totalporyadcount = 0;
  22.             double dist = 3;
  23.             bool smartalg = true;
  24.             double fontheight = 3;
  25.             bool poryadkn = true;
  26.             TypedValue[] filList = new TypedValue[1] { new TypedValue((int)DxfCode.Start, "LWPOLYLINE") };
  27.             SelectionFilter filter = new SelectionFilter(filList);
  28.             PromptSelectionOptions pso = new PromptSelectionOptions();
  29.             pso.MessageForAdding = "\nВыбирете объекты в порядке очередности один за одним и нажмите Enter для экспорта: ";
  30.             PromptSelectionResult per = ed.GetSelection(pso, filter);
  31.             if (per.Status == PromptStatus.OK)
  32.             {
  33.                 Transaction tr = db.TransactionManager.StartTransaction();
  34.                 using (tr)
  35.                 {
  36.                     SelectionSet acSSet = per.Value;
  37.                     int objcount = 0;
  38.                     BlockTable bt = (BlockTable)tr.GetObject(db.BlockTableId, OpenMode.ForRead);
  39.                     BlockTableRecord ms = (BlockTableRecord)tr.GetObject(bt[BlockTableRecord.ModelSpace], OpenMode.ForWrite);
  40.                     foreach (SelectedObject acSSObj in acSSet)
  41.                     {
  42.                         DBObject obj = tr.GetObject(acSSObj.ObjectId, OpenMode.ForRead);
  43.                         Polyline lwp = obj as Polyline;
  44.                         Curve curv = obj as Curve;
  45.                         DBObjectCollection ids = new DBObjectCollection();
  46.                         if (curv.GetOffsetCurves(dist).Count != 0) ids = curv.GetOffsetCurves(dist);
  47.                         else ids.Add(curv);
  48.                         Polyline lwpclone = lwp.Clone() as Polyline;
  49.                         Extents3d ext = lwpclone.GeometricExtents;
  50.                         Point3d p_center = new Point3d(
  51.                             (ext.MinPoint.X + ext.MaxPoint.X) * 0.5,
  52.                             (ext.MinPoint.Y + ext.MaxPoint.Y) * 0.5,
  53.                             (ext.MinPoint.Z + ext.MaxPoint.Z) * 0.5
  54.                         );
  55.                         double scaledist = 1 + dist / 100;
  56.                         lwpclone.TransformBy(Matrix3d.Scaling(scaledist, p_center));
  57.                         Polyline lwp2 = ids[0] as Polyline;
  58.                         int vn2 = 0;
  59.                         if (lwp.NumberOfVertices != lwp2.NumberOfVertices)
  60.                         {
  61.                             lwp2 = lwpclone;
  62.                         }
  63.                         vn2 = lwp2.NumberOfVertices;
  64.                         if (lwp != null)
  65.                         {
  66.                             objcount++;
  67.                             int vn = lwp.NumberOfVertices;
  68.                             Point3d[] smartalgpt = new Point3d[vn];
  69.                             string vertnum = "";
  70.                             for (int i = 0; i < vn; i++)
  71.                             {
  72.                                 Point2d pt = lwp.GetPoint2dAt(i);
  73.                                 Point2d ptclone = lwp2.GetPoint2dAt(i);
  74.                                 // / / / / / / / / / / /SMARTALG
  75.                                 if (smartalg)
  76.                                 {
  77.                                     DBObjectCollection objectsforintersectcheck = new DBObjectCollection();
  78.                                     PromptSelectionResult res = SelectByPolyline(ed, lwp2, true, new TypedValue((int)DxfCode.Start, "MTEXT,LWPOLYLINE,TEXT,INSERT"));
  79.                                     if (res.Status == PromptStatus.OK)
  80.                                     {
  81.                                         foreach (ObjectId oid in res.Value.GetObjectIds())
  82.                                         {
  83.                                             if (oid != null)
  84.                                             {
  85.                                                 DBObject objfi = tr.GetObject(oid, OpenMode.ForRead);
  86.                                                 if (objfi is BlockReference)
  87.                                                 {
  88.                                                     BlockReference br = objfi as BlockReference;
  89.                                                     br.Explode(objectsforintersectcheck);
  90.                                                 }
  91.                                                 objectsforintersectcheck.Add(objfi);
  92.                                             }
  93.                                         }
  94.                                     }
  95.                                     foreach (ObjectId oid in mtexts)
  96.                                     {
  97.                                         DBObject objfi = tr.GetObject(oid, OpenMode.ForRead);
  98.                                         if (!objectsforintersectcheck.Contains(objfi)) objectsforintersectcheck.Add(objfi);
  99.                                     }
  100.                                     if (!objectsforintersectcheck.Contains(lwp)) objectsforintersectcheck.Add(lwp);
  101.                                     bool allintersect = false;
  102.                                     MText mt2 = new MText();
  103.                                     mt2.TextHeight = fontheight;
  104.                                     mt2.Location = new Point3d(ptclone.X, ptclone.Y, 0);
  105.                                     mt2.Attachment = AttachmentPoint.MiddleCenter;
  106.                                     if (vertnum == "") mt2.Contents = "0";
  107.                                     else mt2.Contents = vertnum;
  108.                                     ms.AppendEntity(mt2);
  109.                                     tr.AddNewlyCreatedDBObject(mt2, true);
  110.                                     Point3dCollection pts = new Point3dCollection();
  111.                                     foreach (DBObject dbobj in objectsforintersectcheck)
  112.                                     {
  113.                                         Entity entfi = dbobj as Entity;
  114.                                         mt2.IntersectWith(entfi, Intersect.OnBothOperands, pts, 0, 0);
  115.                                         if (pts.Count > 0)
  116.                                         {
  117.                                             allintersect = true;
  118.                                         }
  119.                                     }
  120.                                     mt2.Erase();
  121.                                     if (!allintersect)
  122.                                     {
  123.                                         smartalgpt[i] = lwp2.GetPoint3dAt(i);
  124.                                         ptclone = new Point2d(smartalgpt[i].X, smartalgpt[i].Y);////
  125.                                     }
  126.                                     else
  127.                                     {
  128.                                         bool happened = false;
  129.                                         Line[] lineList = new Line[17];
  130.                                         double gradus = 0;
  131.                                         DBObjectCollection approvedlines = new DBObjectCollection();
  132.                                         for (int k = 0; k < 17; k++)
  133.                                         {
  134.                                             Vector3d vec3d = new Vector3d();
  135.                                             try
  136.                                             {
  137.                                                 vec3d = lwp.GetFirstDerivative(lwp.GetParameterAtPoint(lwp.GetPoint3dAt(i)));
  138.                                             }
  139.                                             catch (PlatformDb.Runtime.Exception ex)
  140.                                             {
  141.                                                 vec3d = new Vector3d(lwp.GetPoint3dAt(i).X, lwp.GetPoint3dAt(i).Y, lwp.GetPoint3dAt(i).Z);
  142.                                                 ed.WriteMessage("\n" + ex.Message);
  143.                                             }
  144.                                             vec3d = vec3d.GetNormal() * 999999.0;
  145.                                             Vector3d vec3dshort = vec3d.GetNormal() * dist;
  146.                                             vec3d = vec3d.TransformBy(Matrix3d.Rotation(gradus / 180.0 * Math.PI, doc.Editor.CurrentUserCoordinateSystem.CoordinateSystem3d.Zaxis, Point3d.Origin));
  147.                                             vec3dshort = vec3dshort.TransformBy(Matrix3d.Rotation(gradus / 180.0 * Math.PI, doc.Editor.CurrentUserCoordinateSystem.CoordinateSystem3d.Zaxis, Point3d.Origin));
  148.                                             Line line = new Line(lwp.GetPoint3dAt(i), lwp.GetPoint3dAt(i) + vec3d);
  149.                                             Line lineshort = new Line(lwp.GetPoint3dAt(i), lwp.GetPoint3dAt(i) + vec3dshort);
  150.                                             lineList[k] = line;
  151.                                             Point3dCollection points = new Point3dCollection();
  152.                                             line.IntersectWith(lwp, Intersect.OnBothOperands, points, 0, 0);
  153.                                             if (points.Count == 1)
  154.                                             {
  155.                                                 approvedlines.Add(lineshort);
  156.                                             }
  157.                                             gradus = gradus + 22.5;
  158.                                         }
  159.                                         foreach (Line appline in approvedlines)
  160.                                         {
  161.                                             ms.AppendEntity(appline);
  162.                                             tr.AddNewlyCreatedDBObject(appline, true);
  163.                                             MText mt3 = new MText();
  164.                                             mt3.TextHeight = fontheight;
  165.                                             mt3.Location = appline.EndPoint;
  166.                                             mt3.Attachment = AttachmentPoint.MiddleCenter;
  167.                                             if (vertnum == "") mt3.Contents = "0";
  168.                                             else mt3.Contents = vertnum;
  169.                                             ms.AppendEntity(mt3);
  170.                                             tr.AddNewlyCreatedDBObject(mt3, true);
  171.                                             pts = new Point3dCollection();
  172.                                             bool intersect = false;
  173.                                             foreach (DBObject dbobj in objectsforintersectcheck)
  174.                                             {
  175.                                                 Entity entfi = dbobj as Entity;
  176.                                                 mt3.IntersectWith(entfi, Intersect.OnBothOperands, pts, 0, 0);
  177.                                                 if (pts.Count > 0)
  178.                                                 {
  179.                                                     intersect = true;
  180.                                                 }
  181.                                             }
  182.                                             mt3.Erase();
  183.                                             if (!intersect)
  184.                                             {
  185.                                                 smartalgpt[i] = appline.EndPoint;
  186.                                                 ptclone = new Point2d(smartalgpt[i].X, smartalgpt[i].Y);////*/
  187.                                                 happened = true;
  188.                                                 break;
  189.                                             }
  190.                                         }
  191.                                         if (happened == false)
  192.                                         {
  193.                                             ed.WriteMessage("\nСвободное место для вершины не найдено: " + vertnum);
  194.                                         }
  195.                                     }
  196.                                 }
  197.                                 int nextpoint = i + 1;
  198.                                 if (nextpoint >= vn2) nextpoint = 0;
  199.                                 Point2d pt2 = lwp2.GetPoint2dAt(nextpoint);
  200.                                 if (smartalg)
  201.                                 {
  202.                                     pt2 = new Point2d(smartalgpt[nextpoint].X, smartalgpt[nextpoint].Y);
  203.                                 }
  204.                                 if (!poryadkn) vertnum = (i + 1).ToString();
  205.                                 else vertnum = totalporyadcount.ToString();
  206.                                 ObjectId mtId;
  207.                                 MText mt = new MText();
  208.                                 mt.TextHeight = fontheight;
  209.                                 mt.Location = new Point3d(ptclone.X, ptclone.Y, 0);
  210.                                 mt.Attachment = AttachmentPoint.MiddleCenter;
  211.                                 mt.Contents = vertnum;
  212.                                 mtId = ms.AppendEntity(mt);
  213.                                 tr.AddNewlyCreatedDBObject(mt, true);
  214.                                 totalporyadcount++;
  215.                                 mtexts.Add(mtId);
  216.                             }
  217.                         }
  218.                     }
  219.                     tr.Commit();
  220.                 }
  221.             }
  222.         }
  223.  
  224.  
  225.  
  226.         public static PromptSelectionResult SelectByPolyline(Editor ed, Polyline pline, bool mode, params TypedValue[] filter)
  227.         {
  228.             Point3dCollection polygon = new Point3dCollection();
  229.             for (int i = 0; i < pline.NumberOfVertices; i++)
  230.             {
  231.                 polygon.Add(pline.GetPoint3dAt(i));
  232.             }
  233.             PromptSelectionResult result;
  234.             ViewTableRecord view = ed.GetCurrentView();
  235.             Zoom(ed, pline.GeometricExtents);
  236.             if (mode)
  237.                 result = ed.SelectCrossingPolygon(polygon, new SelectionFilter(filter));
  238.             else
  239.                 result = ed.SelectWindowPolygon(polygon, new SelectionFilter(filter));
  240.             ed.SetCurrentView(view);
  241.             return result;
  242.         }
  243.  
  244.         public static void Zoom(Editor ed, Extents3d extents)
  245.         {
  246.             using (ViewTableRecord view = ed.GetCurrentView())
  247.             {
  248.                 Matrix3d worldToEye =
  249.                     Matrix3d.Rotation(-view.ViewTwist, view.ViewDirection, view.Target) *
  250.                     Matrix3d.Displacement(view.Target - Point3d.Origin) *
  251.                     Matrix3d.PlaneToWorld(view.ViewDirection)
  252.                     .Inverse();
  253.                 extents.TransformBy(worldToEye);
  254.                 view.Width = extents.MaxPoint.X - extents.MinPoint.X;
  255.                 view.Height = extents.MaxPoint.Y - extents.MinPoint.Y;
  256.                 view.CenterPoint = new Point2d(
  257.                     (extents.MaxPoint.X + extents.MinPoint.X) / 2.0,
  258.                     (extents.MaxPoint.Y + extents.MinPoint.Y) / 2.0);
  259.                 ed.SetCurrentView(view);
  260.             }
  261.         }
  262.     }
  263. }

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

  • Administrator
  • *****
  • Сообщений: 13898
  • Карма: 1790
  • Рыцарь ObjectARX
  • Skype: rivilis
Задача непростая, неоднозначная, не всегда имеющая решение. Ну и постановка достаточно размытая...
В коде сразу увидел ошибки связанные с методами IntersectWith - они работают далеко не со всеми типами примитивов.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн trir

  • ADN Club
  • ****
  • Сообщений: 475
  • Карма: 63
надо строить граф

Цитировать
Может существует какая-либо функция API для этого? Как думаете, решаемая задача?
В Civil'е

Оффлайн Привалов Дмитрий

  • ADN Club
  • *****
  • Сообщений: 554
  • Карма: 119
Вобщем нумерует оно в итоге коряво.
А что конкретно тебя не устраивает?
Вроде задача почти решена.

на первом этапе определи точки-вершины, для которых нужно проставить номера.
Считай полилинию в память(или вершины в массив), удали наложенные вершины. и проряди рядом стоящие вершины.

Для проверки можешь добавить оптимизированную полилинию в чертеж и проверить где будут вершины.

на втором этапе тебе нужно просто подписать все вершины, оставшиеся в полилинии.
расставляешь номера по своему алгоритму , а где место не найдено, ставь текст в вершину полилинии. Чтобы оператор мог вручную перенести куда надо. Можешь выделить место, где не смог расставить красным кругом или закинуть в другой слой.
Как мне кажется не хорошо пропускать номера или писать много в консоль, потом дольше разбираться.

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

  • ADN OPEN
  • Сообщений: 25
  • Карма: 3
надо строить граф

Цитировать
Может существует какая-либо функция API для этого? Как думаете, решаемая задача?
В Civil'е
Спасибо, но Civil'а у нас к сожалению нет

Вобщем нумерует оно в итоге коряво.
А что конкретно тебя не устраивает?
Вроде задача почти решена.

на первом этапе определи точки-вершины, для которых нужно проставить номера.
Считай полилинию в память(или вершины в массив), удали наложенные вершины. и проряди рядом стоящие вершины.

Для проверки можешь добавить оптимизированную полилинию в чертеж и проверить где будут вершины.

на втором этапе тебе нужно просто подписать все вершины, оставшиеся в полилинии.
расставляешь номера по своему алгоритму , а где место не найдено, ставь текст в вершину полилинии. Чтобы оператор мог вручную перенести куда надо. Можешь выделить место, где не смог расставить красным кругом или закинуть в другой слой.
Как мне кажется не хорошо пропускать номера или писать много в консоль, потом дольше разбираться.
Спасибо за дельные советы! Да я бы и сам впринципе добил бы так, чтобы оно нумеровало максимально верно, просто сроки были "до вчера", и я подумал, мало ли, может есть какая-нить функция для этого, или кто-то похожую задачу уже решал, вот и создал тему :)

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

  • Administrator
  • *****
  • Сообщений: 13898
  • Карма: 1790
  • Рыцарь ObjectARX
  • Skype: rivilis
Как мне кажется не хорошо пропускать номера или писать много в консоль, потом дольше разбираться.
Насчет пропуска номеров - не знаю. Зависит от постановки задачи. А вот то, что писать в консоль бессмысленно - это точно. Тем более, что нумеруются не вершины одной, а всех выбранных полилиний. Найти по пропущенным номерам, выведенным в консоли, нужные мне видится нереальным. Или потребуется еще одна программа для этого...
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

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

  • ADN OPEN
  • Сообщений: 25
  • Карма: 3
ну вывод в консоль был сделан чисто для отладки :)
понятно, что нужно улучшать алгоритм, а те вершины которым места не нашлось лепить в самом месте вершины без отскока