package de.tutorials;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Polygon;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionAdapter;
import java.awt.geom.Area;
import java.awt.geom.Line2D;
import java.awt.geom.PathIterator;
import java.awt.geom.Point2D;
import java.awt.image.BufferStrategy;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import javax.swing.JFrame;
public class PolygonIntersectionExample extends JFrame {
private BufferStrategy bufferStrategy;
private Area landscapeArea;
private Area intersectionArea;
private Polygon player;
private volatile Point playerPosition;
private List<Point2D> currentIntersectionPoints;
private Runnable processingLoop = new Runnable() {
public void run() {
landscapeArea = generateArea();
player = generatePoly(100, 100, 60, 6);
playerPosition = getLocation();
while (true) {
Graphics2D g = (Graphics2D) bufferStrategy.getDrawGraphics();
updateState();
drawScene(g);
g.dispose();
bufferStrategy.show();
try {
TimeUnit.MILLISECONDS.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
};
private void drawScene(Graphics2D g) {
g.clearRect(0, 0, getWidth(), getHeight());
g.setColor(Color.RED);
g.draw(landscapeArea);
g.setColor(Color.GREEN);
g.draw(player);
g.setColor(Color.BLUE);
g.draw(intersectionArea);
g.setColor(Color.YELLOW);
int r = 5;
for (Point2D point : currentIntersectionPoints) {
int x = (int) (point.getX() - r / 2.0);
int y = (int) (point.getY() - r / 2.0);
g.fillOval(x, y, r, r);
}
}
protected Area generateArea() {
Polygon[] polygons = generatePolygons(10, 512, 512, 200, 6, 13);
Area areaUnion = null;
for (Polygon p : polygons) {
Area area = new Area(p);
if (areaUnion == null) {
areaUnion = area;
} else {
areaUnion.add(area);
}
}
return areaUnion;
}
private void updateState() {
updatePlayerPosition();
computeIntersectionArea();
List<Line2D> intersectionLines = computeIntersectionLines();
computeIntersectionPoints(intersectionLines);
}
private void updatePlayerPosition() {
int x = player.xpoints[0];
int y = player.ypoints[0];
player.translate(playerPosition.x - x, playerPosition.y - y);
}
private void computeIntersectionArea() {
intersectionArea = new Area();
intersectionArea.add(landscapeArea);
intersectionArea.intersect(new Area(player));
}
private void computeIntersectionPoints(List<Line2D> intersectionLines) {
// // Schnittpunkte der Geraden ermitteln
currentIntersectionPoints = new ArrayList<Point2D>();
for (int i = 0, len = intersectionLines.size(); i < len; i++) {
for (int j = i + 1; j < len; j++) {
Line2D firstLine = intersectionLines.get(i);
Line2D secondLine = intersectionLines.get(j);
Point2D.Double point = computeIntersectionPoint(firstLine,
secondLine);
if (point != null) {
// Auskommentieren, falls Punkte innerhalb der Area auch
// berücksichtigt werden sollen
if (landscapeArea.contains(point)) {
continue;
}
currentIntersectionPoints.add(point);
// System.out.printf("Found intersection at: %s%n", point);
}
}
}
}
private List<Line2D> computeIntersectionLines() {
List<Line2D> intersectionLines = new ArrayList<Line2D>();
PathIterator pathItr = intersectionArea.getPathIterator(null);
double[] current = new double[2];
double[] first = null;
double[] previous = null;
while (!pathItr.isDone()) {
int coordType = pathItr.currentSegment(current);
// System.out.println(coordType + " -> " +
// Arrays.toString(current));
if (previous != null) {
intersectionLines.add(new Line2D.Double(current[0], current[1],
previous[0], previous[1]));
} else { // this is the first iteration
first = current.clone();
}
if (coordType == PathIterator.SEG_CLOSE) { // this is the last
// iteration
intersectionLines.add(new Line2D.Double(current[0], current[1],
first[0], first[1]));
}
previous = current.clone();
pathItr.next();
}
return intersectionLines;
}
public PolygonIntersectionExample() {
super("PolygonIntersectionExample");
setDefaultCloseOperation(EXIT_ON_CLOSE);
this.setPreferredSize(new Dimension(800, 600));
setupMouseListener();
setVisible(true);
createBufferStrategy(2);
this.bufferStrategy = getBufferStrategy();
pack();
startRenderLoop();
}
private void setupMouseListener() {
addMouseMotionListener(new MouseMotionAdapter() {
@Override
public void mouseMoved(MouseEvent e) {
playerPosition = e.getPoint();
}
});
}
private void startRenderLoop() {
Executors.newSingleThreadExecutor().execute(processingLoop);
}
public static void main(String[] args) throws Exception {
new PolygonIntersectionExample();
}
private static Polygon[] generatePolygons(int count, int x, int y,
int radius, int points, int seed) {
Polygon[] ps = new Polygon[count];
Random rnd = seed == 0 ? new Random() : new Random(seed);
for (int i = 0; i < count; i++) {
ps[i] = generatePoly(rnd.nextInt(x), rnd.nextInt(y),
(int) (radius * rnd.nextDouble()), points);
}
return ps;
}
public static Polygon generatePoly(int x, int y, int r, int n) {
// Quelle:
// http://www.informatik.htw-dresden.de/~iwe/grundlagen/java/galileo/java_140006.htm#Rxxjava_140006282NEckezeichnen
Polygon p = new Polygon();
for (int i = 0; i < n; i++) {
p.addPoint((int) (x + r * Math.cos(i * 2 * Math.PI / n)),
(int) (y + r * Math.sin(i * 2 * Math.PI / n)));
}
return p;
}
private static Point2D.Double computeIntersectionPoint(Line2D firstLine,
Line2D secondLine) {
float firstX1 = (float) firstLine.getX1();
float firstX2 = (float) firstLine.getX2();
float firstY1 = (float) firstLine.getY1();
float firstY2 = (float) firstLine.getY2();
float secondX1 = (float) secondLine.getX1();
float secondX2 = (float) secondLine.getX2();
float secondY1 = (float) secondLine.getY1();
float secondY2 = (float) secondLine.getY2();
float den = ((firstX2 - firstX1) * (secondY2 - secondY1))
- ((firstY2 - firstY1) * (secondX2 - secondX1));
// firstLine & secondLine are parallel -> no interception
if (den == 0) {
return null;
}
float n1 = ((firstY1 - secondY1) * (secondX2 - secondX1))
- ((firstX1 - secondX1) * (secondY2 - secondY1));
float r = n1 / den;
// -> no interception
if (r < 0 || r > 1) {
return null;
}
float n2 = ((firstY1 - secondY1) * (firstX2 - firstX1))
- ((firstX1 - secondX1) * (firstY2 - firstY1));
float s = n2 / den;
// -> no interception
if (s < 0 || s > 1) {
return null;
}
float interX = firstX1 + (r * (firstX2 - firstX1));
float interY = firstY1 + (r * (firstY2 - firstY1));
return new Point2D.Double(interX, interY);
}
}