Статьи > Опубликованные статьи
Как восстановить потерянные границы штриховки?
Александр Ривилис:
Как восстановить потерянные границы штриховки?
Александр Ривилис:
Мне подсказали, что в ряде случаев код не работает:
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 и он прекрасно зеркалит нормаль.
Навигация
Перейти к полной версии