bilaldursun1 / nettopologysuite

Automatically exported from code.google.com/p/nettopologysuite
0 stars 0 forks source link

Operation.Polygonize.Polygonizer quirks #15

Closed GoogleCodeExporter closed 9 years ago

GoogleCodeExporter commented 9 years ago
NTS 1.7.3 RC2

Hi Diego,

It seems that Polygonizer fails when constituent geometries being 
processed form a polygon with hole(s). It fails on Polygonizer.Polygons 
getter call. Here's exception part pointing to CGAlgorithms.IsPointInRing 
function as an error source:

System.Reflection.TargetInvocationException: Exception has been thrown by 
the target of an invocation. ---> System.NullReferenceException: Object 
reference not set to an instance of an object.

at:
GisSharpBlog.NetTopologySuite.Algorithm.CGAlgorithms.IsPointInRing
(ICoordinate p, ICoordinate[] ring) 
in:
NetTopologySuite\Algorithm\CGAlgorithms.cs:line 98

at: 
GisSharpBlog.NetTopologySuite.Operation.Polygonize.EdgeRing.FindEdgeRingCon
taining(EdgeRing testEr, IList shellList) 
in: 
NetTopologySuite\Operation\Polygonize\EdgeRing.cs:line 52

at:
GisSharpBlog.NetTopologySuite.Operation.Polygonize.Polygonizer.AssignHolesT
oShells(IList holeList, IList shellList)
in: 
NetTopologySuite\Operation\Polygonize\Polygonizer.cs:line 267

at:
GisSharpBlog.NetTopologySuite.Operation.Polygonize.Polygonizer.Polygonize
() 
in:
NetTopologySuite\Operation\Polygonize\Polygonizer.cs:line 212
----------------------

I guess adding a simple:

public static bool IsPointInRing(ICoordinate p, ICoordinate[] ring) 
        {
            if (p == null) 
                return false;

...
...

in NetTopologySuite\Algorithm\CGAlgorithms.cs might solve an issue, at 
least with error throwing. Although I should better check why p was null 
in first place :-)

Regards,
Maksim Sestic

Original issue reported on code.google.com by LivelyTe...@gmail.com on 8 Mar 2008 at 10:48

GoogleCodeExporter commented 9 years ago
I'm not sure that your sugest is correct, maybe I need a test case for try to
replicate the error.
BTW, I've check the method in JTS and looks really different from NTS impl 
(maybe a
chabge that I've not see in my port).
So please try to change your NTS code, maybe retrieving the code from the trunk 
or
change manually using this code:
        public static bool IsPointInRing(ICoordinate p, ICoordinate[] ring) 
        {
            if (p == null) 
                throw new ArgumentNullException("p", "coordinate 'p' is null");
            if (ring == null) 
                throw new ArgumentNullException("ring", "ring 'ring' is null");

            int crossings = 0;            
            /*
            *  For each segment l = (i-1, i), see if it crosses ray from test point
in positive x direction.
            */
            for (int i = 1; i < ring.Length; i++) 
            {
                int i1 = i - 1;
                ICoordinate p1 = ring[i];
                ICoordinate p2 = ring[i1];                

                if (((p1.Y > p.Y) && (p2.Y <= p.Y)) || ((p2.Y > p.Y) && (p1.Y <= p.Y))) 
                {
                    double x1 = p1.X - p.X;
                    double y1 = p1.Y - p.Y;
                    double x2 = p2.X - p.X;
                    double y2 = p2.Y - p.Y;
                    /*
                    *  segment straddles x axis, so compute intersection.
                    */
                    double xInt = RobustDeterminant.SignOfDet2x2(x1, y1, x2, y2) /
(y2 - y1);

                    /*
                    *  crosses ray if strictly positive intersection.
                    */
                    if (0.0 < xInt) 
                        crossings++;
                }
            }

            /*
            *  p is inside if number of crossings is odd.
            */
            if ((crossings % 2) == 1) 
                return true;            
            else return false;
        }

Let me see if this solve the problem, or please post a test case :)
Thanks

Original comment by diegogu...@gmail.com on 8 Mar 2008 at 11:25

Attachments:

GoogleCodeExporter commented 9 years ago
Yap, fails on:

if (p == null) throw new ArgumentNullException("p", "coordinate 'p' is null");

Tracing it back to the origin, IsPointInRing was called by:
public static EdgeRing FindEdgeRingContaining(EdgeRing testEr, IList shellList)

ILinearRing teString = testEr.Ring;
...
ICoordinate testPt = teString.GetCoordinateN(0);

Here it is - a testPt being re-assigned further at:
testPt = PointNotInList(teString.Coordinates, tryRing.Coordinates);

And later passed to IsPointInRing as in:
if (tryEnv.Contains(testEnv) && CGAlgorithms.IsPointInRing(testPt, 
tryRing.Coordinates)) isContained = true;

So probably the best place to look for the cause of this particular error is in 
FindEdgeRingContaining() function of EdgeRing.cs.

Oh, I don't have a test case :-) I mean - I have it in DWG format. Would it be 
of 
any use if I convert troublesome geometry to WKT and post here resulting 
strings?

Regards,
Maksim Sestic

Original comment by LivelyTe...@gmail.com on 8 Mar 2008 at 12:10

GoogleCodeExporter commented 9 years ago
Let's see... I guess that order of geometries being Add-ed to Polygonizer is 
irrelevant for that matter. WKT follows:

LINESTRING(159084.138183715 215384.465334836,159085.255551952 
215382.299118879,159084.287081382 215380.125720536,159081.909029527 
215380.063184668,159080.685184241 215382.030015885,159081.870080819 
215384.260803017,159084.138183715 215384.465334836)
LINESTRING(159081.417 215432.901,159081.484 215412.286,159069.343 
215411.729,159063.929 215411.79,159063.765 215441.011,159055.84 
215440.909,159055.756 215439.794,159050.254 215439.759,159050.231 
215426.571,159029.91 215426.438,159029.894 215420.862,159028.749 
215420.841,159028.787 215412.904,159050.376 215412.995,159050.394 
215404.475,159051.839 215404.512,159051.721 215397.907,159050.448 
215397.876,159050.48 215385.756,159037.29 215385.669,159037.274 
215380.139,159036.129 215380.118,159036.18 215372.161,159050.58 
215372.256,159050.641 215357.846,159061.806 215357.884,159061.764 
215355.578,159063.703 215355.583,159063.834 215344.331,159062.797 
215344.264,159062.878 215338.481,159063.885 215338.48,159063.94 
215333.569,159062.002 215333.52,159062.061 215329.565,159063.973 
215329.565,159064.019 215324.529,159063.008 215324.569,159062.948 
215318.85,159064.078 215318.847,159064.229 215304.453,159074.999 
215304.543,159074.895 215315.988,159082.789 215316.117,159082.751291265 
215325.067329746,159076.257853729 215325.010585012,159076.145672787 
215330.246673065,159077.726943351 215330.292687136,159077.64265916 
215336.096838446,159075.46670601 215336.028874838,159075.17015073 
215349.460814847,159091.770139291 215349.583804507,159091.835913025 
215356.268745225,159114.649 215356.642,159114.529 215396.632,159109.671 
215396.625,159109.501 215398.902,159112.021 215398.92,159111.982 
215404.407,159112.999 215404.421,159113.001 215412.415,159095.019 
215412.366,159094.928 215434.091,159086.987 215433.984,159086.928 
215432.972,159081.417 215432.901)
LINESTRING(159063.929280482 215399.247659686,159103.333615111 
215398.947801304,159103.342074891 215397.380179598,159101.054815857 
215397.403687265,159101.283398228 215370.145108237,159064.458615271 
215370.009119945,159063.929280482 215399.247659686)

It threw an error before changes were made to CGAlgorithms.cs. I'll post more 
examples if you need.

Regards,
Maksim Sestic

Original comment by LivelyTe...@gmail.com on 8 Mar 2008 at 12:24

GoogleCodeExporter commented 9 years ago
I've tried in JTS and the same code looks working well, so I need to test a 
little
bit and see what happens

Original comment by diegogu...@gmail.com on 8 Mar 2008 at 1:48

GoogleCodeExporter commented 9 years ago
I've found the error!
In the GisSharpBlog.NetTopologySuite.Operation.Polygonize.FindEdgeRingContaining
change the line
ICoordinate testPt = PointNotInList(teString.Coordinates, tryRing.Coordinates);
with the line
ICoordinate testPt = CoordinateArrays.PointNotInList(teString.Coordinates,
tryRing.Coordinates);
Fixed in trunk.
Thanks for support

Original comment by diegogu...@gmail.com on 8 Mar 2008 at 2:06