754 lines
30 KiB
Java
754 lines
30 KiB
Java
package com.aaaaahhhhhhh.bananapuncher714.minietest;
|
|
|
|
import java.awt.Color;
|
|
import java.awt.Font;
|
|
import java.awt.Graphics;
|
|
import java.awt.MouseInfo;
|
|
import java.awt.event.ComponentAdapter;
|
|
import java.awt.event.ComponentEvent;
|
|
import java.awt.event.MouseAdapter;
|
|
import java.awt.event.MouseEvent;
|
|
import java.awt.event.MouseWheelEvent;
|
|
import java.io.BufferedReader;
|
|
import java.io.File;
|
|
import java.io.FileNotFoundException;
|
|
import java.io.FileReader;
|
|
import java.io.IOException;
|
|
import java.util.ArrayList;
|
|
import java.util.Arrays;
|
|
import java.util.Collection;
|
|
import java.util.Collections;
|
|
import java.util.HashSet;
|
|
import java.util.List;
|
|
import java.util.Random;
|
|
import java.util.Set;
|
|
|
|
import javax.swing.JFrame;
|
|
import javax.swing.JPanel;
|
|
import javax.swing.SwingUtilities;
|
|
|
|
import org.bukkit.util.Vector;
|
|
|
|
import com.aaaaahhhhhhh.bananapuncher714.mesh.EdgeSet;
|
|
import com.aaaaahhhhhhh.bananapuncher714.mesh.HalfEdge;
|
|
import com.aaaaahhhhhhh.bananapuncher714.mesh.Mesh;
|
|
import com.aaaaahhhhhhh.bananapuncher714.mesh.Mesh.Chain;
|
|
import com.aaaaahhhhhhh.bananapuncher714.mesh.Mesh.EdgePolygon;
|
|
import com.aaaaahhhhhhh.bananapuncher714.mesh.Point;
|
|
import com.aaaaahhhhhhh.bananapuncher714.mesh.Polygon;
|
|
import com.aaaaahhhhhhh.bananapuncher714.mesh.Vector2d;
|
|
import com.aaaaahhhhhhh.bananapuncher714.mesh.Vertex;
|
|
import com.aaaaahhhhhhh.bananapuncher714.mesh.region.simple.RegionRuleWinding;
|
|
import com.aaaaahhhhhhh.bananapuncher714.mesh.region.simple.RegionSimple;
|
|
import com.aaaaahhhhhhh.bananapuncher714.mesh.region.simple.RegionSimple.GluWindingRule;
|
|
import com.aaaaahhhhhhh.bananapuncher714.minietest.objects.ChunkLocation;
|
|
import com.aaaaahhhhhhh.bananapuncher714.minietest.objects.mesh.Facet;
|
|
import com.aaaaahhhhhhh.bananapuncher714.minietest.objects.mesh.MeshBuilder;
|
|
import com.aaaaahhhhhhh.bananapuncher714.minietest.objects.mesh.Plane;
|
|
|
|
public class MeshingTest2 extends JPanel {
|
|
private static final File BASE = new File( System.getProperty( "user.dir" ) );
|
|
private static final File CHUNK_DIR = new File( BASE, "chunks" );
|
|
|
|
JFrame f;
|
|
|
|
// private int windowWidth = 1200;
|
|
// private int windowHeight = 1000;
|
|
|
|
private int windowWidth = 1200;
|
|
private int windowHeight = 800;
|
|
|
|
// private int centerX = 600;
|
|
// private int centerY = 400;
|
|
|
|
private int offsetX = windowWidth >> 1;
|
|
private int offsetY = windowHeight >> 1;
|
|
|
|
private double centerX = 0;
|
|
private double centerY = 0;
|
|
|
|
private double scale = 8;
|
|
|
|
private Collection< Vertex > data;
|
|
private Collection< EdgePolygon > polygons;
|
|
|
|
// Temporary... Remove at some point
|
|
private static Collection< Chain > chains;
|
|
|
|
public static void main( String[] args ) {
|
|
if ( CHUNK_DIR.exists() && CHUNK_DIR.isDirectory() ) {
|
|
System.out.println( "Found " + CHUNK_DIR.list().length + " files" );
|
|
for ( File file : CHUNK_DIR.listFiles() ) {
|
|
List< Plane > planes = mesh( file );
|
|
|
|
Plane draw = null;
|
|
|
|
System.out.println( "Planes: " + planes.size() );
|
|
for ( Plane plane : planes ) {
|
|
if ( plane.polygons.size() > 100 ) {
|
|
draw = plane;
|
|
break;
|
|
}
|
|
}
|
|
|
|
// Select a random plane to draw
|
|
// draw = planes.get( new Random().nextInt( planes.size() ) );
|
|
|
|
System.out.println( "Draw is " + draw );
|
|
// Attempt to mesh all planes
|
|
try {
|
|
test( planes );
|
|
} catch ( PolygonException e ) {
|
|
draw = e.getPlane();
|
|
System.out.println( "Draw is now " + draw );
|
|
}
|
|
|
|
final Collection< Vertex > data = process( draw );
|
|
final Collection< EdgePolygon > polys = triangulate( draw );
|
|
// final Collection< EdgePolygon > polys = test();
|
|
|
|
System.out.println( "Polygon count: " + polys.size() );
|
|
|
|
SwingUtilities.invokeLater( new Runnable() {
|
|
@Override
|
|
public void run() {
|
|
new MeshingTest2( data, polys );
|
|
}
|
|
} );
|
|
break;
|
|
}
|
|
} else {
|
|
System.err.println( "No such directory exists: " + CHUNK_DIR );
|
|
}
|
|
}
|
|
|
|
private static List< Plane > mesh( File file ) {
|
|
String name = file.getName();
|
|
String[] split = name.split( "," );
|
|
ChunkLocation location = new ChunkLocation( split[ 0 ], Integer.parseInt( split[ 1 ] ), Integer.parseInt( split[ 2 ] ) );
|
|
|
|
System.out.println( "Parsing chunk " + location );
|
|
|
|
// First parse the file to get a list of all bounding boxes that we can use
|
|
List< AABB > boxes = new ArrayList< AABB >();
|
|
try ( BufferedReader reader = new BufferedReader( new FileReader( file ) ) ) {
|
|
String line;
|
|
while ( ( line = reader.readLine() ) != null ) {
|
|
if ( !line.isEmpty() ) {
|
|
String[] values = line.split( "," );
|
|
double minX = Double.parseDouble( values[ 0 ] );
|
|
double minY = Double.parseDouble( values[ 1 ] );
|
|
double minZ = Double.parseDouble( values[ 2 ] );
|
|
double maxX = Double.parseDouble( values[ 3 ] );
|
|
double maxY = Double.parseDouble( values[ 4 ] );
|
|
double maxZ = Double.parseDouble( values[ 5 ] );
|
|
boxes.add( new AABB( minX, minY, minZ, maxX, maxY, maxZ ) );
|
|
}
|
|
}
|
|
} catch ( FileNotFoundException e ) {
|
|
e.printStackTrace();
|
|
return null;
|
|
} catch ( IOException e ) {
|
|
e.printStackTrace();
|
|
return null;
|
|
}
|
|
|
|
System.out.println( "Found " + boxes.size() + " boxes" );
|
|
// Now that we have a bunch of bounding boxes, do whatever
|
|
|
|
MeshBuilder builder = new MeshBuilder();
|
|
for ( AABB box : boxes ) {
|
|
for ( Facet facet : generateFacetsFor( box ) ) {
|
|
builder.addFacet( facet );
|
|
}
|
|
}
|
|
|
|
return builder.planes;
|
|
}
|
|
|
|
public static class PolygonException extends RuntimeException {
|
|
Plane plane;
|
|
|
|
PolygonException( Plane plane ) {
|
|
this.plane = plane;
|
|
}
|
|
|
|
Plane getPlane() {
|
|
return plane;
|
|
}
|
|
}
|
|
|
|
private static void test( final Collection< Plane > planes ) {
|
|
final long processAllStart = System.currentTimeMillis();
|
|
planes.stream().forEach( plane -> {
|
|
try {
|
|
Mesh< RegionSimple > mesh = new Mesh< RegionSimple >( () -> { return new RegionSimple( GluWindingRule.ODD ); } );
|
|
|
|
for ( Polygon poly : plane.polygons ) {
|
|
mesh.addPolygon( poly, RegionRuleWinding.CLOCKWISE );
|
|
}
|
|
long start = System.currentTimeMillis();
|
|
mesh.simplify();
|
|
mesh.generateRegions();
|
|
final Collection< EdgePolygon > polys = mesh.copyOf().mesh( false );
|
|
long end = System.currentTimeMillis();
|
|
System.out.println( plane.polygons.size() + " to " + polys.size() + ":\t " + ( end - start ) + "ms" );
|
|
} catch ( IllegalStateException e ) {
|
|
e.printStackTrace();
|
|
throw new PolygonException( plane );
|
|
}
|
|
} );
|
|
final long processAllEnd = System.currentTimeMillis();
|
|
System.out.println( "Took " + ( processAllEnd - processAllStart ) + "ms to process " + planes.size() + " planes" );
|
|
}
|
|
|
|
private static Collection< Vertex > process( final Plane plane ) {
|
|
if ( plane != null ) {
|
|
System.out.println( "Norm:\t" + plane.normal );
|
|
System.out.println( "Ref:\t" + plane.point );
|
|
System.out.println( "Size:\t" + plane.polygons.size() );
|
|
|
|
Mesh< RegionSimple > mesh = new Mesh< RegionSimple >( () -> { return new RegionSimple( GluWindingRule.ODD ); } );
|
|
for ( Polygon poly : plane.polygons ) {
|
|
mesh.addPolygon( poly, RegionRuleWinding.CLOCKWISE );
|
|
}
|
|
|
|
System.out.println( "Initial vertex count: " + mesh.getVertices().size() );
|
|
System.out.println( "Initial edge count: " + ( mesh.getRuleSize() / 2 ) );
|
|
|
|
long start = System.currentTimeMillis();
|
|
mesh.simplify();
|
|
|
|
System.out.println( "After simplify vertex count: " + mesh.getVertices().size() );
|
|
System.out.println( "After simplify edge count: " + ( mesh.getRuleSize() / 2 ) );
|
|
|
|
mesh.generateRegions();
|
|
long end = System.currentTimeMillis();
|
|
|
|
System.out.println( "After generating regions vertex count: " + mesh.getVertices().size() );
|
|
System.out.println( "After generating regions edge count: " + ( mesh.getRuleSize() / 2 ) );
|
|
|
|
|
|
System.out.println( "Took " + ( end - start ) + "ms" );
|
|
return mesh.getVertices();
|
|
} else {
|
|
System.out.println( "No data!" );
|
|
return Collections.emptySet();
|
|
}
|
|
}
|
|
|
|
private static Collection< EdgePolygon > triangulate( final Plane plane ) {
|
|
if ( plane != null ) {
|
|
System.out.println( "Norm:\t" + plane.normal );
|
|
System.out.println( "Ref:\t" + plane.point );
|
|
System.out.println( "Size:\t" + plane.polygons.size() );
|
|
|
|
Mesh< RegionSimple > mesh = new Mesh< RegionSimple >( () -> { return new RegionSimple( GluWindingRule.ODD ); } );
|
|
for ( Polygon poly : plane.polygons ) {
|
|
mesh.addPolygon( poly, RegionRuleWinding.CLOCKWISE );
|
|
}
|
|
|
|
System.out.println( "Initial vertex count: " + mesh.getVertices().size() );
|
|
System.out.println( "Initial edge count: " + ( mesh.getRuleSize() / 2 ) );
|
|
|
|
long start = System.currentTimeMillis();
|
|
mesh.simplify();
|
|
|
|
System.out.println( "After simplify vertex count: " + mesh.getVertices().size() );
|
|
System.out.println( "After simplify edge count: " + ( mesh.getRuleSize() / 2 ) );
|
|
|
|
mesh.generateRegions();
|
|
|
|
System.out.println( "After generating regions vertex count: " + mesh.getVertices().size() );
|
|
System.out.println( "After generating regions edge count: " + ( mesh.getRuleSize() / 2 ) );
|
|
|
|
// Make sure this works
|
|
mesh = mesh.copyOf();
|
|
|
|
Collection< EdgePolygon > polys;
|
|
|
|
try {
|
|
polys = mesh.mesh( false );
|
|
chains = mesh.chains;
|
|
} catch ( IllegalStateException e ) {
|
|
e.printStackTrace();
|
|
|
|
polys = mesh.mesh( true );
|
|
chains = mesh.chains;
|
|
}
|
|
|
|
long end = System.currentTimeMillis();
|
|
System.out.println( "Took " + ( end - start ) + "ms" );
|
|
|
|
return polys;
|
|
} else {
|
|
System.out.println( "No data!" );
|
|
return Collections.emptySet();
|
|
}
|
|
}
|
|
|
|
private static Collection< EdgePolygon > test() {
|
|
Mesh< RegionSimple > mesh = new Mesh< RegionSimple >( () -> { return new RegionSimple( GluWindingRule.ODD ); } );
|
|
|
|
// mesh.addPolygon( new Polygon( Arrays.asList(
|
|
// new Point( -1, 0 ),
|
|
// new Point( 1, -2 ),
|
|
// new Point( 1, -1 ),
|
|
// new Point( 2, -1 ),
|
|
// new Point( 1, 0 ),
|
|
// new Point( 1, 1 )
|
|
// ) ), RegionRuleWinding.CLOCKWISE );
|
|
// mesh.addPolygon( new Polygon( Arrays.asList(
|
|
// new Point( 0, 0 ),
|
|
// new Point( 5, 0 ),
|
|
// new Point( 5, 1 ),
|
|
// new Point( 4, 1 ),
|
|
// new Point( 4, 2 ),
|
|
// new Point( 3, 2 ),
|
|
// new Point( 3, 3 ),
|
|
// new Point( 2, 3 ),
|
|
// new Point( 2, 4 ),
|
|
// new Point( 0, 4 )
|
|
// ) ), RegionRuleWinding.CLOCKWISE );
|
|
// mesh.addPolygon( new Polygon( Arrays.asList(
|
|
// new Point( 0, 0 ),
|
|
// new Point( 2, 0 ),
|
|
// new Point( 2, 1 ),
|
|
// new Point( 1, 1 ),
|
|
// new Point( 1, 2 ),
|
|
// new Point( 2, 2 ),
|
|
// new Point( 2, 4 ),
|
|
// new Point( 1, 4 ),
|
|
// new Point( 1, 3 ),
|
|
// new Point( 0, 3 )
|
|
// ) ), RegionRuleWinding.CLOCKWISE );
|
|
// mesh.addPolygon( new Polygon( Arrays.asList(
|
|
// new Point( 0, 0 ),
|
|
// new Point( 3, 0 ),
|
|
// new Point( 3, 1 ),
|
|
// new Point( 4, 1 ),
|
|
// new Point( 4, 2 ),
|
|
// new Point( 2, 2 ),
|
|
// new Point( 2, 1 ),
|
|
// new Point( 1, 1 ),
|
|
// new Point( 0, 1 )
|
|
// ) ), RegionRuleWinding.CLOCKWISE );
|
|
|
|
// mesh.addPolygon( new Polygon( Arrays.asList(
|
|
// new Point( 0, 0 ),
|
|
// new Point( 2, 0 ),
|
|
// new Point( 2, 1 ),
|
|
// new Point( 3, 1 ),
|
|
// new Point( 3, 2 ),
|
|
// new Point( 2, 2 ),
|
|
// new Point( 2, 5 ),
|
|
// new Point( 1, 5 ),
|
|
// new Point( 1, 7 ),
|
|
// new Point( 0, 7 ),
|
|
// new Point( 0, 4 ),
|
|
// new Point( 1, 4 ),
|
|
// new Point( 1, 1 ),
|
|
// new Point( 0, 1 )
|
|
// ) ), RegionRuleWinding.CLOCKWISE );
|
|
// mesh.addPolygon( new Polygon( Arrays.asList(
|
|
// new Point( 1, 0 ),
|
|
// new Point( 6, 0 ),
|
|
// new Point( 6, 1 ),
|
|
// new Point( 4, 1 ),
|
|
// new Point( 4, 2 ),
|
|
// new Point( 2, 2 ),
|
|
// new Point( 2, 3 ),
|
|
// new Point( 0, 3 ),
|
|
// new Point( 0, 1 ),
|
|
// new Point( 1, 1 )
|
|
// ) ), RegionRuleWinding.CLOCKWISE );
|
|
// mesh.addPolygon( new Polygon( Arrays.asList(
|
|
// new Point( 3, 1 ),
|
|
// new Point( 3, 0 ),
|
|
// new Point( 10, 0 ),
|
|
// new Point( 10, 6 ),
|
|
// new Point( 9, 6 ),
|
|
// new Point( 9, 4 ),
|
|
// new Point( 8, 4 ),
|
|
// new Point( 8, 3 ),
|
|
// new Point( 5, 3 ),
|
|
// new Point( 5, 2 ),
|
|
// new Point( 0, 2 ),
|
|
// new Point( 0, 1 )
|
|
// ) ), RegionRuleWinding.CLOCKWISE );
|
|
// mesh.addPolygon( new Polygon( Arrays.asList(
|
|
// new Point( 7, 2 ),
|
|
// new Point( 9, 2 ),
|
|
// new Point( 9, 3 ),
|
|
// new Point( 7, 3 )
|
|
// ) ), RegionRuleWinding.CLOCKWISE );
|
|
|
|
// mesh.addPolygon( new Polygon( Arrays.asList(
|
|
// new Point( 0, 0 ),
|
|
// new Point( 6, 1 ),
|
|
// new Point( 7, 2 ),
|
|
// new Point( 1, 1 )
|
|
// ) ), RegionRuleWinding.CLOCKWISE );
|
|
// mesh.addPolygon( new Polygon( Arrays.asList(
|
|
// new Point( 2, 2 ),
|
|
// new Point( 8, 3 ),
|
|
// new Point( 9, 4 ),
|
|
// new Point( 3, 3 )
|
|
// ) ), RegionRuleWinding.CLOCKWISE );
|
|
|
|
// mesh.addPolygon( new Polygon( Arrays.asList(
|
|
// new Point( 2.816104467407629, -3.7472939407853763 ),
|
|
// new Point( 2.815383313894849, -2.9972942874937156 ),
|
|
// new Point( 2.0028836894955497, -2.9980755371325607 ),
|
|
// new Point( 2.0036048430083304, -3.7480751904242213 )
|
|
// ) ), RegionRuleWinding.CLOCKWISE );
|
|
// mesh.addPolygon( new Polygon( Arrays.asList(
|
|
// new Point( 2.8144217758778085, -1.9972947497715015 ),
|
|
// new Point( 2.0019221514785093, -1.998075999410347 ),
|
|
// new Point( 2.00264330499129, -2.748075652702007 ),
|
|
// new Point( 2.8151429293905887, -2.747294403063162 )
|
|
// ) ), RegionRuleWinding.CLOCKWISE );
|
|
|
|
mesh.simplify();
|
|
|
|
mesh.generateRegions();
|
|
|
|
try {
|
|
final Collection< EdgePolygon > polys = mesh.mesh( false );
|
|
chains = mesh.chains;
|
|
return polys;
|
|
} catch ( Exception e ) {
|
|
e.printStackTrace();
|
|
}
|
|
|
|
final Collection< EdgePolygon > polys = mesh.mesh( true );
|
|
chains = mesh.chains;
|
|
|
|
return polys;
|
|
}
|
|
|
|
private static List< Facet > generateFacetsFor( AABB box ) {
|
|
List< Facet > facets = new ArrayList< Facet >();
|
|
|
|
Vector p1 = new Vector( box.xmin, box.ymin, box.zmin );
|
|
Vector p2 = new Vector( box.xmin, box.ymin, box.zmax );
|
|
Vector p3 = new Vector( box.xmin, box.ymax, box.zmin );
|
|
Vector p4 = new Vector( box.xmin, box.ymax, box.zmax );
|
|
Vector p5 = new Vector( box.xmax, box.ymin, box.zmin );
|
|
Vector p6 = new Vector( box.xmax, box.ymin, box.zmax );
|
|
Vector p7 = new Vector( box.xmax, box.ymax, box.zmin );
|
|
Vector p8 = new Vector( box.xmax, box.ymax, box.zmax );
|
|
|
|
{
|
|
Facet facet = new Facet();
|
|
facet.points.add( p1 );
|
|
facet.points.add( p2 );
|
|
facet.points.add( p4 );
|
|
facet.points.add( p3 );
|
|
facet.normal = new Vector( -1, 0, 0 );
|
|
facets.add( facet );
|
|
}
|
|
|
|
{
|
|
Facet facet = new Facet();
|
|
facet.points.add( p5 );
|
|
facet.points.add( p6 );
|
|
facet.points.add( p8 );
|
|
facet.points.add( p7 );
|
|
facet.normal = new Vector( 1, 0, 0 );
|
|
facets.add( facet );
|
|
}
|
|
|
|
{
|
|
Facet facet = new Facet();
|
|
facet.points.add( p1 );
|
|
facet.points.add( p2 );
|
|
facet.points.add( p6 );
|
|
facet.points.add( p5 );
|
|
facet.normal = new Vector( 0, -1, 0 );
|
|
facets.add( facet );
|
|
}
|
|
|
|
{
|
|
Facet facet = new Facet();
|
|
facet.points.add( p3 );
|
|
facet.points.add( p4 );
|
|
facet.points.add( p8 );
|
|
facet.points.add( p7 );
|
|
facet.normal = new Vector( 0, 1, 0 );
|
|
facets.add( facet );
|
|
}
|
|
|
|
{
|
|
Facet facet = new Facet();
|
|
facet.points.add( p1 );
|
|
facet.points.add( p3 );
|
|
facet.points.add( p7 );
|
|
facet.points.add( p5 );
|
|
facet.normal = new Vector( 0, 0, -1 );
|
|
facets.add( facet );
|
|
}
|
|
|
|
{
|
|
Facet facet = new Facet();
|
|
facet.points.add( p2 );
|
|
facet.points.add( p4 );
|
|
facet.points.add( p8 );
|
|
facet.points.add( p6 );
|
|
facet.normal = new Vector( 0, 0, 1 );
|
|
facets.add( facet );
|
|
}
|
|
|
|
return facets;
|
|
}
|
|
|
|
static class AABB {
|
|
double xmin, ymin, zmin;
|
|
double xmax, ymax, zmax;
|
|
|
|
AABB( double xmin, double ymin, double zmin, double xmax, double ymax, double zmax ) {
|
|
this.xmin = xmin;
|
|
this.ymin = ymin;
|
|
this.zmin = zmin;
|
|
|
|
this.xmax = xmax;
|
|
this.ymax = ymax;
|
|
this.zmax = zmax;
|
|
}
|
|
|
|
double getVolume() {
|
|
return ( xmax - xmin ) * ( ymax - ymin ) * ( zmax - zmin );
|
|
}
|
|
|
|
@Override
|
|
public String toString() {
|
|
return String.format( "(%f, %f, %f) -> (%f, %f, %f)", xmin, ymin, zmin, xmax, ymax, zmax );
|
|
}
|
|
}
|
|
|
|
public MeshingTest2( Collection< Vertex > polys, Collection< EdgePolygon > polygons ) {
|
|
data = polys;
|
|
this.polygons = polygons;
|
|
|
|
f = new JFrame( "Drawing Board" );
|
|
f.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
|
|
|
|
final MouseAdapter adapter = new MouseAdapter() {
|
|
private boolean dragging = false;
|
|
private double initX, initY;
|
|
private int dragX, dragY;
|
|
private double scroll = Math.log( scale );
|
|
|
|
@Override
|
|
public void mousePressed( MouseEvent e ) {
|
|
dragging = true;
|
|
|
|
initX = centerX;
|
|
initY = centerY;
|
|
|
|
dragX = e.getXOnScreen();
|
|
dragY = e.getYOnScreen();
|
|
}
|
|
|
|
@Override
|
|
public void mouseReleased( MouseEvent e ) {
|
|
dragging = false;
|
|
}
|
|
|
|
@Override
|
|
public void mouseDragged( MouseEvent e ) {
|
|
if ( dragging ) {
|
|
centerX = initX + ( ( e.getXOnScreen() - dragX ) / scale );
|
|
centerY = initY + ( ( e.getYOnScreen() - dragY ) / scale );
|
|
|
|
repaint();
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public void mouseWheelMoved( MouseWheelEvent e ) {
|
|
if ( e.getWheelRotation() < 0 ) {
|
|
scroll += e.isControlDown() ? 0.1 : 0.5;
|
|
} else {
|
|
scroll -= e.isControlDown() ? 0.1 : 0.5;
|
|
}
|
|
scale = Math.exp( scroll );
|
|
|
|
repaint();
|
|
}
|
|
|
|
@Override
|
|
public void mouseMoved( MouseEvent e ) {
|
|
super.mouseMoved( e );
|
|
|
|
repaint();
|
|
}
|
|
};
|
|
|
|
addMouseListener( adapter );
|
|
addMouseMotionListener( adapter );
|
|
addMouseWheelListener( adapter );
|
|
|
|
f.addComponentListener( new ComponentAdapter() {
|
|
public void componentResized( ComponentEvent e ) {
|
|
offsetX = getWidth() >> 1;
|
|
offsetY = getHeight() >> 1;
|
|
};
|
|
} );
|
|
|
|
f.add( this );
|
|
|
|
f.setSize( windowWidth, windowHeight );
|
|
f.setVisible( true );
|
|
f.setResizable( true );
|
|
|
|
f.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
|
|
}
|
|
|
|
private static Vector2d rotate( Vector2d a, double angle ) {
|
|
double cos = Math.cos( angle );
|
|
double sin = Math.sin( angle );
|
|
double ax = a.getX() * cos - a.getY() * sin;
|
|
double ay = a.getX() * sin + a.getY() * cos;
|
|
return new Vector2d( ax, ay );
|
|
}
|
|
|
|
@Override
|
|
public void paintComponent( Graphics g ) {
|
|
super.paintComponent( g );
|
|
|
|
g.setColor( new Color( 200, 200, 200 ) );
|
|
g.drawLine( ( int ) ( scale * centerX ) + offsetX, 0, ( int ) ( scale * centerX ) + offsetX, getHeight() );
|
|
g.drawLine( 0, ( int ) ( scale * centerY ) + offsetY, getWidth(), ( int ) ( scale * centerY ) + offsetY );
|
|
g.setColor( Color.BLACK );
|
|
|
|
int highestX = 40;
|
|
if ( data != null ) {
|
|
Collection< Vertex > polygons = data;
|
|
|
|
highestX = ( int ) ( polygons.parallelStream()
|
|
.max( ( a, b ) -> { return Double.compare( a.getPosition().getX(), b.getPosition().getX() ); } ).get().getPosition().getX() + 40.5 );
|
|
|
|
EdgeSet edges = new EdgeSet();
|
|
for ( Vertex vert : polygons ) {
|
|
for ( HalfEdge edge : vert ) {
|
|
if ( edges.add( edge ) ) {
|
|
Point p1 = edge.getOrigin().getPosition();
|
|
Point p2 = edge.getDest().getPosition();
|
|
g.drawLine(
|
|
( int ) ( ( centerX + p1.getX() + highestX ) * scale ) + offsetX,
|
|
( int ) ( ( centerY - p1.getY() ) * scale ) + offsetY,
|
|
( int ) ( ( centerX + p2.getX() + highestX ) * scale ) + offsetX,
|
|
( int ) ( ( centerY - p2.getY() ) * scale ) + offsetY
|
|
);
|
|
}
|
|
}
|
|
|
|
final double diff = scale * 0.15;
|
|
final Point point = vert.getPosition();
|
|
g.setColor( Color.BLACK );
|
|
g.drawRect( ( int ) ( ( centerX + point.getX() + highestX ) * scale ) - ( int ) diff + offsetX, ( int ) ( ( centerY - point.getY() ) * scale ) - ( int ) diff + offsetY, ( int ) ( diff * 2 ), ( int ) ( diff * 2 ) );
|
|
}
|
|
}
|
|
|
|
if ( polygons != null ) {
|
|
g.setColor( Color.BLACK );
|
|
int count = 2;
|
|
Random random = new Random( hashCode() );
|
|
|
|
final int spacing = 25;
|
|
for ( final EdgePolygon p : polygons ) {
|
|
final Collection< HalfEdge > edges = p.getEdges();
|
|
|
|
final Set< Vertex > verts = new HashSet< Vertex >();
|
|
g.setColor( Color.BLACK );
|
|
for ( HalfEdge edge : edges ) {
|
|
Point p1 = edge.getOrigin().getPosition();
|
|
Point p2 = edge.getDest().getPosition();
|
|
g.drawLine(
|
|
( int ) ( ( centerX + p1.getX() + count * spacing ) * scale ) + offsetX,
|
|
( int ) ( ( centerY - p1.getY() - 150 ) * scale ) + offsetY,
|
|
( int ) ( ( centerX + p2.getX() + count * spacing ) * scale ) + offsetX,
|
|
( int ) ( ( centerY - p2.getY() - 150 ) * scale ) + offsetY
|
|
);
|
|
|
|
g.drawLine(
|
|
( int ) ( ( centerX + p1.getX() ) * scale ) + offsetX,
|
|
( int ) ( ( centerY - p1.getY() - 150 ) * scale ) + offsetY,
|
|
( int ) ( ( centerX + p2.getX() ) * scale ) + offsetX,
|
|
( int ) ( ( centerY - p2.getY() - 150 ) * scale ) + offsetY
|
|
);
|
|
|
|
final double diff = scale * 0.15;
|
|
if ( !verts.add( edge.getOrigin() ) ) {
|
|
g.drawRect( ( int ) ( ( centerX + p1.getX() + count * spacing ) * scale ) - ( int ) diff + offsetX, ( int ) ( ( centerY - p1.getY() - 150 ) * scale ) - ( int ) diff + offsetY, ( int ) ( diff * 2 ), ( int ) ( diff * 2 ) );
|
|
}
|
|
}
|
|
count++;
|
|
|
|
int size = edges.size();
|
|
int[] xPoints = new int[ size ];
|
|
int[] yPoints = new int[ size ];
|
|
|
|
final Set< Vertex > verts2 = new HashSet< Vertex >();
|
|
|
|
HalfEdge edge = edges.iterator().next();
|
|
for ( int i = 0; i < edges.size(); ++i ) {
|
|
final Point point = edge.getOrigin().getPosition();
|
|
xPoints[ i ] = ( int ) ( ( centerX + point.getX() ) * scale ) + offsetX;
|
|
yPoints[ i ] = ( int ) ( ( centerY - point.getY() ) * scale ) + offsetY;
|
|
|
|
final double diff = scale * 0.15;
|
|
if ( !verts2.add( edge.getOrigin() ) ) {
|
|
g.setColor( Color.ORANGE );
|
|
} else {
|
|
g.setColor( Color.BLACK );
|
|
}
|
|
g.drawRect( ( int ) ( ( centerX + point.getX() + highestX ) * scale ) - ( int ) diff + offsetX, ( int ) ( ( centerY - point.getY() ) * scale ) - ( int ) diff + offsetY, ( int ) ( diff * 2 ), ( int ) ( diff * 2 ) );
|
|
|
|
edge = edge.getNext();
|
|
}
|
|
|
|
g.setColor( new Color( random.nextInt( 0x1000000 ) ) );
|
|
g.fillPolygon( xPoints, yPoints, size );
|
|
}
|
|
}
|
|
|
|
if ( chains != null ) {
|
|
int i = 0;
|
|
for ( Chain chain : chains ) {
|
|
Point p1 = chain.getOrigin().getPosition();
|
|
Point p2 = chain.getDest().getPosition();
|
|
g.setColor( Color.RED );
|
|
g.drawLine(
|
|
( int ) ( ( centerX + p1.getX() + highestX ) * scale ) + offsetX + i,
|
|
( int ) ( ( centerY - p1.getY() ) * scale ) + offsetY + i,
|
|
( int ) ( ( centerX + p2.getX() + highestX ) * scale ) + offsetX + i,
|
|
( int ) ( ( centerY - p2.getY() ) * scale ) + offsetY + i
|
|
);
|
|
|
|
// for ( HalfEdge e : chain.getLinks() ) {
|
|
// Point e1 = e.getOrigin().getPosition();
|
|
// Point e2 = e.getSym().getOrigin().getPosition();
|
|
// g.setColor( Color.BLUE );
|
|
// g.drawLine(
|
|
// ( int ) ( ( centerX + e1.getX() + 40 ) * scale ) + offsetX + i + 1,
|
|
// ( int ) ( ( centerY - e1.getY() ) * scale ) + offsetY + i + 1,
|
|
// ( int ) ( ( centerX + e2.getX() + 40 ) * scale ) + offsetX + i + 1,
|
|
// ( int ) ( ( centerY - e2.getY() ) * scale ) + offsetY + i + 1
|
|
// );
|
|
// }
|
|
// i += 2;
|
|
}
|
|
}
|
|
|
|
java.awt.Point p = MouseInfo.getPointerInfo().getLocation();
|
|
java.awt.Point componentLocation = getLocation();
|
|
SwingUtilities.convertPointToScreen( componentLocation, this );
|
|
p = new java.awt.Point( p.x - componentLocation.x, p.y - componentLocation.y );
|
|
g.setColor( Color.RED );
|
|
g.setFont( new Font( Font.MONOSPACED, Font.BOLD, 30 ) );
|
|
g.drawString( "X: " + ( ( p.x - offsetX ) / scale - centerX ), 10, 30 );
|
|
g.drawString( "Y: " + ( - ( ( p.y - offsetY ) / scale - centerY ) ), 10, 60 );
|
|
}
|
|
} |