Fixed bad sorting

Should now sort edges based on the correct cross product
Fixed support edge connecting to the wrong vertex
Added in some more checks
Draw shapes slightly more correctly?
This commit is contained in:
2025-05-04 18:50:40 -04:00
parent d16041f977
commit 510fcc7b7d
2 changed files with 108 additions and 49 deletions

View File

@@ -726,7 +726,7 @@ public class Mesh< T extends Region > {
} else if ( e1.getDest() == e2.getDest() ) { } else if ( e1.getDest() == e2.getDest() ) {
return 0; return 0;
} else { } else {
final double cross = e1.toVector2d().cross( e2.toVector2d() ); final double cross = e2.toVector2d().cross( e1.toVector2d() );
return Double.compare( cross, 0 ); return Double.compare( cross, 0 );
} }
} ); } );
@@ -761,6 +761,10 @@ public class Mesh< T extends Region > {
HalfEdge edge = internalEdge; HalfEdge edge = internalEdge;
if ( edge.getPrev() == edge ) {
throw new IllegalStateException( "Double sided interior edges detected" );
}
// Fast forward to the start of a potential colinear chain, since this edge may be in the middle of one // Fast forward to the start of a potential colinear chain, since this edge may be in the middle of one
while ( Math.abs( edge.toVector2d().normalize().cross( edge.getPrev().toVector2d().normalize() ) ) <= ANGLE_TOLERANCE ) { while ( Math.abs( edge.toVector2d().normalize().cross( edge.getPrev().toVector2d().normalize() ) ) <= ANGLE_TOLERANCE ) {
edge = edge.getNext(); edge = edge.getNext();
@@ -1006,6 +1010,13 @@ public class Mesh< T extends Region > {
supportEdges.add( edge ); supportEdges.add( edge );
} else if ( marked.equals( eventMark ) ) { } else if ( marked.equals( eventMark ) ) {
// If a right-marked vertex is between the same
// upper/lower region as this vertex, then
// that must be because this vertex is left marked
if ( !leftGoing.isEmpty() ) {
throw new IllegalStateException( "Vertex is not left-marked!" );
}
// Are there two marked vertices between the same edges? // Are there two marked vertices between the same edges?
final HalfEdge edge = new HalfEdge(); final HalfEdge edge = new HalfEdge();
@@ -1013,12 +1024,22 @@ public class Mesh< T extends Region > {
edge.getSym().setOrigin( prev ); edge.getSym().setOrigin( prev );
HalfEdge.splice( edge, event.getEdge() ); HalfEdge.splice( edge, event.getEdge() );
HalfEdge.splice( edge, prev.getEdge() ); HalfEdge.splice( edge.getSym(), prev.getEdge() );
// Add the edge to the left-going for this vertex
// so it can be considered "fixed"
leftGoing.add( edge ); leftGoing.add( edge );
supportEdges.add( edge ); supportEdges.add( edge );
// Technically both vertices need to be sorted
toSort.add( event ); toSort.add( event );
toSort.add( prev );
// Can break out of this loop early, since this vertex must have
// been a left-marked vertex, and therefore cannot fulfill any of the
// conditions above anymore.
it.remove();
break;
} else { } else {
continue; continue;
} }
@@ -1112,8 +1133,8 @@ public class Mesh< T extends Region > {
edge.setOrigin( prev ); edge.setOrigin( prev );
edge.getSym().setOrigin( vertex ); edge.getSym().setOrigin( vertex );
HalfEdge.splice( edge.getSym(), vertex.getEdge() );
HalfEdge.splice( edge, prev.getEdge() ); HalfEdge.splice( edge, prev.getEdge() );
HalfEdge.splice( edge.getSym(), vertex.getEdge() );
supportEdges.add( edge ); supportEdges.add( edge );
@@ -1143,12 +1164,15 @@ public class Mesh< T extends Region > {
HalfEdge.splice( copy, edge ); HalfEdge.splice( copy, edge );
HalfEdge.splice( copy.getSym(), edge.getNext() ); HalfEdge.splice( copy.getSym(), edge.getNext() );
interior.add( copy );
interior.add( edge.getSym() );
} }
// Now that we've split the polygon into monotone regions, we must // Now that we've split the polygon into monotone regions, we must
// also return a collection of the newly created polygon, since each // also return a collection of the newly created polygon, since each
// monotone region is its own separate polygon // monotone region is its own separate polygon
Collection< EdgePolygon > newPolygons = new HashSet< EdgePolygon >(); final Collection< EdgePolygon > newPolygons = new ArrayDeque< EdgePolygon >();
// Keep track of all edges that we've seen // Keep track of all edges that we've seen
final Set< HalfEdge > scanned = new HashSet< HalfEdge >(); final Set< HalfEdge > scanned = new HashSet< HalfEdge >();
@@ -1182,13 +1206,13 @@ public class Mesh< T extends Region > {
} }
private void triangulate() { private void triangulate() {
// TODO
} }
/* /*
* Assumes region a and b overlap somewhere on the x axis * Assumes region a and b overlap somewhere on the x axis
* Assume both wings do not intersect, and are nonzero and positive * Assume both edges do not intersect, and are nonzero and positive
* Assume that a and b cannot both be vertical and not share the same origin * Assume that a and b cannot both be vertical and share the same origin
*/ */
private static boolean greaterThanOrEqualTo( final HalfEdge a, final HalfEdge b ) { private static boolean greaterThanOrEqualTo( final HalfEdge a, final HalfEdge b ) {
// Assume each region is marked by an upper edge going from right to left, up to down // Assume each region is marked by an upper edge going from right to left, up to down
@@ -1222,11 +1246,15 @@ public class Mesh< T extends Region > {
* @param edge * @param edge
* @return * @return
*/ */
private static boolean isPositive( HalfEdge edge ) { public static boolean isPositive( HalfEdge edge ) {
return compare( edge.getOrigin(), edge.getDest() ) <= 0; return compare( edge.getOrigin(), edge.getDest() ) <= 0;
} }
private static int compare( final Vertex a, final Vertex b ) { private static int compare( final Vertex a, final Vertex b ) {
if ( a == b ) {
return 0;
}
final Vector2d aPos = a.getPosition(); final Vector2d aPos = a.getPosition();
final Vector2d bPos = b.getPosition(); final Vector2d bPos = b.getPosition();

View File

@@ -11,7 +11,9 @@ import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collection; import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Set;
import javax.swing.JFrame; import javax.swing.JFrame;
import javax.swing.JPanel; import javax.swing.JPanel;
@@ -41,14 +43,17 @@ public class MeshingTest2 extends JPanel {
JFrame f; JFrame f;
// private int windowWidth = 1200;
// private int windowHeight = 1000;
private int windowWidth = 1200; private int windowWidth = 1200;
private int windowHeight = 1000; private int windowHeight = 1400;
// private int centerX = 600; // private int centerX = 600;
// private int centerY = 400; // private int centerY = 400;
private int centerX = 400; private int centerX = 400;
private int centerY = 1200; private int centerY = 100;
private Graphics g; private Graphics g;
@@ -389,6 +394,20 @@ public class MeshingTest2 extends JPanel {
if ( data != null ) { if ( data != null ) {
Collection< Vertex > polygons = data; Collection< Vertex > polygons = data;
// Set< HalfEdge > positiveEdges = new HashSet< HalfEdge >();
// Set< HalfEdge > negativeEdges = new HashSet< HalfEdge >();
//
// for ( Vertex v : polygons ) {
// for ( HalfEdge e : v ) {
// if ( Mesh.isPositive( e ) ) {
// positiveEdges.add( e );
// } else {
// negativeEdges.add( e );
// }
// }
// }
EdgeSet edges = new EdgeSet(); EdgeSet edges = new EdgeSet();
for ( Vertex vert : polygons ) { for ( Vertex vert : polygons ) {
for ( HalfEdge edge : vert ) { for ( HalfEdge edge : vert ) {
@@ -397,60 +416,72 @@ public class MeshingTest2 extends JPanel {
Point p2 = edge.getDest().getPosition(); Point p2 = edge.getDest().getPosition();
g.drawLine( g.drawLine(
( int ) ( p1.getX() * scale ) + centerX, ( int ) ( p1.getX() * scale ) + centerX,
( int ) ( p1.getY() * scale ) + centerY, ( int ) ( - p1.getY() * scale ) + centerY,
( int ) ( p2.getX() * scale ) + centerX, ( int ) ( p2.getX() * scale ) + centerX,
( int ) ( p2.getY() * scale ) + centerY ( int ) ( - p2.getY() * scale ) + centerY
); );
} }
} }
final double diff = scale * 0.3; final double diff = scale * 0.15;
final Point point = vert.getPosition(); final Point point = vert.getPosition();
g.drawRect( ( int ) ( point.getX() * scale ) + centerX - ( int ) diff, ( int ) ( point.getY() * scale ) + centerY - ( int ) diff, ( int ) ( diff * 2 ), ( int ) ( diff * 2 ) ); g.setColor( Color.BLACK );
g.drawRect( ( int ) ( point.getX() * scale ) + centerX - ( int ) diff, ( int ) ( - point.getY() * scale ) + centerY - ( int ) diff, ( int ) ( diff * 2 ), ( int ) ( diff * 2 ) );
} }
} }
if ( polygons != null ) { if ( polygons != null ) {
System.out.println( "Polygon count: " + polygons.size() ); // System.out.println( "Polygon count: " + polygons.size() );
g.setColor( Color.BLACK ); g.setColor( Color.BLACK );
int count = 2;
for ( final EdgePolygon p : polygons ) { for ( final EdgePolygon p : polygons ) {
final Collection< HalfEdge > edges = p.getEdges(); final Collection< HalfEdge > edges = p.getEdges();
for ( HalfEdge edge : edges ) { // g.setColor( Color.BLACK );
Point p1 = edge.getOrigin().getPosition(); // for ( HalfEdge edge : edges ) {
Point p2 = edge.getDest().getPosition(); // Point p1 = edge.getOrigin().getPosition();
g.drawLine( // Point p2 = edge.getDest().getPosition();
( int ) ( p1.getX() * scale ) + centerX + 400, // g.drawLine(
( int ) ( p1.getY() * scale ) + centerY, // ( int ) ( p1.getX() * scale ) + centerX + ( 170 * count ),
( int ) ( p2.getX() * scale ) + centerX + 400, // ( int ) ( - p1.getY() * scale ) + centerY,
( int ) ( p2.getY() * scale ) + centerY // ( int ) ( p2.getX() * scale ) + centerX + ( 170 * count ),
); // ( int ) ( - p2.getY() * scale ) + centerY
} // );
// int size = edges.size();
// int[] xPoints = new int[ size ];
// int[] yPoints = new int[ size ];
// //
// HalfEdge edge = edges.iterator().next(); // g.drawLine(
// for ( int i = 0; i < edges.size(); ++i ) { // ( int ) ( p1.getX() * scale ) + centerX + 170,
// final Point point = edge.getOrigin().getPosition(); // ( int ) ( - p1.getY() * scale ) + centerY,
// xPoints[ i ] = ( int ) ( point.getX() * scale ) + centerX; // ( int ) ( p2.getX() * scale ) + centerX + 170,
// yPoints[ i ] = ( int ) ( point.getY() * scale ) + centerY; // ( int ) ( - p2.getY() * scale ) + centerY
// );
// } // }
// // count++;
// g.setColor( new Color( ( int ) ( Math.random() * 0xFFFFFF ) ) );
// g.fillPolygon( xPoints, yPoints, size );
}
g.setColor( Color.BLACK ); int size = edges.size();
for ( final EdgePolygon p : polygons ) { int[] xPoints = new int[ size ];
for ( final Vertex v : p.getVertices() ) { int[] yPoints = new int[ size ];
final Point point = v.getPosition();
double diff = scale * .3; HalfEdge edge = edges.iterator().next();
g.drawRect( 400 + ( int ) ( point.getX() * scale ) + centerX - ( int ) diff, ( int ) ( point.getY() * scale ) + centerY - ( int ) diff, ( int ) ( diff * 2 ), ( int ) ( diff * 2 ) ); for ( int i = 0; i < edges.size(); ++i ) {
final Point point = edge.getOrigin().getPosition();
xPoints[ i ] = ( int ) ( point.getX() * scale ) + centerX + 400;
yPoints[ i ] = ( int ) ( - point.getY() * scale ) + centerY;
edge = edge.getNext();
} }
g.setColor( new Color( ( int ) ( Math.random() * 0xFFFFFF ) ) );
g.fillPolygon( xPoints, yPoints, size );
} }
// g.setColor( Color.BLACK );
// for ( final EdgePolygon p : polygons ) {
// for ( final Vertex v : p.getVertices() ) {
// final Point point = v.getPosition();
//
// double diff = scale * .3;
// g.drawRect( 400 + ( int ) ( point.getX() * scale ) + centerX - ( int ) diff, ( int ) ( point.getY() * scale ) + centerY - ( int ) diff, ( int ) ( diff * 2 ), ( int ) ( diff * 2 ) );
// }
// }
} }
// Point[] points = { // Point[] points = {