.NET
cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Spatial Query in Autocad 2010

10 REPLIES 10
SOLVED
Reply
Message 1 of 11
imago69_
3431 Views, 10 Replies

Spatial Query in Autocad 2010

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!

10 REPLIES 10
Message 2 of 11
_gile
in reply to: imago69_

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

Message 3 of 11
imago69_
in reply to: _gile

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?

Message 4 of 11
hgasty1001
in reply to: imago69_

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

Message 5 of 11
_gile
in reply to: imago69_

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

Message 6 of 11
imago69_
in reply to: _gile

Ok, I will try the solution exposed by Gaston

Message 7 of 11
imago69_
in reply to: imago69_

Gilles,

 

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

Message 8 of 11
_gile
in reply to: imago69_

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
imago69_
in reply to: _gile

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?

Message 10 of 11
_gile
in reply to: imago69_

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
OCODER
in reply to: imago69_

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.

Can't find what you're looking for? Ask the community or share your knowledge.

Post to forums  

Autodesk DevCon in Munich May 28-29th


Autodesk Design & Make Report

”Boost