package com.revolsys.geometry.test.function; import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; import java.util.List; import com.revolsys.geometry.algorithm.LineIntersector; import com.revolsys.geometry.algorithm.RobustLineIntersector; import com.revolsys.geometry.model.Geometry; import com.revolsys.geometry.model.LineString; import com.revolsys.geometry.model.Point; import com.revolsys.geometry.noding.BasicSegmentString; import com.revolsys.geometry.noding.FastNodingValidator; import com.revolsys.geometry.noding.IntersectionAdder; import com.revolsys.geometry.noding.MCIndexNoder; import com.revolsys.geometry.noding.NodedSegmentString; import com.revolsys.geometry.noding.Noder; import com.revolsys.geometry.noding.ScaledNoder; import com.revolsys.geometry.noding.SegmentString; import com.revolsys.geometry.noding.snapround.MCIndexSnapRounder; public class NodingFunctions { public static Geometry checkNoding(final Geometry geom) { final List segs = newSegmentStrings(geom); final FastNodingValidator nv = new FastNodingValidator(segs); nv.setFindAllIntersections(true); nv.isValid(); final List intPts = nv.getIntersections(); final Point[] pts = new Point[intPts.size()]; for (int i = 0; i < intPts.size(); i++) { final Point coord = (Point)intPts.get(i); // use default factory in case intersections are not fixed pts[i] = FunctionsUtil.getFactoryOrDefault(null).point(coord); } return FunctionsUtil.getFactoryOrDefault(null).punctual(pts); } private static Geometry fromSegmentStrings(final Collection segStrings) { final LineString[] lines = new LineString[segStrings.size()]; int index = 0; for (final Iterator i = segStrings.iterator(); i.hasNext();) { final SegmentString ss = (SegmentString)i.next(); final LineString line = FunctionsUtil.getFactoryOrDefault(null).lineString(ss.getPoints()); lines[index++] = line; } return FunctionsUtil.getFactoryOrDefault(null).lineal(lines); } public static Geometry MCIndexNoding(final Geometry geom) { final List segs = newNodedSegmentStrings(geom); final Noder noder = new MCIndexNoder(new IntersectionAdder(new RobustLineIntersector())); noder.computeNodes(segs); final Collection nodedSegStrings = noder.getNodedSubstrings(); return fromSegmentStrings(nodedSegStrings); } public static Geometry MCIndexNodingWithPrecision(final Geometry geom, final double scaleFactor) { final List segs = newNodedSegmentStrings(geom); final LineIntersector li = new RobustLineIntersector(scaleFactor); final Noder noder = new MCIndexNoder(new IntersectionAdder(li)); noder.computeNodes(segs); final Collection nodedSegStrings = noder.getNodedSubstrings(); return fromSegmentStrings(nodedSegStrings); } private static List<NodedSegmentString> newNodedSegmentStrings(final Geometry geom) { final List<NodedSegmentString> segs = new ArrayList<>(); final List<LineString> lines = geom.getGeometries(LineString.class); for (final LineString line : lines) { segs.add(new NodedSegmentString(line, null)); } return segs; } private static List<SegmentString> newSegmentStrings(final Geometry geom) { final List<SegmentString> segs = new ArrayList<>(); final List<LineString> lines = geom.getGeometries(LineString.class); for (final LineString line : lines) { segs.add(new BasicSegmentString(line, null)); } return segs; } /** * Runs a ScaledNoder on input. * Input vertices should be rounded to precision model. * * @param geom * @param scaleFactor * @return the noded geometry */ public static Geometry scaledNoding(final Geometry geom, final double scaleFactor) { final List segs = newSegmentStrings(geom); final Noder noder = new ScaledNoder(new MCIndexSnapRounder(1.0), scaleFactor); noder.computeNodes(segs); final Collection nodedSegStrings = noder.getNodedSubstrings(); return fromSegmentStrings(nodedSegStrings); } }