From 566a7fb15f0125d23a4d2bf455e28dd80ab15d2a Mon Sep 17 00:00:00 2001 From: BananaPuncher714 Date: Sat, 17 May 2025 17:11:17 -0400 Subject: [PATCH] Remove intersecting chains Removed intersecting chains using a greedy method Fixed issue where chains found after splitting partitions do not get checked for intersection --- .../bananapuncher714/mesh/Mesh.java | 60 +++++++++++++++++-- 1 file changed, 56 insertions(+), 4 deletions(-) diff --git a/src/main/java/com/aaaaahhhhhhh/bananapuncher714/mesh/Mesh.java b/src/main/java/com/aaaaahhhhhhh/bananapuncher714/mesh/Mesh.java index 67838bb..632371b 100644 --- a/src/main/java/com/aaaaahhhhhhh/bananapuncher714/mesh/Mesh.java +++ b/src/main/java/com/aaaaahhhhhhh/bananapuncher714/mesh/Mesh.java @@ -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 ) {