Skip to content

Commit

Permalink
Merge pull request #4630 from kwvanderlinde/refactor/4506-improved-ar…
Browse files Browse the repository at this point in the history
…ea-union

Improve last path exposure with better unions
  • Loading branch information
cwisniew authored Jan 12, 2024
2 parents 2a884d6 + acdbe7a commit 2af826c
Show file tree
Hide file tree
Showing 2 changed files with 67 additions and 4 deletions.
47 changes: 47 additions & 0 deletions src/main/java/net/rptools/lib/GeometryUtil.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Objects;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.locationtech.jts.awt.ShapeReader;
Expand Down Expand Up @@ -61,6 +62,52 @@ public static double getAngleDelta(double sourceAngle, double targetAngle) {
return targetAngle;
}

/**
* Unions several areas into one.
*
* <p>The results are the same as progressively `.add()`ing all areas in the collection, but
* performs much better when the result is complicated.
*
* @param areas The areas to union.
* @return The union of {@code areas}
*/
public static Area union(Collection<Area> areas) {
final var copy = new ArrayList<>(areas);
copy.replaceAll(Area::new);

return destructiveUnion(copy);
}

/**
* Like {@link #union(java.util.Collection)}, but will modify the areas and collection for
* performance gains.
*
* @param areas The areas to union.
* @return The union of {@code areas}
*/
public static Area destructiveUnion(List<Area> areas) {
areas.removeIf(Area::isEmpty);

// Union two-by-two, on repeat until only one is left.
while (areas.size() >= 2) {
for (int i = 0; i + 1 < areas.size(); i += 2) {
final var a = areas.get(i);
final var b = areas.get(i + 1);

a.add(b);
areas.set(i + 1, null);
}
areas.removeIf(Objects::isNull);
}

if (areas.isEmpty()) {
// Just in case, maybe it's possible for Area() to have edge cases the produce empty unions?
return new Area();
}

return areas.getFirst();
}

public static PrecisionModel getPrecisionModel() {
return precisionModel;
}
Expand Down
24 changes: 20 additions & 4 deletions src/main/java/net/rptools/maptool/client/ui/zone/FogUtil.java
Original file line number Diff line number Diff line change
Expand Up @@ -360,7 +360,7 @@ public static void exposeLastPath(final ZoneRenderer renderer, final Set<GUID> t

final Token tokenClone = new Token(token);
final ZoneView zoneView = renderer.getZoneView();
Area visionArea = new Area();
final var visibleAreas = new ArrayList<Area>();

// Lee: get path according to zone's way point exposure toggle...
List<? extends AbstractPoint> processPath =
Expand All @@ -371,6 +371,7 @@ public static void exposeLastPath(final ZoneRenderer renderer, final Set<GUID> t
int stepCount = processPath.size();
log.debug("Path size = " + stepCount);

timer.start("Get visible areas");
Consumer<ZonePoint> revealAt =
zp -> {
tokenClone.setX(zp.x);
Expand All @@ -379,8 +380,7 @@ public static void exposeLastPath(final ZoneRenderer renderer, final Set<GUID> t
Area currVisionArea =
zoneView.getVisibleArea(tokenClone, renderer.getPlayerView());
if (currVisionArea != null) {
visionArea.add(currVisionArea);
meta.addToExposedAreaHistory(currVisionArea);
visibleAreas.add(currVisionArea);
}

zoneView.flush(tokenClone);
Expand All @@ -397,15 +397,31 @@ public static void exposeLastPath(final ZoneRenderer renderer, final Set<GUID> t
assert finalCell instanceof ZonePoint;
revealAt.accept((ZonePoint) finalCell);
}
timer.stop("Get visible areas");

timer.start("Union visible areas");
Area visionArea = GeometryUtil.destructiveUnion(visibleAreas);
timer.stop("Union visible areas");

timer.start("Add to token exposed area");
meta.addToExposedAreaHistory(visionArea);
timer.stop("Add to token exposed area");

timer.stop("exposeLastPath-" + token.getName());
renderer.flush(tokenClone);

filteredToks.clear();
filteredToks.add(token.getId());

timer.start("Update zone");
zone.putToken(token);
timer.stop("Update zone");

timer.start("Send results");
MapTool.serverCommand().exposeFoW(zone.getId(), visionArea, filteredToks);
MapTool.serverCommand().updateExposedAreaMeta(zone.getId(), exposedGUID, meta);
timer.stop("Send results");

timer.stop("exposeLastPath-" + token.getName());
}
});
}
Expand Down

0 comments on commit 2af826c

Please sign in to comment.