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);