Thư viện TryCombine
1 Thêm class TryCombineExts.cs
Lưu mã sau dưới dạng tệp tin TryCombineExts.cs
Code:
using Autodesk.AutoCAD.DatabaseServices; using Autodesk.AutoCAD.Geometry; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace AJS_TryCombine { static class TryCombineExts { public static DBObjectCollection TryCombine(this DBObjectCollection cvs, bool samelayer = false, double tol = 1e-5) { DBObjectCollection res = new DBObjectCollection(); if (cvs.Count < 2) return cvs; // Explode Region -> collection of Curves / Regions // Create a plane to convert 3D coords // into Region coord system bool finished = false; while (!finished && cvs.Count > 0) { // Count the Curves and the non-Curves, and find // the index of the first Curve in the collection int cvCnt = 0, nonCvCnt = 0, fstCvIdx = -1; for (int i = 0; i < cvs.Count; i++) { Curve tmpCv = cvs[i] as Curve; if (tmpCv == null) nonCvCnt++; else { if (tmpCv.Closed || tmpCv.StartPoint.DistanceTo(tmpCv.EndPoint) < tol) { res.Add(tmpCv); cvs.Remove(tmpCv); // Decrement, so we don't miss an item i--; } else { cvCnt++; if (fstCvIdx == -1) fstCvIdx = i; } } } if (fstCvIdx >= 0) { // For the initial segment take the first // Curve in the collection Curve fstCv = (Curve)cvs[fstCvIdx]; // The resulting Polyline Polyline p = new Polyline(); p.XData = fstCv.XData; //fstCv.CopyPropertiesTo(p); // Set common entity properties from the Region // Add the first two vertices, but only set the // bulge on the first (the second will be set // retroactively from the second segment) // We also assume the first segment is counter- // clockwise (the default for arcs), as we're // not swapping the order of the vertices to // make them fit the Polyline's order //EDs.Princ(fstCv.StartPoint.ToString() + " d2=" + fstCv.StartPoint.To2d()); p.AddVertexAt(p.NumberOfVertices, fstCv.StartPoint.To2d(), BulgeFromCurve(fstCv, false), 0, 0); p.AddVertexAt(p.NumberOfVertices, fstCv.EndPoint.To2d(), 0, 0, 0); cvs.Remove(fstCv); // The next point to look for Point3d nextPt = fstCv.EndPoint; // We no longer need the curve //try { if (fstCv.Layer != "" && fstCv.LayerId != ObjectId.Null) p.LayerId = fstCv.LayerId; if (fstCv.ColorIndex >= 0 && fstCv.ColorIndex <= 256) p.ColorIndex = fstCv.ColorIndex; p.LineWeight = fstCv.LineWeight; } //catch { } //fstCv.Dispose(); // Find the line that is connected to // the next point // If for some reason the lines returned were not // connected, we could loop endlessly. // So we store the previous curve count and assume // that if this count has not been decreased by // looping completely through the segments once, // then we should not continue to loop. // Hopefully this will never happen, as the curves // should form a closed loop, but anyway... // Set the previous count as artificially high, // so that we loop once, at least. int prevCnt = cvs.Count + 1; while (cvs.Count > nonCvCnt && cvs.Count < prevCnt) { prevCnt = cvs.Count; foreach (DBObject obj in cvs) { Curve cv = obj as Curve; if (cv != null && (!samelayer || cv.Layer == p.Layer)) { // If one end of the curve connects with the // point we're looking for... if (cv.StartPoint.Equal(nextPt, tol) || cv.EndPoint.Equal(nextPt, tol)) { // Calculate the bulge for the curve and // set it on the previous vertex double bulge = BulgeFromCurve(cv, cv.EndPoint.Equal(nextPt, tol)); if (bulge != 0.0) p.SetBulgeAt(p.NumberOfVertices - 1, bulge); // Reverse the points, if needed if (cv.StartPoint.Equal(nextPt, tol)) nextPt = cv.EndPoint; else // cv.EndPoint == nextPt nextPt = cv.StartPoint; // Add out new vertex (bulge will be set next // time through, as needed) p.AddVertexAt(p.NumberOfVertices, nextPt.To2d(), 0, 0, 0); // Remove our curve from the list, which // decrements the count, of course cvs.Remove(cv); //cv.Dispose(); break; } } } } p.ReverseCurve(); nextPt = p.EndPoint; // We no longer need the curve // Find the line that is connected to // the next point // If for some reason the lines returned were not // connected, we could loop endlessly. // So we store the previous curve count and assume // that if this count has not been decreased by // looping completely through the segments once, // then we should not continue to loop. // Hopefully this will never happen, as the curves // should form a closed loop, but anyway... // Set the previous count as artificially high, // so that we loop once, at least. prevCnt = cvs.Count + 1; while (cvs.Count > nonCvCnt && cvs.Count < prevCnt) { prevCnt = cvs.Count; foreach (DBObject obj in cvs) { Curve cv = obj as Curve; if (cv != null && (!samelayer || cv.Layer == p.Layer)) { // If one end of the curve connects with the // point we're looking for... if (cv.StartPoint.Equal(nextPt, tol) || cv.EndPoint.Equal(nextPt, tol)) { // Calculate the bulge for the curve and // set it on the previous vertex double bulge = BulgeFromCurve(cv, cv.EndPoint.Equal(nextPt, tol)); if (bulge != 0.0) p.SetBulgeAt(p.NumberOfVertices - 1, bulge); // Reverse the points, if needed if (cv.StartPoint.Equal(nextPt, tol)) nextPt = cv.EndPoint; else // cv.EndPoint == nextPt nextPt = cv.StartPoint; // Add out new vertex (bulge will be set next // time through, as needed) p.AddVertexAt(p.NumberOfVertices, nextPt.To2d(), 0, 0, 0); // Remove our curve from the list, which // decrements the count, of course cvs.Remove(cv); //cv.Dispose(); break; } } } } // Once we have added all the Polyline's vertices, // transform it to the original region's plane //p.TransformBy(Matrix3d.PlaneToWorld(pl)); p.ReverseCurve(); res.Add(p); if (cvs.Count == nonCvCnt) finished = true; } // If there are any Regions in the collection, // recurse to explode and add their geometry if (nonCvCnt > 0 && cvs.Count > 0) { foreach (DBObject obj in cvs) { Region subReg = obj as Region; if (subReg != null) { foreach (Entity e in subReg.ToPolylines()) res.Add(e); cvs.Remove(subReg); //subReg.Dispose(); } } } if (cvs.Count == 0) finished = true; } return res; } public static Point2d To2d(this Point3d p) { return new Point2d(p.X, p.Y); } public static bool Equal(this Point3d pt, Point3d thatpt, double tol = 0.000001) => pt.DistanceTo(thatpt) < tol; public static double BulgeFromCurve(this Curve cv, bool clockwise) { double bulge = 0.0; Arc a = cv as Arc; if (a != null) { double newStart; // The start angle is usually greater than the end, // as arcs are all counter-clockwise. // (If it isn't it's because the arc crosses the // 0-degree line, and we can subtract 2PI from the // start angle.) if (a.StartAngle > a.EndAngle) newStart = a.StartAngle - 8 * Math.Atan(1); else newStart = a.StartAngle; // Bulge is defined as the tan of // one fourth of the included angle bulge = Math.Tan((a.EndAngle - newStart) / 4); // If the curve is clockwise, we negate the bulge if (clockwise) bulge = -bulge; } return bulge; } } }
Cách dùng
1 Thêm class cmdTryCombine.cs
Lưu mã sau dưới dạng tệp tin cmdTryCombine.cs
Code:
// (C) Copyright 2024 by // using Autodesk.AutoCAD.ApplicationServices; using Autodesk.AutoCAD.DatabaseServices; using Autodesk.AutoCAD.EditorInput; using Autodesk.AutoCAD.Runtime; using System.Linq; // This line is not mandatory, but improves loading performances [assembly: CommandClass(typeof(AJS_TryCombine.MyCommands))] namespace AJS_TryCombine { // This class is instantiated by AutoCAD for each document when // a command is called by the user the first time in the context // of a given document. In other words, non static data in this class // is implicitly per-document! public class MyCommands { // Modal Command with localized name [CommandMethod("TryCombine", CommandFlags.Modal)] public void MyCommand_TryCombine() // This method can have any name { // Put your command code here Document doc = Application.DocumentManager.MdiActiveDocument; if (doc != null) { var ed = doc.Editor; ed.WriteMessage("Hello, this is your first command. Create by www.lisp.vn"); var psr = ed.GetSelection(new SelectionFilter(new TypedValue[] { new TypedValue(0, "*line,arc") })); if (psr.Status != PromptStatus.OK) return; var ids = psr.Value.GetObjectIds().ToList(); using (var tr = HostApplicationServices.WorkingDatabase.TransactionManager.StartTransaction()) { var ents = ids.Select(x => tr.GetObject(x, OpenMode.ForWrite, false, true) as Entity).ToList(); var cvs = new DBObjectCollection(); foreach (var ent in ents) { if (ent is Arc || ent is Line) cvs.Add(ent.Clone() as Curve); else { var dbs = new DBObjectCollection(); ent.Explode(dbs); foreach (Entity e in dbs) if (e is Arc || e is Line) cvs.Add(e as Curve); } } var btr = tr.GetObject(HostApplicationServices.WorkingDatabase.CurrentSpaceId, OpenMode.ForWrite) as BlockTableRecord; var pls = cvs.TryCombine(); foreach (Curve pl in pls) { btr.AppendEntity(pl); tr.AddNewlyCreatedDBObject(pl, true); } tr.Commit(); } } } } }
Link tải Solution
Nhóm AutoCAD dotNet
Link tham gia nhóm Zalo: http://dnz.lisp.vn
---------------------------------------------------------------------------------------------
Mọi thông tin xin liên hệ Fanpage AutoLISP Thật là đơn giản!
Cảm ơn bạn đã theo dõi!
Không có nhận xét nào:
Đăng nhận xét