SEANT Posted June 26, 2010 Posted June 26, 2010 Here is a prototype C# routine to create a point at the center of gravity of a selection set of lines and/or polylines (without bulges). This example code is in response to the query made in this thread: http://www.cadtutor.net/forum/showthread.php?t=48143 Limited testing. Use sensible precaution! To run: unzip lcog.zip In AutoCAD: Command: netload (navigate to, and load file LCOG.dll) Command: LCOG Select linear elements: // Written by Sean Tessier June 25 2010 // Rev1 - Bug fix June 27 2010 using System; using System.Collections.Generic; using Autodesk.AutoCAD.Runtime; using Autodesk.AutoCAD.ApplicationServices; using Autodesk.AutoCAD.DatabaseServices; using Autodesk.AutoCAD.EditorInput; using Autodesk.AutoCAD.Geometry; [assembly: CommandClass(typeof(LinesCOG.CTCommands))] namespace LinesCOG { public class CTCommands { public CTCommands() { } [CommandMethod("LCOG")] static public void LCOGinit() { Editor ed = Application.DocumentManager.MdiActiveDocument.Editor; Database db = HostApplicationServices.WorkingDatabase; ObjectIdCollection oidColl = new ObjectIdCollection(); WeightedMidCollection wmc = new WeightedMidCollection(); PromptSelectionOptions pso = new PromptSelectionOptions(); pso.MessageForAdding = "\nSelect linear elements: "; pso.SinglePickInSpace = true; pso.SingleOnly = true; Vector3d v3d = new Vector3d(0.0, 0.0, 1.0); //Only process lines and polylines with an elevation of 0 TypedValue[] filter = { new TypedValue(-4, "<or"), new TypedValue(0, "LINE"), new TypedValue(-4, "<and"), new TypedValue(0, "LWPOLYLINE"), new TypedValue(38, 0), new TypedValue(-4, "and>"), new TypedValue(-4, "or>") }; SelectionFilter selFilter = new SelectionFilter(filter); bool Canceled = false; using (Transaction trans = db.TransactionManager.StartTransaction()) { do { PromptSelectionResult result = ed.GetSelection(pso, selFilter); if (result.Status == PromptStatus.OK) { ObjectId[] oids = result.Value.GetObjectIds(); foreach (ObjectId oid in oids) { if (!oidColl.Contains(oid)) { oidColl.Add(oid); Line ln = trans.GetObject(oid, OpenMode.ForRead) as Line; if (ln != null) { Point3d stpt = ln.StartPoint; Point3d ndpt = ln.EndPoint; if (stpt.Z == 0.0 && ndpt.Z == 0.0)//only process lines on the WCS XY { ln.Highlight(); WeightedMid wm = new WeightedMid(new Point2d(ln.StartPoint.X, ln.StartPoint.Y), new Point2d(ln.EndPoint.X, ln.EndPoint.Y)); wmc.Add(wm); } } else { Polyline pln = trans.GetObject(oid, OpenMode.ForRead) as Polyline; if (pln != null && !pln.HasBulges)//exclude polylines with bulges { for (int i = 0; i < pln.NumberOfVertices - 1; i++) { WeightedMid wm = new WeightedMid(pln.GetPoint2dAt(i), pln.GetPoint2dAt(i + 1)); wmc.Add(wm); } pln.Highlight(); if (!oidColl.Contains(oid)) oidColl.Add(oid); } } } } ed.WriteMessage("\nPocessing " + oidColl.Count.ToString() + " linear elements"); } else Canceled = true; } while (!Canceled); if (oidColl.Count == 0) return; wmc.ProccessMids(); if (wmc.IsValid) { try { DBPoint COGpt = new DBPoint(wmc.COG); BlockTableRecord btr = (BlockTableRecord)(trans.GetObject(db.CurrentSpaceId, OpenMode.ForWrite)); btr.AppendEntity(COGpt); trans.AddNewlyCreatedDBObject(COGpt, true); } catch { ed.WriteMessage("\nExecution Error: Operation cancelled!"); } finally { foreach (ObjectId oid in oidColl)//remove highlighting { Entity ent = trans.GetObject(oid, OpenMode.ForRead) as Entity; ent.Unhighlight(); } } } else ed.WriteMessage("\nOperation aborted!"); trans.Commit(); } } } struct WeightedMid //Process individual lines { //fields public double X; public double Y; public double MomentX; public double MomentY; public double length; //Constructor public WeightedMid(Point2d StartPoint, Point2d EndPoint) { X = (StartPoint.X + EndPoint.X) / 2.0; Y = (StartPoint.Y + EndPoint.Y) / 2.0; length = StartPoint.GetDistanceTo(EndPoint); MomentX = length * X; MomentY = length * Y; } } class WeightedMidCollection : List<WeightedMid> //Process lines as a collection { //Fields private double m_totLength; private Point3d m_cog; private double m_combinedXMoments; private double m_combinedYMoments; private bool m_isValid = false; //Constructor public WeightedMidCollection() { } //Properties public Point3d COG { get { return m_cog; } } public bool IsValid { get { return m_isValid; } } //Methods public void ProccessMids() { foreach (WeightedMid wm in this) { m_totLength += wm.length; m_combinedXMoments += wm.MomentX; m_combinedYMoments += wm.MomentY; } try { m_cog = new Point3d(m_combinedXMoments / m_totLength, m_combinedYMoments / m_totLength, 0.0); m_isValid = true; } catch { m_isValid = false; } } } } LCOG_rev2.zip Quote
Pete_IC Posted June 27, 2010 Posted June 27, 2010 SEANT, i get a fatal error when I try and use LCOG, got any ideas why? Quote
SEANT Posted June 27, 2010 Author Posted June 27, 2010 That’s not good. AutoCAD 2009 is the platform with which I debugged and compiled. Conceivably, though, it should work with anything 2007+ Are you using the 64bit version? Is there any additional information you can give me? Quote
Pete_IC Posted June 27, 2010 Posted June 27, 2010 As far as i know its just normal full version 2009, the only difference is its a floating version so the license is on our server as we also run 2006LT. Later on today I will see if it works on a different computer. Quote
SEANT Posted June 28, 2010 Author Posted June 28, 2010 I’m not sure what the ramifications are with regard to floating licenses. I’ll look into that asap. The LCOG.dll should be run from a local drive (i.e., not from a server). Is that the case? Quote
Pete_IC Posted June 28, 2010 Posted June 28, 2010 that could be the problem I will more it to a local drive and give it a go Quote
Pete_IC Posted June 28, 2010 Posted June 28, 2010 that was the problem, needed to be on a local drive Quote
SEANT Posted June 28, 2010 Author Posted June 28, 2010 Cool. I've got to remember to make that known up front. Thanks. Quote
Pete_IC Posted June 28, 2010 Posted June 28, 2010 Now its working I have noticed if i select the polylines using LCOG I get a point, then if I do it again I get another point, but its in a slightly different location. Quote
SEANT Posted June 28, 2010 Author Posted June 28, 2010 Could you put that geometry in a separate file and upload it here? Quote
Pete_IC Posted June 28, 2010 Posted June 28, 2010 Interesting, im getting 2 different point locations for the polylines, but for the exploded lines i get the same location for the point lcog.dwg Quote
SEANT Posted June 28, 2010 Author Posted June 28, 2010 When I run it here I can only get the point on the right. I’m not sure why the point on the left would appear unless some of the geometry is not being processed correctly. Given the left shift, I assume some additional geometry is included left of center, or some geometry is being missed right of center. I won’t have any more time tonight but will take another peak at the situation tomorrow morning. Quote
SEANT Posted June 28, 2010 Author Posted June 28, 2010 Ah yes, there was a bug. One of my steps was out of sequence and allowed processing geometry twice given a multiple crossing window selections. The first post has been updated with the corrected code. Quote
SEANT Posted June 28, 2010 Author Posted June 28, 2010 The selection process was not very user friendly in the original; I modified it a bit for a more AutoCAD like feel. Modified source code is available if necessary. LCOG_rev3.zip Quote
RMS Posted July 2, 2010 Posted July 2, 2010 The selection process was not very user friendly in the original; I modified it a bit for a more AutoCAD like feel. Modified source code is available if necessary. OMG C# ....breath deep, its really just VB with some curly things {}.....and and the comments are like C/C++ Nice Job Sean! I can see we have some Naval Architects / boat builders here and that is awesome! Quote
emarijt Posted January 3, 2012 Posted January 3, 2012 I'm trying to load the dll file but something is going wrong. Can someone help me out? This is what i get: ----------------------------- Command: NETLOAD Cannot load assembly. Error details: System.BadImageFormatException: Could not load file or assembly 'file:///C:\Program Files\Autodesk\AutoCAD 2011\LCOG.dll' or one of its dependencies. The module was expected to contain an assembly manifest. File name: 'file:///C:\Program Files\Autodesk\AutoCAD 2011\LCOG.dll' at System.Reflection.Assembly._nLoad(AssemblyName fileName, String codeBase, Evidence assemblySecurity, Assembly locationHint, StackCrawlMark& stackMark, Boolean throwOnFileNotFound, Boolean forIntrospection) at System.Reflection.Assembly.nLoad(AssemblyName fileName, String codeBase, Evidence assemblySecurity, Assembly locationHint, StackCrawlMark& stackMark, Boolean throwOnFileNotFound, Boolean forIntrospection) at System.Reflection.Assembly.InternalLoad(AssemblyName assemblyRef, Evidence assemblySecurity, StackCrawlMark& stackMark, Boolean forIntrospection) at System.Reflection.Assembly.InternalLoadFrom(String assemblyFile, Evidence securityEvidence, Byte[] hashValue, AssemblyHashAlgorithm hashAlgorithm, Boolean forIntrospection, StackCrawlMark& stackMark) at System.Reflection.Assembly.LoadFrom(String assemblyFile) at Autodesk.AutoCAD.Runtime.ExtensionLoader.Load(String fileName) at loadmgd() WRN: Assembly binding logging is turned OFF. To enable assembly bind failure logging, set the registry value [HKLM\Software\Microsoft\Fusion!EnableLog] (DWORD) to 1. Note: There is some performance penalty associated with assembly bind failure logging. To turn this feature off, remove the registry value [HKLM\Software\Microsoft\Fusion!EnableLog]. Thanx in advance Quote
SEANT Posted January 4, 2012 Author Posted January 4, 2012 (edited) Preliminary investigation suggests this to be a problem with 32bit/64bit compatibility. What version of AutoCAD 2011 are you using? Edited January 4, 2012 by SEANT Quote
emarijt Posted January 4, 2012 Posted January 4, 2012 thanks for your reply. I'm running AutoCAD 2011 on a 32bit machine. Quote
SEANT Posted January 4, 2012 Author Posted January 4, 2012 Due to more specific targeting, this version may perform better. LCOG.zip Quote
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.