1 import javax.swing.JPanel;
3 import org.jdelaunay.delaunay.ConstrainedMesh;
4 import org.jdelaunay.delaunay.error.DelaunayError;
5 import org.jdelaunay.delaunay.geometries.DEdge;
6 import org.jdelaunay.delaunay.geometries.DPoint;
8 import java.awt.BasicStroke;
10 import java.awt.Graphics;
11 import java.awt.Graphics2D;
12 import java.awt.event.MouseEvent;
13 import java.awt.event.MouseListener;
14 import java.awt.event.MouseMotionListener;
15 import java.awt.geom.Line2D;
16 import java.awt.geom.Rectangle2D;
17 import java.awt.image.BufferedImage;
18 import java.util.ArrayList;
28 private boolean bundlingActive;
29 private int mousePosX, mousePosY;
30 private int radius = 5;
31 private ArrayList<Edge> edges;
32 private ArrayList<Edge> meshEdges;
33 private ArrayList<Node> meshNodes;
34 private ArrayList<Node> nodes;
36 private Node selectedNode;
43 setBackground(Color.WHITE);
45 edges =
new ArrayList<Edge>();
46 meshEdges =
new ArrayList<Edge>();
47 meshNodes =
new ArrayList<Node>();
48 nodes =
new ArrayList<Node>();
49 bundlingActive =
false;
57 addMouseListener(
new MouseListener() {
60 public void mouseReleased(MouseEvent e) {
63 if(selectedNode != null){
64 boolean occupied =
false;
65 for(
Node node : nodes){
66 if(
clickedNode(e, node) && !node.equals(selectedNode)){
72 selectedNode.
setCoords(mousePosX, mousePosY);
76 nodes.add(
new Node(e.getX(), e.getY()));
80 for(
Node node : nodes){
82 if(!node.equals(selectedNode)){
83 edges.add(
new Edge(selectedNode, node));
92 for(
Node node : nodes){
95 ArrayList<Edge> edgesToDelete =
new ArrayList<Edge>();
96 for(
Edge edge : edges){
97 if(edge.isIncident(node))
98 edgesToDelete.add(edge);
100 edges.removeAll(edgesToDelete);
105 for(
Edge edge : edges){
115 if(selectedNode != null){
116 boolean occupied =
false;
117 for(
Node node : meshNodes){
118 if(
clickedNode(e, node) && !node.equals(selectedNode)){
124 selectedNode.
setCoords(mousePosX, mousePosY);
128 meshNodes.add(
new Node(e.getX(), e.getY()));
132 for(
Node node : meshNodes){
134 if(!node.equals(selectedNode)){
135 meshEdges.add(
new Edge(selectedNode, node));
144 for(
Node node : meshNodes){
146 meshNodes.remove(node);
147 ArrayList<Edge> edgesToDelete =
new ArrayList<Edge>();
148 for(
Edge edge : meshEdges){
149 if(edge.isIncident(node))
150 edgesToDelete.add(edge);
152 meshEdges.removeAll(edgesToDelete);
156 for(
Edge edge : meshEdges){
158 meshEdges.remove(edge);
165 paintComponent(getGraphics());
169 public void mousePressed(MouseEvent e) {
172 for(
Node node : nodes){
181 for(
Node node : nodes){
190 for(
Node node : meshNodes){
199 for(
Node node : meshNodes){
209 public void mouseExited(MouseEvent e) {
213 public void mouseEntered(MouseEvent e) {
217 public void mouseClicked(MouseEvent e) {
221 addMouseMotionListener(
new MouseMotionListener() {
224 public void mouseMoved(MouseEvent e) {
229 public void mouseDragged(MouseEvent e) {
230 if(selectedNode != null){
231 mousePosX = e.getX();
232 mousePosY = e.getY();
233 paintComponent(getGraphics());
240 public void paintComponent(Graphics g){
241 super.paintComponent(g);
242 BufferedImage bimg =
new BufferedImage(getSize().width, getSize().width,
243 BufferedImage.TYPE_INT_ARGB);
244 Graphics2D g2d = bimg.createGraphics();
247 g2d.setColor(
new Color(0, 0, 0, 0.10f));
248 g2d.setStroke(
new BasicStroke(3));
249 for(
Edge edge : edges){
251 ArrayList<Node> pathNodes =
new ArrayList<Node>();
252 ArrayList<Node> remainingNodes =
new ArrayList<Node>(edge.getSubNodes());
253 remainingNodes.add(edge.getEndNode());
254 Node currentNode = edge.getStartNode();
255 while(currentNode != edge.getEndNode()){
256 pathNodes.add(currentNode);
258 double minDist = Double.POSITIVE_INFINITY;
259 for(
Node node : remainingNodes){
260 if(currentNode.
distance(node) < minDist){
261 minDist = currentNode.
distance(node);
266 remainingNodes.remove(minNode);
267 currentNode = minNode;
272 pathNodes.add(currentNode);
273 int[] subNodesX =
new int[pathNodes.size()];
274 int[] subNodesY =
new int[pathNodes.size()];
275 for(
int i=0; i<pathNodes.size(); i++){
276 subNodesX[i] = pathNodes.get(i).
getXInt();
277 subNodesY[i] = pathNodes.get(i).getYInt();
279 g2d.drawPolyline(subNodesX, subNodesY, pathNodes.size());
282 g2d.drawLine(edge.getStartNode().getXInt(), edge.getStartNode().getYInt(),
283 edge.getEndNode().getXInt(), edge.getEndNode().getYInt());
286 int[] pixels = bimg.getRGB(0, 0, getSize().width, getSize().height, null, 0, getSize().width);
287 for(
int p=0; p < getSize().width*getSize().height; p++){
288 int alpha = pixels[p]>>24 & 255;
290 pixels[p] = alpha<<24 | alpha<<16 | (255-alpha);
292 bimg.setRGB(0, 0, getSize().width, getSize().height, pixels, 0, getSize().width);
295 g2d.setColor(Color.BLACK);
296 for(
Node node : nodes){
297 if(node.equals(selectedNode)){
299 g2d.fillOval(mousePosX-radius, mousePosY-radius, radius*2, radius*2);
301 g2d.fillOval(node.getXInt()-radius, node.getYInt()-radius, radius*2, radius*2);
302 g2d.drawLine(node.getXInt(), node.getYInt(), mousePosX, mousePosY);
306 g2d.fillOval(node.getXInt()-radius, node.getYInt()-radius, radius*2, radius*2);
311 g2d.setColor(Color.GREEN);
312 for(
Edge edge : meshEdges){
313 g2d.drawLine(edge.getStartNode().getXInt(), edge.getStartNode().getYInt(),
314 edge.getEndNode().getXInt(), edge.getEndNode().getYInt());
316 for(
Node node : meshNodes){
317 if(node.equals(selectedNode)){
319 g2d.fillOval(mousePosX-radius, mousePosY-radius, radius*2, radius*2);
321 g2d.fillOval(node.getXInt()-radius, node.getYInt()-radius, radius*2, radius*2);
322 g2d.drawLine(node.getXInt(), node.getYInt(), mousePosX, mousePosY);
326 g2d.fillOval(node.getXInt()-radius, node.getYInt()-radius, radius*2, radius*2);
329 this.getGraphics().drawImage(bimg, 0, 0, null);
337 public void addEdge(
int startNodeIndex,
int endNodeIndex){
338 edges.add(
new Edge(nodes.get(startNodeIndex), nodes.get(endNodeIndex)));
347 nodes.add(
new Node(x, y));
370 for(
Edge edge : edges)
371 edge.deleteSubNodes();
374 for(
Edge m : meshEdges){
375 ArrayList<Node> sNodes =
new ArrayList<Node>();
376 ArrayList<Edge> sEdges =
new ArrayList<Edge>();
380 Node s = m.intersection(e);
386 if(sNodes.size() > 0){
387 for(
Node n : sNodes){
391 Node control =
new Node(sumX/sNodes.size(), sumY/sNodes.size());
393 e.addSubNode(control);
397 bundlingActive =
true;
398 paintComponent(getGraphics());
409 paintComponent(getGraphics());
418 paintComponent(getGraphics());
426 for(
int i=0; i<nodes.size(); i++)
427 for(
int j=i+1; j<nodes.size(); j++)
428 edges.add(
new Edge(nodes.get(i), nodes.get(j)));
429 paintComponent(getGraphics());
438 int width = getSize().width/dx + 1;
439 int height = getSize().height/dy + 1;
442 if(meshEdges.size() == 0){
445 for(
int x=0; x<width; x++)
446 for(
int y=0; y<height; y++)
450 ArrayList<GridRegion> regions =
createRegions(width, height, cellArray);
455 ConstrainedMesh mesh =
new ConstrainedMesh();
456 for(
Edge e : meshEdges){
458 mesh.addConstraintEdge(e.toDEdge());
459 }
catch (DelaunayError e1) {
460 System.out.println(
"Could not add constraint.");
464 mesh.processDelaunay();
467 ArrayList<DPoint> meshPoints =
new ArrayList<DPoint>();
468 for(DPoint p : mesh.getPoints()){
470 meshNodes.add(
new Node(p));
472 for(DEdge e : mesh.getEdges()){
473 Node startNode = meshNodes.get(meshPoints.indexOf(e.getStartPoint()));
474 Node endNode = meshNodes.get(meshPoints.indexOf(e.getEndPoint()));
475 meshEdges.add(
new Edge(startNode, endNode));
477 }
catch (DelaunayError e1) {
478 System.out.println(
"Could not process Delaunay. Using original constraints instead.");
486 bundlingActive =
false;
487 for(
Edge edge: edges)
488 edge.deleteSubNodes();
489 paintComponent(getGraphics());
510 return (e.getX() >= node.
getX()-radius && e.getX() <= node.
getX()+radius &&
511 e.getY() >= node.
getY()-radius && e.getY() <= node.
getY()+radius);
520 return Math.exp(-Math.pow(x, 2)/2)/Math.sqrt(2*Math.PI);
528 private ArrayList<Double>
kde(ArrayList<Double> angles){
529 ArrayList<Double> density =
new ArrayList<Double>();
530 double h = 1.06*Math.pow(angles.size(), -1/5);
531 for(
int j=0; j<1800; j++){
532 double x = (double)j/10;
534 for(
int i=0; i<angles.size(); i++){
535 double difference = x-angles.get(i);
537 difference = 180 - difference;
538 else if(difference < -90)
539 difference = -180 - difference;
542 density.add(sum/(h*angles.size()));
554 ArrayList<Edge> constraints =
new ArrayList<Edge>();
556 double normalAngle = r.getPrimaryAngle() + 90;
557 if(normalAngle >= 180)
559 Edge normal =
new Edge(r.center(), normalAngle);
560 double nodeX = r.center().getX();
561 double nodeY = r.center().getY();
562 while(r.contains(
new Node(nodeX, nodeY))){
563 nodeX += normal.
dx();
564 nodeY += normal.
dy();
566 Node nStart =
new Node(nodeX, nodeY);
567 nodeX = r.center().getX();
568 nodeY = r.center().getY();
569 while(r.contains(
new Node(nodeX, nodeY))){
570 nodeX -= normal.
dx();
571 nodeY -= normal.
dy();
574 constraints.add(
new Edge(nStart, nEnd));
587 ArrayList<GridRegion> regions =
new ArrayList<GridRegion>();
588 for(
int x=0; x<width; x++){
589 for(
int y=0; y<height; y++){
590 if(cellArray[x][y].getPrimaryAngle() > -1){
591 double minDiff = Double.POSITIVE_INFINITY;
592 int minDiffRegion = -1;
595 if(regionIndex >= 0){
597 - regions.get(regionIndex).getPrimaryAngle();
598 if(Math.abs(diff) > 90)
599 diff = 180-Math.abs(diff);
601 diff = Math.abs(diff);
604 minDiffRegion = regionIndex;
610 if(regionIndex >= 0){
612 - regions.get(regionIndex).getPrimaryAngle();
613 if(Math.abs(diff) > 90)
614 diff = 180-Math.abs(diff);
616 diff = Math.abs(diff);
619 minDiffRegion = regionIndex;
623 if(minDiff <= 10 && minDiffRegion >= 0){
625 regions.get(minDiffRegion).addCell(cellArray[x][y]);
630 region.
addCell(cellArray[x][y]);
650 Rectangle2D bounds = cell.
bounds();
651 ArrayList<Double> angles =
new ArrayList<Double>();
653 if(bounds.intersectsLine(e.getStartNode().getX(), e.getStartNode().getY(),
654 e.getEndNode().getX(), e.getEndNode().getY()))
655 angles.add(e.angleXAxis());
657 if(angles.size() == 0)
661 ArrayList<Double> density =
kde(angles);
663 double maxDensity = 0;
664 for(
int d=0; d<1800; d++){
665 if(density.get(d) > maxDensity){
666 maxDensity = density.get(d);
672 double densitySum = 0;
673 for(
int d=maxIndex-100; d<maxIndex+100; d++){
679 densitySum += density.get(i);