From 3e4a5062eeb9bcbd0a71d594dfc105103d3a24d5 Mon Sep 17 00:00:00 2001 From: nicolas-f <1382241+nicolas-f@users.noreply.github.com> Date: Tue, 10 Dec 2024 17:12:52 +0100 Subject: [PATCH] insert primary key in cut profile for wall and buildings --- .../noisemodelling/jdbc/NoiseMapLoader.java | 27 ++- .../jdbc/AttenuationCnossosTest.java | 198 +++++------------- .../noisemodelling/pathfinder/PathFinder.java | 3 + .../pathfinder/profilebuilder/Building.java | 10 +- .../profilebuilder/CutPointReflection.java | 15 +- .../CutPointVEdgeDiffraction.java | 8 + .../profilebuilder/CutPointWall.java | 22 +- .../profilebuilder/ProfileBuilder.java | 42 ++-- .../pathfinder/profilebuilder/Wall.java | 11 + .../pathfinder/PathFinderTest.java | 4 +- 10 files changed, 144 insertions(+), 196 deletions(-) diff --git a/noisemodelling-jdbc/src/main/java/org/noise_planet/noisemodelling/jdbc/NoiseMapLoader.java b/noisemodelling-jdbc/src/main/java/org/noise_planet/noisemodelling/jdbc/NoiseMapLoader.java index 762445513..f5c2b6108 100644 --- a/noisemodelling-jdbc/src/main/java/org/noise_planet/noisemodelling/jdbc/NoiseMapLoader.java +++ b/noisemodelling-jdbc/src/main/java/org/noise_planet/noisemodelling/jdbc/NoiseMapLoader.java @@ -25,6 +25,7 @@ import org.noise_planet.noisemodelling.pathfinder.profilebuilder.Building; import org.noise_planet.noisemodelling.pathfinder.path.Scene; import org.noise_planet.noisemodelling.pathfinder.profilebuilder.ProfileBuilder; +import org.noise_planet.noisemodelling.pathfinder.profilebuilder.Wall; import org.noise_planet.noisemodelling.pathfinder.profilebuilder.WallAbsorption; import org.noise_planet.noisemodelling.propagation.cnossos.AttenuationCnossosParameters; import org.slf4j.Logger; @@ -388,11 +389,15 @@ protected void fetchCellSoilAreas(Connection connection, Envelope fetchEnvelope, * @throws SQLException if an SQL exception occurs while fetching the buildings data. */ void fetchCellBuildings(Connection connection, Envelope fetchEnvelope, ProfileBuilder builder) throws SQLException { - ArrayList buildings = new ArrayList<>(); - fetchCellBuildings(connection, fetchEnvelope, buildings); + List buildings = new LinkedList<>(); + List walls = new LinkedList<>(); + fetchCellBuildings(connection, fetchEnvelope, buildings, walls); for(Building building : buildings) { builder.addBuilding(building); } + for (Wall wall : walls) { + builder.addWall(wall); + } } /** @@ -402,7 +407,7 @@ void fetchCellBuildings(Connection connection, Envelope fetchEnvelope, ProfileBu * @param buildings the list to which the fetched buildings will be added. * @throws SQLException if an SQL exception occurs while fetching the building data. */ - void fetchCellBuildings(Connection connection, Envelope fetchEnvelope, List buildings) throws SQLException { + void fetchCellBuildings(Connection connection, Envelope fetchEnvelope, List buildings, List walls) throws SQLException { Geometry envGeo = geometryFactory.toGeometry(fetchEnvelope); boolean fetchAlpha = JDBCUtilities.hasField(connection, buildingsTableName, alphaFieldName); String additionalQuery = ""; @@ -447,7 +452,7 @@ void fetchCellBuildings(Connection connection, Envelope fetchEnvelope, List`_\n"); - - }catch (IOException e) { - System.out.println("Erreur lors de l'écriture dans le fichier : " + e.getMessage()); - }*/ - - + assertDoubleArrayEquals("LA - vertical plane", expectedLA, actualLA, ERROR_EPSILON_VERY_LOW); } /** diff --git a/noisemodelling-pathfinder/src/main/java/org/noise_planet/noisemodelling/pathfinder/PathFinder.java b/noisemodelling-pathfinder/src/main/java/org/noise_planet/noisemodelling/pathfinder/PathFinder.java index 2b4c1bc1f..d6ff05cef 100644 --- a/noisemodelling-pathfinder/src/main/java/org/noise_planet/noisemodelling/pathfinder/PathFinder.java +++ b/noisemodelling-pathfinder/src/main/java/org/noise_planet/noisemodelling/pathfinder/PathFinder.java @@ -348,16 +348,19 @@ public CutProfile computeVEdgeDiffraction(ReceiverPointInfo rcv, SourcePointInfo for(int i=0; i 0 ) { // update first point as it is not source but diffraction point cutPoints.add(new CutPointVEdgeDiffraction(profile.getSource())); } else { + profile.getSource().id = src.sourceIndex; cutPoints.add(profile.getSource()); } cutPoints.addAll(profile.cutPoints.subList(1, profile.cutPoints.size() - 1)); if(i+1 == coordinates.size() - 1) { // we keep the last point as it is really the receiver + profile.getReceiver().id = rcv.receiverIndex; cutPoints.add(profile.getReceiver()); } } diff --git a/noisemodelling-pathfinder/src/main/java/org/noise_planet/noisemodelling/pathfinder/profilebuilder/Building.java b/noisemodelling-pathfinder/src/main/java/org/noise_planet/noisemodelling/pathfinder/profilebuilder/Building.java index 6f10d4079..5ece9da7a 100644 --- a/noisemodelling-pathfinder/src/main/java/org/noise_planet/noisemodelling/pathfinder/profilebuilder/Building.java +++ b/noisemodelling-pathfinder/src/main/java/org/noise_planet/noisemodelling/pathfinder/profilebuilder/Building.java @@ -34,7 +34,7 @@ public class Building { final boolean zBuildings; /** Primary key of the building in the database. */ - int pk = -1; + long primaryKey = -1; List walls = new ArrayList<>(); /** @@ -78,14 +78,14 @@ public void poly2D_3D(){ * @param alphas Absorption coefficients. * @param key Primary key of the building in the database. */ - public Building(Polygon poly, double height, List alphas, int key, boolean zBuildings) { + public Building(Polygon poly, double height, List alphas, long key, boolean zBuildings) { this.poly = poly; // Fix clock wise orientation of the polygon and inner holes this.poly.normalize(); this.height = height; this.alphas = new ArrayList<>(); this.alphas.addAll(alphas); - this.pk = key; + this.primaryKey = key; this.zBuildings = zBuildings; } @@ -116,8 +116,8 @@ public List getAlphas() { * Retrieve the primary key of the building in the database. If there is no primary key, returns -1. * @return The primary key of the building in the database or -1. */ - public int getPrimaryKey() { - return pk; + public long getPrimaryKey() { + return primaryKey; } /** diff --git a/noisemodelling-pathfinder/src/main/java/org/noise_planet/noisemodelling/pathfinder/profilebuilder/CutPointReflection.java b/noisemodelling-pathfinder/src/main/java/org/noise_planet/noisemodelling/pathfinder/profilebuilder/CutPointReflection.java index 6954e0224..f1af1d29e 100644 --- a/noisemodelling-pathfinder/src/main/java/org/noise_planet/noisemodelling/pathfinder/profilebuilder/CutPointReflection.java +++ b/noisemodelling-pathfinder/src/main/java/org/noise_planet/noisemodelling/pathfinder/profilebuilder/CutPointReflection.java @@ -26,6 +26,9 @@ public class CutPointReflection extends CutPoint { */ public long wallPrimaryKey = -1; + /** Database primary key value of the obstacle */ + public Long wallPk = null; + /** * Empty constructor for deserialization */ @@ -45,15 +48,9 @@ public CutPointReflection(CutPoint cutPoint, LineSegment wall, List wall this.wallAlpha = wallAlpha; } - /** - * Copy constructor - * @param other - */ - public CutPointReflection(CutPointReflection other) { - super(other); - this.wall = other.wall; - this.wallPrimaryKey = other.wallPrimaryKey; - this.wallAlpha = other.wallAlpha; + public CutPointReflection setPk(long pk) { + this.wallPk = pk; + return this; } /** Wall absorption coefficient per frequency band.*/ diff --git a/noisemodelling-pathfinder/src/main/java/org/noise_planet/noisemodelling/pathfinder/profilebuilder/CutPointVEdgeDiffraction.java b/noisemodelling-pathfinder/src/main/java/org/noise_planet/noisemodelling/pathfinder/profilebuilder/CutPointVEdgeDiffraction.java index f6ed38243..f58eaedff 100644 --- a/noisemodelling-pathfinder/src/main/java/org/noise_planet/noisemodelling/pathfinder/profilebuilder/CutPointVEdgeDiffraction.java +++ b/noisemodelling-pathfinder/src/main/java/org/noise_planet/noisemodelling/pathfinder/profilebuilder/CutPointVEdgeDiffraction.java @@ -13,6 +13,14 @@ */ public class CutPointVEdgeDiffraction extends CutPoint { + /** Database primary key value of the obstacle */ + public Long wallPk = null; + + public CutPointVEdgeDiffraction setPk(long pk) { + this.wallPk = pk; + return this; + } + /** * Empty constructor for deserialization */ diff --git a/noisemodelling-pathfinder/src/main/java/org/noise_planet/noisemodelling/pathfinder/profilebuilder/CutPointWall.java b/noisemodelling-pathfinder/src/main/java/org/noise_planet/noisemodelling/pathfinder/profilebuilder/CutPointWall.java index 723e36093..7be81a254 100644 --- a/noisemodelling-pathfinder/src/main/java/org/noise_planet/noisemodelling/pathfinder/profilebuilder/CutPointWall.java +++ b/noisemodelling-pathfinder/src/main/java/org/noise_planet/noisemodelling/pathfinder/profilebuilder/CutPointWall.java @@ -33,6 +33,16 @@ public class CutPointWall extends CutPoint { @JsonIgnore public int processedWallIndex = -1; + /** This point encounter this kind of limit + * - We can enter or exit a polygon + * - pass a line (a wall without width) */ + public enum INTERSECTION_TYPE { AREA_ENTER, AREA_EXIT, LINE_ENTER_EXIT} + + public INTERSECTION_TYPE intersectionType = INTERSECTION_TYPE.LINE_ENTER_EXIT; + + /** Database primary key value of the obstacle */ + public Long wallPk = null; + /** * Empty constructor for deserialization */ @@ -46,15 +56,9 @@ public CutPointWall(int processedWallIndex, Coordinate intersection, LineSegment this.wallAlpha = wallAlpha; } - /** - * Copy constructor - * @param other Other instance - */ - public CutPointWall(CutPointWall other) { - super(other); - this.wall = other.wall; - this.wallAlpha = other.wallAlpha; - this.processedWallIndex = other.processedWallIndex; + public CutPointWall setPk(long pk) { + this.wallPk = pk; + return this; } /** diff --git a/noisemodelling-pathfinder/src/main/java/org/noise_planet/noisemodelling/pathfinder/profilebuilder/ProfileBuilder.java b/noisemodelling-pathfinder/src/main/java/org/noise_planet/noisemodelling/pathfinder/profilebuilder/ProfileBuilder.java index 8c9eb3e7d..86167e3d8 100644 --- a/noisemodelling-pathfinder/src/main/java/org/noise_planet/noisemodelling/pathfinder/profilebuilder/ProfileBuilder.java +++ b/noisemodelling-pathfinder/src/main/java/org/noise_planet/noisemodelling/pathfinder/profilebuilder/ProfileBuilder.java @@ -394,6 +394,16 @@ public ProfileBuilder addWall(Coordinate[] coords, int id) { return addWall(FACTORY.createLineString(coords), 0.0, new ArrayList<>(), id); } + /** + * Add the given {@link Geometry} footprint, height, alphas (absorption coefficients) and a database id as wall. + * @param wall + */ + public ProfileBuilder addWall(Wall wall) { + walls.add(wall); + wallTree.insert(new Envelope(wall.p0, wall.p1), walls.size()); + return this; + } + /** * Add the given {@link Geometry} footprint, height, alphas (absorption coefficients) and a database id as wall. * @param geom Wall footprint. @@ -414,8 +424,7 @@ public ProfileBuilder addWall(LineString geom, double height, List alpha Wall wall = new Wall(geom.getCoordinateN(i), geom.getCoordinateN(i+1), id, IntersectionType.BUILDING); wall.setHeight(height); wall.setAlpha(alphas); - walls.add(wall); - wallTree.insert(new Envelope(wall.p0, wall.p1), walls.size()); + addWall(wall); } return this; } @@ -772,6 +781,7 @@ public ProfileBuilder finishFeeding() { LineSegment lineSegment = new LineSegment(coords[i], coords[i + 1]); Wall w = new Wall(lineSegment, j, IntersectionType.BUILDING).setProcessedWallIndex(processedWalls.size()); walls.add(w); + w.setPrimaryKey(building.getPrimaryKey()); w.setAlpha(building.alphas); processedWalls.add(w); rtree.insert(lineSegment.toGeometry(FACTORY).getEnvelopeInternal(), processedWalls.size()-1); @@ -785,6 +795,7 @@ public ProfileBuilder finishFeeding() { LineSegment lineSegment = new LineSegment(coords[i], coords[i + 1]); Wall w = new Wall(lineSegment, j, IntersectionType.WALL).setProcessedWallIndex(processedWalls.size()); w.setAlpha(wall.alphas); + w.setPrimaryKey(wall.primaryKey); processedWalls.add(w); rtree.insert(lineSegment.toGeometry(FACTORY).getEnvelopeInternal(), processedWalls.size()-1); } @@ -1011,16 +1022,12 @@ public int getIntersectingGroundAbsorption(Geometry query) { private boolean processWall(int processedWallIndex, Coordinate intersection, Wall facetLine, LineSegment fullLine, List newCutPoints, boolean stopAtObstacleOverSourceReceiver, CutProfile profile) { - Vector2D directionAfter = Vector2D.create(fullLine.p0, fullLine.p1).normalize().multiply(MILLIMETER); - Vector2D directionBefore = directionAfter.negate(); - newCutPoints.add(new CutPointWall(processedWallIndex, - Vector2D.create(intersection).add(directionBefore).toCoordinate(), - facetLine.getLineSegment(), facetLine.alphas)); - newCutPoints.add(new CutPointWall(processedWallIndex, - intersection, facetLine.getLineSegment(), facetLine.alphas)); - newCutPoints.add(new CutPointWall(processedWallIndex, - Vector2D.create(intersection).add(directionAfter).toCoordinate(), - facetLine.getLineSegment(), facetLine.alphas)); + + CutPointWall cutPointWall = new CutPointWall(processedWallIndex, + intersection, facetLine.getLineSegment(), facetLine.alphas); + cutPointWall.intersectionType = CutPointWall.INTERSECTION_TYPE.LINE_ENTER_EXIT; + cutPointWall.setPk(facetLine.primaryKey); + newCutPoints.add(cutPointWall); double zRayReceiverSource = Vertex.interpolateZ(intersection, fullLine.p0, fullLine.p1); if (zRayReceiverSource <= intersection.z) { @@ -1037,8 +1044,8 @@ private boolean processBuilding(int processedWallIndex, Coordinate intersection, boolean stopAtObstacleOverSourceReceiver, CutProfile profile) { CutPointWall wallCutPoint = new CutPointWall(processedWallIndex, intersection, facetLine.getLineSegment(), buildings.get(facetLine.getOriginId()).alphas); + wallCutPoint.setPk(facetLine.primaryKey); newCutPoints.add(wallCutPoint); - wallCutPoint.setGroundCoefficient(Scene.DEFAULT_G_BUILDING); double zRayReceiverSource = Vertex.interpolateZ(intersection, fullLine.p0, fullLine.p1); // add a point at the bottom of the building on the exterior side of the building Vector2D facetVector = Vector2D.create(facetLine.p0, facetLine.p1); @@ -1046,9 +1053,12 @@ private boolean processBuilding(int processedWallIndex, Coordinate intersection, // it works also with polygon holes as interiors are CCW Vector2D exteriorVector = facetVector.rotate(LEFT_SIDE).normalize().multiply(MILLIMETER); Coordinate exteriorPoint = exteriorVector.add(Vector2D.create(intersection)).toCoordinate(); - CutPointWall exteriorPointCutPoint = new CutPointWall(wallCutPoint); - exteriorPointCutPoint.coordinate = exteriorPoint; - newCutPoints.add(exteriorPointCutPoint); + // exterior point closer to source so we know that we enter the building + if(exteriorPoint.distance(fullLine.p0) < intersection.distance(fullLine.p0)) { + wallCutPoint.intersectionType = CutPointWall.INTERSECTION_TYPE.AREA_ENTER; + } else { + wallCutPoint.intersectionType = CutPointWall.INTERSECTION_TYPE.AREA_EXIT; + } if (zRayReceiverSource <= intersection.z) { profile.hasBuildingIntersection = true; diff --git a/noisemodelling-pathfinder/src/main/java/org/noise_planet/noisemodelling/pathfinder/profilebuilder/Wall.java b/noisemodelling-pathfinder/src/main/java/org/noise_planet/noisemodelling/pathfinder/profilebuilder/Wall.java index a3c10cda1..177baccd4 100644 --- a/noisemodelling-pathfinder/src/main/java/org/noise_planet/noisemodelling/pathfinder/profilebuilder/Wall.java +++ b/noisemodelling-pathfinder/src/main/java/org/noise_planet/noisemodelling/pathfinder/profilebuilder/Wall.java @@ -17,6 +17,7 @@ public class Wall { public final ProfileBuilder.IntersectionType type; /** Id or index of the source building or topographic triangle. */ public final int originId; + public long primaryKey = -1; /** Wall alpha value. */ public List alphas; /** Wall height, if -1, use z coordinate. */ @@ -55,6 +56,16 @@ public Wall(Coordinate p0, Coordinate p1, int originId, ProfileBuilder.Intersect this.alphas = new ArrayList<>(); } + /** + * Database primary key of this wall or the building + * @param primaryKey primary key value + * @return this + */ + public Wall setPrimaryKey(long primaryKey) { + this.primaryKey = primaryKey; + return this; + } + /** * @return Index of this wall in the ProfileBuild list */ diff --git a/noisemodelling-pathfinder/src/test/java/org/noise_planet/noisemodelling/pathfinder/PathFinderTest.java b/noisemodelling-pathfinder/src/test/java/org/noise_planet/noisemodelling/pathfinder/PathFinderTest.java index 5ac28966e..084e758b2 100644 --- a/noisemodelling-pathfinder/src/test/java/org/noise_planet/noisemodelling/pathfinder/PathFinderTest.java +++ b/noisemodelling-pathfinder/src/test/java/org/noise_planet/noisemodelling/pathfinder/PathFinderTest.java @@ -49,7 +49,7 @@ public class PathFinderTest { /** * Overwrite project resource expected test cases */ - public boolean overwriteTestCase = false; + public boolean overwriteTestCase = true; /** * Error for coordinates @@ -94,7 +94,7 @@ public static void assertCutProfile(InputStream expected, CutProfile got) throws public static void assertCutProfile(CutProfile expected, CutProfile got) { assertNotNull(expected); assertNotNull(got); - assertEquals(expected.cutPoints.size(), got.cutPoints.size()); + assertEquals(expected.cutPoints.size(), got.cutPoints.size(), "Not the same number of cut points"); for (int i = 0; i < expected.cutPoints.size(); i++) { CutPoint expectedCutPoint = expected.cutPoints.get(i); CutPoint gotCutPoint = got.cutPoints.get(i);