.NET

Reply
Valued Contributor
cnicholas
Posts: 55
Registered: ‎03-26-2007
Message 1 of 12 (442 Views)
Accepted Solution

How to determine if a point is within a hatch's area

442 Views, 11 Replies
03-05-2014 06:53 AM

Hi

I'd like to determine when a user selects a point in model space if it is within a hatched area.

 

I started to a look at using the Editor's SelectCrossingWindow but if you zoom in and select a point in between a graphical elements nothing is selected.

 

Please can someone suggest how to do this?

 

Thanks

Craig

Found im my codes

 <CommandMethod("ph")> _
Public Sub pickHatch()
Dim doc As Document = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument
Dim ed As Editor = doc.Editor
Dim db As Database = doc.Database
Dim ppo As New PromptPointOptions(vbLf & "Pick a Point: ")
Dim ppr As PromptPointResult
ppr = ed.GetPoint(ppo)
If ppr.Status <> PromptStatus.OK Then
ed.WriteMessage(vbCrLf & "Wrong point specification!")
Exit Sub
End If
Dim p As Point3d = ppr.Value
Dim fuzz As Double = 5 '<-- change fuzz to suit
'------------------------------------------------------------''
Dim vd As Vector3d = New Vector3d(fuzz, fuzz * 1.1, 0) '<-- change fuzz to suit (1.1 - to rotate fence)
Dim pMin As Point3d = p - vd
Dim pMax As Point3d = p + vd
Dim tvs() As TypedValue = New TypedValue() {New TypedValue(0, "hatch")}
Dim points As Point3dCollection = New Point3dCollection
points.Add(pMin)
points.Add(pMax)
Dim sf As SelectionFilter = New SelectionFilter(tvs)
Dim sres As PromptSelectionResult = ed.SelectFence(points, sf)
If sres.Status <> PromptStatus.OK Then
ed.WriteMessage("\nWrong selection!")
Return
End If
If sres.Value.Count = 0 Then
ed.WriteMessage("\nNothing selected!")
Return
End If
''-----------------------------------------------------------''
Using tr As Transaction = db.TransactionManager.StartTransaction()
'' cast entity as Hatch
Dim eid As ObjectId = sres.Value.GetObjectIds(0)
Dim ent As Entity = TryCast(tr.GetObject(eid, OpenMode.ForRead), Entity)
''-----------------------------------------------------------''
Dim ht As Hatch = TryCast(ent, Hatch)
If ht IsNot Nothing Then
Dim pts As Point3dCollection = New Point3dCollection
ht.GetStretchPoints(pts)
ed.WriteMessage(vbLf + "Selected: {0} object" + vbLf + "center point: {1:f3},{2:f3},{3:f3}", ent.GetRXClass().DxfName, pts(0).X, pts(0).Y, pts(0).Z)
End If
''-------------------- rest your work here ----------------''
tr.Commit()
End Using
End Sub

 

*Expert Elite*
Hallex
Posts: 1,569
Registered: ‎10-08-2008
Message 2 of 12 (420 Views)

Re: How to determine if a point is within a hatch's area

03-05-2014 01:23 PM in reply to: cnicholas

Don't know if this help, anyway try it on your end

I've used SinglePickInSpace option to select hatch

and return boundary coordinates

        [CommandMethod("ssh", CommandFlags.UsePickSet)]

        public void testHatchSelection()
        {

            Document doc = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument;

            Database db = doc.Database;

            Editor ed = doc.Editor;

            Matrix3d ucs=ed.CurrentUserCoordinateSystem;

            PromptSelectionOptions pso = new PromptSelectionOptions();
            pso.MessageForRemoval = "\nNothig selected";
            pso.MessageForAdding = "\nSelect hatch";
            pso.ForceSubSelections = false;
            pso.SelectEverythingInAperture = true;
            pso.SingleOnly = true;
            pso.SinglePickInSpace = true;
            SelectionFilter filt = new SelectionFilter(new TypedValue[]{
                new TypedValue(0,"hatch")});
            PromptSelectionResult res = ed.GetSelection(pso, filt);

            Transaction tr = doc.TransactionManager.StartTransaction();

            using (tr)
            {

                BlockTable bt = (BlockTable)tr.GetObject(doc.Database.BlockTableId, OpenMode.ForRead);

                BlockTableRecord btr = (BlockTableRecord)tr.GetObject(db.CurrentSpaceId, OpenMode.ForWrite);

                if (res.Status != PromptStatus.OK)
                {
                    Autodesk.AutoCAD.ApplicationServices.Application.ShowAlertDialog("nothing selected");
                    return;
                }
                SelectionSet sset = res.Value;
                
                foreach (SelectedObject sobj in sset)
                {
                    Entity ent = (Entity)tr.GetObject(sobj.ObjectId, OpenMode.ForRead);
                    if (ent != null)
                    {
                        Point3dCollection pts = new Point3dCollection();
                        Hatch hth = ent as Hatch;
                        
                        if (hth.GetLoopAt(0).IsPolyline)
                        {

                            BulgeVertexCollection bulges = hth.GetLoopAt(0).Polyline;// as Polyline;

                            double zc = hth.Elevation;
   
                            int i = 0;

                            for (i = 0; i < bulges.Count; i++)
                            {
                                BulgeVertex bulg = bulges[i];
                                Point2d pt = bulg.Vertex;
                                pts.Add(new Point3d(pt.X, pt.Y, zc).TransformBy(ucs));
                            }

                        }
                        PromptSelectionResult wres = ed.SelectWindowPolygon(pts);
                        if (wres.Status != PromptStatus.OK)
                        {
                            Autodesk.AutoCAD.ApplicationServices.Application.ShowAlertDialog("nothing inside the hatch");
                            return;
                        }
                        //rest your code here
                        SelectionSet wset = wres.Value;
                        
                        foreach (SelectedObject wobj in wset)
                        {
                            Entity went = (Entity)tr.GetObject(wobj.ObjectId, OpenMode.ForRead);
                            if (went != null)
                            {
                                ed.WriteMessage("\nFound object: {0}\n" + went.GetRXClass().DxfName);
                            }
                        }
                    }
                }
                tr.Commit();


            }
        }

 

_____________________________________
C6309D9E0751D165D0934D0621DFF27919
Valued Contributor
cnicholas
Posts: 55
Registered: ‎03-26-2007
Message 3 of 12 (398 Views)

Re: How to determine if a point is within a hatch's area

03-06-2014 03:42 AM in reply to: cnicholas

Hi

Thanks for the reply. There are some functions in the code that I haven't used before so I will need to familiarise myself with them.

It almost does the reverse of what I would like to achieve. What I want to be able to answer is when a point is selected, is it within the area that is hatched. In the image below, the pointer is within the area covered by the hatch but the hatch would not be selected because there appears to be no graphical element associated with the hatch below the pointer.

hatch.jpg

*Expert Elite*
Hallex
Posts: 1,569
Registered: ‎10-08-2008
Message 4 of 12 (391 Views)

Re: How to determine if a point is within a hatch's area

03-06-2014 04:15 AM in reply to: cnicholas
Don't know ith helps, see article here
about TraceBoundary function:
http://through-the-interface.typepad.com/through_the_interface/2014/02/striking-an-enclosed-text-are...
_____________________________________
C6309D9E0751D165D0934D0621DFF27919
Valued Contributor
cnicholas
Posts: 55
Registered: ‎03-26-2007
Message 5 of 12 (358 Views)

Re: How to determine if a point is within a hatch's area

03-07-2014 03:20 AM in reply to: Hallex
Perhaps it can be dealt with at a higher level in the way I am using AutoCAD to pick the hatch. If the hatch pattern is solid, I am always able to select the hatch. If the hatch pattern is made up of lines as in the image, I have to click one of the hatch pattern lines to select it. Is there a way to create a selection set that includes 'the nearest' to the selected point?
*Expert Elite*
_gile
Posts: 2,086
Registered: ‎04-29-2006
Message 6 of 12 (345 Views)

Re: How to determine if a point is within a hatch's area

03-07-2014 11:24 AM in reply to: cnicholas

Hi,

 

I think I got a way using a MPolygon.

MPolygon is an AutoCAD MAP object but it also available in Vanilla AutoCAD.

To use it from .NET, then the project need to reference the AcMPolygonMGD.dll and it is required to load the object enabler AcMPolygonObjXX.dbx into AutoCAD prior to using MPolygon functions. Both files can be found in AutoCAD's install folder.

 

The MPolygon object is quite close to a Hatch an have a IsPointInsideMPolygon() method.

The method returns an IntegerCollection which is empty if the point is outside and contains the loops indices (may be several because MPolygon allows crossing loops).

It's quite easy to create a MPolygon from a Hatch but with some restrictions: as Polylines MPolygons can only be composed of arcs an line segments.

 

If the hatch contains more than one loop, it may be difficult to evaluate if the point is inside the hatch according to the HatchStyle (mainly with HatchStyle.Normal) and/or with non-separated hatches.

 

Anyway, here's a little sample to start:

 

// (C) Copyright 2012 by Gilles Chanteau 
//
using System;
using System.Collections.Generic;
using System.Linq;
using Autodesk.AutoCAD.Runtime;
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.Geometry;
using Autodesk.AutoCAD.EditorInput;
using AcAp = Autodesk.AutoCAD.ApplicationServices.Application;
using AcRx = Autodesk.AutoCAD.Runtime;

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

        public void Terminate()
        { }

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

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

            using (Transaction tr = db.TransactionManager.StartTransaction())
            {
                Hatch hatch = (Hatch)tr.GetObject(per.ObjectId, OpenMode.ForRead);
                try
                {
                    using (MPolygon mpolygon = HatchToMpolygon(hatch))
                    {
                        while (true)
                        {
                            PromptPointOptions opts = new PromptPointOptions("\nSpecify a point: ");
                            opts.AllowNone = true;
                            PromptPointResult ppr = ed.GetPoint(opts);
                            if (ppr.Status != PromptStatus.OK)
                                break;
                            Point3d pt = ppr.Value.TransformBy(ed.CurrentUserCoordinateSystem);
                            IntegerCollection ints = mpolygon.IsPointInsideMPolygon(pt, 1e-9);
                            string msg;
                            if (ints.Count == 0)
                                msg = "Outside";
                            else if (ints[0] == 0)
                                msg = "Inside";
                            else
                                switch (ints[0])
                                {
                                    case 1: msg = "Inside the 1st inner loop"; break;
                                    case 2: msg = "Inside the 2nd inner loop"; break;
                                    case 3: msg = "Inside the 3rd inner loop"; break;
                                    default: msg = "Inside the " + ints[0] + "th inner loop"; break;
                                }
                            AcAp.ShowAlertDialog(msg);
                        }
                    }
                }
                catch (System.Exception ex)
                {
                    ed.WriteMessage("\nError: " + ex.Message);
                }
                tr.Commit();
            }
        }

        private MPolygon HatchToMpolygon(Hatch hatch)
        {
            MPolygon mpolygon = new MPolygon();
            mpolygon.Elevation = hatch.Elevation;
            mpolygon.Normal = hatch.Normal;
            for (int i = 0; i < hatch.NumberOfLoops; i++)
            {
                BulgeVertexCollection bulges = hatch.GetLoopAt(i).Polyline;
                if (bulges == null)
                    throw new InvalidOperationException("Unable to create a MPolygon");
                MPolygonLoop loop = new MPolygonLoop();
                foreach (BulgeVertex bulge in bulges)
                {
                    loop.Add(bulge);
                }
                mpolygon.AppendMPolygonLoop(loop, true, 1e-9);
            }
            mpolygon.BalanceTree();
            return mpolygon;
        }
    }
}

 

Gilles Chanteau
*Expert Elite*
Hallex
Posts: 1,569
Registered: ‎10-08-2008
Message 7 of 12 (332 Views)

Re: How to determine if a point is within a hatch's area

03-07-2014 01:55 PM in reply to: cnicholas

Found im my codes

        <CommandMethod("ph")> _
        Public Sub pickHatch()
            Dim doc As Document = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument
            Dim ed As Editor = doc.Editor
            Dim db As Database = doc.Database

            Dim ppo As New PromptPointOptions(vbLf & "Pick a Point: ")
            Dim ppr As PromptPointResult
            ppr = ed.GetPoint(ppo)
            If ppr.Status <> PromptStatus.OK Then
                ed.WriteMessage(vbCrLf & "Wrong point specification!")
                Exit Sub
            End If
            Dim p As Point3d = ppr.Value

            Dim fuzz As Double = 5 '<--  change fuzz to suit
            '------------------------------------------------------------''
            Dim vd As Vector3d = New Vector3d(fuzz, fuzz * 1.1, 0) '<--    change fuzz to suit (1.1 - to rotate fence)
            Dim pMin As Point3d = p - vd
            Dim pMax As Point3d = p + vd
            Dim tvs() As TypedValue = New TypedValue() {New TypedValue(0, "hatch")}
            Dim points As Point3dCollection = New Point3dCollection
            points.Add(pMin)
            points.Add(pMax)
            Dim sf As SelectionFilter = New SelectionFilter(tvs)
            Dim sres As PromptSelectionResult = ed.SelectFence(points, sf)
            If sres.Status <> PromptStatus.OK Then
                ed.WriteMessage("\nWrong selection!")
                Return
            End If

            If sres.Value.Count = 0 Then
                ed.WriteMessage("\nNothing selected!")
                Return
            End If
            ''-----------------------------------------------------------''
            Using tr As Transaction = db.TransactionManager.StartTransaction()
                '' cast entity as Hatch
                Dim eid As ObjectId = sres.Value.GetObjectIds(0)
                Dim ent As Entity = TryCast(tr.GetObject(eid, OpenMode.ForRead), Entity)
                ''-----------------------------------------------------------''
                Dim ht As Hatch = TryCast(ent, Hatch)
                If ht IsNot Nothing Then
                    Dim pts As Point3dCollection = New Point3dCollection
                    ht.GetStretchPoints(pts)
                    ed.WriteMessage(vbLf + "Selected: {0} object" + vbLf + "center point: {1:f3},{2:f3},{3:f3}", ent.GetRXClass().DxfName, pts(0).X, pts(0).Y, pts(0).Z)
                End If
                ''-------------------- rest your work here ----------------''
                tr.Commit()

            End Using
        End Sub

 

_____________________________________
C6309D9E0751D165D0934D0621DFF27919
ADN Support Specialist
philippe.leefsma
Posts: 632
Registered: ‎06-02-2009
Message 8 of 12 (293 Views)

Re: How to determine if a point is within a hatch's area

03-09-2014 03:06 AM in reply to: Hallex

You can use Editor.GetPoint followed by a call to Editor.TraceBoundary.

 

Take a look at the help files for more details about that method.

 

Regards,

Philippe.



Philippe Leefsma
Developer Technical Services
Autodesk Developer Network

*Expert Elite*
Hallex
Posts: 1,569
Registered: ‎10-08-2008
Message 9 of 12 (288 Views)

Re: How to determine if a point is within a hatch's area

03-09-2014 03:47 AM in reply to: philippe.leefsma
Thanks, Philippe,I'd already tested this method, it didn't work
If you're pick a point between the hatch lines
Have a nice day :smileyhappy:
_____________________________________
C6309D9E0751D165D0934D0621DFF27919
ADN Support Specialist
philippe.leefsma
Posts: 632
Registered: ‎06-02-2009
Message 10 of 12 (285 Views)

Re: How to determine if a point is within a hatch's area

03-09-2014 04:17 AM in reply to: Hallex

What do you mean it doesn't work? In the following recording, I am creating an hatch with very spaced lines, so I'm sure not to pick one, then I use the following code to find out if the selected point is inside a boundary.

 

Seems to work fine to me, let me know if I am missing something...

 

http://screencast.com/t/nhZOw7IZx

 

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

    PromptPointOptions ppo = new PromptPointOptions("\nSelect seed point: ");
            
    PromptPointResult ppr = ed.GetPoint(ppo);

    if(ppr.Status != PromptStatus.OK)
        return;

    PromptKeywordOptions pko = new PromptKeywordOptions("\nDraw clip boundary?");
    pko.AllowNone = false;
    pko.Keywords.Add("Yes");
    pko.Keywords.Add("No");
    pko.Keywords.Default = "Yes";

    PromptResult pkr = ed.GetKeywords(pko);

    if (pkr.Status != PromptStatus.OK)
        return;

    using (Transaction tr = doc.TransactionManager.StartTransaction())
    {
        DBObjectCollection dbo = ed.TraceBoundary(
            ppr.Value, 
            (pkr.StringResult == "Yes" ? true : false));

        if (dbo != null)
        {
            BlockTableRecord btr = tr.GetObject(
                db.CurrentSpaceId, 
                OpenMode.ForWrite) 
                as BlockTableRecord;

            foreach (DBObject obj in dbo)
            {
                Entity entity = obj as Entity;
                entity.ColorIndex = 1;

                btr.AppendEntity(entity);
                tr.AddNewlyCreatedDBObject(obj, true);
            }
        }

        tr.Commit();
    }
}

 Philippe.



Philippe Leefsma
Developer Technical Services
Autodesk Developer Network

Announcements
Autodesk Alert | We are currently working on restoring Previous Version License request access in the Autodesk Subscription Center. If you are a subscription customer and would like to request a Previous Version License, please use this link as a temporary workaround. We apologize for the inconvenience and thank you for your patience.
Need installation help?

Start with some of our most frequented solutions or visit the Installation and Licensing Forum to get help installing your software.