Spatial Query in Autocad 2010

Spatial Query in Autocad 2010

Anonymous
Not applicable
4,528 Views
10 Replies
Message 1 of 11

Spatial Query in Autocad 2010

Anonymous
Not applicable

Hello,

 

I need to know if a point is into a polygon, developing in VB.NET fro Autocad 2010.

 

Is this possible? Or is any method to do something similar?

 

Thanks!

0 Likes
Accepted solutions (2)
4,529 Views
10 Replies
Replies (10)
Message 2 of 11

_gile
Consultant
Consultant

Hi,

 

You can use a MPolygon, a MAP entity which is also available in vanilla while the AcMPolygonObj##.dbx module is loaded.

In your project, you'll also have to add a reference to the AcMPolygonMGD.dll (you'll find it in the AutoCAD installation folder.

 

Here's a little sample with a testing command, it implements IExtensionApplication interface to load the module at startup.

 

using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Geometry;
using Autodesk.AutoCAD.Runtime;

namespace PointInside
{
    public class CommandMethods : IExtensionApplication
    {
        public void Initialize()
        {
            SystemObjects.DynamicLinker.LoadModule(
                "AcMPolygonObj" + Application.Version.Major + ".dbx", false, false);
        }

        public void Terminate() { }

        private bool IsPointInside(Point3d point, Polyline pline)
        {
            double tolerance = Tolerance.Global.EqualPoint;
            using (MPolygon mpg = new MPolygon())
            {
                mpg.AppendLoopFromBoundary(pline, true, tolerance);
                return mpg.IsPointInsideMPolygon(point, tolerance).Count == 1;
            }
        }

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

            PromptEntityOptions peo = new PromptEntityOptions("\nSelect a polyline: ");
            peo.SetRejectMessage("Only a polyline !");
            peo.AddAllowedClass(typeof(Polyline), true);
            PromptEntityResult per = ed.GetEntity(peo);
            if (per.Status != PromptStatus.OK) 
                return;

            using (Transaction tr = db.TransactionManager.StartOpenCloseTransaction())
            {
                Polyline pline = (Polyline)tr.GetObject(per.ObjectId, OpenMode.ForRead);
                PromptPointOptions ppo = new PromptPointOptions("\nPick a point <quit>: ");
                ppo.AllowNone = true;
                while (true)
                {
                    PromptPointResult ppr = ed.GetPoint(ppo);
                    if (ppr.Status != PromptStatus.OK) 
                        break;
                    Application.ShowAlertDialog(
                        IsPointInside(ppr.Value, pline) ? "Inside" : "Outside");
                }
            }
        }
    }
}

 



Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

0 Likes
Message 3 of 11

Anonymous
Not applicable

Thanks Gilles!

 

I am testing your code, and it crashes in method "IsPointInside" when trying to create the MPolygon object. Exception throws this message:

 

"Se produjo una excepción de tipo 'System.IO.FileLoadException' en AcMPolygonMGD.dll pero no se controló en el código del usuario

Información adicional: acmpolygonobj18d.dbx"

 

What is the problem?

0 Likes
Message 4 of 11

hgasty1001
Advisor
Advisor

Hi,

 

There are many ways to test if a point it's inside a polygon, the more direct from the API is editor.TraceBoundary(TestPoint) it returns a dbObjectCollection, if empty the point it's outside, otherwise you have your point.

 

Also this link may help : Containment

 

Gaston Nunez

0 Likes
Message 5 of 11

_gile
Consultant
Consultant

Oh yes, I remember now.

There's a bug in the AutoCad 2010 version of AcMPolygonMGD.dll which tries to load AcMPolygonObj18d.dll instead of AcMPolygonObj18.dll (AFAIK this bug haven't been fixed for this version).

As Gaston said, you can use the Editor.TraceBoundary() method or use the boundary representation API (Brep) as shown by Tony Tanzillo in the link Gaston provided.



Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

0 Likes
Message 6 of 11

Anonymous
Not applicable

Ok, I will try the solution exposed by Gaston

0 Likes
Message 7 of 11

Anonymous
Not applicable

Gilles,

 

The method "editor.TraceBoundary(TestPoint)" doesn´t exist in AutoCad 2010...

0 Likes
Message 8 of 11

_gile
Consultant
Consultant
Accepted solution

So, you can try the Brep route as shown by Tony Tanzillo here (you have to add reference to acdbmgdbrep.dll and Import Autodesk.AutoCAD.BoundaryRepresentation namespace).

 

Here's a little example largely inspired by Tony's one which works with polylines on AutoCAD 2010.

 

        [CommandMethod("TEST")]
        public void Test()
        {
            Document doc = Application.DocumentManager.MdiActiveDocument;
            Database db = doc.Database;
            Editor ed = doc.Editor;

            PromptEntityOptions peo = new PromptEntityOptions("\nSelect a polyline: ");
            peo.SetRejectMessage("Only a polyline !");
            peo.AddAllowedClass(typeof(Polyline), true);
            PromptEntityResult per = ed.GetEntity(peo);
            if (per.Status != PromptStatus.OK)
                return;

            using (Transaction tr = db.TransactionManager.StartOpenCloseTransaction())
            {
                Polyline pline = (Polyline)tr.GetObject(per.ObjectId, OpenMode.ForRead);
                if (!pline.Closed)
                {
                    ed.WriteMessage("\nPolyline must be closed.");
                    return;
                }
                DBObjectCollection curves = new DBObjectCollection();
                curves.Add(pline);
                try
                {
                    using (DBObjectCollection regions = Region.CreateFromCurves(curves))
                    using (Region region = (Region)regions[0])
                    {
                        PromptPointOptions ppo = new PromptPointOptions("\nPick a point <quit>: ");
                        ppo.AllowNone = true;
                        while (true)
                        {
                            PromptPointResult ppr = ed.GetPoint(ppo);
                            if (ppr.Status != PromptStatus.OK)
                                break;
                            Application.ShowAlertDialog(
                                GetPointContainment(region, ppr.Value).ToString());
                        }
                    }
                }
                catch (System.Exception exn)
                {
                    ed.WriteMessage("\nError: " + exn.Message);
                }
            }
        }

        private PointContainment GetPointContainment(Region region, Point3d point)
        {
            PointContainment result = PointContainment.Outside;
            using (Brep brep = new Brep(region))
            {
                if (brep != null)
                {
                    using (BrepEntity ent = brep.GetPointContainment(point, out result))
                    {
                        if (ent is Autodesk.AutoCAD.BoundaryRepresentation.Face)
                        {
                            result = PointContainment.Inside;
                        }
                    }
                }
            }
            return result;
        }

 

 



Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

Message 9 of 11

Anonymous
Not applicable

Thanks Gilles!

 

It works! Now, I have to make some changes to work as I want. First of all, do you know how can I select a polyline from my dwg without user interaction?

0 Likes
Message 10 of 11

_gile
Consultant
Consultant
Accepted solution

Hi,

 

You can use Editor.SelectAll() method with an appropriate selection filter or iterate through the entities contained in the model space (and/or paper spaces) to look for polylines.

If you want to select a particular polyline, you'd have to check for some particularity (geometry, xdata, ...) of this polyline.



Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

Message 11 of 11

Anonymous
Not applicable

Hi Giles


Thank you for your time.


i wrote polyline instead of polygon mistakenly in the title, sorry for that.
I tried the two ways, they work fine with normal polyline. i tried to use the code with polygone but it reads the polygon as a polyline>
Also tried to convert the polygon to a polyline but i failed.
My problem exactly that i need to search for BlockReferences or polygons on PS or MS, then find any Text (Inside) the block or (Inside) the polygon.
The BlockReferences option is my favourite, but it is not necessary.

Any help please.

Thanks.

0 Likes