Lars,

That's some pretty ugly geometries you have there! They are full of "zero-width spikes" - ie places where a section of linework is so narrow that it is *almost* coincident. The reason the difference op is failing is that the geometries internally get "snapped" in order to try and cope with the nearly-coincident lines. However, the snapping perturbs them just enough that one or both inputs end up being invalid.

I have found a simple fix that works in this case. The solution is to "self-snap" the input geometries and then clean them (using buffer(0), for lack of anything better). This eliminates vertices which are so close to other linework that they cause topology collapse.

You might want to try this approach on your other test cases as well. The fix is attached - it's provided as an enhancement to your unit test code.

Let me know how it goes.... If this looks good, I will consider how this could be integrated into JTS.

Martin

Lars Aksel Opahl wrote:
Hi

We get the TopologyException error from time. I now have a case where we do difference between 2 polygons and we get the error. See the example JUNIT code below. The area we try to remove is bridge in he big polygon, so there should be one less inner ring after the difference. Both polygons are valid. Doing a buffer 0.0 does not change the behavior.
com.vividsolutions.jts.geom.TopologyException: side location conflict
[ (1912.6666044428991, 3056.6918339405856, NaN) ]
        at com.vividsolutions.jts.geomgraph.EdgeEndStar.propagateSideLabels
(EdgeEndStar.java:297)
        at com.vividsolutions.jts.geomgraph.EdgeEndStar.computeLabelling
(EdgeEndStar.java:135)
        at com.vividsolutions.jts.geomgraph.DirectedEdgeStar.computeLabelling
(DirectedEdgeStar.java:127)
        at com.vividsolutions.jts.operation.overlay.OverlayOp.computeLabelling
(OverlayOp.java:365)
        at com.vividsolutions.jts.operation.overlay.OverlayOp.computeOverlay
(OverlayOp.java:165)
        at com.vividsolutions.jts.operation.overlay.OverlayOp.getResultGeometry
(OverlayOp.java:127)
        at com.vividsolutions.jts.operation.overlay.OverlayOp.overlayOp
(OverlayOp.java:66)
        at
com.vividsolutions.jts.operation.overlay.snap.SnapOverlayOp.getResultGeometry(SnapOverlayOp.java:68)
        at
com.vividsolutions.jts.operation.overlay.snap.SnapOverlayOp.overlayOp
(SnapOverlayOp.java:25)
        at
com.vividsolutions.jts.operation.overlay.snap.SnapIfNeededOverlayOp.getResultGeometry(SnapIfNeededOverlayOp.java:76)
        at
com.vividsolutions.jts.operation.overlay.snap.SnapIfNeededOverlayOp.overlayOp(SnapIfNeededOverlayOp.java:25)
        at com.vividsolutions.jts.geom.Geometry.difference(Geometry.java:1126)
        at
no.skogoglandskap.map.filedownload.TopologyExecptionTest.test_differnce
(TopologyExecptionTest.java:68)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke
(NativeMethodAccessorImpl.java:39)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke
(DelegatingMethodAccessorImpl.java:25)
        at java.lang.reflect.Method.invoke(Method.java:585)
        at junit.framework.TestCase.runTest(TestCase.java:164)
        at junit.framework.TestCase.runBare(TestCase.java:130)
        at junit.framework.TestResult$1.protect(TestResult.java:106)
        at junit.framework.TestResult.runProtected(TestResult.java:124)
        at junit.framework.TestResult.run(TestResult.java:109)
        at junit.framework.TestCase.run(TestCase.java:120)
        at junit.framework.TestSuite.runTest(TestSuite.java:230)
        at junit.framework.TestSuite.run(TestSuite.java:225)
        at org.eclipse.jdt.internal.junit.runner.junit3.JUnit3TestReference.run
(JUnit3TestReference.java:130)
        at org.eclipse.jdt.internal.junit.runner.TestExecution.run
(TestExecution.java:38)
        at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests
(RemoteTestRunner.java:460)
        at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests
(RemoteTestRunner.java:673)
        at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run
(RemoteTestRunner.java:386)
        at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main
(RemoteTestRunner.java:196)



Example code  ---->

publicvoidtest_differnce() throwsException {


Geometry bigPolygon = readGeom("bigPolygon.wkt.txt");
assertTrue("Is not valid", bigPolygon.isValid());

Geometry areaToRemove = readGeom("areaToRemove.wkt.txt");
assertTrue("Is not valid", areaToRemove.isValid());

Geometry diff = bigPolygon.difference(areaToRemove);


assertNotNull("Result is found", diff);

assertTrue("New area is equal", diff.getArea() < bigPolygon.getArea());


}


privateGeometry readGeom(String fileName) throwsFileNotFoundException,
ParseException,

IOException {

FileReader fRdr = newFileReader(fileName);

WKTReader wktRdr = newWKTReader();

Geometry geom = wktRdr.read(fRdr);

fRdr.close();

IsValidOp validOp = newIsValidOp(geom);

TopologyValidationError err = validOp.getValidationError();

if(err != null) {

thrownewRuntimeException(err.getMessage());

}

returngeom;

}


Lars

------------------------------------------------------------------------

_______________________________________________
jts-devel mailing list
jts-devel@lists.jump-project.org
http://lists.refractions.net/mailman/listinfo/jts-devel

--
Martin Davis
Senior Technical Architect
Refractions Research, Inc.
(250) 383-3022

package mdjtstest.ext.larso;

import java.io.*;

import junit.framework.TestCase;
import com.vividsolutions.jts.geom.*;
import com.vividsolutions.jts.io.*;
import com.vividsolutions.jts.operation.valid.*;

import com.vividsolutions.jts.operation.overlay.snap.*;

public class TestTopoException 
extends TestCase 
{
  public static void main(String[] args) {
    junit.textui.TestRunner.run(TestTopoException.class);
  }

        public TestTopoException(String name) {
                super(name);
        }

        public void testDifference() 
                throws Exception 
        {
                Geometry bigPolygon = readGeom("bigPolygon.wkt.txt");
                assertTrue("Is not valid", bigPolygon.isValid());

                Geometry areaToRemove = readGeom("areaToRemove.wkt.txt");
                assertTrue("Is not valid", areaToRemove.isValid());

                // self-snap the geometries, to eliminate "zero-width spikes" 
                double snapTol = 
GeometrySnapper.computeOverlaySnapTolerance(bigPolygon, areaToRemove );
                Geometry aFix = selfSnap(bigPolygon, snapTol);
                Geometry bFix = selfSnap(areaToRemove, snapTol);
                
                Geometry diff = aFix.difference(bFix);
//              Geometry diff = bigPolygon.difference(areaToRemove);

                System.out.println(diff);
                
                assertNotNull("Result is found", diff);
                assertTrue("New area is equal", diff.getArea() < 
bigPolygon.getArea());

        }

        Geometry selfSnap(Geometry g, double snapTolerance)
        {
                GeometrySnapper snapper = new GeometrySnapper(g);
                Geometry snapped = snapper.snapTo(g, snapTolerance);
                // need to "clean" snapped geometry - use buffer(0) as a simple 
way to do this
                Geometry fix = snapped.buffer(0);
                return fix;
        }
        
        private Geometry readGeom(String fileName) throws FileNotFoundException,
                        ParseException, IOException {

                FileReader fRdr = new FileReader(fileName);
                WKTReader wktRdr = new WKTReader();

                Geometry geom = wktRdr.read(fRdr);
                fRdr.close();

                IsValidOp validOp = new IsValidOp(geom);
                TopologyValidationError err = validOp.getValidationError();
                if (err != null) {
                        throw new RuntimeException(err.getMessage());
                }
                return geom;
        }
}
_______________________________________________
jts-devel mailing list
jts-devel@lists.jump-project.org
http://lists.refractions.net/mailman/listinfo/jts-devel

Reply via email to