Introduce fuzzy iterating when finding chains; Found another bug when detecting chain collisions
This commit is contained in:
@@ -231,6 +231,25 @@ public class Mesh< T extends Region > {
|
||||
return copy;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* @return A collection of triangles
|
||||
*/
|
||||
public Collection< Polygon > meshify() {
|
||||
switch ( state ) {
|
||||
case DIRTY:
|
||||
simplify();
|
||||
case SIMPLIFIED:
|
||||
generateRegions();
|
||||
case TRIANGULATION_READY:
|
||||
return mesh();
|
||||
default:
|
||||
throw new IllegalStateException( "Invalid mesh state!" );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Do a check over all vertices to see if there are any within
|
||||
* VERTEX_TOLERANCE of each other. If so, then merge them.
|
||||
@@ -973,13 +992,13 @@ public class Mesh< T extends Region > {
|
||||
}
|
||||
|
||||
// Have a single set of edges
|
||||
final TreeSet< Vertex > vertices = new TreeSet< Vertex >( Mesh::compare );
|
||||
vertices.addAll( newVertices.values() );
|
||||
final TreeSet< Vertex > fuzzyVertices = new TreeSet< Vertex >( Mesh::fuzzyCompare );
|
||||
fuzzyVertices.addAll( newVertices.values() );
|
||||
|
||||
// Sort each vertex so that the edge they are pointing to is the least edge
|
||||
vertices.parallelStream().forEach( v -> sort( v ) );
|
||||
fuzzyVertices.parallelStream().forEach( v -> sort( v ) );
|
||||
|
||||
final Collection< Link > allChains = findChains( vertices, edges );
|
||||
final Collection< Link > allChains = findChains( fuzzyVertices, edges );
|
||||
final Collection< Link > chains = maximizeChains( allChains );
|
||||
if ( !handlers.isEmpty() ) {
|
||||
final Collection< Chain > newChains = new HashSet< Chain >();
|
||||
@@ -1034,10 +1053,15 @@ public class Mesh< T extends Region > {
|
||||
|
||||
mergeChains( chains, edges );
|
||||
|
||||
return partitionMonotone( vertices, edges ).parallelStream()
|
||||
.map( Mesh::triangulate )
|
||||
.flatMap( p -> p.parallelStream() )
|
||||
.collect( Collectors.toSet() );
|
||||
// return Collections.emptySet();
|
||||
final TreeSet< Vertex > vertices = new TreeSet< Vertex >( Mesh::compare );
|
||||
vertices.addAll( fuzzyVertices );
|
||||
|
||||
return Collections.emptySet();
|
||||
// return partitionMonotone( vertices, edges ).parallelStream()
|
||||
// .map( Mesh::triangulate )
|
||||
// .flatMap( p -> p.parallelStream() )
|
||||
// .collect( Collectors.toSet() );
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1431,6 +1455,10 @@ public class Mesh< T extends Region > {
|
||||
// The new chain is a continuation of this chain
|
||||
other.next = chain;
|
||||
chain.previous = other;
|
||||
} else if ( chainMidpoint == other.getOrigin() && chainDestination == other.getMidpoint() ) {
|
||||
System.out.println( "BUG" );
|
||||
other.previous = chain;
|
||||
chain.next = other;
|
||||
} else if ( compare( other.getDest(), chainOrigin ) > 0 ) {
|
||||
// Do the chains even overlap?
|
||||
if ( chainOrigin == other.getMidpoint() ) {
|
||||
@@ -1457,6 +1485,31 @@ public class Mesh< T extends Region > {
|
||||
intersects = otherDirection.cross( secondLink.toVector2d() ) < 0 ^ cross < 0;
|
||||
}
|
||||
|
||||
if ( intersects ) {
|
||||
synchronized ( intersections ) {
|
||||
intersections.add( other );
|
||||
}
|
||||
other.intersections.add( chain );
|
||||
}
|
||||
} else if ( chainDestination == other.getMidpoint() ) {
|
||||
System.out.println( "BUG 2" );
|
||||
final Vector2d otherDirection = other.getDest().getPosition().subtracted( other.getOrigin().getPosition() );
|
||||
final double cross = r.cross( otherDirection );
|
||||
|
||||
boolean intersects = true;
|
||||
final HalfEdge firstLink = other.links.get( 0 );
|
||||
final HalfEdge secondLink = other.links.get( 1 );
|
||||
if ( firstLink.getDest() == other.getMidpoint() ) {
|
||||
// Is the first link a direct connection?
|
||||
intersects = interior.contains( firstLink ) ^ cross < 0;
|
||||
} else if ( secondLink.getDest() == other.getDest() ) {
|
||||
// Is the second link a direct connection?
|
||||
intersects = interior.contains( secondLink ) ^ cross < 0;
|
||||
} else {
|
||||
// The chain is comprised of only vertices...
|
||||
intersects = otherDirection.cross( secondLink.toVector2d() ) < 0 ^ cross < 0;
|
||||
}
|
||||
|
||||
if ( intersects ) {
|
||||
synchronized ( intersections ) {
|
||||
intersections.add( other );
|
||||
@@ -1478,6 +1531,27 @@ public class Mesh< T extends Region > {
|
||||
intersects = r.cross( secondEdgeVec ) < 0 ^ cross < 0;
|
||||
}
|
||||
|
||||
if ( intersects ) {
|
||||
synchronized ( intersections ) {
|
||||
intersections.add( other );
|
||||
}
|
||||
other.intersections.add( chain );
|
||||
}
|
||||
} else if ( other.getOrigin() == chainMidpoint ) {
|
||||
// Third and last case
|
||||
// destination. We need to check for that case too.
|
||||
final Vector2d otherDirection = other.getDest().getPosition().subtracted( other.getOrigin().getPosition() ).normalize();
|
||||
final double cross = r.cross( otherDirection );
|
||||
|
||||
boolean intersects = true;
|
||||
if ( firstEdge.getDest() == chainMidpoint ) {
|
||||
intersects = interior.contains( firstEdge ) ^ cross < 0;
|
||||
} else if ( secondEdge.getDest() == chainDestination ) {
|
||||
intersects = interior.contains( secondEdge ) ^ cross < 0;
|
||||
} else {
|
||||
intersects = r.cross( secondEdgeVec ) < 0 ^ cross < 0;
|
||||
}
|
||||
|
||||
if ( intersects ) {
|
||||
synchronized ( intersections ) {
|
||||
intersections.add( other );
|
||||
@@ -1808,8 +1882,6 @@ public class Mesh< T extends Region > {
|
||||
throw new IllegalStateException( "Lower partition not found!" );
|
||||
}
|
||||
|
||||
top.chains.addAll( bottom.chains );
|
||||
|
||||
lowerEdgeMap.remove( bottom.upper );
|
||||
|
||||
// Merge the top and bottom partition
|
||||
@@ -1821,7 +1893,13 @@ public class Mesh< T extends Region > {
|
||||
// Update all visibility regions for the top and bottom partitions, separately
|
||||
top.incrementLower( topLeft );
|
||||
bottom.incrementUpper( bottomLeft );
|
||||
|
||||
|
||||
// Problem... need to make bottom chains and top chains the same because merging regions must use the same chain map...
|
||||
// TODO Do it... make a reverse region map for each chain... it only makes some sense...
|
||||
// And then technically just combine all chain maps at the end because that also only makes sense
|
||||
// Fixes the issues...
|
||||
top.chains.addAll( bottom.chains );
|
||||
|
||||
// Merge the two partitions
|
||||
top.add( bottom );
|
||||
|
||||
@@ -2342,6 +2420,7 @@ public class Mesh< T extends Region > {
|
||||
if ( upper == null ) {
|
||||
throw new IllegalStateException( "Lower does not have an upper edge!" );
|
||||
} if ( !interior.contains( upper.getSym() ) ) {
|
||||
System.out.println( upper );
|
||||
throw new IllegalStateException( "Polygon is not simple!" );
|
||||
} else if ( upper.getOrigin() == event || lower.getOrigin() == event ) {
|
||||
throw new IllegalStateException( "Vertex is invalid!" );
|
||||
@@ -2641,8 +2720,11 @@ public class Mesh< T extends Region > {
|
||||
|
||||
// Lazy solution, just sort the vertices
|
||||
// Eventually we will remove this
|
||||
// TODO Remove this NOW
|
||||
toSort.parallelStream().forEach( v -> sort( v ) );
|
||||
|
||||
Map< Vertex, Point > pointMap = polygon.vertices.parallelStream().collect( Collectors.toMap( Function.identity(), v -> { return new Point( v.getPosition() ); } ) );
|
||||
|
||||
final Collection< Polygon > polygons = new ArrayDeque< Polygon >();
|
||||
final Set< HalfEdge > scanned = new HashSet< HalfEdge >();
|
||||
for ( final HalfEdge edge : polygon.getEdges() ) {
|
||||
@@ -2651,7 +2733,7 @@ public class Mesh< T extends Region > {
|
||||
|
||||
final List< Point > points = new ArrayList< Point >();
|
||||
do {
|
||||
points.add( new Point( temp.getOrigin().getPosition() ) );
|
||||
points.add( pointMap.get( temp.getOrigin() ) );
|
||||
} while ( scanned.add( temp = temp.getNext() ) );
|
||||
|
||||
if ( points.size() != 3 ) {
|
||||
@@ -2701,10 +2783,32 @@ public class Mesh< T extends Region > {
|
||||
* @param edge
|
||||
* @return
|
||||
*/
|
||||
public static boolean isPositive( HalfEdge edge ) {
|
||||
private static boolean isPositive( HalfEdge edge ) {
|
||||
return compare( edge.getOrigin(), edge.getDest() ) <= 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Since sometimes vertices will be off by a few floating point errors,
|
||||
* it will cause problems because we have checks for tolerance, but if
|
||||
* the sorting for vertices does not, it causes issues.
|
||||
*/
|
||||
private static int fuzzyCompare( final Vertex a, final Vertex b ) {
|
||||
if ( a == b ) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
final Vector2d aPos = a.getPosition();
|
||||
final Vector2d bPos = b.getPosition();
|
||||
|
||||
final double xDiff = aPos.getX() - bPos.getX();
|
||||
if ( Math.abs( xDiff ) < VERTEX_TOLERANCE ) {
|
||||
return Double.compare( aPos.getY(), bPos.getY() );
|
||||
} else {
|
||||
return Double.compare( aPos.getX(), bPos.getX() );
|
||||
}
|
||||
}
|
||||
|
||||
private static int compare( final Vertex a, final Vertex b ) {
|
||||
if ( a == b ) {
|
||||
return 0;
|
||||
|
||||
Reference in New Issue
Block a user