Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Simplify AreaMeta and move vision blocking algorithm into a dedicated class #4577

Merged

Conversation

kwvanderlinde
Copy link
Collaborator

@kwvanderlinde kwvanderlinde commented Dec 22, 2023

Identify the Bug or Feature request

First part of #4506

Description of the Change

This change is mainly for the complexity & organization aspects of #4506. There is a very small performance improvement in complex cases due to AreaTree constructor changes, but there are no big wins - only ~300ms was saved over the ~30s test case referenced in the issue. Another PR will include performance improvements, but would add too much noise to include here.

AreaTree, etc.

This is the bulk of the PR. The quartet of AreaTree, AreaContainer, AreaIsland, and AreaOcean have been condensed into AreaTree with nodes represented by the very plain AreaTree.Node. The main mutually-recursive algorithm AreaTree.getContainerAt(Point2D) has been replaced by the iterative AreaTree.locate(Coordinate), which additionally returns more context to better support VisionBlockingAccumulator.

AreaTree construction is simplified and more performant due to using JTS' Polygonizer which associates islands with child oceans for us. It also plays well with the new representation of AreaMeta as a list of Coordinate vertices forming a ring, which is sufficient for all uses of AreaMeta.

VisionBlockingAccumulator

A small refactoring in VisionBlockingAccumulator unifies a common case across all VBL types where blocking needs to be added for the boundaries of a container and its children. Hill VBL and Pit VBL already had this case factored out for islands, but now Wall VBL and Cover VBL have the same case factored out for oceans. Also included is a new add(TopologyType, AreaTree) method so that we dont need to call distinct public methods for each type (helps FogUtil out a bit).

FogUtil

The final change is pretty trivlal: the visibility sweep algorithm (FogUtil.calculateVisibleArea() and related) has been moved out of FogUtil into a dedicated VisibilityProblem class that doesn't depend so heavily on static methods. A future PR will further refine this with some algorithmic improvements.

Possible Drawbacks

Should be none.

Documentation Notes

N/A

Release Notes

  • Improved the organization of vision blocking internals.

This change is Reviewable

Given that topology trees are alternating islands and oceans, and since vision is only blocked at boundaries of each,
all VBL types follow a common pattern in their case work:
1. Find containers that vision is allowed to pass through (oceans for Wall and Cover, islands for Hill and Pit).
2. Use part of those containers' boundaries to block vision.
3. Use part of those containers' childrens' boundaries to block vision.

The new `blockVisionBeyondContainer(AreaIsland)` and `blockVisionBeyondContainer(AreaOcean)` helpers give direct support
to this pattern and reduces noise in the case work. The `AreaIsland` overload was previously called
`addIslandForHillBlocking(AreaIsland)` and used for Hill and Pit VBL, but the new naming makes it clearer that it is not
specific to Hill VBL and is consistent with the `AreaOcean` version.

Another pattern relies on the fact that the result of `AreaTree.getDeepestContainerAt(Point2D)` is either an ocean or
has an ocean as a parent (the same is not true of islands). The case work for Hill and Cover VBL is identical in both
cases, so they can be flattened by anchoring the implemetations at this nearest ocean then mixing in the presence of
islands as needed.

As a convenience, it is now possible to call `VisionBlockingAccumulator.add(TopologyType, AreaTree)` to add topology of
a given type, rather than having separate public methods for each. This makes `FogUtil` a bit more natural to read.
The quartet of `AreaTree`, `AreaContainer`, `AreaIsland`, and `AreaOcean` have been condensed into `AreaTree` for a
clearer structure and smaller code size. `AreaTree` no longer allows modifications after construction, has a more
efficient construction process using JTS' `Polygonizer`, and more directly supports the patterns established in
cbf91d1. Each node in the tree is now represented by a simple `AreaTree.Node` type which only contains references to
its children and the associated `AreaMeta`. All logic is either in `AreaTree` (for traversing the tree) or in
`AreaMeta` (for operations on the region itself).

`AreaMeta` has been simplified as well. It is no longer mutable, and doesn't possess or build an AWT `Area`. It is
represented as a list of vertices which defines the polygonal boundary of the region it represents. There are other
fields, but they are derived entirely from the vertices and exist solely for efficiency. `AreaMeta` is also now capable
of representing the root ocean, which simplifies the usage of `AreaTree` nodes as they no longer have to check for
possibly-null `AreaMeta` for just this one case.

`AreaTree.getArea()` has been removed since it only existed to support `VisibilityInspector`. Since that is just a
debugging tool, and the method is kind of dangerous (doesn't protect against changes), it doesn't make sense to keep it
around. Instead `VisibilityInspector` keeps track of its own `Area` objects, alongside some other minor
simplifications.
A new class `VisibilityProblem` is responsible for collecting blocking segments and generating a visibility polygon from
them. No meaningful changes have been made to the algorithm itself, though it does support some new conveniences such as
progressively building up the problem set before solving.
@cwisniew cwisniew added the refactor Refactoring the code for optimal awesomeness. label Dec 23, 2023
@cwisniew cwisniew added this pull request to the merge queue Dec 23, 2023
Merged via the queue into RPTools:develop with commit f4a63e5 Dec 23, 2023
4 checks passed
@kwvanderlinde kwvanderlinde deleted the refactor/4506-visibility-cleanup branch January 9, 2024 09:12
@cwisniew cwisniew added the code-maintenance Adding/editing javadocs, unit tests, formatting. label Mar 16, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
code-maintenance Adding/editing javadocs, unit tests, formatting. refactor Refactoring the code for optimal awesomeness.
Projects
Development

Successfully merging this pull request may close these issues.

None yet

2 participants