Jump to content

.NET - Find COG of linear elements


SEANT

Recommended Posts

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

Link to comment
Share on other sites

  • Replies 23
  • Created
  • Last Reply

Top Posters In This Topic

  • SEANT

    12

  • Pete_IC

    6

  • emarijt

    5

  • RMS

    1

Top Posters In This Topic

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?

Link to comment
Share on other sites

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.

Link to comment
Share on other sites

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?

Link to comment
Share on other sites

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.

Link to comment
Share on other sites

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.

Link to comment
Share on other sites

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. :geek:

 

The first post has been updated with the corrected code.

Link to comment
Share on other sites

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

Link to comment
Share on other sites

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# :o....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!

Link to comment
Share on other sites

  • 1 year later...

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

Link to comment
Share on other sites

Preliminary investigation suggests this to be a problem with 32bit/64bit compatibility. What version of AutoCAD 2011 are you using?

Edited by SEANT
Link to comment
Share on other sites

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.

Guest
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.


×
×
  • Create New...