public static class Extensions
{
public static bool IsPointInside(this Polyline pl, Point2d pt)
{
Curve2d[] ca = new Curve2d[pl.NumberOfVertices];
for(int i = 0; i < pl.NumberOfVertices; i++)
{
bool last = i == pl.NumberOfVertices - 1;
Point2d sp = pl.GetPoint2dAt(i);
Point2d ep = pl.GetPoint2dAt(last ? 0 : i + 1);
double b = last && !pl.Closed ? 0.0 : pl.GetBulgeAt(i);
if(b == 0.0)
ca[i] = new LineSegment2d(sp, ep);
else
ca[i] = new CircularArc2d(sp, ep, b, false);
}
int n = 0;
using(CompositeCurve2d c2d = new CompositeCurve2d(ca))
using(Ray2d r2d = new Ray2d(pt, Vector2d.XAxis))
using(CurveCurveIntersector2d cci2d = new CurveCurveIntersector2d(c2d, r2d))
{
for(int i = 0; i < cci2d.NumberOfIntersectionPoints; i++)
if(cci2d.IsTransversal(i)) n++;
}
return(n % 2 != 0);
}
}
public class Commands
{
Database db;
Editor ed;
public Commands()
{
Document doc = AcadApp.DocumentManager.MdiActiveDocument;
db = doc.Database;
ed = doc.Editor;
}
[CommandMethod("TestIsPointInside")]
public void testIsPointInside()
{
PromptEntityOptions peo = new PromptEntityOptions("\nSelect a Polyline: ");
peo.SetRejectMessage("\nOnly Polyline permitted. ");
peo.AddAllowedClass(typeof(Polyline), true);
PromptEntityResult per = ed.GetEntity(peo);
if (per.Status != PromptStatus.OK) return;
PromptIntegerOptions pio = new PromptIntegerOptions("\nNumber of points: ");
pio.AllowNegative = false;
pio.AllowNone = false;
pio.AllowZero = false;
PromptIntegerResult pir = ed.GetInteger(pio);
if (pir.Status != PromptStatus.OK) return;
using (Transaction tr = db.TransactionManager.StartTransaction())
{
Polyline pl = (Polyline)tr.GetObject(per.ObjectId, OpenMode.ForRead);
BlockTableRecord cs = (BlockTableRecord)tr.GetObject(db.CurrentSpaceId, OpenMode.ForWrite);
Extents3d ext = pl.GeometricExtents;
double dx = ext.MaxPoint.X - ext.MinPoint.X;
double dy = ext.MaxPoint.Y - ext.MinPoint.Y;
double cenx = ext.MinPoint.X + dx / 2.0;
double ceny = ext.MinPoint.Y + dy / 2.0;
dx = dx * 1.2; dy = dy * 1.2;
double minx = cenx - dx / 2.0;
double miny = ceny - dy / 2.0;
Random rnd = new System.Random();
for (int i = 0; i < pir.Value; i++)
{
Point2d pt = new Point2d(minx + rnd.NextDouble() * dx, miny + rnd.NextDouble() * dy);
DBPoint dp = new DBPoint(new Point3d(pt.X, pt.Y, 0.0));
if(pl.IsPointInside(pt))
dp.ColorIndex = 1;
cs.AppendEntity(dp);
tr.AddNewlyCreatedDBObject(dp, true);
}
tr.Commit();
}
}
}
the idea behind that function was to avoid the use of any object or rays
public static class Extensions
{
public static bool IsBetween (this Point2d pt, Point2d p1, Point2d p2)
{
return((pt - p1).GetNormal() == (p2 - pt).GetNormal());
}
public static Point2d To2d (this Point3d pt)
{
return(new Point2d(pt.X, pt.Y));
}
public static bool IsPointInside(this Curve c, Point2d pt)
{
if(c.StartParam != 0.0 || (c.EndParam - Math.Truncate(c.EndParam) != 0.0))
throw(new ArgumentException("Invalid Curve Parameter"));
int n = (int)c.EndParam;
Curve2d[] ca = new Curve2d[n];
for(int i = 0; i < n; i++)
{
Point2d sp = (c.GetPointAtParameter(i)).To2d();
Point2d mp = (c.GetPointAtParameter(i + 0.5)).To2d();
Point2d ep = (c.GetPointAtParameter(i + 1.0)).To2d();
if(mp.IsBetween(sp, ep))
ca[i] = new LineSegment2d(sp, ep);
else
ca[i] = new CircularArc2d(sp, mp, ep);
}
n = 0;
using(CompositeCurve2d c2d = new CompositeCurve2d(ca))
using(Ray2d r2d = new Ray2d(pt, Vector2d.XAxis))
using(CurveCurveIntersector2d cci2d = new CurveCurveIntersector2d(c2d, r2d))
{
for(int i = 0; i < cci2d.NumberOfIntersectionPoints; i++)
if(cci2d.IsTransversal(i)) n++;
}
return(n % 2 != 0);
}
}
[CommandMethod("CheckForPointInsideClosedPloyline")]
public void CheckForPointInsideClosedPloyline() // This method can have any name
{
Document doc = Application.DocumentManager.MdiActiveDocument;
Database db = doc.Database;
Editor ed = doc.Editor;
Point3dCollection vertices = new Point3dCollection();
ObjectId dbPntId = ObjectId.Null;
using (Transaction trx = db.TransactionManager.StartTransaction())
{
BlockTable bt = (BlockTable)trx.GetObject(db.BlockTableId, OpenMode.ForRead);
BlockTableRecord btr = (BlockTableRecord)trx.GetObject(db.CurrentSpaceId, OpenMode.ForWrite);
Point3d pnt = ed.GetPoint("\nSelectPoint").Value;
Polyline polyLine = (Polyline)trx.GetObject(ed.GetEntity("\nSelect PolyLine").ObjectId, OpenMode.ForRead);
DBPoint dbPnt = new DBPoint(pnt);
dbPntId = btr.AppendEntity(dbPnt);
trx.AddNewlyCreatedDBObject(dbPnt, true);
for (int i = 0; i < polyLine.NumberOfVertices; i++)
{
vertices.Add(polyLine.GetPoint3dAt(i));
}
trx.Commit();
}
using (Transaction trx = db.TransactionManager.StartTransaction())
{
DBPoint dbPnt = (DBPoint)trx.GetObject(dbPntId, OpenMode.ForWrite);
SelectionSet ssWP = ed.SelectWindowPolygon(vertices).Value;
if (ssWP != null)
{
foreach (ObjectId id in ssWP.GetObjectIds())
{
if (id == dbPntId)
{
ed.WriteMessage("\nIs Inside");
dbPnt.Erase();
trx.Commit();
return;
}
}
}
SelectionSet ssCP = ed.SelectCrossingPolygon(vertices).Value;
if (ssCP != null)
{
foreach (ObjectId id in ssCP.GetObjectIds())
{
if (id == dbPntId)
{
ed.WriteMessage("\nIs On Polyline");
dbPnt.Erase();
trx.Commit();
return;
}
}
}
ed.WriteMessage("\nIs not Inside or On Polyline");
dbPnt.Erase();
trx.Commit();
}
}
also, no idea if you have seen this:
http://www.theswamp.org/index.php?topic=17222.msg207884#msg207884
Here is a cheating way and probably has gotchas like if a polyline that is self intersecting etc....
// Extensions to convert Curve to CompositeCurve2d
public static class Extensions
{
public static bool IsBetween (this Point2d pt, Point2d p1, Point2d p2)
{
return((pt - p1).GetNormal() == (p2 - pt).GetNormal());
}
public static Point2d To2d (this Point3d pt)
{
return(new Point2d(pt.X, pt.Y));
}
public static Point2d GetPointAtRelativeParam(this Curve c, double rpm)
{
double spm = c.StartParam;
double epm = c.EndParam;
return c.GetPointAtParameter(spm + (epm - spm) * rpm).To2d();
}
public static Curve2d[] ToCurve2dArray(this Arc a)
{
Point2d sp = a.GetPointAtRelativeParam(0.0);
Point2d mp = a.GetPointAtRelativeParam(0.5);
Point2d ep = a.GetPointAtRelativeParam(1.0);
return new Curve2d[2]{
new CircularArc2d(sp, mp, ep),
new LineSegment2d(ep, sp)
};
}
public static Curve2d[] ToCurve2dArray(this Circle ci)
{
Point2d sp = ci.GetPointAtRelativeParam(0.0);
Point2d q1 = ci.GetPointAtRelativeParam(0.25);
Point2d ep = ci.GetPointAtRelativeParam(0.5);
Point2d q3 = ci.GetPointAtRelativeParam(0.75);
return new Curve2d[2]{
new CircularArc2d(sp, q1, ep),
new CircularArc2d(ep, q3, sp)
};
}
public static Curve2d[] ToCurve2dArray(this Curve c)
{
if (c.StartParam != 0.0 || (c.EndParam - Math.Truncate(c.EndParam) != 0.0))
throw (new ArgumentException("Invalid Curve Parameter"));
int n = (int)c.EndParam;
Curve2d[] ca = new Curve2d[c.Closed ? n : n + 1];
Point2d sp0 = (c.GetPointAtParameter(0.0)).To2d();
Point2d sp = sp0;
for (int i = 0; i < n; i++)
{
Point2d mp = (c.GetPointAtParameter(i + 0.5)).To2d();
Point2d ep = (c.GetPointAtParameter(i + 1.0)).To2d();
if (mp.IsBetween(sp, ep))
ca[i] = new LineSegment2d(sp, ep);
else
ca[i] = new CircularArc2d(sp, mp, ep);
sp = ep;
}
if (!c.Closed)
ca[n] = new LineSegment2d(sp, sp0);
return ca;
}
public static CompositeCurve2d ToCompositeCurve2d(this Curve c)
{
Curve2d[] ca;
Arc a = c as Arc;
if (a != null)
ca = a.ToCurve2dArray();
else
{
Circle ci = c as Circle;
if (ci != null)
ca = ci.ToCurve2dArray();
else
ca = c.ToCurve2dArray();
}
return new CompositeCurve2d(ca);
}
public static bool IsPointInside(this Curve c, Point2d pt)
{
int n = 0;
using(CompositeCurve2d c2d = c.ToCompositeCurve2d())
using(Ray2d r2d = new Ray2d(pt, Vector2d.XAxis))
using(CurveCurveIntersector2d cci2d = new CurveCurveIntersector2d(c2d, r2d))
{
for(int i = 0; i < cci2d.NumberOfIntersectionPoints; i++)
if(cci2d.IsTransversal(i)) n++;
}
return(n % 2 != 0);
}
}
BTW le, would you consider yourself yet another victim of the burst property bubble?
Here is a cheating way and probably has gotchas like if a polyline that is self intersecting etc.....
If you ain't cheating your ain't tryingHere is a cheating way and probably has gotchas like if a polyline that is self intersecting etc.....
Jeff, after searching for a while on the best way to do this, I've decided that your cheating way is a nice simple solution to a complex problem.
Thank you!