Solved! Go to Solution.
I am having the same issue. I have a point that I have converted to an extremely small envelope, but I get get 3 results back from my query and should only be getting one. This seems like a bug.
Anyone from ESRI reading these?
It's only a bug if the three returned shapes do not overlap the requested envelope. Do they? Can you provide a FGDB data sample and the corners of the envelope with which you're querying?
ALL application code must handle the possibility that a point-in-poly query could return zero, one, or many features. With a simple envelope search, the probability of multiple return rows approaches unity.
Since there's no way to alter the design without including a full geometry processing library in the FGDBAPI DLL (and that doesn't seem likely), the best possible solution is going to be a simple helper function to test point-in-polygon (and even that will need to return a ternary response -- {"IN", "OUT", "ON"}).
- V
THanks, I will provide a data and code sample in the morning when I am back at my PC.
Attached is a small file geodatabase with one featureclass. When I query with the point shown on the attached map(expanded slightly to make an envelope), I get three results. The correct one, David James, but also Tandy and Hamilton, which is obviously wrong. There should be only one row returned, but I am getting three.
Thanks
Code:
static void Main(string[] args) { Geodatabase geodatabase = null; Table table = null; try { geodatabase = Geodatabase.Open(@"C:\Temp\test.gdb"); Esri.FileGDB.Point pt = new Esri.FileGDB.Point(); double x = 1204123.4375; double y = 273148.87152777775; pt.x = x; pt.y = y; Envelope envelope = new Envelope(); envelope.xMin = x - .00001; envelope.yMin = y - .00001; envelope.xMax = x + .00001; envelope.yMax = y + .00001; table = geodatabase.OpenTable("MetroCouncil"); RowCollection spQueryRows = table.Search("*", "", envelope, RowInstance.Recycle); foreach (Row spQueryRow in spQueryRows) { Console.WriteLine(spQueryRow.GetString("COUN_NAME").ToString()); } Console.ReadLine(); } catch (Exception ex) { } finally { table.Close(); geodatabase.Close(); } }
Well, I couldn't read the FGDB, but the JPEG indicates an envelope-on-envelope search is being conducted (which is what I expected).
The results are not incorrect, they're just imprecise. The spatial search just nominates candidates which are close enough to have a relationship (beyond envelope_overlap). You need to do the point-in-polygon test on your own (which is what I wrote in March).
- V
Thanks Vince, it all made perfect sense as soon as I saw your attached image.
I went ahead and put together the helper function earlier and am attaching this process for anyone else who finds this, its working well now:
RowCollection spQueryRows = table.Search("*", "", envelope, RowInstance.Recycle); MultiPartShapeBuffer rowGeomPoly = new MultiPartShapeBuffer(); foreach (Row spQueryRow in spQueryRows) { //Get the row polygon rowGeomPoly = spQueryRow.GetGeometry(); //Convert ESRI Geometry to PointF array System.Drawing.PointF[] polyPts = new PointF[rowGeomPoly.Points.Length]; System.Drawing.PointF point; for(int j = 0;j<=rowGeomPoly.Points.Length -1;j++) { point = new PointF { X = (float)rowGeomPoly.Points.x, Y = (float)rowGeomPoly.Points polyPts.y }; = point; } //Intersect bool isIntersected = PointIsInPolygon(polyPts, new System.Drawing.PointF { X = (float)pt.x, Y = (float)pt.y }); if (isIntersected) { Console.WriteLine(spQueryRow.GetString("COUN_NAME").ToString()); break; } }
private static bool PointIsInPolygon(PointF[] polygon, PointF target_point) { // Make a GraphicsPath containing the polygon. GraphicsPath path = new GraphicsPath(); path.AddPolygon(polygon); // See if the point is inside the path. return path.IsVisible(target_point); }