Author Topic: centroid of closed polyline  (Read 22630 times)

0 Members and 1 Guest are viewing this topic.

Chumplybum

  • Newt
  • Posts: 97
centroid of closed polyline
« on: November 05, 2008, 10:10:45 PM »
hi all, i'm trying to find the centroid of a closed polyline.

i've read a few lisp examples that can do this (including one on the swamp http://www.theswamp.org/index.php?topic=18725.0) but haven't been able to transform this code to .net. From the lisp examples it seems that the polyline is converted to a region and then the centriod is found from the region, however from what i can see there is no centroid property (although there is a centroid property under solid3dmassproperties).
So i couldn't convert lisp to .net and went off and found the formula for the centroid of a polyline (http://en.wikipedia.org/wiki/Centroid) as well as a vb.net sample (http://www.vb-helper.com/howto_net_polygon_centroid.html) after slightly modifying the code i've come up with the following...

Code: [Select]
        ' For polylines
        Dim pl As AADS.Polyline = TryCast(context.PickedObject, AADS.Polyline)

        If pl Is Nothing OrElse pl.Closed = False Then Return

        Dim RunningX As Long
        Dim RunningY As Long
        Dim second_factor As Long

        For Counter As Integer = 0 To pl.NumberOfVertices - 2
            second_factor = pl.GetPoint2dAt(Counter).X * pl.GetPoint2dAt(Counter + 1).Y - pl.GetPoint2dAt(Counter + 1).X * pl.GetPoint2dAt(Counter).Y

            RunningX += (pl.GetPoint2dAt(Counter).X + pl.GetPoint2dAt(Counter + 1).X) * second_factor
            RunningY += (pl.GetPoint2dAt(Counter).Y + pl.GetPoint2dAt(Counter + 1).Y) * second_factor
        Next


        Dim X, Y As Long

        ' Divide by 6 times the polygon's area.
        Dim polygon_area As Single = pl.Area
        X = RunningX / (6 * pl.Area)
        Y = RunningY / (6 * pl.Area)

        ' If the values are negative, the polygon is
        ' oriented counterclockwise. Reverse the signs.
        If X < 0 Then
            X = -X
            Y = -Y
        End If

        Dim CentroidPoint As AAG.Point3d = New AAG.Point3d(X, Y, pl.Elevation)


the code works for a rectangle that is drawn at 0,0... however, when the polyline moves away from 0,0 the code produces some crazy results and if the polyline is in a different quadrant about the usc it produces some more crazy results

does anyone know of a better / easier way to find the centroid, or a problem with my code???

any help would be great


cheers, Mark

pkohut

  • Guest
Re: centroid of closed polyline
« Reply #1 on: November 06, 2008, 01:55:02 AM »
You have to do the calculations relative to the object you're trying to measure.  The code would
look something like this (sorry I don't have VB skills)
Code: [Select]
dim ptRef as Point2d
dim pt1 as Point2d
dim pt2 as Point2d
dim second_factor as double
dim drX as double
dim drY as double

For Counter as Integer = 0 To pl.NumberOfVertices - 2
  pt1 = pl.GetPoint2dAt(Counter)
  Pt2 = pl.GetPoint2dAt(counter + 1)
  if i == 0 then
      ptRef = pt1
  endif
  second_factor = (pt1.x - ptRef.x) * (pt2.y - ptRef.y) - (pt2.x - ptRef.x) * (pt1.y - ptRef.y);
  drX += ((pt1.x - ptRef.x) + (pt2.x - ptRef.x)) * b0;
  drY += ((pt1.y - ptRef.y) + (pt2.y - ptRef.y)) * b0;
Next

x = drX / (6 * pl.area) + ptRef.x
y = drY / (6 * pl.area) + ptRef.y


With this there is no need to reverse sign at the end.  Your example code is declaring some variables
as Long when they should be doubles (or whatever VB calls them).  Was your code returning
a float or double for those computations?  If they are then I would turn on the Option strict to get a
little tighter control over the VB.

Paul

Cathy

  • Guest
Re: centroid of closed polyline
« Reply #2 on: November 06, 2008, 03:01:21 PM »
It looks to me like you are missing one side of the polygon -- the one from the last point to the first point.  I note that the sample code at http://www.vb-helper.com/howto_net_polygon_centroid.html makes a copy of the first point at the end, but I don't see where you do that.

SomeCallMeDave

  • Guest
Re: centroid of closed polyline
« Reply #3 on: November 06, 2008, 03:27:18 PM »
You could also used TF.net  http://code.google.com/p/tf-net/ and let it do the work for you.


C# code, but I'm sure you can convert it
Code: [Select]

using System;
using System.Linq;
using System.Text;
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.Runtime;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Geometry;
using Topology.Geometries;
using Topology.IO.Dwg;

namespace TF_Test
{

    public class TF_Test
    {
        [CommandMethod("TFCentroid")]
        public void FindCentroid()
        {
            {
                Document doc = Application.DocumentManager.MdiActiveDocument;
                Database db = doc.Database;
                Editor ed = doc.Editor;

                PromptEntityOptions opts = new PromptEntityOptions("\nSelect Entity to Query: ");
                opts.AllowNone = true;
                opts.AllowObjectOnLockedLayer = true;
                opts.SetRejectMessage("\nDon't pick that kind ");
                opts.AddAllowedClass(typeof(Polyline), false);


                //Select the object on-screen
                PromptEntityResult res = ed.GetEntity(opts);
                if (res.Status == PromptStatus.OK)
                {
                    ObjectId ObjID = res.ObjectId;
                    try
                    {
                        using (Transaction trans = db.TransactionManager.StartTransaction())
                        {
                            Entity ent = (Entity)trans.GetObject(ObjID, OpenMode.ForRead, false);
                            DwgReader reader = new DwgReader();
                            DwgWriter writer = new DwgWriter();
                            Geometry geometry = (Geometry)reader.ReadGeometry(ent);
                            IPoint centroid = geometry.Centroid;
                            ed.WriteMessage("\nCentroid is " + centroid.ToString());




                        }//using
                    }//end try
                    catch (System.Exception ex)
                    {
                        ed.WriteMessage("Error Reading Centroid: " + ex.Message);

                    }
                }// if

            }
        }


Chumplybum

  • Newt
  • Posts: 97
Re: centroid of closed polyline
« Reply #4 on: November 06, 2008, 07:01:47 PM »
thanks pkohut for your help / code...

i've amended my code to suit your changes (see below), however, the code only seems to produce an accurate result if the polyline is drawn counterclockwise (see attached images, the polyline has been mirrod to get counterclockwise vs clockwise)


Code: [Select]
       

imports AADS = AutoDesk.AutoCAD.DatabaseServices
imports AAG = Autodesk.AutoCAD.Geometry

Public Shared Function GetCentroid(ByVal polyline As AADS.Polyline) As AAG.Point3d

            Dim ReferencePoint As AAG.Point2d
            Dim RunningX As Double
            Dim RunningY As Double
            Dim second_factor As Double
            Dim Point1 As AAG.Point2d
            Dim Point2 As AAG.Point2d

            For Counter As Integer = 0 To polyline.NumberOfVertices - 2
                Point1 = polyline.GetPoint2dAt(Counter)
                Point2 = polyline.GetPoint2dAt(Counter + 1)

                If Counter = 0 Then ReferencePoint = Point1

                second_factor = (Point1.X - ReferencePoint.X) * (Point2.Y - ReferencePoint.Y) - (Point2.X - ReferencePoint.X) * (Point1.Y - ReferencePoint.Y)

                RunningX += ((Point1.X - ReferencePoint.X) + (Point2.X - ReferencePoint.X)) * second_factor
                RunningY += ((Point1.Y - ReferencePoint.Y) + (Point2.Y - ReferencePoint.Y)) * second_factor
            Next

            Dim X, Y As Double

            X = RunningX / (6 * polyline.Area) + ReferencePoint.X
            Y = RunningY / (6 * polyline.Area) + ReferencePoint.Y


            Return New AAG.Point3d(X, Y, polyline.Elevation)

        End Function
« Last Edit: November 06, 2008, 07:04:52 PM by Chumplybum »

pkohut

  • Guest
Re: centroid of closed polyline
« Reply #5 on: November 06, 2008, 07:56:41 PM »
The easiest way to fix this is to keep a running total of second_factor during the loop.  Then
once out of the loop if the summation is negative then you'll need to multiply your X and Y
calculations with -1.0.  FYI, the area of the polyline is the abs(summation) * 0.5   (straight
line segments only).

Cathy mentions possibly missing the final segment.  You'll need to check if the first and last
vertex are the same or not.  You already know the polyline is closed, so the final segment
may be interpolated across the final vertex to the first vertex, and you would miss that.

Paul

pkohut

  • Guest
Re: centroid of closed polyline
« Reply #6 on: November 06, 2008, 08:26:21 PM »
Need to correct a sentence in my last post from:
Quote
Then
once out of the loop if the summation is negative then you'll need to multiply your X and Y
calculations with -1.0.

to:

Quote
Then once out of the loop if the summation is negative then you'll need to multiply
RunningX and RunningY with -1.0.  Here's an example:

dim dVal as double
dVal = 1.0
if summation < 0.0 then dVal = -1.0
    X = (RunningX * dVal) / (6 * polyline.Area) + ReferencePoint.X
    Y = (RunningY * dVal) / (6 * polyline.Area) + ReferencePoint.Y


Paul

Chumplybum

  • Newt
  • Posts: 97
Re: centroid of closed polyline
« Reply #7 on: November 06, 2008, 08:48:31 PM »
awesome... thanks pkohut, that fixed it up


cheers, Mark

gile

  • Gator
  • Posts: 2507
  • Marseille, France
Re: centroid of closed polyline
« Reply #8 on: November 09, 2008, 01:34:53 PM »
Hi,

It was quite difficult for me (I'm a complete beginer with .NET), but it was a fine exercice.
Here's a translation (C#) of the LISP routines I gave here.

All comments are welcome.

It works with arc polylines.

EDIT: added a testing command and a LISP function.
The "pline_centroid" command draws a point on the selected polyline centroid.
(pline_centroid (car (entsel))) returns the WCS coordinates of the centroid.

Code: [Select]
using System;
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Geometry;
using Autodesk.AutoCAD.Runtime;

namespace PolylineCentroid
{
    // Main class
    public class Centroid
    {
        public Point3d GetCentroid(Polyline pl)
        {
            Point2d p0 = pl.GetPoint2dAt(0);
            Point2d cen = new Point2d(0.0, 0.0);
            double area = 0.0;
            double bulge = pl.GetBulgeAt(0);
            int last = pl.NumberOfVertices - 1;
            double tmpArea;
            Point2d tmpPoint;

            if (bulge != 0.0)
            {
                double[] datas = getArcGeom(pl, bulge, 0, 1);
                area = datas[0];
                cen = new Point2d(datas[1], datas[2]) * datas[0];
            }
            for (int i = 1; i < last; i++)
            {
                tmpArea = triangleAlgebricArea(p0, pl.GetPoint2dAt(i), pl.GetPoint2dAt(i + 1));
                tmpPoint = triangleCentroid(p0, pl.GetPoint2dAt(i), pl.GetPoint2dAt(i + 1));
                cen += (tmpPoint * tmpArea).GetAsVector();
                area += tmpArea;
                bulge = pl.GetBulgeAt(i);
                if (bulge != 0.0)
                {
                    double[] datas = getArcGeom(pl, bulge, i, i + 1);
                    area += datas[0];
                    cen += new Vector2d(datas[1], datas[2]) * datas[0];
                }
            }
            bulge = pl.GetBulgeAt(last);
            if (bulge != 0.0)
            {
                double[] datas = getArcGeom(pl, bulge, last, 0);
                area += datas[0];
                cen += new Vector2d(datas[1], datas[2]) * datas[0];
            }
            cen = cen.DivideBy(area);
            Point3d result = new Point3d(cen.X, cen.Y, pl.Elevation);
            return result.TransformBy(Matrix3d.PlaneToWorld(pl.Normal));
        }

        public double[] GetArcGeom(Polyline pl, double bulge, int index1, int index2)
        {
            CircularArc2d arc = (pl.GetArcSegment2dAt(index1));
            double arcRadius = arc.Radius;
            Point2d arcCenter = arc.Center;
            double arcAngle = 4.0 * Math.Atan(bulge);
            double tmpArea = arcAlgebricArea(arcRadius, arcAngle);
            Point2d tmpPoint = arcCentroid(pl.GetPoint2dAt(index1), pl.GetPoint2dAt(index2), arcCenter, tmpArea);
            return new double[3] { tmpArea, tmpPoint.X, tmpPoint.Y };
        }

        public Point2d TriangleCentroid(Point2d p0, Point2d p1, Point2d p2)
        {
            return (p0 + p1.GetAsVector() + p2.GetAsVector()) / 3.0;
        }

        public double TriangleAlgebricArea(Point2d p0, Point2d p1, Point2d p2)
        {
            return (((p1.X - p0.X) * (p2.Y - p0.Y)) - ((p2.X - p0.X) * (p1.Y - p0.Y))) / 2.0;
        }

        public Point2d ArcCentroid(Point2d start, Point2d end, Point2d cen, double tmpArea)
        {
            double chord = start.GetDistanceTo(end);
            double angle = angleFromTo(start, end);
            return polar2d(cen, angle - (Math.PI / 2.0), (chord * chord * chord) / (12.0 * tmpArea));
        }

        public double ArcAlgebricArea(double rad, double ang)
        {
            return rad * rad * (ang - Math.Sin(ang)) / 2.0;
        }

        public double AngleFromTo(Point2d p1, Point2d p2)
        {
            return (p2 - p1).Angle;
        }

        public Point2d Polar2d(Point2d org, double angle, double distance)
        {
            return new Point2d(org.X + distance, org.Y).RotateBy(angle, org);
        }
    }

    // Testing command
    public class MyClass
    {
        [CommandMethod("pline_centroid")]
        public void centroid()
        {
            Document doc = Application.DocumentManager.MdiActiveDocument;
            Database db = doc.Database;
            Editor ed = doc.Editor;

            PromptEntityOptions opts = new PromptEntityOptions("\nSelect a polyline: ");
            opts.AllowNone = true;
            opts.AllowObjectOnLockedLayer = true;
            opts.SetRejectMessage("\nEntité non valide.");
            opts.AddAllowedClass(typeof(Polyline), false);
            PromptEntityResult pline = ed.GetEntity(opts);
            if (pline.Status == PromptStatus.OK)
            {
                ObjectId ObjID = pline.ObjectId;
                try
                {
                    using (Transaction trans = db.TransactionManager.StartTransaction())
                    {
                        Polyline ent = (Polyline)trans.GetObject(ObjID, OpenMode.ForRead, false);
                        Centroid c = new Centroid();
                        Point3d cen = c.GetCentroid(ent);
                        DBPoint pt = new DBPoint(cen);
                        BlockTable bTable = (BlockTable)trans.GetObject(db.BlockTableId, OpenMode.ForRead);
                        BlockTableRecord mSpace = (BlockTableRecord)trans.GetObject(bTable[BlockTableRecord.ModelSpace], OpenMode.ForWrite);
                        mSpace.AppendEntity(pt);
                        trans.AddNewlyCreatedDBObject(pt, true);
                        trans.Commit();
                    }
                }
                catch (System.Exception ex)
                {
                    ed.WriteMessage("Error: " + ex.Message);
                }
            }
        }
    }

    // LISP function
    public class LispCentoid
    {
        [LispFunction("pline_centroid")]
        public static object centroid(ResultBuffer buff)
        {
            Document doc = Application.DocumentManager.MdiActiveDocument;
            Database db = doc.Database;
            Editor ed = doc.Editor;

            if (buff == null)
            {
                ed.WriteMessage("Error: none argument.\n");
                return false;
            }

            TypedValue[] args = buff.AsArray();
            if (args[0].TypeCode != (int)LispDataType.ObjectId)
            {
                ed.WriteMessage("Error: incorrect argument type: lentityp {0}.\n", args[0].Value);
                return false;
            }
            ObjectId objID = (ObjectId)args[0].Value;
            try
            {
                using (Transaction trans = db.TransactionManager.StartTransaction())
                {
                    Entity ent = (Entity)trans.GetObject(objID, OpenMode.ForRead, false);
                    string entType = ent.GetType().ToString().Substring(34);
                    if (entType == "Polyline")
                    {
                        Polyline pl = (Polyline)trans.GetObject(objID, OpenMode.ForRead, false);
                        Centroid c = new Centroid();
                        return c.GetCentroid(pl);
                    }
                    else
                    {
                        if (entType.Contains("DB")) entType = entType.Substring(2);
                        ed.WriteMessage("Error: incorrect entity type: " + entType + "\n");
                        return null;
                    }
                }
            }
            catch (System.Exception ex)
            {
                ed.WriteMessage("\nError: " + ex.Message + "\n");
                return false;
            }
        }
    }
}
« Last Edit: November 15, 2008, 03:48:32 AM by gile »
Speaking English as a French Frog

gile

  • Gator
  • Posts: 2507
  • Marseille, France
Re: centroid of closed polyline
« Reply #9 on: November 11, 2008, 04:23:36 AM »
I edited the Centroid class code so that some methods, as angleFromTo, polar2d, triangleAlgebricArea, triangleCentroid and so on, which may be usefull are more easily readable.
Speaking English as a French Frog

It's Alive!

  • Retired
  • Needs a day job
  • Posts: 8704
  • AKA Daniel
Re: centroid of closed polyline
« Reply #10 on: November 11, 2008, 08:26:38 AM »
Excellent gile!

gile

  • Gator
  • Posts: 2507
  • Marseille, France
Re: centroid of closed polyline
« Reply #11 on: November 11, 2008, 09:03:39 AM »
Thanks Daniel..
Speaking English as a French Frog

Chumplybum

  • Newt
  • Posts: 97
Re: centroid of closed polyline
« Reply #12 on: November 11, 2008, 05:37:46 PM »
nice one, thanks gile

pkohut

  • Guest
Re: centroid of closed polyline
« Reply #13 on: November 11, 2008, 06:24:45 PM »
Ya Gile looks good.  Since your a self admitted beginner at .Net
may I suggest making all those "int" doubles into doubles
instead of letting the compiler upcast them for you. 
return (p0 + p1.GetAsVector() + p2.GetAsVector()) / 3
to
return (p0 + p1.GetAsVector() + p2.GetAsVector()) / 3.0

if(bulge != 0)
to
if(bulge != 0.0)

The compiler will happily up cast for you, but that isn't something
you should let it do.  Make your intent known to the compiler
and it will help you when you make a mistake.  It also helps
you and others with a visual clue about your intent.

Later,
Paul

gile

  • Gator
  • Posts: 2507
  • Marseille, France
Re: centroid of closed polyline
« Reply #14 on: November 12, 2008, 02:19:52 AM »
Thanks Paul,

It makes sense, I edit the code according to your suggestion.
Speaking English as a French Frog

SEANT

  • Bull Frog
  • Posts: 345
Re: centroid of closed polyline
« Reply #15 on: November 13, 2008, 10:16:33 AM »
In a similar fashion to the Polyline to Region process mentioned earlier, here an alternate method of retrieving centroids.  Sure it’s cheating and ridiculously heavy handed, but isn’t that truly the American way.   Just kidding. :-)

Granted, it is probably even slower still than the Poly/Region method – it does, however, allow for the inclusion of “Curved” Polys, Splines, and Regions.


Code: [Select]
        [CommandMethod("EntCen")]
        static public void centroid()
        {
            Document doc = Application.DocumentManager.MdiActiveDocument;
            Database db = doc.Database;
            Editor ed = doc.Editor;

            PromptEntityOptions opts = new PromptEntityOptions("\nSelect a planar entity: ");
            opts.AllowNone = true;
            opts.AllowObjectOnLockedLayer = true;
            opts.SetRejectMessage("\nEntity not valid.");
            opts.AddAllowedClass(typeof(Polyline), false);
            opts.AddAllowedClass(typeof(Polyline2d), false);
            opts.AddAllowedClass(typeof(Region), false);
            opts.AddAllowedClass(typeof(Spline), false);
            PromptEntityResult per = ed.GetEntity(opts);
            if (per.Status == PromptStatus.OK)
            {
                ObjectId ObjID = per.ObjectId;
                try
                {
                    using (Transaction trans = db.TransactionManager.StartTransaction())
                    {
                        Entity ent = (Entity)trans.GetObject(ObjID, OpenMode.ForRead, false);
                        CentroidViaSol c = new CentroidViaSol(ent);

                        if (c.Success)
                        {
                            Point3d cen = c.DerivedCentroid;
                            DBPoint pt = new DBPoint(cen);
                            BlockTable bTable = (BlockTable)trans.GetObject(db.BlockTableId, OpenMode.ForRead);
                            BlockTableRecord cSpace = (BlockTableRecord)trans.GetObject(db.CurrentSpaceId, OpenMode.ForWrite);
                            cSpace.AppendEntity(pt);
                            trans.AddNewlyCreatedDBObject(pt, true);
                            trans.Commit();
                        }
                    }
                }
                catch (System.Exception ex)
                {
                    ed.WriteMessage("Error: " + ex.Message);
                }
            }
        }



        // New Class //////////////
        class CentroidViaSol
        {
            //Fields
            public Boolean Success;
            private Region m_region;
            private Solid3d m_derivedSolid;
            private Vector3d m_normal;
            private Point3d m_centroid;
            private DBObjectCollection m_entCol;
 
            //Constructor ///////////
            public CentroidViaSol(Entity PlanarEnt)
            {
                m_entCol = new DBObjectCollection();
                string entType = PlanarEnt.GetType().ToString();
                switch (entType)
                {
                    case "Autodesk.AutoCAD.DatabaseServices.Polyline":
                        Polyline poly = PlanarEnt as Polyline;
                        if (poly.Closed)
                        {
                            m_entCol.Add(poly);
                            CreateRegion();
                        }
                        break;
                    case "Autodesk.AutoCAD.DatabaseServices.Polyline2d":
                        Polyline2d poly2d = PlanarEnt as Polyline2d;
                        if (poly2d.Closed)
                        {
                            m_entCol.Add(poly2d);
                            CreateRegion();
                        }
                        break;
                    case "Autodesk.AutoCAD.DatabaseServices.Spline":
                        Spline entSpline = PlanarEnt as Spline;
                        if (entSpline.IsPlanar && entSpline.Closed)
                        {
                            m_entCol.Add(entSpline);
                            CreateRegion();
                        }
                       
                        break;
                    case "Autodesk.AutoCAD.DatabaseServices.Region":
                        m_region = (Region)PlanarEnt;
                        Success = true;
                        break;
                }
                if (!m_region.IsNull)
                {
                    m_normal = m_region.Normal;
                    m_derivedSolid = new Solid3d();
                    m_derivedSolid.Extrude(m_region, 2.0, 0.0);
                    m_centroid = m_derivedSolid.MassProperties.Centroid;
                    m_centroid = m_centroid - m_normal;
                }
            }



            //Properties //////////

            public Point3d DerivedCentroid
            {
                get { return m_centroid; }
            }



            //Internal ////////////

            private void CreateRegion()
            {
                try
                {
                    m_region = (Region)(Region.CreateFromCurves(m_entCol)[0]);
                    Success = true;
                }
                catch
                {
                    Success = false;
                }
            }

        }
« Last Edit: November 13, 2008, 11:29:17 AM by SEANT »
Sean Tessier
AutoCAD 2016 Mechanical

Spike Wilbury

  • Guest

Spike Wilbury

  • Guest
Re: centroid of closed polyline
« Reply #17 on: November 13, 2008, 10:41:02 AM »
In a similar fashion to the Polyline to Region process mentioned earlier, here an alternate method of retrieving centroids.  Sure it’s cheating and ridiculously heavy handed, but isn’t that truly the American way.   Just kidding. :-)

Granted, it is probably slower still than the Poly/Region method – it does, however, allow for the inclusion of “Curved” Polys, Splines, and Regions.


Code: [Select]
                                
if (poly.Closed)
                        {
                            poly.Explode(m_entCol);
                            CreateRegion();
                        }


}


Why you need the explode method?

SEANT

  • Bull Frog
  • Posts: 345
Re: centroid of closed polyline
« Reply #18 on: November 13, 2008, 10:59:11 AM »
Why you need the explode method?

I admit I did not confirm that it was actually needed but the docs seemed to imply that it was.

And, I should also admit that despite the aforementioned "Heavyhandedness", I think the methodology interesting.  Your link demos the more conventional method of dealing with regions, splines and splined polys.
Sean Tessier
AutoCAD 2016 Mechanical

Spike Wilbury

  • Guest
Re: centroid of closed polyline
« Reply #19 on: November 13, 2008, 11:06:02 AM »
Why you need the explode method?

I admit I did not confirm that it was actually needed but the docs seemed to imply that it was.

And, I should also admit that despite the aforementioned "Heavyhandedness", I think the methodology interesting.  Your link demos the more conventional method of dealing with regions, splines and splined polys.

Sean,

If you can, and have the ObjectARX refererence help (part of the SDK) have a look at AcDbRegion::createFromCurves appears that they change it?.... what version of autocad you are using?


Below it is a quote from the a2009 ARX SDK docs....
Quote
Description
This static member function creates a set of AcDbRegion objects from the closed loops represented by the curves contained in the curveSegments array. The newly created region objects are returned in the regions array.

The curveSegments array must contain only pointers to AcDbLine, AcDbArc, AcDbEllipse, AcDbCircle, AcDbSpline, AcDb3dPolyline, or AcDbPolyline objects.

SEANT

  • Bull Frog
  • Posts: 345
Re: centroid of closed polyline
« Reply #20 on: November 13, 2008, 11:23:02 AM »
Sean,

If you can, and have the ObjectARX refererence help (part of the SDK) have a look at AcDbRegion::createFromCurves appears that they change it?.... what version of autocad you are using?


Cool! It appears that the Autocad 2009: Managed Class Reference Guide may have a misprint.  I'll eliminate that explode call.  It's not much by my "alternate method" needs every bit of optimization it can get.  :wink:
Sean Tessier
AutoCAD 2016 Mechanical

Spike Wilbury

  • Guest
Re: centroid of closed polyline
« Reply #21 on: November 13, 2008, 11:36:28 AM »
Sean,

If you can, and have the ObjectARX refererence help (part of the SDK) have a look at AcDbRegion::createFromCurves appears that they change it?.... what version of autocad you are using?


Cool! It appears that the Autocad 2009: Managed Class Reference Guide may have a misprint.  I'll eliminate that explode call.  It's not much by my "alternate method" needs every bit of optimization it can get.  :wink:

Good.


You can port the arx function (per the link I posted) to C# - and avoid all the hassle :)

SEANT

  • Bull Frog
  • Posts: 345
Re: centroid of closed polyline
« Reply #22 on: November 13, 2008, 11:55:18 AM »
I am indeed looking into it.  It would appear, and correct me again if I’m wrong, that there is no direct way to get at a region’s mass props via the Managed API.  The link you posted shows that it’s all accessible via a port.  Thanks for the pointer. 
Sean Tessier
AutoCAD 2016 Mechanical

Spike Wilbury

  • Guest
Re: centroid of closed polyline
« Reply #23 on: November 13, 2008, 12:16:58 PM »
I am indeed looking into it.  It would appear, and correct me again if I’m wrong, that there is no direct way to get at a region’s mass props via the Managed API.  The link you posted shows that it’s all accessible via a port.  Thanks for the pointer. 

a quick review to the docs they have it in:

Solid3dMassProperties Properties

SEANT

  • Bull Frog
  • Posts: 345
Re: centroid of closed polyline
« Reply #24 on: November 13, 2008, 01:31:53 PM »
Hmm, I can see how to use that with a solid but couldn’t see any hook into that with a region. 
Neither can I avoid an exception with the example below:

Brep brp = new Brep(m_region);
foreach (Autodesk.AutoCAD.BoundaryRepresentation.Face fce in brp.Faces)
{
    double ar = fce.GetArea(); //works okay
    double pl = fce.GetPerimeterLength(); //works okay
    MassProperties mp = fce.GetMassProperties(); //Exception
}
Sean Tessier
AutoCAD 2016 Mechanical

Spike Wilbury

  • Guest
Re: centroid of closed polyline
« Reply #25 on: November 13, 2008, 02:09:20 PM »
Hmm, I can see how to use that with a solid but couldn’t see any hook into that with a region. 
Neither can I avoid an exception with the example below:

Brep brp = new Brep(m_region);
foreach (Autodesk.AutoCAD.BoundaryRepresentation.Face fce in brp.Faces)
{
    double ar = fce.GetArea(); //works okay
    double pl = fce.GetPerimeterLength(); //works okay
    MassProperties mp = fce.GetMassProperties(); //Exception
}

Do you need the Faces ?

- Can you cast As Entity the Region and pass that to the Brep(Entity); ?

Sorry, do not have my tools or code here at the office....

SEANT

  • Bull Frog
  • Posts: 345
Re: centroid of closed polyline
« Reply #26 on: November 13, 2008, 03:03:53 PM »

Do you need the Faces ?

- Can you cast As Entity the Region and pass that to the Brep(Entity); ?

Sorry, do not have my tools or code here at the office....

No need to apologize.  Exploring the various possibilities is kind entertaining.  I know, I need a life:|

I’ve tried various levels of Breps.  I’ve also alternated using the region as entity and as region for the Brep constructor.    The best I was able to do was avoid the exception during the MassProperties assignment, but everything set at 0.  Actually, the RadiiOfGyration had “NaN” values – whatever that means. 

I’ll keep looking.  Something seems likely – given that the info is available via both COM and ARX.
Sean Tessier
AutoCAD 2016 Mechanical