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

19/07/2013

Как восстановить потерянные границы штриховки?

Вопрос:

Как можно восстановить границы штриховки, если они были потеряны по каким-то причинам?

Ответ:

В AutoCAD’е нет отдельной команды, которая бы восстанавливала контур штриховки, но это можно сделать средствами ObjectARX API.

Наиболее сложной является задача обработки сплайнов в связи с обилием различных типов сплайнов в AutoCAD, таких как сплайн с определяющими точками, рациональный сплайн, нерациональный сплайн, и т.д. Обратите внимание, что проверка ошибок сделана минимальной для краткости. Пожалуйста имейте в виду, что невозможно в точности восстановить оригинальную границу штриховки, так как основные объекты геометрической библиотеки (с префиксом AcGe) в AcDbHatch не соответствуют в точности примитивам AutoCAD (с префиксом AcDb) один в один. Например, если замкнутый контур состоял из множества отрезков в оригинальной границе штриховки, то он станет полилинией в результате операции восстановления.

В примере, восстановленные границы станут красными и будут на текущем слое. Вы можете воспользоваться фильтром выбора для дальнейших модификаций. Для проверки работоспособности программы в архив добавлен файл Test.dwg

Как использовать пример:

1. Постройте приложенный проект при помощи VC 2010 или скопируйте код “BzhRestoreHatchBoundary” в свой собственный проект.

2. Запустите AutoCAD

3. Загрузите ARX-файл

4. Откройте чертеж в котором собираетесь восстановить контуры штриховок

5. Выполните команду с коротким именем RHB или длинным именем RESTOREHATCHBOUNDARY

6. Выберите примитивы штриховок, контуры которых вы хотите восстановить. Вы можете выбрать сразу несколько штриховок одновременно

Здесь код и тестовый файл: RestoreHatchBoundary.zip

Примечание переводчика 1: В последних версиях AutoCAD есть возможность восстановить контур штриховки встроенными методами:

Или команда _HATCHGENERATEBOUNDARY

 

Примечание переводчика 2: средствами AutoCAD .NET API можно добиться тех же результатов:

Код - C#: [Выделить]
  1. using System;
  2. using System.Reflection;
  3. using Autodesk.AutoCAD.Runtime;
  4. using Autodesk.AutoCAD.ApplicationServices;
  5. using Autodesk.AutoCAD.DatabaseServices;
  6. using Autodesk.AutoCAD.Geometry;
  7. using Autodesk.AutoCAD.EditorInput;
  8.  
  9. [assembly: CommandClass(typeof(Rivilis.HatchUtils))]
  10.  
  11. namespace Rivilis
  12. {
  13.   public class HatchUtils
  14.   {
  15.     [CommandMethod("RHB", CommandFlags.Modal)]
  16.     public void RHB()
  17.     {
  18.       Document doc = Application.DocumentManager.MdiActiveDocument;
  19.       Editor ed = doc.Editor;
  20.       PromptEntityOptions prOps = new PromptEntityOptions("\nSelect Hatch: ");
  21.       prOps.SetRejectMessage("\nNot a Hatch");
  22.       prOps.AddAllowedClass(typeof(Hatch), false);
  23.       PromptEntityResult prRes = ed.GetEntity(prOps);
  24.       if (prRes.Status != PromptStatus.OK) return;
  25.       using (Transaction tr = doc.TransactionManager.StartTransaction()) {
  26.         Hatch hatch = tr.GetObject(prRes.ObjectId, OpenMode.ForRead) as Hatch;
  27.         if (hatch != null) {
  28.           BlockTableRecord btr = tr.GetObject(hatch.OwnerId, OpenMode.ForWrite) as BlockTableRecord;
  29.           if (btr == null) return;
  30.           Plane plane = hatch.GetPlane();
  31.           int nLoops = hatch.NumberOfLoops;
  32.           for (int i = 0; i < nLoops; i++) {
  33.             HatchLoop loop = hatch.GetLoopAt(i);
  34.             if (loop.IsPolyline) {
  35.               using (Polyline poly = new Polyline()) {
  36.                 int iVertex = 0;
  37.                 foreach (BulgeVertex bv in loop.Polyline) {
  38.                   poly.AddVertexAt(iVertex++, bv.Vertex, bv.Bulge, 0.0, 0.0);
  39.                 }
  40.                 btr.AppendEntity(poly);
  41.                 tr.AddNewlyCreatedDBObject(poly, true);
  42.               }
  43.             } else {
  44.               foreach (Curve2d cv in loop.Curves) {
  45.                 LineSegment2d line2d = cv as LineSegment2d;
  46.                 CircularArc2d arc2d = cv as CircularArc2d;
  47.                 EllipticalArc2d ellipse2d = cv as EllipticalArc2d;
  48.                 NurbCurve2d spline2d = cv as NurbCurve2d;
  49.                 if (line2d != null) {
  50.                   using (Line ent = new Line()) {
  51.                     ent.StartPoint = new Point3d(plane, line2d.StartPoint);
  52.                     ent.EndPoint = new Point3d(plane, line2d.EndPoint);
  53.                     btr.AppendEntity(ent);
  54.                     tr.AddNewlyCreatedDBObject(ent, true);
  55.                   }
  56.                 } else if (arc2d != null) {
  57.                   if (Math.Abs(arc2d.StartAngle - arc2d.EndAngle) < 1e-5) {
  58.                     using (Circle ent = new Circle(new Point3d(plane, arc2d.Center), plane.Normal, arc2d.Radius)) {
  59.                       btr.AppendEntity(ent);
  60.                       tr.AddNewlyCreatedDBObject(ent, true);
  61.                     }
  62.                   } else {
  63.                     double angle = new Vector3d(plane, arc2d.ReferenceVector).AngleOnPlane(plane);
  64.                     using (Arc ent = new Arc(new Point3d(plane, arc2d.Center), arc2d.Radius, arc2d.StartAngle + angle, arc2d.EndAngle + angle)) {
  65.                       btr.AppendEntity(ent);
  66.                       tr.AddNewlyCreatedDBObject(ent, true);
  67.                     }
  68.                   }
  69.                 } else if (ellipse2d != null) {
  70.                   //-------------------------------------------------------------------------------------------
  71.                   // Ошибка: Нельзя присвоить StartParam и EndParam примитиву  эллипс:
  72.                   // Ellipse ent = new Ellipse(new Point3d(plane, e2d.Center), plane.Normal,
  73.                   //      new Vector3d(plane,e2d.MajorAxis) * e2d.MajorRadius,
  74.                   //      e2d.MinorRadius / e2d.MajorRadius, e2d.StartAngle, e2d.EndAngle);
  75.                   // ent.StartParam = e2d.StartAngle;
  76.                   // ent.EndParam = e2d.EndAngle;
  77.                   // error CS0200: Property or indexer 'Autodesk.AutoCAD.DatabaseServices.Curve.StartParam' cannot be assigned to -- it is read only
  78.                   // error CS0200: Property or indexer 'Autodesk.AutoCAD.DatabaseServices.Curve.EndParam' cannot be assigned to -- it is read only
  79.                   //---------------------------------------------------------------------------------------------
  80.                   // Обходим эту ошибку используя «отражение» (Reflection)
  81.                   //
  82.                   using (Ellipse ent = new Ellipse(new Point3d(plane, ellipse2d.Center), plane.Normal,
  83.                        new Vector3d(plane, ellipse2d.MajorAxis) * ellipse2d.MajorRadius,
  84.                        ellipse2d.MinorRadius / ellipse2d.MajorRadius, ellipse2d.StartAngle, ellipse2d.EndAngle)) {
  85.                     ent.GetType().InvokeMember("StartParam", BindingFlags.SetProperty, null,
  86.                       ent, new object[] { ellipse2d.StartAngle });
  87.                     ent.GetType().InvokeMember("EndParam", BindingFlags.SetProperty, null,
  88.                       ent, new object[] { ellipse2d.EndAngle });
  89.                     btr.AppendEntity(ent);
  90.                     tr.AddNewlyCreatedDBObject(ent, true);
  91.                   }
  92.  
  93.                 } else if (spline2d != null) {
  94.                   if (spline2d.HasFitData) {
  95.                     NurbCurve2dFitData n2fd = spline2d.FitData;
  96.                     using (Point3dCollection p3ds = new Point3dCollection()) {
  97.                       foreach (Point2d p in n2fd.FitPoints) p3ds.Add(new Point3d(plane, p));
  98.                       using (Spline ent = new Spline(p3ds, new Vector3d(plane, n2fd.StartTangent), new Vector3d(plane, n2fd.EndTangent),
  99.                         /* n2fd.KnotParam, */  n2fd.Degree, n2fd.FitTolerance.EqualPoint)) {
  100.                         btr.AppendEntity(ent);
  101.                         tr.AddNewlyCreatedDBObject(ent, true);
  102.                       }
  103.                     }
  104.                   } else {
  105.                     NurbCurve2dData n2fd = spline2d.DefinitionData;
  106.                     using (Point3dCollection p3ds = new Point3dCollection()) {
  107.                       DoubleCollection knots = new DoubleCollection(n2fd.Knots.Count);
  108.                       foreach (Point2d p in n2fd.ControlPoints) p3ds.Add(new Point3d(plane, p));
  109.                       foreach (double k in n2fd.Knots) knots.Add(k);
  110.                       double period = 0;
  111.                       using (Spline ent = new Spline(n2fd.Degree, n2fd.Rational,
  112.                                spline2d.IsClosed(), spline2d.IsPeriodic(out period),
  113.                                p3ds, knots, n2fd.Weights, n2fd.Knots.Tolerance, n2fd.Knots.Tolerance)) {
  114.                         btr.AppendEntity(ent);
  115.                         tr.AddNewlyCreatedDBObject(ent, true);
  116.                       }
  117.                     }
  118.                   }
  119.                 }
  120.               }
  121.             }
  122.           }
  123.         }
  124.         tr.Commit();
  125.       }
  126.     }
  127.   }
  128. }

 

Источник: http://adndevblog.typepad.com/autocad/2013/01/restore-hatch-boundaries-if-they-have-been-lost.html

Обсуждение: http://adn-cis.org/forum/index.php?topic=134.0

 

 

Опубликовано 19.07.2013
Отредактировано 04.08.2013 в 17:12:12