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;
}
}
}