Remove intersecting chains

Removed intersecting chains using a greedy method
Fixed issue where chains found after splitting partitions do not get checked for intersection
This commit is contained in:
2025-05-17 17:11:17 -04:00
parent 7e39c48d76
commit 566a7fb15f

View File

@@ -1390,7 +1390,13 @@ public class Mesh< T extends Region > {
}
/*
* Check all previous chains for intersections and stuff
* Check all previous chains for intersections and stuff. This method
* is unfortunately polynomial time(O(n^2)) and there's not much we can do about it.
*
* Maybe parallelize the intersection checking though? We'd need to ensure that the
* intersection collection for each chain is synchronized, but otherwise entirely possible.
*
* TODO Good idea, now someone needs to implement that.
*/
void addChain( final Chain chain ) {
final Vertex chainOrigin = chain.getOrigin();
@@ -1582,8 +1588,9 @@ public class Mesh< T extends Region > {
final Partition copy = new Partition( lower, newUpper );
// Copy all chains from the previous region in case of intersection
copy.chains.addAll( toSplit.chains );
// Share chains since new chains from one region may intersect
// with chains from another region
copy.chains = toSplit.chains;
toSplit.lower = newLower;
@@ -1724,6 +1731,7 @@ public class Mesh< T extends Region > {
}
top.chains.addAll( bottom.chains );
lowerEdgeMap.remove( bottom.upper );
// Merge the top and bottom partition
@@ -1848,10 +1856,54 @@ public class Mesh< T extends Region > {
System.out.println( "DUPLICATE!" );
}
}
return chains;
// Given a chain link, select the links which intersect the least, and remove any that it intersects with from the
// queue. Essentially, a greedy method, which is more or less guaranteed optimal results.
// This is also unfortunately an O(n^2) time algorithm that can't be simplified.
// Keep track of all chains that we want
final Collection< Chain > selectedChains = new HashSet< Chain >();
// Keep track of all remaining chains that needs to be scanned
final Collection< Chain > remainingChains = new HashSet< Chain >( chains );
// Do a quick scan and remove any chains that have 0 intersections, since we can get
// this done in linear time and all at once
for ( final Iterator< Chain > it = remainingChains.iterator(); it.hasNext(); ) {
final Chain chain = it.next();
if ( chain.intersections.size() == 0 ) {
selectedChains.add( chain );
it.remove();
}
}
while ( !remainingChains.isEmpty() ) {
// Find the chain with the least amount of intersections
final Chain least = remainingChains.parallelStream().min( ( c1, c2 ) -> {
return Integer.compare( c1.intersections.size(), c2.intersections.size() );
} ).get();
System.out.println( "Removing chain " + least.getOrigin() + ",\t" + least.getDest() );
System.out.println( "Intersection with " + least.intersections.size() );
for ( Chain c : least.intersections ) {
System.out.println( "\t" + c.getOrigin() + ",\t" + c.getDest() );
}
// Now remove this chain and all other chains that it intersects with
remainingChains.remove( least );
if ( !least.intersections.isEmpty() ) {
remainingChains.removeAll( least.intersections );
// Remove all intersected chains from other chains
remainingChains.parallelStream().forEach( c -> c.intersections.removeAll( least.intersections ) );
}
selectedChains.add( least );
}
System.out.println( "After reducing the amount of intersecting chains: " + selectedChains.size() );
return selectedChains;
}
private static Collection< EdgePolygon > partitionMonotone( final TreeSet< Vertex > vertices, final Collection< HalfEdge > interior ) {