Статьи > Опубликованные статьи

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

(1/2) > >>

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

Александр Ривилис:
Мне подсказали, что в ряде случаев код не работает:
1. Если граница штриховки окружность;
2. Если один из дуговых сегментов по часовой стрелке;
В результате исправленный код выглядит так:

--- Код - C# [Выбрать] ---using System;using System.Reflection;using Autodesk.AutoCAD.Runtime;using Autodesk.AutoCAD.ApplicationServices;using Autodesk.AutoCAD.DatabaseServices;using Autodesk.AutoCAD.Geometry;using Autodesk.AutoCAD.EditorInput; [assembly: CommandClass(typeof(Rivilis.HatchUtils))] namespace Rivilis{  public class HatchUtils  {    [CommandMethod("RHB", CommandFlags.Modal)]    public void RHB()    {      Document doc = Application.DocumentManager.MdiActiveDocument;      Editor ed = doc.Editor;      PromptEntityOptions prOps = new PromptEntityOptions("\nSelect Hatch: ");      prOps.SetRejectMessage("\nNot a Hatch");      prOps.AddAllowedClass(typeof(Hatch), false);      PromptEntityResult prRes = ed.GetEntity(prOps);      if (prRes.Status != PromptStatus.OK) return;      using (Transaction tr = doc.TransactionManager.StartTransaction())      {        Hatch hatch = tr.GetObject(prRes.ObjectId, OpenMode.ForRead) as Hatch;        if (hatch != null)        {          BlockTableRecord btr = tr.GetObject(hatch.OwnerId, OpenMode.ForWrite) as BlockTableRecord;          Plane plane = hatch.GetPlane();          int nLoops = hatch.NumberOfLoops;          for (int i = 0; i < nLoops; i++)          {            HatchLoop loop = hatch.GetLoopAt(i);            if (loop.IsPolyline)            {              using (Polyline poly = new Polyline())              {                int iVertex = 0;                foreach (BulgeVertex bv in loop.Polyline)                {                  poly.AddVertexAt(iVertex++, bv.Vertex, bv.Bulge, 0.0, 0.0);                }                btr.AppendEntity(poly);                tr.AddNewlyCreatedDBObject(poly, true);              }            }            else            {              foreach (Curve2d cv in loop.Curves)              {                LineSegment2d line2d = cv as LineSegment2d;                CircularArc2d arc2d = cv as CircularArc2d;                EllipticalArc2d ellipse2d = cv as EllipticalArc2d;                NurbCurve2d spline2d = cv as NurbCurve2d;                if (line2d != null)                {                  using (Line ent = new Line())                  {                    ent.StartPoint = new Point3d(plane, line2d.StartPoint);                    ent.EndPoint = new Point3d(plane, line2d.EndPoint);                    btr.AppendEntity(ent);                    tr.AddNewlyCreatedDBObject(ent, true);                  }                }                else if (arc2d != null)                {                  if (arc2d.IsClosed() || Math.Abs(arc2d.EndAngle - arc2d.StartAngle) < 1e-5)                  {                    using (Circle ent = new Circle(new Point3d(plane, arc2d.Center), plane.Normal, arc2d.Radius))                    {                      btr.AppendEntity(ent);                      tr.AddNewlyCreatedDBObject(ent, true);                    }                  }                  else                  {                    if (arc2d.IsClockWise) {                      arc2d = arc2d.GetReverseParameterCurve() as CircularArc2d;                    }                    double angle = new Vector3d(plane, arc2d.ReferenceVector).AngleOnPlane(plane);                    double startAngle = arc2d.StartAngle + angle;                    double endAngle = arc2d.EndAngle + angle;                    using (Arc ent = new Arc(new Point3d(plane, arc2d.Center), plane.Normal, arc2d.Radius, startAngle, endAngle))                    {                      btr.AppendEntity(ent);                      tr.AddNewlyCreatedDBObject(ent, true);                    }                  }                }                else if (ellipse2d != null)                {                  //-------------------------------------------------------------------------------------------                  // Bug: Can not assign StartParam and EndParam of Ellipse:                  // Ellipse ent = new Ellipse(new Point3d(plane, e2d.Center), plane.Normal,                   //      new Vector3d(plane,e2d.MajorAxis) * e2d.MajorRadius,                  //      e2d.MinorRadius / e2d.MajorRadius, e2d.StartAngle, e2d.EndAngle);                  // ent.StartParam = e2d.StartAngle;                   // ent.EndParam = e2d.EndAngle;                  // error CS0200: Property or indexer 'Autodesk.AutoCAD.DatabaseServices.Curve.StartParam' cannot be assigned to -- it is read only                  // error CS0200: Property or indexer 'Autodesk.AutoCAD.DatabaseServices.Curve.EndParam' cannot be assigned to -- it is read only                  //---------------------------------------------------------------------------------------------                  // Workaround is using Reflection                  //                   using (Ellipse ent = new Ellipse(new Point3d(plane, ellipse2d.Center), plane.Normal,                       new Vector3d(plane, ellipse2d.MajorAxis) * ellipse2d.MajorRadius,                       ellipse2d.MinorRadius / ellipse2d.MajorRadius, ellipse2d.StartAngle, ellipse2d.EndAngle))                  {                    ent.GetType().InvokeMember("StartParam", BindingFlags.SetProperty, null,                      ent, new object[] { ellipse2d.StartAngle });                    ent.GetType().InvokeMember("EndParam", BindingFlags.SetProperty, null,                      ent, new object[] { ellipse2d.EndAngle });                    btr.AppendEntity(ent);                    tr.AddNewlyCreatedDBObject(ent, true);                  }                 }                else if (spline2d != null)                {                  if (spline2d.HasFitData)                  {                    NurbCurve2dFitData n2fd = spline2d.FitData;                    using (Point3dCollection p3ds = new Point3dCollection())                    {                      foreach (Point2d p in n2fd.FitPoints) p3ds.Add(new Point3d(plane, p));                      using (Spline ent = new Spline(p3ds, new Vector3d(plane, n2fd.StartTangent), new Vector3d(plane, n2fd.EndTangent),                        /* n2fd.KnotParam, */  n2fd.Degree, n2fd.FitTolerance.EqualPoint))                      {                        btr.AppendEntity(ent);                        tr.AddNewlyCreatedDBObject(ent, true);                      }                    }                  }                  else                  {                    NurbCurve2dData n2fd = spline2d.DefinitionData;                    using (Point3dCollection p3ds = new Point3dCollection())                    {                      DoubleCollection knots = new DoubleCollection(n2fd.Knots.Count);                      foreach (Point2d p in n2fd.ControlPoints) p3ds.Add(new Point3d(plane, p));                      foreach (double k in n2fd.Knots) knots.Add(k);                      double period = 0;                      using (Spline ent = new Spline(n2fd.Degree, n2fd.Rational,                               spline2d.IsClosed(), spline2d.IsPeriodic(out period),                               p3ds, knots, n2fd.Weights, n2fd.Knots.Tolerance, n2fd.Knots.Tolerance))                      {                        btr.AppendEntity(ent);                        tr.AddNewlyCreatedDBObject(ent, true);                      }                    }                  }                }              }            }          }        }        tr.Commit();      }    }  }}

avc:
Указанный код работает только в плоскости XY. Требуется назначить нормаль для линии и полилинии, а полилинию еще сдвинуть на plane.PointOnPlane.
У сплайнов направление нормали может получиться противоположным к plane.Normal. Как исправить - я пока не придумал. Трансформация Mirroring через plane почему-то не меняет нормаль. Хотя должна бы...

Александр Ривилис:

--- Цитата: avc от 27-04-2024, 18:41:11 ---Трансформация Mirroring через plane почему-то не меняет нормаль. Хотя должна бы...
--- Конец цитаты ---
Думаешь должна? Если этот сплайн находится в этой плоскости, то отзеркаливание ничего не делает. Из спортивного интереса можешь попробовать метод ReverseCurve.

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

Навигация

[0] Главная страница сообщений

[#] Следующая страница

Перейти к полной версии