ComputeRays { public static double splitLineStringIntoPoints(LineString geom, double segmentSizeConstraint, List<Coordinate> pts) { double geomLength = geom.getLength(); if(geomLength < segmentSizeConstraint) { Coordinate[] points = geom.getCoordinates(); double segmentLength = 0; final double targetSegmentSize = geomLength / 2.0; for (int i = 0; i < points.length - 1; i++) { Coordinate a = points[i]; final Coordinate b = points[i + 1]; double length = a.distance3D(b); if(length + segmentLength > targetSegmentSize) { double segmentLengthFraction = (targetSegmentSize - segmentLength) / length; Coordinate midPoint = new Coordinate(a.x + segmentLengthFraction * (b.x - a.x), a.y + segmentLengthFraction * (b.y - a.y), a.z + segmentLengthFraction * (b.z - a.z)); pts.add(midPoint); break; } segmentLength += length; } return geom.getLength(); } else { double targetSegmentSize = geomLength / Math.ceil(geomLength / segmentSizeConstraint); Coordinate[] points = geom.getCoordinates(); double segmentLength = 0.; Coordinate midPoint = null; for (int i = 0; i < points.length - 1; i++) { Coordinate a = points[i]; final Coordinate b = points[i + 1]; double length = a.distance3D(b); if(Double.isNaN(length)) { length = a.distance(b); } while (length + segmentLength > targetSegmentSize) { double segmentLengthFraction = (targetSegmentSize - segmentLength) / length; Coordinate splitPoint = new Coordinate(); splitPoint.x = a.x + segmentLengthFraction * (b.x - a.x); splitPoint.y = a.y + segmentLengthFraction * (b.y - a.y); splitPoint.z = a.z + segmentLengthFraction * (b.z - a.z); if(midPoint == null && length + segmentLength > targetSegmentSize / 2) { segmentLengthFraction = (targetSegmentSize / 2.0 - segmentLength) / length; midPoint = new Coordinate(a.x + segmentLengthFraction * (b.x - a.x), a.y + segmentLengthFraction * (b.y - a.y), a.z + segmentLengthFraction * (b.z - a.z)); } pts.add(midPoint); a = splitPoint; length = a.distance3D(b); if(Double.isNaN(length)) { length = a.distance(b); } segmentLength = 0; midPoint = null; } if(midPoint == null && length + segmentLength > targetSegmentSize / 2) { double segmentLengthFraction = (targetSegmentSize / 2.0 - segmentLength) / length; midPoint = new Coordinate(a.x + segmentLengthFraction * (b.x - a.x), a.y + segmentLengthFraction * (b.y - a.y), a.z + segmentLengthFraction * (b.z - a.z)); } segmentLength += length; } if(midPoint != null) { pts.add(midPoint); } return targetSegmentSize; } } ComputeRays(PropagationProcessData data); static double[] sumArrayWithPonderation(double[] array1, double[] array2, double p); static double[] sumDbArray(double[] array1, double[] array2); static double[] multArray(double[] array1, double[] array2); static double sumArray(int nbfreq, double energeticSum[]); static double sumArray(double energeticSum[]); static double[] sumArray(double array1[], double array2[]); int getThreadCount(); void setThreadCount(int threadCount); void makeSourceRelativeZToAbsolute(); void makeRelativeZToAbsolute(); void makeReceiverRelativeZToAbsolute(); static double dbaToW(double dBA); static double[] dbaToW(double[] dBA); static double wToDba(double w); static double[] wToDba(double[] w); static double splitLineStringIntoPoints(LineString geom, double segmentSizeConstraint,
                                             List<Coordinate> pts); void computeReflexionOverBuildings(Coordinate p0, Coordinate p1, List<PointPath> points, List<SegmentPath> segments, List<SegmentPath> srPath); static int[] asWallArray(MirrorReceiverResult res); List<PropagationPath> computeReflexion(Coordinate receiverCoord,
                                            Coordinate srcCoord, boolean favorable, List<FastObstructionTest.Wall> nearBuildingsWalls); PropagationPath computeFreefield(Coordinate receiverCoord,
                                            Coordinate srcCoord,List<TriIdWithIntersection> inters); PropagationPath computeHorizontalEdgeDiffraction(boolean obstructedSourceReceiver, Coordinate receiverCoord,
                                                            Coordinate srcCoord, List<TriIdWithIntersection> allInterPoints); static Plane ComputeZeroRadPlane(Coordinate p0, Coordinate p1); static org.apache.commons.math3.geometry.euclidean.threed.Vector3D CoordinateToVector(Coordinate p); static List<Coordinate> cutRoofPointsWithPlane(Plane plane, List<Coordinate> roofPts); List<Coordinate> computeSideHull(boolean left, Coordinate p1, Coordinate p2); void computeRaysAtPosition(Coordinate receiverCoord, int idReceiver, List<PropagationDebugInfo> debugInfo, IComputeRaysOut dataOut, ProgressVisitor progressVisitor); void initStructures(); void runDebug(IComputeRaysOut computeRaysOut, List<PropagationDebugInfo> debugInfo); void run(IComputeRaysOut computeRaysOut);  }
@Test public void TestSplitLineStringIntoPoints() { GeometryFactory factory = new GeometryFactory(); List<Coordinate> sourcePoints = new ArrayList<>(); LineString geom = factory.createLineString(new Coordinate[]{new Coordinate(1,2,0), new Coordinate(4,2,0), new Coordinate(4, 0, 0)}); Coordinate receiverCoord = new Coordinate(-4, 2, 0); Coordinate nearestPoint = JTSUtility.getNearestPoint(receiverCoord, geom); double segmentSizeConstraint = Math.max(1, receiverCoord.distance3D(nearestPoint) / 2.0); assertEquals(2.5, ComputeRays.splitLineStringIntoPoints(geom , segmentSizeConstraint, sourcePoints), 1e-6); assertEquals(2, sourcePoints.size()); assertEquals(0, new Coordinate(2.25, 2, 0).distance3D(sourcePoints.get(0)), 1e-6); assertEquals(0, new Coordinate(4, 1.25, 0).distance3D(sourcePoints.get(1)), 1e-6); }
@Test public void TestSplitRegression() throws ParseException { LineString geom = (LineString)new WKTReader().read("LINESTRING (26.3 175.5 0.0000034909259558, 111.9 90.9 0, 123 -70.9 0, 345.2 -137.8 0)"); double constraint = 82.98581729762442; List<Coordinate> pts = new ArrayList<>(); ComputeRays.splitLineStringIntoPoints(geom, constraint, pts); for(Coordinate pt : pts) { assertNotNull(pt); } assertEquals(7, pts.size()); }