ComputeRays { public List<Coordinate> computeSideHull(boolean left, Coordinate p1, Coordinate p2) { if(p1.equals(p2)) { return new ArrayList<>(); } Set<LineSegment> freeFieldSegments = new HashSet<>(); GeometryFactory geometryFactory = new GeometryFactory(); List<Coordinate> input = new ArrayList<>(); Coordinate[] coordinates = new Coordinate[0]; int indexp1 = 0; int indexp2 = 0; boolean convexHullIntersects = true; input.add(p1); input.add(p2); Set<Integer> buildingInHull = new HashSet<>(); Plane cutPlane = ComputeZeroRadPlane(p1, p2); IntersectionRayVisitor intersectionRayVisitor = new IntersectionRayVisitor( data.freeFieldFinder.getPolygonWithHeight(), p1, p2, data.freeFieldFinder, input, buildingInHull, cutPlane); data.freeFieldFinder.getBuildingsOnPath(p1, p2, intersectionRayVisitor); int k; while (convexHullIntersects) { ConvexHull convexHull = new ConvexHull(input.toArray(new Coordinate[0]), geometryFactory); Geometry convexhull = convexHull.getConvexHull(); if (convexhull.getLength() / p1.distance(p2) > MAX_RATIO_HULL_DIRECT_PATH) { return new ArrayList<>(); } convexHullIntersects = false; coordinates = convexhull.getCoordinates(); input.clear(); input.addAll(Arrays.asList(coordinates)); indexp1 = -1; for (int i = 0; i < coordinates.length - 1; i++) { if (coordinates[i].equals(p1)) { indexp1 = i; break; } } if (indexp1 == -1) { return new ArrayList<>(); } Coordinate[] coordinatesShifted = new Coordinate[coordinates.length]; int len = (coordinates.length - 1) - indexp1; System.arraycopy(coordinates, indexp1, coordinatesShifted, 0, len); System.arraycopy(coordinates, 0, coordinatesShifted, len, coordinates.length - len - 1); coordinatesShifted[coordinatesShifted.length - 1] = coordinatesShifted[0]; coordinates = coordinatesShifted; indexp1 = 0; indexp2 = -1; for (int i = 1; i < coordinates.length - 1; i++) { if (coordinates[i].equals(p2)) { indexp2 = i; break; } } if (indexp2 == -1) { return new ArrayList<>(); } for (k = 0; k < coordinates.length - 1; k++) { LineSegment freeFieldTestSegment = new LineSegment(coordinates[k], coordinates[k + 1]); if (left && k < indexp2 || !left && k >= indexp2) { if (!freeFieldSegments.contains(freeFieldTestSegment)) { if(!data.freeFieldFinder.getMeshEnvelope().contains(coordinates[k]) || !data.freeFieldFinder.getMeshEnvelope().contains(coordinates[k+1])) { return new ArrayList<>(); } intersectionRayVisitor = new IntersectionRayVisitor(data.freeFieldFinder.getPolygonWithHeight(), coordinates[k], coordinates[k + 1], data.freeFieldFinder, input, buildingInHull, cutPlane); data.freeFieldFinder.getBuildingsOnPath(coordinates[k], coordinates[k + 1], intersectionRayVisitor); if(!intersectionRayVisitor.doContinue()) { convexHullIntersects = true; } if (!convexHullIntersects) { freeFieldSegments.add(freeFieldTestSegment); } else { break; } } } } } for(Coordinate p : coordinates) { if(p.z < 0) { return new ArrayList<>(); } } if(left) { return Arrays.asList(Arrays.copyOfRange(coordinates,indexp1, indexp2 + 1)); } else { ArrayList<Coordinate> inversePath = new ArrayList<>(); inversePath.addAll(Arrays.asList(Arrays.copyOfRange(coordinates,indexp2, coordinates.length))); Collections.reverse(inversePath); return inversePath; } } 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 TestcomputeVerticalEdgeDiffraction() throws LayerDelaunayError, ParseException { GeometryFactory factory = new GeometryFactory(); WKTReader wktReader = new WKTReader(factory); Envelope cellEnvelope = new Envelope(new Coordinate(0, 0, 0.), new Coordinate(20, 15, 0.)); MeshBuilder mesh = new MeshBuilder(); mesh.addGeometry(wktReader.read("POLYGON((5 6, 6 5, 7 5, 7 8, 6 8, 5 7, 5 6))"), 4); mesh.addGeometry(wktReader.read("POLYGON((9 7, 11 7, 11 11, 9 11, 9 7))"), 4); mesh.addGeometry(wktReader.read("POLYGON((12 8, 13 8, 13 10, 12 10, 12 8))"), 4); mesh.addGeometry(wktReader.read("POLYGON((10 4, 11 4, 11 6, 10 6, 10 4))"), 4); mesh.finishPolygonFeeding(cellEnvelope); FastObstructionTest manager = new FastObstructionTest(mesh.getPolygonWithHeight(), mesh.getTriangles(), mesh.getTriNeighbors(), mesh.getVertices()); PropagationProcessData processData = new PropagationProcessData(manager); ComputeRays computeRays = new ComputeRays(processData); Coordinate p1 = new Coordinate(2, 6.5, 1.6); Coordinate p2 = new Coordinate(14, 6.5, 1.6); List<Coordinate> ray = computeRays.computeSideHull(true, p1, p2); int i = 0; assertEquals(0, p1.distance(ray.get(i++)), 0.02); assertEquals(0, new Coordinate(9, 11).distance(ray.get(i++)), 0.02); assertEquals(0, new Coordinate(11, 11).distance(ray.get(i++)), 0.02); assertEquals(0, new Coordinate(13, 10).distance(ray.get(i++)), 0.02); assertEquals(0, p2.distance(ray.get(i++)), 0.02); ray = computeRays.computeSideHull(false, p1, p2); i = 0; assertEquals(0, p1.distance(ray.get(i++)), 0.02); assertEquals(0, new Coordinate(6, 5).distance(ray.get(i++)), 0.02); assertEquals(0, new Coordinate(10, 4).distance(ray.get(i++)), 0.02); assertEquals(0, new Coordinate(11, 4).distance(ray.get(i++)), 0.02); assertEquals(0, p2.distance(ray.get(i++)), 0.02); ray = computeRays.computeSideHull(false, p2, p1); i = 0; assertEquals(0, p2.distance(ray.get(i++)), 0.02); assertEquals(0, new Coordinate(13, 10).distance(ray.get(i++)), 0.02); assertEquals(0, new Coordinate(11, 11).distance(ray.get(i++)), 0.02); assertEquals(0, new Coordinate(9, 11).distance(ray.get(i++)), 0.02); assertEquals(0, p1.distance(ray.get(i++)), 0.02); ray = computeRays.computeSideHull(true, p2, p1); i = 0; assertEquals(0, p2.distance(ray.get(i++)), 0.02); assertEquals(0, new Coordinate(11, 4).distance(ray.get(i++)), 0.02); assertEquals(0, new Coordinate(10, 4).distance(ray.get(i++)), 0.02); assertEquals(0, new Coordinate(6, 5).distance(ray.get(i++)), 0.02); assertEquals(0, p1.distance(ray.get(i++)), 0.02); }
@Test public void TestcomputeVerticalEdgeDiffractionRayOverBuilding() throws LayerDelaunayError, ParseException { GeometryFactory factory = new GeometryFactory(); WKTReader wktReader = new WKTReader(factory); Envelope cellEnvelope = new Envelope(new Coordinate(0, 0, 0.), new Coordinate(20, 15, 0.)); MeshBuilder mesh = new MeshBuilder(); mesh.addGeometry(wktReader.read("POLYGON((5 5, 7 5, 7 6, 8 6, 8 8, 5 8, 5 5))"), 4.3); mesh.addGeometry(wktReader.read("POLYGON((9 7, 10 7, 10 9, 9 9, 9 7))"), 4.3); mesh.finishPolygonFeeding(cellEnvelope); FastObstructionTest manager = new FastObstructionTest(mesh.getPolygonWithHeight(), mesh.getTriangles(), mesh.getTriNeighbors(), mesh.getVertices()); PropagationProcessData processData = new PropagationProcessData(manager); ComputeRays computeRays = new ComputeRays(processData); Coordinate p1 = new Coordinate(4, 3, 3); Coordinate p2 = new Coordinate(13, 10, 6.7); assertFalse(manager.isFreeField(p1, p2)); List<Coordinate> b1OffsetRoof = manager.getWideAnglePointsByBuilding(1, Math.PI * (1 + 1 / 16.0), Math.PI * (2 - (1 / 16.))); int i = 0; assertEquals(0, new Coordinate(5, 5).distance(b1OffsetRoof.get(i++)), 2 * FastObstructionTest.wideAngleTranslationEpsilon); assertEquals(0, new Coordinate(7, 5).distance(b1OffsetRoof.get(i++)), 2 * FastObstructionTest.wideAngleTranslationEpsilon); assertEquals(0, new Coordinate(8, 6).distance(b1OffsetRoof.get(i++)), 2 * FastObstructionTest.wideAngleTranslationEpsilon); assertEquals(0, new Coordinate(8, 8).distance(b1OffsetRoof.get(i++)), 2 * FastObstructionTest.wideAngleTranslationEpsilon); assertEquals(0, new Coordinate(5, 8).distance(b1OffsetRoof.get(i++)), 2 * FastObstructionTest.wideAngleTranslationEpsilon); assertEquals(0, new Coordinate(5, 5).distance(b1OffsetRoof.get(i++)), 2 * FastObstructionTest.wideAngleTranslationEpsilon); List<Coordinate> ray = computeRays.computeSideHull(true, p1, p2); i = 0; assertEquals(0, p1.distance(ray.get(i++)), 0.02); assertEquals(0, new Coordinate(5, 8).distance(ray.get(i++)), 0.02); assertEquals(0, p2.distance(ray.get(i++)), 0.02); ray = computeRays.computeSideHull(false, p1, p2); i = 0; assertEquals(0, p1.distance(ray.get(i++)), 0.02); assertEquals(0, new Coordinate(7, 5).distance(ray.get(i++)), 0.02); assertEquals(0, p2.distance(ray.get(i++)), 0.02); ray = computeRays.computeSideHull(false, p2, p1); i = 0; assertEquals(0, p2.distance(ray.get(i++)), 0.02); assertEquals(0, new Coordinate(5, 8).distance(ray.get(i++)), 0.02); assertEquals(0, p1.distance(ray.get(i++)), 0.02); ray = computeRays.computeSideHull(true, p2, p1); i = 0; assertEquals(0, p2.distance(ray.get(i++)), 0.02); assertEquals(0, new Coordinate(7, 5).distance(ray.get(i++)), 0.02); assertEquals(0, p1.distance(ray.get(i++)), 0.02); }
@Test public void TestConcaveVerticalEdgeDiffraction() throws LayerDelaunayError, ParseException { GeometryFactory factory = new GeometryFactory(); WKTReader wktReader = new WKTReader(factory); Envelope cellEnvelope = new Envelope(new Coordinate(0, 0, 0.), new Coordinate(20, 15, 0.)); MeshBuilder mesh = new MeshBuilder(); mesh.addGeometry(wktReader.read("POLYGON((5 6, 4 5, 7 5, 7 8, 4 8, 5 7, 5 6))"), 4); mesh.addGeometry(wktReader.read("POLYGON((9 7, 11 7, 11 11, 9 11, 9 7))"), 4); mesh.addGeometry(wktReader.read("POLYGON((12 8, 13 8, 13 10, 12 10, 12 8))"), 4); mesh.addGeometry(wktReader.read("POLYGON((10 4, 11 4, 11 6, 10 6, 10 4))"), 4); mesh.finishPolygonFeeding(cellEnvelope); FastObstructionTest manager = new FastObstructionTest(mesh.getPolygonWithHeight(), mesh.getTriangles(), mesh.getTriNeighbors(), mesh.getVertices()); PropagationProcessData processData = new PropagationProcessData(manager); ComputeRays computeRays = new ComputeRays(processData); Coordinate p1 = new Coordinate(4.5, 6.5, 1.6); Coordinate p2 = new Coordinate(14, 6.5, 1.6); List<Coordinate> ray = computeRays.computeSideHull(true, p1, p2); assertTrue(ray.isEmpty()); ray = computeRays.computeSideHull(false, p1, p2); assertTrue(ray.isEmpty()); ray = computeRays.computeSideHull(false, p2, p1); assertTrue(ray.isEmpty()); ray = computeRays.computeSideHull(true, p2, p1); assertTrue(ray.isEmpty()); }
@Test public void TestVerticalEdgeDiffractionAirplaneSource() throws LayerDelaunayError, ParseException { GeometryFactory factory = new GeometryFactory(); WKTReader wktReader = new WKTReader(factory); Envelope cellEnvelope = new Envelope(); Coordinate source = new Coordinate(223512.78, 6757739.7, 500.0); Coordinate receiver = new Coordinate(223392.04632028608, 6757724.944483406, 2.0); MeshBuilder mesh = new MeshBuilder(); mesh.addGeometry(wktReader.read("POLYGON ((223393 6757706, 223402 6757696, 223409 6757703, 223411 6757705, 223414 6757702, 223417 6757704, 223421 6757709, 223423 6757712, 223437 6757725, 223435 6757728, 223441 6757735, 223448 6757741, 223439 6757751, 223433 6757745, 223432 6757745, 223430 6757747, 223417 6757734, 223402 6757720, 223404 6757717, 223393 6757706)) "), 13); cellEnvelope.expandToInclude(mesh.getGeometriesBoundingBox()); cellEnvelope.expandToInclude(source); cellEnvelope.expandToInclude(receiver); cellEnvelope.expandBy(1200); mesh.finishPolygonFeeding(cellEnvelope); FastObstructionTest manager = new FastObstructionTest(mesh.getPolygonWithHeight(), mesh.getTriangles(), mesh.getTriNeighbors(), mesh.getVertices()); PropagationProcessData processData = new PropagationProcessData(manager); ComputeRays computeRays = new ComputeRays(processData); List<Coordinate> ray = computeRays.computeSideHull(false, receiver, source); assertTrue(ray.isEmpty()); }