Skip to content

Commit

Permalink
fix reflection code. Complete unit test with second order reflection.
Browse files Browse the repository at this point in the history
  • Loading branch information
nicolas-f committed Oct 10, 2024
1 parent 70e8250 commit 27e2d38
Show file tree
Hide file tree
Showing 2 changed files with 91 additions and 82 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -1323,7 +1323,7 @@ public List<PropagationPath> computeReflexion(Coordinate rcvCoord, Coordinate sr
proPath.refPoints = reflIdx;
// Compute direct path between source and first reflection point, add profile to the data
computeReflexionOverBuildings(srcCoord, rayPath.get(0).getReceiverPos(), points, segments, data, orientation, proPath.difHPoints, proPath.difVPoints);
if (points.isEmpty()) {
if (points.isEmpty()) { // no valid path between the two points
continue;
}
PointPath reflPoint = points.get(points.size() - 1);
Expand All @@ -1338,58 +1338,67 @@ public List<PropagationPath> computeReflexion(Coordinate rcvCoord, Coordinate sr
reflPoint.setWallId(rayPath.get(0).getWall().getProcessedWallIndex());
reflPoint.setAlphaWall(rayPath.get(0).getWall().getAlphas());
}
reflPoint.altitude = data.profileBuilder.getZGround(reflPoint.coordinate);
reflPoint.altitude = data.profileBuilder.getZGround(rayPath.get(0).getReceiverPos());
// Add intermediate reflections
for (int idPt = 0; idPt < rayPath.size() - 1; idPt++) {
Coordinate firstPt = rayPath.get(idPt).getReceiverPos();
MirrorReceiverResult refl = rayPath.get(idPt + 1);
reflPoint = new PointPath(refl.getReceiverPos(), 0, new ArrayList<>(), PointPath.POINT_TYPE.REFL);

MirrorReceiverResult firstPoint = rayPath.get(idPt);
MirrorReceiverResult secondPoint = rayPath.get(idPt + 1);
int previousPointSize = points.size();
computeReflexionOverBuildings(firstPoint.getReceiverPos(), secondPoint.getReceiverPos(),
points, segments, data, orientation, proPath.difHPoints, proPath.difVPoints);
if(points.size() == previousPointSize) { // no visibility between the two reflection coordinates
// (maybe there is a blocking building, and we disabled diffraction)
continue;
}
points.remove(previousPointSize); // remove duplicate point
reflIdx.add(points.size() - 1);
// computeReflexionOverBuildings is making X relative to the "receiver" coordinate
// so we have to add the X value of the last path
for(PointPath p : points.subList(previousPointSize, points.size())) {
p.coordinate.x += points.get(previousPointSize - 1).coordinate.x;
}
PointPath lastReflexionPoint = points.get(points.size() - 1);
lastReflexionPoint.setType(PointPath.POINT_TYPE.REFL);
if(rayPath.get(0).getType().equals(BUILDING)) {
reflPoint.setBuildingId(rayPath.get(0).getBuildingId());
reflPoint.buildingHeight = data.profileBuilder.getBuilding(reflPoint.getBuildingId()).getHeight();
reflPoint.setAlphaWall(data.profileBuilder.getBuilding(reflPoint.getBuildingId()).getAlphas());
lastReflexionPoint.setBuildingId(secondPoint.getBuildingId());
lastReflexionPoint.buildingHeight = data.profileBuilder.getBuilding(reflPoint.getBuildingId()).getHeight();
lastReflexionPoint.setAlphaWall(data.profileBuilder.getBuilding(reflPoint.getBuildingId()).getAlphas());
} else {
reflPoint.buildingHeight = rayPath.get(0).getWall().p0.getZ();
reflPoint.setWallId(rayPath.get(0).getWall().getProcessedWallIndex());
reflPoint.setAlphaWall(rayPath.get(0).getWall().getAlphas());
lastReflexionPoint.buildingHeight = secondPoint.getWall().p0.getZ();
lastReflexionPoint.setWallId(secondPoint.getWall().getProcessedWallIndex());
lastReflexionPoint.setAlphaWall(secondPoint.getWall().getAlphas());
}
reflPoint.altitude = data.profileBuilder.getZGround(reflPoint.coordinate);
points.add(reflPoint);
segments.add(new SegmentPath(1, new Vector3D(firstPt), refl.getReceiverPos()));
lastReflexionPoint.altitude = data.profileBuilder.getZGround(secondPoint.getReceiverPos());
}
// Compute direct path between receiver and last reflection point, add profile to the data
List<PointPath> lastPts = new ArrayList<>();
computeReflexionOverBuildings(rayPath.get(rayPath.size() - 1).getReceiverPos(), rcvCoord, lastPts, segments, data, orientation, proPath.difHPoints, proPath.difVPoints);
if (lastPts.isEmpty()) {
int previousPointSize = points.size();
computeReflexionOverBuildings(rayPath.get(rayPath.size() - 1).getReceiverPos(), rcvCoord, points, segments, data, orientation, proPath.difHPoints, proPath.difVPoints);
if(points.size() == previousPointSize) { // no visibility between the last reflection coordinate and the receiver
// (maybe there is a blocking building, and we disabled diffraction)
continue;
}
points.addAll(lastPts.subList(1, lastPts.size()));
double baseX = 0;
for(int i=0; i<points.size(); i++) {
Coordinate c = points.get(i).coordinate;
c.setX(c.getX()+baseX);
if(points.get(i).type.equals(REFL)){
baseX = points.get(i).coordinate.getX();
}
points.remove(previousPointSize); // remove duplicate point (last reflexion coordinate)
// computeReflexionOverBuildings is making X relative to the "receiver" coordinate
// so we have to add the X value of the last path
for(PointPath p : points.subList(previousPointSize, points.size())) {
p.coordinate.x += points.get(previousPointSize - 1).coordinate.x;
}
for (int i = 1; i < points.size(); i++) {
if (points.get(i).type == REFL) {
final PointPath currentPoint = points.get(i);
if (currentPoint.type == REFL) {
if (i < points.size() - 1) {
// A diffraction point may have offset in height the reflection coordinate
points.get(i).coordinate.z = Vertex.interpolateZ(points.get(i).coordinate, points.get(i - 1).coordinate, points.get(i + 1).coordinate);
//check if in building && if under floor
Geometry geom;
if(points.get(i).getBuildingId()!=-1) {
geom = data.profileBuilder.getBuilding(points.get(i).getBuildingId()).getGeometry();
}
else {
geom = data.profileBuilder.getWall(points.get(i).getWallId()).getLine();
}
if (points.get(i).coordinate.z > geom.getCoordinate().z
|| points.get(i).coordinate.z <= data.profileBuilder.getZGround(points.get(i).coordinate)) {
final Coordinate p0 = points.get(i - 1).coordinate;
final Coordinate p1 = currentPoint.coordinate;
final Coordinate p2 = points.get(i + 1).coordinate;
// compute Y value (altitude) by interpolating the Y values of the two neighboring points
currentPoint.coordinate = new CoordinateXY(p1.x, (p1.x-p0.x)/(p2.x-p0.x)*(p2.y-p0.y)+p0.y);
//check if new reflection point altitude is higher than the wall
if (currentPoint.coordinate.y > currentPoint.altitude + currentPoint.buildingHeight) {
// can't reflect higher than the wall
points.clear();
segments.clear();
rayPath.clear();
break;
}
} else {
Expand All @@ -1402,7 +1411,7 @@ public List<PropagationPath> computeReflexion(Coordinate rcvCoord, Coordinate sr
}


if (rayPath.size() > 0) {
if (!rayPath.isEmpty()) {
List<Coordinate> pts = new ArrayList<>();
pts.add(srcCoord);
rayPath.forEach(mrr -> pts.add(mrr.getReceiverPos()));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,6 @@ public void testWideWall() {

@Test
public void testNReflexion() throws ParseException, IOException, SQLException {

GeometryFactory factory = new GeometryFactory();

//Create profile builder
Expand Down Expand Up @@ -124,56 +123,57 @@ public void testNReflexion() throws ParseException, IOException, SQLException {
MirrorReceiverResultIndex receiverMirrorIndex = new MirrorReceiverResultIndex(buildWalls, receiver,
inputData.reflexionOrder, inputData.maxSrcDist, inputData.maxRefDist);

// Keep only mirror receivers potentially visible from the source(and its parents)
List<MirrorReceiverResult> mirrorResults = receiverMirrorIndex.findCloseMirrorReceivers(inputData.
sourceGeometries.get(0).getCoordinate());
assertEquals(18, mirrorResults.size());

try {
try (FileWriter fileWriter = new FileWriter("target/testNReflexion_testVisibilityCone.csv")) {
StringBuilder sb = new StringBuilder();
receiverMirrorIndex.exportVisibility(sb, inputData.maxSrcDist, inputData.maxRefDist,
0, mirrorResults, true);
fileWriter.write(sb.toString());
}
} catch (IOException ex) {
//ignore
}

List<PropagationPath> propagationPaths = computeRays.computeReflexion(receiver,
inputData.sourceGeometries.get(0).getCoordinate(), false,
new Orientation(), receiverMirrorIndex);

// Only one second order reflexion propagation path must be found
assertEquals(1, propagationPaths.size());


// int idPath = 1;
// for(PropagationPath path : propagationPaths) {
// try {
// try (FileWriter fileWriter = new FileWriter(String.format(Locale.ROOT, "target/testVisibilityPath_%03d.geojson", idPath))) {
// fileWriter.write(path.asGeom()));
// }
// } catch (IOException ex) {
// //ignore
// }
// idPath++;
// }

// Keep only mirror receivers potentially visible from the source
List<MirrorReceiverResult> mirrorResults = receiverMirrorIndex.findCloseMirrorReceivers(inputData.
sourceGeometries.get(0).getCoordinate());
assertEquals(18, mirrorResults.size());

// // Or Take all reflections
// List<MirrorReceiverResult> mirrorResults = new ArrayList<>();
// var lst = receiverMirrorIndex.mirrorReceiverTree.query(new Envelope(Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY,
// Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY));
// for(var item : lst) {
// if(item instanceof MirrorReceiverResult) {
// mirrorResults.add((MirrorReceiverResult) item);
// }
// }
// try {
// try (FileWriter fileWriter = new FileWriter("target/testVisibilityCone.csv")) {
// StringBuilder sb = new StringBuilder();
// receiverMirrorIndex.exportVisibility(sb, inputData.maxSrcDist, inputData.maxRefDist,
// 0, mirrorResults, true);
// fileWriter.write(sb.toString());
// }
// } catch (IOException ex) {
// //ignore
// }
//


// Check expected values for the propagation path
PropagationPath firstPath = propagationPaths.get(0);
var it = firstPath.getPointList().iterator();
assertTrue(it.hasNext());
PointPath current = it.next();
assertEquals(PointPath.POINT_TYPE.SRCE ,current.type);
assertEquals(0.0, current.coordinate.x, 1e-12);
current = it.next();
assertEquals(PointPath.POINT_TYPE.REFL ,current.type);
assertEquals(38.68, current.coordinate.x, 0.01);
current = it.next();
assertEquals(PointPath.POINT_TYPE.REFL ,current.type);
assertEquals(53.28, current.coordinate.x, 0.01);
current = it.next();
assertEquals(PointPath.POINT_TYPE.RECV ,current.type);
assertEquals(61.14, current.coordinate.x, 0.01);

int idPath = 1;
for(PropagationPath path : propagationPaths) {
try {
try (FileWriter fileWriter = new FileWriter(String.format(Locale.ROOT, "target/testNReflexion_testVisibilityPath_%03d.geojson", idPath))) {
fileWriter.write(path.profileAsJSON(Integer.MAX_VALUE));
}
} catch (IOException ex) {
//ignore
}
idPath++;
}


}

}

0 comments on commit 27e2d38

Please sign in to comment.