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

Автор Тема: Как восстановить потерянные границы штриховки?  (Прочитано 14058 раз)

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

Оффлайн Александр РивилисАвтор темы

  • Administrator
  • *****
  • Сообщений: 13886
  • Карма: 1788
  • Рыцарь ObjectARX
  • Skype: rivilis
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн Александр РивилисАвтор темы

  • Administrator
  • *****
  • Сообщений: 13886
  • Карма: 1788
  • Рыцарь ObjectARX
  • Skype: rivilis
Мне подсказали, что в ряде случаев код не работает:
1. Если граница штриховки окружность;
2. Если один из дуговых сегментов по часовой стрелке;
В результате исправленный код выглядит так:
Код - 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.       {
  27.         Hatch hatch = tr.GetObject(prRes.ObjectId, OpenMode.ForRead) as Hatch;
  28.         if (hatch != null)
  29.         {
  30.           BlockTableRecord btr = tr.GetObject(hatch.OwnerId, OpenMode.ForWrite) as BlockTableRecord;
  31.           Plane plane = hatch.GetPlane();
  32.           int nLoops = hatch.NumberOfLoops;
  33.           for (int i = 0; i < nLoops; i++)
  34.           {
  35.             HatchLoop loop = hatch.GetLoopAt(i);
  36.             if (loop.IsPolyline)
  37.             {
  38.               using (Polyline poly = new Polyline())
  39.               {
  40.                 int iVertex = 0;
  41.                 foreach (BulgeVertex bv in loop.Polyline)
  42.                 {
  43.                   poly.AddVertexAt(iVertex++, bv.Vertex, bv.Bulge, 0.0, 0.0);
  44.                 }
  45.                 btr.AppendEntity(poly);
  46.                 tr.AddNewlyCreatedDBObject(poly, true);
  47.               }
  48.             }
  49.             else
  50.             {
  51.               foreach (Curve2d cv in loop.Curves)
  52.               {
  53.                 LineSegment2d line2d = cv as LineSegment2d;
  54.                 CircularArc2d arc2d = cv as CircularArc2d;
  55.                 EllipticalArc2d ellipse2d = cv as EllipticalArc2d;
  56.                 NurbCurve2d spline2d = cv as NurbCurve2d;
  57.                 if (line2d != null)
  58.                 {
  59.                   using (Line ent = new Line())
  60.                   {
  61.                     ent.StartPoint = new Point3d(plane, line2d.StartPoint);
  62.                     ent.EndPoint = new Point3d(plane, line2d.EndPoint);
  63.                     btr.AppendEntity(ent);
  64.                     tr.AddNewlyCreatedDBObject(ent, true);
  65.                   }
  66.                 }
  67.                 else if (arc2d != null)
  68.                 {
  69.                   if (arc2d.IsClosed() || Math.Abs(arc2d.EndAngle - arc2d.StartAngle) < 1e-5)
  70.                   {
  71.                     using (Circle ent = new Circle(new Point3d(plane, arc2d.Center), plane.Normal, arc2d.Radius))
  72.                     {
  73.                       btr.AppendEntity(ent);
  74.                       tr.AddNewlyCreatedDBObject(ent, true);
  75.                     }
  76.                   }
  77.                   else
  78.                   {
  79.                     if (arc2d.IsClockWise) {
  80.                       arc2d = arc2d.GetReverseParameterCurve() as CircularArc2d;
  81.                     }
  82.                     double angle = new Vector3d(plane, arc2d.ReferenceVector).AngleOnPlane(plane);
  83.                     double startAngle = arc2d.StartAngle + angle;
  84.                     double endAngle = arc2d.EndAngle + angle;
  85.                     using (Arc ent = new Arc(new Point3d(plane, arc2d.Center), plane.Normal, arc2d.Radius, startAngle, endAngle))
  86.                     {
  87.                       btr.AppendEntity(ent);
  88.                       tr.AddNewlyCreatedDBObject(ent, true);
  89.                     }
  90.                   }
  91.                 }
  92.                 else if (ellipse2d != null)
  93.                 {
  94.                   //-------------------------------------------------------------------------------------------
  95.                   // Bug: Can not assign StartParam and EndParam of Ellipse:
  96.                   // Ellipse ent = new Ellipse(new Point3d(plane, e2d.Center), plane.Normal,
  97.                   //      new Vector3d(plane,e2d.MajorAxis) * e2d.MajorRadius,
  98.                   //      e2d.MinorRadius / e2d.MajorRadius, e2d.StartAngle, e2d.EndAngle);
  99.                   // ent.StartParam = e2d.StartAngle;
  100.                   // ent.EndParam = e2d.EndAngle;
  101.                   // error CS0200: Property or indexer 'Autodesk.AutoCAD.DatabaseServices.Curve.StartParam' cannot be assigned to -- it is read only
  102.                   // error CS0200: Property or indexer 'Autodesk.AutoCAD.DatabaseServices.Curve.EndParam' cannot be assigned to -- it is read only
  103.                   //---------------------------------------------------------------------------------------------
  104.                   // Workaround is using Reflection
  105.                   //
  106.                   using (Ellipse ent = new Ellipse(new Point3d(plane, ellipse2d.Center), plane.Normal,
  107.                        new Vector3d(plane, ellipse2d.MajorAxis) * ellipse2d.MajorRadius,
  108.                        ellipse2d.MinorRadius / ellipse2d.MajorRadius, ellipse2d.StartAngle, ellipse2d.EndAngle))
  109.                   {
  110.                     ent.GetType().InvokeMember("StartParam", BindingFlags.SetProperty, null,
  111.                       ent, new object[] { ellipse2d.StartAngle });
  112.                     ent.GetType().InvokeMember("EndParam", BindingFlags.SetProperty, null,
  113.                       ent, new object[] { ellipse2d.EndAngle });
  114.                     btr.AppendEntity(ent);
  115.                     tr.AddNewlyCreatedDBObject(ent, true);
  116.                   }
  117.  
  118.                 }
  119.                 else if (spline2d != null)
  120.                 {
  121.                   if (spline2d.HasFitData)
  122.                   {
  123.                     NurbCurve2dFitData n2fd = spline2d.FitData;
  124.                     using (Point3dCollection p3ds = new Point3dCollection())
  125.                     {
  126.                       foreach (Point2d p in n2fd.FitPoints) p3ds.Add(new Point3d(plane, p));
  127.                       using (Spline ent = new Spline(p3ds, new Vector3d(plane, n2fd.StartTangent), new Vector3d(plane, n2fd.EndTangent),
  128.                         /* n2fd.KnotParam, */  n2fd.Degree, n2fd.FitTolerance.EqualPoint))
  129.                       {
  130.                         btr.AppendEntity(ent);
  131.                         tr.AddNewlyCreatedDBObject(ent, true);
  132.                       }
  133.                     }
  134.                   }
  135.                   else
  136.                   {
  137.                     NurbCurve2dData n2fd = spline2d.DefinitionData;
  138.                     using (Point3dCollection p3ds = new Point3dCollection())
  139.                     {
  140.                       DoubleCollection knots = new DoubleCollection(n2fd.Knots.Count);
  141.                       foreach (Point2d p in n2fd.ControlPoints) p3ds.Add(new Point3d(plane, p));
  142.                       foreach (double k in n2fd.Knots) knots.Add(k);
  143.                       double period = 0;
  144.                       using (Spline ent = new Spline(n2fd.Degree, n2fd.Rational,
  145.                                spline2d.IsClosed(), spline2d.IsPeriodic(out period),
  146.                                p3ds, knots, n2fd.Weights, n2fd.Knots.Tolerance, n2fd.Knots.Tolerance))
  147.                       {
  148.                         btr.AppendEntity(ent);
  149.                         tr.AddNewlyCreatedDBObject(ent, true);
  150.                       }
  151.                     }
  152.                   }
  153.                 }
  154.               }
  155.             }
  156.           }
  157.         }
  158.         tr.Commit();
  159.       }
  160.     }
  161.   }
  162. }
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн avc

  • ADN Club
  • *****
  • Сообщений: 822
  • Карма: 167
    • Мои плагины к Автокаду
Указанный код работает только в плоскости XY. Требуется назначить нормаль для линии и полилинии, а полилинию еще сдвинуть на plane.PointOnPlane.
У сплайнов направление нормали может получиться противоположным к plane.Normal. Как исправить - я пока не придумал. Трансформация Mirroring через plane почему-то не меняет нормаль. Хотя должна бы...

Оффлайн Александр РивилисАвтор темы

  • Administrator
  • *****
  • Сообщений: 13886
  • Карма: 1788
  • Рыцарь ObjectARX
  • Skype: rivilis
Трансформация Mirroring через plane почему-то не меняет нормаль. Хотя должна бы...
Думаешь должна? Если этот сплайн находится в этой плоскости, то отзеркаливание ничего не делает. Из спортивного интереса можешь попробовать метод ReverseCurve.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн avc

  • ADN Club
  • *****
  • Сообщений: 822
  • Карма: 167
    • Мои плагины к Автокаду
Логично было бы, чтоб зеркалился сплайн, как все остальные объекты. А он остается тот же самый даже если сдвинуть плоскость в сторону (просто перемещается). Для себя уже решил эту проблему - мне в любом случае нужны регионы. Преобразую в Region и он прекрасно зеркалит нормаль.

Оффлайн Александр РивилисАвтор темы

  • Administrator
  • *****
  • Сообщений: 13886
  • Карма: 1788
  • Рыцарь ObjectARX
  • Skype: rivilis
Логично было бы, чтоб зеркалился сплайн, как все остальные объекты. А он остается тот же самый даже если сдвинуть плоскость в сторону (просто перемещается). Для себя уже решил эту проблему - мне в любом случае нужны регионы. Преобразую в Region и он прекрасно зеркалит нормаль.
Вообще-то Spline - это 3D-объект (в отличии от Polyline и Region). Что ты понимаешь под его нормалью? Свойства Normal у него нет.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн avc

  • ADN Club
  • *****
  • Сообщений: 822
  • Карма: 167
    • Мои плагины к Автокаду
Свойства Normal у него нет.
О да, со сплайнами все сложно :) Есть плоские сплайны (IsPlanar == true), у них можно вызвать GetPlane. Вот там и нормаль.
И для меня важно, что по этой плоскости и ее нормали уже будет строиться Region (CreateFromCurves). Так как у одной штриховки петли-сплайны получаются с разными нормалями, то они между собой не склеиваются и не вычитаются и я построить полный регион с дырками и островками не могу. Ну то есть не мог. Уже выкрутился.