Thanks Martin. We were doing isValid checks other places in the code (inside the wrapped geometry initializations), and I assumed that was happening for MultiPolygon too, which it wasn't. And I haven't quite internalized what vector data is invalid and what's valid.

Is it the case that most operations will throw a TopologyException for invalid geometries? I've been debating not putting the isValid check inside the wrapped Geometry class initializers, since this article: http://www.vividsolutions.com/jts/caseStudy_largePolyValidation.htm worries me about the potential performance hit of validating each geometry on creation. But if most operations you would do with an invalid polygon would throw TopologyExceptions, it might be worth it to eat the performance hit and make sure everything is valid before letting the user start working with the geometry, for the scala wrapper.

On Tue, May 20, 2014 at 5:30 PM, Martin Davis wrote:
The TopologyException occurs because the MultiPolygon is not valid.  The two components overlap (precisely, the first polygon contains the second).

On Tue, May 20, 2014 at 2:17 PM, Rob Emanuele wrote:
Hello,

I was wondering if I could get some insight on why this would be throwing a TopologyException. I've been looking through the JTS source, and trying different variations on the MultiPolygon, but I can't seem to nail down what about this is causing the issue (sorry for the scala code, I did this example in the interpreter, but I think it should be clear):

import com.vividsolutions.jts.geom._

val f = new GeometryFactory()
val l = f.createLineString(Array(new Coordinate(0,0), new Coordinate(2,2)))

val exterior1 = f.createLinearRing(Array(new Coordinate(0,0), new Coordinate(0,2), new Coordinate(2,2), new Coordinate(2,0), new Coordinate(0,0)))

val exterior2 = f.createLinearRing(Array(new Coordinate(0,0), new Coordinate(0,1), new Coordinate(2,1), new Coordinate(2,0), new Coordinate(0,0)))

val p1 = f.createPolygon(exterior1, Array())

val p2 = f.createPolygon(exterior2, Array())

val mp = f.createMultiPolygon(Array(p1, p2))

mp.union(l)

Here is the exception thrown in the interpreter:
com.vividsolutions.jts.geom.TopologyException: side location conflict [ (0.0, 1.0, NaN) ]
at com.vividsolutions.jts.geomgraph.EdgeEndStar.propagateSideLabels(EdgeEndStar.java:300)
at com.vividsolutions.jts.geomgraph.EdgeEndStar.computeLabelling(EdgeEndStar.java:136)
at com.vividsolutions.jts.geomgraph.DirectedEdgeStar.computeLabelling(DirectedEdgeStar.java:127)
at com.vividsolutions.jts.operation.overlay.OverlayOp.computeLabelling(OverlayOp.java:373)
at com.vividsolutions.jts.operation.overlay.OverlayOp.computeOverlay(OverlayOp.java:173)
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.SnapIfNeededOverlayOp.getResultGeometry(SnapIfNeededOverlayOp.java:96)
at com.vividsolutions.jts.operation.overlay.snap.SnapIfNeededOverlayOp.overlayOp(SnapIfNeededOverlayOp.java:58)
at com.vividsolutions.jts.geom.Geometry.union(Geometry.java:1395)
at .<init>(<console>:18)
at .<clinit>(<console>)
at .<init>(<console>:7)
at .<clinit>(<console>)
at \$print(<console>)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at scala.tools.nsc.interpreter.IMain.interpret(IMain.scala:604)
at scala.tools.nsc.interpreter.IMain.interpret(IMain.scala:568)
at scala.tools.nsc.interpreter.ILoop.reallyInterpret\$1(ILoop.scala:756)
at scala.tools.nsc.interpreter.ILoop.interpretStartingWith(ILoop.scala:801)
at scala.tools.nsc.interpreter.ILoop.command(ILoop.scala:713)
at scala.tools.nsc.interpreter.ILoop.processLine\$1(ILoop.scala:577)
at scala.tools.nsc.interpreter.ILoop.innerLoop\$1(ILoop.scala:584)
at scala.tools.nsc.interpreter.ILoop.loop(ILoop.scala:587)
at scala.tools.nsc.interpreter.ILoop\$\$anonfun\$process\$1.apply\$mcZ\$sp(ILoop.scala:878)
at scala.tools.nsc.interpreter.ILoop\$\$anonfun\$process\$1.apply(ILoop.scala:833)
at scala.tools.nsc.interpreter.ILoop\$\$anonfun\$process\$1.apply(ILoop.scala:833)
at scala.tools.nsc.interpreter.ILoop.process(ILoop.scala:833)
at scala.tools.nsc.interpreter.ILoop.main(ILoop.scala:900)
at xsbt.ConsoleInterface.run(ConsoleInterface.scala:57)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at sbt.compiler.AnalyzingCompiler.call(AnalyzingCompiler.scala:73)
at sbt.compiler.AnalyzingCompiler.console(AnalyzingCompiler.scala:64)
at sbt.Console.console0\$1(Console.scala:23)
at sbt.Console\$\$anonfun\$apply\$2\$\$anonfun\$apply\$1.apply\$mcV\$sp(Console.scala:24)
at sbt.TrapExit\$.executeMain\$1(TrapExit.scala:33)
at sbt.TrapExit\$\$anon\$1.run(TrapExit.scala:42)

Any insights on why this simple example is throwing?

Thanks,
Rob

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