Leaderboard
Popular Content
Showing content with the highest reputation since 09/11/2026 in Posts
-
Attached is an improved version of getfiled that implements powershell with the option to select single or multiple files returning a list of the selected item(s): Examples: (pl:getfiledps "Select Files" (getvar"dwgprefix") "dwg" 0) ; for single selection of file type dwg (pl:getfiledps "Select Files" (strcat (getenv "userprofile") "\\downloads") "dwg;dxf" 1) ; for multiple selection of file types dwg & dxf Feedback & comments are welcome. pl_getfiledps.lsp5 points
-
Yes, I was working on that for my home computer with 2000i. Since I had some home time today with AutoCAD 2000i, I did some updating to your code. Seems to work great with minimal testing. Here is my Test Code... ; ================================================================ ; Test command ; ================================================================ (defun c:SelectDWGs (/ files) (setq files (pl:getfiledps "Select DWG Files" (getvar "DWGPREFIX") "dwg" 1 ) ) (if files (progn (princ "\nSelected files:" ) (foreach file files (princ (strcat "\n" file ) ) ) ) (princ "\nNo files selected." ) ) (princ) ) pl_getfiledps_2000i.lsp3 points
-
I usually just keep it docked on the right side and use ctrl+1 to open it if needed. any of these will open properties (command "Properties") (command "PR") (command "CH") (command "MO")2 points
-
I added a note in the file where to change to keep PowerShell open. ; ---------------------------------------------------------- ; Wait until PowerShell finishes. ; ---------------------------------------------------------- (vlax-invoke-method shell "Run" cmd 0 ; <=== Change 0 to 1 if you want PowerShell to stay open. :vlax-true ) (vlax-release-object shell) ) ) I was running some tests at work to see if there was a method to determine if PowerShell was blocked to give a message... (princ "\nPowerShell access is blocked.") (princ "\nPowerShell access is allowed.")) Right now all I get on the commandline is... error: Automation Error. Description was not provided. Though I had to get to some of my "paid to do" work done yesterday. This is probably above my pay grade. I just realized who the OP is, a big time Guru over at Autodesk forums and AUGI.2 points
-
@Danielm103 Well I did managed to scrape some milliseconds. However not where it counts in the pairing. Most of the gain in collection of entities. So in the end it is still gile's code. ymg Command: PAIRKD --------- TIMING ------------------------------- Collecting entities: 236 milliseconds Building kdTree: 67 milliseconds Pairing lines and texts: 34 milliseconds Coloring lines and texts: 123 milliseconds Total Elapsed Time: 460 milliseconds Total Number of Groups: 102 using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Threading.Tasks; using Gile.AutoCAD.R20.Geometry; using Autodesk.AutoCAD.EditorInput; using Autodesk.AutoCAD.ApplicationServices; using Autodesk.AutoCAD.DatabaseServices; using Autodesk.AutoCAD.Geometry; using Autodesk.AutoCAD.Runtime; using AcAp = Autodesk.AutoCAD.ApplicationServices.Core.Application; [assembly: CommandClass(typeof(PairLinesWithTextsR17.Commands))] namespace PairLinesWithTextsR17 { public class Commands { private struct EntityPosition { public Entity Entity { get; } public Point3d Position { get; } public EntityPosition(Entity entity, Point3d position) { Entity = entity; Position = position; } } [CommandMethod("PAIRKD")] public void ParallelPairTextsWithLines3() { // Force GC collection prior to timing to avoid GC halts during execution GC.Collect(); GC.WaitForPendingFinalizers(); Stopwatch stopwatch = Stopwatch.StartNew(); Document doc = AcAp.DocumentManager.MdiActiveDocument; Database db = doc.Database; Editor ed = doc.Editor; RXClass lineClass = RXObject.GetClass(typeof(Line)); RXClass textClass = RXObject.GetClass(typeof(DBText)); // Pre-allocate generous capacity to prevent memory reallocations List<EntityPosition> midLines = new List<EntityPosition>(16384); List<EntityPosition> textList = new List<EntityPosition>(16384); using (doc.LockDocument()) using (Transaction tr = db.TransactionManager.StartOpenCloseTransaction()) { LayerTable lt = (LayerTable)tr.GetObject(db.LayerTableId, OpenMode.ForRead); ObjectId lineLayerId = lt.Has("1") ? lt["1"] : ObjectId.Null; ObjectId textLayerId = lt.Has("4") ? lt["4"] : ObjectId.Null; BlockTableRecord modelSpace = (BlockTableRecord)tr.GetObject( SymbolUtilityServices.GetBlockModelSpaceId(db), OpenMode.ForRead); // 1. Fast Collection Phase foreach (ObjectId id in modelSpace) { RXClass rxClass = id.ObjectClass; if (rxClass == lineClass) { Line line = (Line)tr.GetObject(id, OpenMode.ForRead); if (line.LayerId == lineLayerId) { Point3d midPoint = new Point3d( (line.StartPoint.X + line.EndPoint.X) * 0.5, (line.StartPoint.Y + line.EndPoint.Y) * 0.5, (line.StartPoint.Z + line.EndPoint.Z) * 0.5 ); midLines.Add(new EntityPosition(line, midPoint)); } } else if (rxClass == textClass) { DBText text = (DBText)tr.GetObject(id, OpenMode.ForRead); if (text.LayerId == textLayerId) { Point3d pos = (text.Justify == AttachmentPoint.BaseLeft) ? text.Position : text.AlignmentPoint; textList.Add(new EntityPosition(text, pos)); } } } EntityPosition[][] textGroups = textList .GroupBy(t => ((DBText)t.Entity).TextString) .Select(g => g.ToArray()) .ToArray(); long t1 = stopwatch.ElapsedMilliseconds; // 2. KdTree Construction KdTree<EntityPosition> lineTree = new KdTree<EntityPosition>(midLines, ml => ml.Position, 2); long t2 = stopwatch.ElapsedMilliseconds; // 3. Parallel pairing (Math + Spatial Search) int numGroups = textGroups.Length; HashSet<Entity>[] uniqueGroupEntities = new HashSet<Entity>[numGroups]; Parallel.For(0, numGroups, i => { EntityPosition[] group = textGroups[i]; HashSet<Entity> uniqueSet = new HashSet<Entity>(group.Length * 2); for (int j = 0; j < group.Length; j++) { EntityPosition textItem = group[j]; uniqueSet.Add(textItem.Entity); Entity nearestLine = lineTree.GetNearestNeighbour(textItem.Position).Entity; uniqueSet.Add(nearestLine); } uniqueGroupEntities[i] = uniqueSet; }); long t3 = stopwatch.ElapsedMilliseconds; // 4. Sequential Database Modification Phase for (int i = 0; i < numGroups; i++) { int colorIndex = (i % 255) + 1; HashSet<Entity> uniqueSet = uniqueGroupEntities[i]; foreach (Entity entity in uniqueSet) { if (entity.ColorIndex != colorIndex) { if (!entity.IsWriteEnabled) { entity.UpgradeOpen(); } entity.ColorIndex = colorIndex; } } } long t4 = stopwatch.ElapsedMilliseconds; stopwatch.Stop(); ed.WriteMessage($"\n--------- TIMING -------------------------------"); ed.WriteMessage($"\nCollecting entities: {t1} milliseconds"); ed.WriteMessage($"\nBuilding kdTree: {t2 - t1} milliseconds"); ed.WriteMessage($"\nPairing lines and texts: {t3 - t2} milliseconds"); ed.WriteMessage($"\nColoring lines and texts: {t4 - t3} milliseconds\n"); ed.WriteMessage($"\nTotal Elapsed Time: {t4} milliseconds"); ed.WriteMessage($"\nTotal Number of Groups: {numGroups}"); tr.Commit(); } } } } pairkd.dll2 points
-
(that was an awesome thread....) Yes, that was the start of me making the above, and using BigAl for inspiration2 points
-
From @Steven P's thread. AutoLISP Code Scroll down to Blk_Lib.lsp Blk_Lib.dcl Blk_Lib.doc Also some information on making these types of DCL. Getting Started with Dcl Dialogs just scroll down for DCLs with slide images and Image buttons. This is pretty good as well. https://www.theswamp.org/index.php?topic=20878.msg253445#msg2534452 points
-
I use a variation of the ssx.lsp to select objects in the drawing. In Bricscad v15 using (sssetfirst ss1 ss1) would both activate grips and activate the properties window to show info on those objects. For example select all blocks with same name, I could quickly edit the attribute value for all of them. I'm testing upgrade to v26 and the properties window no longer activates unless I manually toggle the property preview button. Is there a system variable to use the old behavior? Here is the simple code: (setq ss1 (ssget)) (sssetfirst ss1 ss1)1 point
-
Honestly, I've been using AI to code in AutoLISP for the past year or so and I think it's more successful at it than I am. I'm not saying it's clean code, but I'm saying it's already useful. I had a sales engineer ask me info on a project that they're selling trying to verify if what they sold was feasible and with the tool the AI built, I could give them concrete details. If I had to finish that tool, it would have taken me months to write it. I had to test it a bunch of times in autocad and give feedback and it'll find the problem. I had to upgrade which models I used if it gets stuck or restart a new chat. I have a bunch of md files for it to remember how the codebase works but it's getting there. I would say the AI didn't code the whole thing, I still gave it most of the ideas to use, it just had to fill stuff in between for the implementation. At the end of the day, I just want it to work. I had it write a debug.txt which it can read after each test run. I had it create toy functions to measure what it did after the fact. There's a couple of good engineering practices still in place, it's just that I'm allowing myself to have 'fuzzy' details about the implementation.1 point
-
@GLAVCVS thanks for the feedback. I assume to use a single Powershell session you would have to run a batch file that launches Powershell first before starting autocad? Then when autocad closes or crashes out that session of Powershell also closes.1 point
-
Yes: as @SLW210 says, it seems to work well. On the other hand: Have you considered having the script written only if it does not already exist in the expected directory, and keeping PowerShell running from the initial load? This would make the dialog box load faster on subsequent calls. In this regard, the script check/creation could be done when the code is loaded. This would also improve the speed of the first execution slightly.1 point
-
I think AI is definitely part of the reason, but probably not the whole story. A lot of questions that used to become forum threads can now be answered quickly with ChatGPT or Copilot, especially when the problem is a small piece of code or a common error. The interesting part is exactly what you mentioned: when the AI-generated solution fails, people still need somewhere to ask a human who understands the bigger context. AI can produce working-looking code very quickly, but debugging someone else's real project is a different problem. I also think newer users are less attached to forums than they used to be. Many will try a search, ask an AI, or post in a Discord/Reddit community before they ever find a specialist forum. So the drop in posts doesn't necessarily mean people have stopped needing help; the questions may simply be going elsewhere.1 point
-
Yes you can have custom buttons Ok_Cancel_Width. Have to go back to my R12 paper manual for details.1 point
-
Professionally all updates are via email. Recorded in the company systems and auditable.1 point
-
Works great often do old fashioned DOS to get file names list or use the VL files functions. A suggestion remove "result" from the local variables list. As the answer disappears. Or ; Example: ; (setq files (pl:getfiledps "Select Files" (getvar"dwgprefix") "dwg" 1)) A side comment I have used Powershell with Bricscad and sometimes does not work. Your code may help as you do a deeper dive into running Powershell. I generally only do a "Power shell and script" I have used it to change programs, I jump to Excel from CAD.1 point
-
One observation: in older versions of AutoCAD (2000 and 2002, at least), 'vla-get-HWND' applies to the Document object rather than the Acad object.1 point
-
I'm not going to troubleshoot it since Powershell is blocked at work, but if the load has that error, then it's something in the Code, probable in the DCL write-line part.1 point
-
if you're running Civil 3D 2019, then xdrx.x64.25.arx is not the correct version, it would be xdrx.x64.23.arx1 point
-
I forgot to mention, for keeping up with the revisions we have Excel drawing lists with the Drawing names, dates and latest revision number on the network. P&IDs keep a dated track of each and every revision in cast things get put back to an older revision.1 point
-
Well done, nice use of Parallel.For! Kdtree’s are definitely a must have in the CAD programmer’s tool box.1 point
-
1 point
-
@Danielm103, I did build gile's code to autocad 2017 and ran it testmore.dwg Results for PLWT_KDTREE: --------- TIMING------------------------------- Collecting entities: 315 milliseconds Building kdTree: 69 milliseconds Pairing lines and texts: 28 milliseconds Coloring lines and texts: 121 milliseconds Total Elapsed Time: 533 milliseconds Total Number of Colors: 102 colors With that kind of results, I don't see what I could improve on here. I am attaching the cs file converted for acad 2017 and Gile.AutoCAD.R20.Geometry ymg pairs.cs1 point
-
this was a fun challenge using KDTrees https://www.theswamp.org/index.php?topic=59487.01 point
-
@gile, Here I build a bridge to your GeometryExtensions.NET library, exposing essentially the same command that I had in mine . The only addition being GC:KD-MINNODE. I have also built a concavehull in C# using your kd-tree if anybody is interested. ymg using System; using System.IO; using System.Linq; using System.Globalization; using System.Collections.Generic; using Autodesk.AutoCAD.Runtime; using Autodesk.AutoCAD.ApplicationServices; using Autodesk.AutoCAD.DatabaseServices; using Autodesk.AutoCAD.Geometry; using Gile.AutoCAD.R20.Geometry; namespace LispGileBridge { public class ExtensionLoader : IExtensionApplication { public void Initialize() { try { var ed = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument.Editor; // Extracts the absolute running file path dynamically via Reflection string assemblyPath = System.Reflection.Assembly.GetExecutingAssembly().Location; string assemblyName = System.IO.Path.GetFileName(assemblyPath); ed.WriteMessage($"\n--> Assembly File Loaded: \"{assemblyName}\""); ed.WriteMessage($"\n--> Full Path: {assemblyPath}"); ed.WriteMessage("\n--> Available commands:"); ed.WriteMessage("\n (GC:KD-BUILD pointList [dimensions] [customHandle])"); ed.WriteMessage("\n (GC:KD-NEAREST handle Point [count] [maxRadius] [sortFlag])"); ed.WriteMessage("\n (GC:KD-NEAREST-INFO handle Point [count] [maxRadius])"); ed.WriteMessage("\n (GC:KD-RANGE handle Point radius)"); ed.WriteMessage("\n (GC:KD-MINNODE handle dimension)"); ed.WriteMessage("\n (GC:KD-FREE [handle])"); } catch { // Fallback safety silent escape check } } public void Terminate() { } } public class KdTreeBridge { // Thread-safe dictionary tracking string handles to their specific tree instances and properties private static readonly Dictionary<string, (Point3dTree Tree, bool Is2D)> _registry = new Dictionary<string, (Point3dTree, bool)>(StringComparer.OrdinalIgnoreCase); private static int _autoId = 1; // -------------------------------------------------------------------------------- // 1. (gc:kd-build pointList [dimensions] [customHandle]) // -------------------------------------------------------------------------------- [LispFunction("GC:KD-BUILD")] public static object GileKdBuild(ResultBuffer args) { if (args == null) return null; TypedValue[] arr = args.AsArray(); if (arr.Length == 0) return null; try { List<Point3d> pts = ParseLispPoints(arr, 0, out int pointsReadCount); if (pts.Count == 0) return null; // Default dimension to 2D unless explicitly specified as 3 int dimensions = 2; string customHandle = null; if (arr.Length > pointsReadCount) { int nextIdx = pointsReadCount; if (arr[nextIdx].TypeCode == (int)LispDataType.Int32 || arr[nextIdx].TypeCode == (int)LispDataType.Int16) { dimensions = Convert.ToInt32(arr[nextIdx].Value); nextIdx++; } if (arr.Length > nextIdx && arr[nextIdx].TypeCode == (int)LispDataType.Text) { customHandle = Convert.ToString(arr[nextIdx].Value); } } bool is2D = (dimensions == 2); // Gilles' constructor: ignoreZ parameter directly matches our is2D rule Point3dTree tree = new Point3dTree(pts, is2D); string handle = string.IsNullOrEmpty(customHandle) ? $"<KD-TREE-{_autoId++}>" : customHandle; _registry[handle] = (tree, is2D); return handle; } catch (System.Exception ex) { Application.DocumentManager.MdiActiveDocument.Editor.WriteMessage($"\nError in KD-BUILD: {ex.Message}\n"); return null; } } // -------------------------------------------------------------------------------- // 2. (gc:kd-nearest handle targetPoint [count] [maxRadius] [sortFlag]) // -------------------------------------------------------------------------------- [LispFunction("GC:KD-NEAREST")] public static object GileKdNearest(ResultBuffer args) { if (args == null) return null; TypedValue[] arr = args.AsArray(); if (arr.Length < 2) return null; try { string handle = Convert.ToString(arr[0].Value); if (!_registry.TryGetValue(handle, out var entry)) return null; if (arr[1].TypeCode != (int)LispDataType.Point3d) return null; Point3d targetPt = (Point3d)arr[1].Value; int count = 1; double maxRadius = double.MaxValue; int sortFlag = 1; // Default: Sort by Angle if (arr.Length >= 3) count = Convert.ToInt32(arr[2].Value); if (arr.Length >= 4) maxRadius = Convert.ToDouble(arr[3].Value); if (arr.Length >= 5) sortFlag = Convert.ToInt32(arr[4].Value); var searchCollection = entry.Tree.GetNearestNeighbours(targetPt, count); if (searchCollection == null) return null; // Filter by radius limit and compile working list List<Point3d> filtered = new List<Point3d>(); foreach (Point3d pt in searchCollection) { double dist = entry.Is2D ? targetPt.DistanceTo(new Point3d(pt.X, pt.Y, targetPt.Z)) : targetPt.DistanceTo(pt); if (dist <= maxRadius) filtered.Add(pt); } if (filtered.Count == 0) return null; // Execute selected Sort mode if (sortFlag == 0) { filtered = filtered.OrderBy(p => entry.Is2D ? targetPt.DistanceTo(new Point3d(p.X, p.Y, targetPt.Z)) : targetPt.DistanceTo(p)).ToList(); } else { filtered = filtered.OrderBy(p => { double angle = Math.Atan2(p.Y - targetPt.Y, p.X - targetPt.X); return angle < 0 ? angle + (2 * Math.PI) : angle; }).ToList(); } // API Standard Rule Check: If count is 1, return single item. Else, return list. if (count == 1) { return filtered[0]; } ResultBuffer rb = new ResultBuffer(); rb.Add(new TypedValue((int)LispDataType.ListBegin)); foreach (Point3d pt in filtered) rb.Add(new TypedValue((int)LispDataType.Point3d, pt)); rb.Add(new TypedValue((int)LispDataType.ListEnd)); return rb; } catch { return null; } } // -------------------------------------------------------------------------------- // 3. (gc:kd-nearest-info handle targetPoint [count] [maxRadius]) // -------------------------------------------------------------------------------- [LispFunction("GC:KD-NEAREST-INFO")] public static object GileKdNearestInfo(ResultBuffer args) { if (args == null) return null; TypedValue[] arr = args.AsArray(); if (arr.Length < 2) return null; try { string handle = Convert.ToString(arr[0].Value); if (!_registry.TryGetValue(handle, out var entry)) return null; Point3d targetPt = (Point3d)arr[1].Value; int count = 1; double maxRadius = double.MaxValue; if (arr.Length >= 3) count = Convert.ToInt32(arr[2].Value); if (arr.Length >= 4) maxRadius = Convert.ToDouble(arr[3].Value); var searchCollection = entry.Tree.GetNearestNeighbours(targetPt, count); if (searchCollection == null) return null; ResultBuffer rb = new ResultBuffer(); rb.Add(new TypedValue((int)LispDataType.ListBegin)); // Re-locate matches to extract array index mappings cleanly int idx = 0; foreach (Point3d pt in searchCollection) { double dist = entry.Is2D ? targetPt.DistanceTo(new Point3d(pt.X, pt.Y, targetPt.Z)) : targetPt.DistanceTo(pt); if (dist <= maxRadius) { rb.Add(new TypedValue((int)LispDataType.ListBegin)); rb.Add(new TypedValue((int)LispDataType.Point3d, pt)); rb.Add(new TypedValue((int)LispDataType.Int32, idx)); // Metadata index placement rb.Add(new TypedValue((int)LispDataType.Double, dist)); rb.Add(new TypedValue((int)LispDataType.ListEnd)); } idx++; } rb.Add(new TypedValue((int)LispDataType.ListEnd)); return rb; } catch { return null; } } // -------------------------------------------------------------------------------- // 4. (gc:kd-range handle centerPoint radius) // -------------------------------------------------------------------------------- [LispFunction("GC:KD_RANGE")] public static object GileKdRange(ResultBuffer args) { if (args == null) return null; TypedValue[] arr = args.AsArray(); if (arr.Length < 3) return null; try { string handle = Convert.ToString(arr[0].Value); if (!_registry.TryGetValue(handle, out var entry)) return null; Point3d centerPt = (Point3d)arr[1].Value; double radius = Convert.ToDouble(arr[2].Value); // Passing a double directly to GetNearestNeighbours switches Gilles' engine to range search var searchCollection = entry.Tree.GetNearestNeighbours(centerPt, radius); if (searchCollection == null) return null; // Enforce distance sort ordering var sorted = searchCollection.OrderBy(p => entry.Is2D ? centerPt.DistanceTo(new Point3d(p.X, p.Y, centerPt.Z)) : centerPt.DistanceTo(p)).ToList(); ResultBuffer rb = new ResultBuffer(); rb.Add(new TypedValue((int)LispDataType.ListBegin)); foreach (Point3d pt in sorted) rb.Add(new TypedValue((int)LispDataType.Point3d, pt)); rb.Add(new TypedValue((int)LispDataType.ListEnd)); return rb; } catch { return null; } } // -------------------------------------------------------------------------------- // 5. NEW! (gc:kd-minnode handle dimension) -> Useful for Concave Hull base logic // -------------------------------------------------------------------------------- [LispFunction("GC:KD-MINNODE")] public static object GileKdMinNode(ResultBuffer args) { if (args == null) return null; TypedValue[] arr = args.AsArray(); if (arr.Length < 2) return null; try { string handle = Convert.ToString(arr[0].Value); if (!_registry.TryGetValue(handle, out var entry)) return null; int dimension = Convert.ToInt32(arr[1].Value); // 0=X, 1=Y, 2=Z // Target standard range query over all nodes to run aggregate matching var allPoints = entry.Tree.GetNearestNeighbours(Point3d.Origin, double.MaxValue); if (allPoints == null || !allPoints.Any()) return null; Point3d minPoint; switch (dimension) { case 0: // Minimum X coordinate minPoint = allPoints.OrderBy(p => p.X).First(); break; case 1: // Minimum Y coordinate minPoint = allPoints.OrderBy(p => p.Y).First(); break; case 2: // Minimum Z coordinate minPoint = allPoints.OrderBy(p => p.Z).First(); break; default: return null; } return minPoint; } catch { return null; } } // -------------------------------------------------------------------------------- // 6. (gc:kd-free [handle]) // -------------------------------------------------------------------------------- [LispFunction("GC:KD-FREE")] public static object GileKdFree(ResultBuffer args) { int removedCount = 0; if (args == null) { removedCount = _registry.Count; _registry.Clear(); _autoId = 1; } else { TypedValue[] arr = args.AsArray(); if (arr.Length > 0 && arr[0].TypeCode == (int)LispDataType.Text) { string handle = Convert.ToString(arr[0].Value); if (_registry.Remove(handle)) removedCount = 1; } else { removedCount = _registry.Count; _registry.Clear(); _autoId = 1; } } GC.Collect(); GC.WaitForPendingFinalizers(); return removedCount; } // -------------------------------------------------------------------------------- // INTERNAL ROUTINE: Streamlined input coordinate list extractor // -------------------------------------------------------------------------------- private static List<Point3d> ParseLispPoints(TypedValue[] arr, int startIndex, out int readCount) { var collected = new List<Point3d>(); readCount = 0; for (int i = startIndex; i < arr.Length; i++) { if (arr[i].Value is Point3d pt) { collected.Add(pt); readCount++; } else if (arr[i].TypeCode == (int)LispDataType.ListEnd || arr[i].TypeCode == (int)LispDataType.Int32 || arr[i].TypeCode == (int)LispDataType.Text) { break; // Stopped at non-point parameter boundaries } } return collected; } } } essentially the same command that I had in my post.1 point
-
The latest version is now in the first post. I used the @BIGAL codes for MS Excel and LibreOffice Calc, all credit given. Hopefully works in non-AutoCAD programs as well, it worked in AutoCAD 2000i on my home computer, batch wasn't an available option, so I may or may not see why. I forgot how much better Calc looks than Excel, it really looked better with my dark theme, I might need to work on my Excel at work. I just used a quickly made Metric drawing, so hopefully everything is correct, I know getting metric measurements in my Imperial drawings is correct. It now has option for the complete report or just the totals. It also gives the actual measurement of a scaled block and the 1:1 total. It also should first ask to save the CSV in the same folder as the drawing now.1 point
-
The best thing about QuickSelect is that you can append or remove your selections to/from the previous set. If you need all the manhole blocks on one layer and all the sewer lines on a different layer, for instance, you can pick one of each and use Similar. On the other hand, if you need the pipes in a particular range of lengths, you build one set without the shorter pipes, then remove the pipes that are too long, QED. It may be more complex than other methods, but if there are hundreds or thousands of items to process, it will be quicker.1 point
-
@BIGAL this is beautiful, probably this is where AutoDesk got inspiration for the Block Library Pallette. Do you mind sharing the DCL code?1 point
-
@gile, Did not know that. At least I learned something while doing mine. I've look at the extension and there are many interesting things in there.1 point
-
Hi, The GeometryExtensions.NET library provides a generic KdTree<T> class which uses parallel computation for building the tree. It also provides an example of Point3dTree class but can used with any type of object providing a 'getPosition' function. // public KdTree(IEnumerable<T> source, Func<T, Point3d>?getPosition, int dimension) var tree = new KdTree<BlockReference>(blockList, br => br.Position, 2);1 point
-
Does it break an Ellipse that was created with PELLIPSE = 1, which is the old style Polyline, a.k.a. Heavy Polyline and 2D Polyline? 3D Polylines?1 point
-
Whilst I probably won't use it, have you looked at compiling for Non Acad, say Bricscad a lot of users here.1 point
-
Watching this whole "AI taking over" debate unfold, I feel like I'm seeing people in our industry fall into three different camps: First, there’s the Spectator. They use AI to generate flashy concept art or write basic emails. It’s pure consumption—cool to look at, but they don't really know how the engine works. Then you have the Skeptical Co-Pilot. This is where I sit for my daily development. You let AI do the heavy lifting for specific, tedious tasks, but you absolutely do not trust it blindly. You sandbox its output and rigorously test it before ever putting it into your actual workflow. Finally, there’s the Blind Believer. This is the whole "AI Agent" crowd trying to run a one-man firm. They type a prompt and expect a flawless final product the next morning. The reality? You have no idea what kind of spaghetti code or geometric garbage is hidden inside that black box, and auditing it takes longer than just doing the work yourself. Speaking of that "skeptical co-pilot" approach, I actually went down a massive rabbit hole with it recently. I was trying to solve a very pragmatic problem: How do we get an LLM to generate hyper-precise CAD geometry without eating up a million tokens and spitting out hallucinated garbage? Natural language just doesn't cut it for drafting. So, I worked with an AI to invent a prototype "Universal Morphological Matrix" (I just call it V-Code). The idea was to strip away all the human linguistic fluff and reduce CAD commands down to an absolute, 256-token hex-based root system. It basically compresses professional CAD knowledge into a tiny "Cosmic Language", which a local interpreter can then unpack back into precise AutoCAD/LISP commands. I pushed the experiment so far that I jokingly asked the AI to use this highly compressed logic to solve the P vs NP math problem. It confidently spit out a bunch of hex codes and claimed it had solved it. Did I believe it? Absolutely not, because I couldn't read its alien derivation track at all, haha! At the end of the day, AI is an incredibly powerful engine. But if you take your hands off the steering wheel and just blindly trust the machine, you're going to crash. It remains a tool exclusively for people who already know exactly what they are doing.1 point
-
Hi All I have changed this code to have more options, you can select ByLayer = Layer 0 + ByLayer color ByBlock = Layer 0 + ByBlock color") KeepAllLayers = Keep original layers and colors") you can also select a block or select everything hope someone finds it useful Burst Nested Blocks.lsp1 point
-
1 point
-
1 point
-
All of you here are elite. I don't have any idea what the topic means. I am a newbie here. I am very willing to learn new things. Hope you accept me here.. Thanks in advance1 point
