Dear JTS community,
firstly, thank you for an awesome JTS, it's very helpful with my work.
Secondly, I have a problem.
I'm trying to process contours of a 3D surface and plot them in a 2D
image as lines and filled polygons. In order to do that I'm noding a
large set of individual contour segments (up to hundreds of thousands)
together with a bounding rectangle and then polygonize the noded set. My
problem is sometimes the contouring algorithm is not exact and outputs a
contour which has a coordinate 1ULP off the correct value. When it
happens, the noder I'm using is not reporting it as an intersection with
the bounding rectangle. Therefore, resulting polygonization has dangles
which is not correct result in my domain.
What is wrong with my approach? Should I use a different noder or
precision model?
To illustrate the problem, here is an example code:
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import com.vividsolutions.jts.algorithm.RobustLineIntersector;
import com.vividsolutions.jts.geom.Coordinate;
import com.vividsolutions.jts.geom.Geometry;
import com.vividsolutions.jts.geom.GeometryFactory;
import com.vividsolutions.jts.geom.LineString;
import com.vividsolutions.jts.geom.PrecisionModel;
import com.vividsolutions.jts.noding.IntersectionAdder;
import com.vividsolutions.jts.noding.MCIndexNoder;
import com.vividsolutions.jts.noding.NodedSegmentString;
import com.vividsolutions.jts.noding.Noder;
import com.vividsolutions.jts.noding.SegmentString;
import com.vividsolutions.jts.operation.polygonize.Polygonizer;
public class OneULPProblem {
public static void main(String[] args) {
GeometryFactory gf = new GeometryFactory(new
PrecisionModel(PrecisionModel.FLOATING));
LineString borders = gf.createLineString(new Coordinate[] {
new Coordinate(-180D, -90D),
new Coordinate(180D, -90D),
new Coordinate(180D, 90D),
new Coordinate(-180D, 90D),
new Coordinate(-180D, -90D), });
LineString contourA = gf.createLineString(new Coordinate[] {
new Coordinate(-180D, 0D),
new Coordinate(-90D, -60D),
new Coordinate(90D, 60D),
new Coordinate(180D, 0D), });
LineString contourB = gf.createLineString(new Coordinate[] {
new Coordinate(-180D, 0D),
new Coordinate(-90D, -60D),
new Coordinate(90D, 60D),
new
Coordinate(Double.longBitsToDouble(Double.doubleToLongBits(180D) - 1),
0D), });
System.out.println("Exact contour:");
polygonize(gf, borders, contourA);
System.out.println("\nOff-by-1ULP contour:");
polygonize(gf, borders, contourB);
}
private static void polygonize(GeometryFactory gf, LineString
borders, LineString contour) {
List<SegmentString> segments = new ArrayList<SegmentString>();
segments.add(lineStrToSegmentStr(borders));
segments.add(lineStrToSegmentStr(contour));
Noder noder = new MCIndexNoder(new IntersectionAdder(new
RobustLineIntersector()));
noder.computeNodes(segments);
Collection<?> nodedSubstrings = noder.getNodedSubstrings();
List<LineString> lineStrings = new
ArrayList<>(nodedSubstrings.size());
for (Object obj : nodedSubstrings) {
lineStrings.add(gf.createLineString(((SegmentString)
obj).getCoordinates()));
}
Geometry noded = gf.buildGeometry(lineStrings);
Polygonizer polygonizer = new Polygonizer();
polygonizer.add(noded);
print(polygonizer.getPolygons(), "Polygons");
print(polygonizer.getDangles(), "Dangles");
print(polygonizer.getCutEdges(), "Cut Edges");
print(polygonizer.getInvalidRingLines(), "Invalid Ring Lines");
}
private static final SegmentString lineStrToSegmentStr(LineString ls) {
return new NodedSegmentString(ls.getCoordinates(), null);
}
private static final void print(Collection<?> coll, String type) {
if (coll.isEmpty()) {
return;
}
System.out.println(type + ": ");
for (Object o : coll) {
System.out.println(o);
}
}
}
The code above outputs this:
Exact contour:
Polygons:
POLYGON ((180 0, 90 60, -90 -60, -180 0, -180 90, 180 90, 180 0))
POLYGON ((-180 -90, -180 0, -90 -60, 90 60, 180 0, 180 -90, -180 -90))
Off-by-1ULP contour:
Polygons:
POLYGON ((-180 -90, -180 0, -180 90, 180 90, 180 -90, -180 -90))
Dangles:
LINESTRING (-180 0, -90 -60, 90 60, 179.99999999999997 0)
What can I do to have both resulting polygonizations identical given
that I won't change the input?
Thanks,
--
Peter Kovac
MicroStep-MIS
Programmer
[email protected]
http://www.microstep-mis.com
------------------------------------------------------------------------------
Comprehensive Server Monitoring with Site24x7.
Monitor 10 servers for $9/Month.
Get alerted through email, SMS, voice calls or mobile push notifications.
Take corrective actions from your mobile device.
http://pubads.g.doubleclick.net/gampad/clk?id=154624111&iu=/4140/ostg.clktrk
_______________________________________________
Jts-topo-suite-user mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/jts-topo-suite-user