Как восстановить потерянные границы штриховки?
Вопрос:
Как можно восстановить границы штриховки, если они были потеряны по каким-то причинам?
Ответ:
В 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 можно добиться тех же результатов:
- 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;
- if (btr == null) return;
- 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 (Math.Abs(arc2d.StartAngle - arc2d.EndAngle) < 1e-5) {
- using (Circle ent = new Circle(new Point3d(plane, arc2d.Center), plane.Normal, arc2d.Radius)) {
- btr.AppendEntity(ent);
- tr.AddNewlyCreatedDBObject(ent, true);
- }
- } else {
- double angle = new Vector3d(plane, arc2d.ReferenceVector).AngleOnPlane(plane);
- using (Arc ent = new Arc(new Point3d(plane, arc2d.Center), arc2d.Radius, arc2d.StartAngle + angle, arc2d.EndAngle + angle)) {
- btr.AppendEntity(ent);
- tr.AddNewlyCreatedDBObject(ent, true);
- }
- }
- } else if (ellipse2d != null) {
- //-------------------------------------------------------------------------------------------
- // Ошибка: Нельзя присвоить StartParam и EndParam примитиву эллипс:
- // 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
- //---------------------------------------------------------------------------------------------
- // Обходим эту ошибку используя «отражение» (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();
- }
- }
- }
- }
Источник: 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
Отредактировано 04.08.2013 в 17:12:12