Package org.osm2world.core.map_elevation.creation

Source Code of org.osm2world.core.map_elevation.creation.NNDebugViewer$DebugViewerFrame

package org.osm2world.core.map_elevation.creation;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import java.util.Random;

import javax.swing.AbstractAction;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.KeyStroke;

import org.osm2world.core.map_elevation.creation.DelaunayTriangulation.DelaunayTriangle;
import org.osm2world.core.map_elevation.creation.DelaunayTriangulation.NaturalNeighbors;
import org.osm2world.core.math.AxisAlignedBoundingBoxXZ;
import org.osm2world.core.math.LineSegmentXZ;
import org.osm2world.core.math.PolygonXZ;
import org.osm2world.core.math.TriangleXZ;
import org.osm2world.core.math.VectorXYZ;
import org.osm2world.core.math.VectorXZ;


public class NNDebugViewer {

  public static void main(String[] args) {
    new DebugViewerFrame().setVisible(true);
  }
 
  private static final double SIZE = 100;
 
  private static class NNDebugPanel extends JPanel {
   
    private List<VectorXYZ> points;
    private DelaunayTriangulation triangulation;
   
    //TODO change to AxisAlignedBbox
    private double minX, maxX, minZ, maxZ;
   
    private VectorXZ probePos = null;
   
    public NNDebugPanel() {
      clear();
     
      this.addMouseListener(new MouseAdapter() {
        @Override
        public void mouseClicked(MouseEvent e) {
                   
          VectorXZ point = inverseCoord(e.getX(), e.getY());
         
          if (e.getButton() == MouseEvent.BUTTON1) {
            probePos = point;
          } else {
            add(point.xyz(0));
          }
         
          NNDebugPanel.this.repaint(0);
         
        }
      });
     
    }
   
    public void clear() {
     
      probePos = null;
     
      minX = minZ = -SIZE;
      maxX = maxZ = +SIZE;
     
      points = new ArrayList<VectorXYZ>();
      triangulation = null;
           
      this.repaint(0);
     
    }
   
    public void add(VectorXYZ p) {
     
      probePos = null;
     
      points.add(p);
      updateMinMax(p);
     
      this.repaint(0);
     
      if (triangulation == null) {
       
        triangulation = new DelaunayTriangulation(
            new AxisAlignedBoundingBoxXZ(-SIZE, -SIZE, SIZE, SIZE));
       
      }
     
      triangulation.insert(p);
           
      this.repaint(0);

    }

    private void updateMinMax(VectorXYZ v) {
      if (v.x < minX) minX = v.x;
      if (v.x > maxX) maxX = v.x;
      if (v.z < minZ) minZ = v.z;
      if (v.z > maxZ) maxZ = v.z;
    }
   
    @Override
    public void paint(Graphics g) {
     
      super.paint(g);
     
      if (triangulation == null) return;
     
      /* draw Voronoi cells */
     
      Random colorRandom = new Random(0);
     
      for (VectorXYZ p : points) {
       
        g.setColor(new Color(
            0.5f + colorRandom.nextFloat() / 2,
            0.5f + colorRandom.nextFloat() / 2,
            0.5f + colorRandom.nextFloat() / 2));
       
        for (TriangleXZ t : triangulation.getVoronoiCellSectors(p)) {
          fill(g, t);
        }
       
      }
     
      /* draw circumcircles around most recently added point */
           
      if (!points.isEmpty()) {
     
        VectorXYZ p = points.get(points.size() - 1);
             
        g.setColor(Color.GREEN);
       
        for (DelaunayTriangle t : triangulation.getIncidentTriangles(p)) {
 
          VectorXZ center = t.getCircumcircleCenter();
          double radius = t.p0.distanceToXZ(center);
       
          draw(g, center);
          drawCircle(g, center, radius);
                   
        }
       
      }
             
      /* draw triangles */
     
      g.setColor(Color.RED);
     
      for (DelaunayTriangle triangle : triangulation.getTriangles()) {
        draw(g, triangle.asTriangleXZ());
      }
           
      /* draw points */
     
      g.setColor(Color.BLACK);
     
      for (VectorXYZ p : points) {
        draw(g, p.xz());
      }
     
      /* draw click data */
     
      if (probePos != null) {
       
        draw(g, probePos);
               
        NaturalNeighbors nn = triangulation.probe(probePos);
       
        for (int i = 0; i < nn.neighbors.length; i++) {
         
          VectorXZ neighbor = nn.neighbors[i].xz();
          double relativeWeight = nn.relativeWeights[i];
         
          drawLine(g, probePos, neighbor);
         
          g.drawString(String.format(Locale.US, "%.3f", relativeWeight),
              coordX(neighbor), coordY(neighbor));
         
        }
       
      }
     
    }
     
    private void draw(Graphics g, VectorXZ p) {
      drawPoint(g, p);
    }
   
    private void draw(Graphics g, TriangleXZ t) {
      g.drawPolygon(
          new int[] {coordX(t.v1), coordX(t.v2), coordX(t.v3)},
          new int[] {coordY(t.v1), coordY(t.v2), coordY(t.v3)},
          3);
    }
   
  private void fill(Graphics g, TriangleXZ t) {
    g.fillPolygon(
        new int[] {coordX(t.v1), coordX(t.v2), coordX(t.v3)},
        new int[] {coordY(t.v1), coordY(t.v2), coordY(t.v3)},
        3);
  }
   
    private void draw(Graphics g, PolygonXZ p) {

      for (VectorXZ vertex : p.getVertices()) {
        drawPoint(g, vertex);
      }
     
      for (LineSegmentXZ segment : p.getSegments()) {
        drawLine(g, segment.p1, segment.p2);
      }
     
    }
   
    private void drawPoint(Graphics g, VectorXZ p) {
      int x = coordX(p), y = coordY(p);
      g.fillPolygon(
          new int[] {x-3, x  , x+3, x  },
          new int[] {  y, y+3, y  , y-3},
          4);
    }
   
    private void drawLine(Graphics g, VectorXZ p1, VectorXZ p2) {
      g.drawLine(
          coordX(p1), coordY(p1),
          coordX(p2), coordY(p2));
    }

    private void drawCircle(Graphics g, VectorXZ center, double radius) {
     
      VectorXZ bottomLeft = center.add(new VectorXZ(-radius, radius));
      VectorXZ topRight = center.add(new VectorXZ(radius, -radius));
           
      g.drawOval(
          coordX(bottomLeft), coordY(bottomLeft),
          coordX(topRight) - coordX(bottomLeft),
          coordY(topRight) - coordY(bottomLeft));
     
    }
   
    private void drawArrow(Graphics g, VectorXZ p1, VectorXZ p2) {
     
      drawLine(g, p1, p2);
           
      VectorXZ arrowVector = p2.subtract(p1);
      VectorXZ arrowDir = arrowVector.normalize();
      double headSize = (maxX - minX) / 25;
           
      VectorXZ headBase = p2.subtract(arrowDir.mult(headSize));
      VectorXZ headRight = headBase.add(arrowDir.rightNormal().mult(0.5*headSize));
      VectorXZ headLeft = headBase.subtract(arrowDir.rightNormal().mult(0.5*headSize));
     
      drawLine(g, headRight, p2);
      drawLine(g, headLeft, p2);
     
    }
   
    private int coordX(VectorXZ v) {
      return (int)((this.getWidth()*0.05) + (v.x - minX) / (maxX - minX) * (this.getWidth()*0.9));
    }
   
    private int coordY(VectorXZ v) {
      return (int)((this.getHeight()*0.95) - (v.z - minZ) / (maxZ - minZ) * (this.getHeight()*0.9));
    }
   
    private VectorXZ inverseCoord(int x, int y) {
     
      double relX = ( x - coordX(new VectorXZ(minX, maxZ)) ) / (this.getWidth() * 0.9);
      double relZ = ( y - coordY(new VectorXZ(minX, maxZ)) ) / (this.getHeight() * 0.9);
     
      double totalX = maxX - minX;
      double totalZ = maxZ - minZ;
     
      return new VectorXZ(
          minX + relX * totalX,
          maxZ - relZ * totalZ);
     
    }
   
  }

  private static class DebugViewerFrame extends JFrame {
   
    public DebugViewerFrame() {
      super("Visual Geometry Debugger");
      this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
     
      this.setSize(800, 600);
           
      this.setLayout(new BorderLayout());
      NNDebugPanel panel = new NNDebugPanel();
      this.add(panel, BorderLayout.CENTER);
     
      JMenuBar menuBar = new JMenuBar();
           
      {
        JMenu addMenu = new JMenu("add");
        addMenu.setMnemonic(KeyEvent.VK_A);
       
        addMenu.add(new AddRandomPointAction(panel));
       
        menuBar.add(addMenu);
      }
     
      menuBar.add(new JMenuItem(new ClearAction(panel)));
   
      this.setJMenuBar(menuBar);
     
    }
   
  }
 
  private static final class ClearAction extends AbstractAction {

    private final NNDebugPanel panel;
   
    public ClearAction(NNDebugPanel panel) {
      super("clear");
      putValue(ACCELERATOR_KEY, KeyStroke.getKeyStroke(
          KeyEvent.VK_C, ActionEvent.CTRL_MASK));
      this.panel = panel;
    }
   
    @Override
    public void actionPerformed(ActionEvent e) {
      panel.clear();
    }
   
  }

  private static final class AddRandomPointAction extends AbstractAction {
   
    private final NNDebugPanel panel;
   
    private static Random random = new Random();
   
    public AddRandomPointAction(NNDebugPanel panel) {
      super("random point");
      putValue(ACCELERATOR_KEY, KeyStroke.getKeyStroke(
          KeyEvent.VK_R, ActionEvent.CTRL_MASK));
      this.panel = panel;
    }
   
    @Override
    public void actionPerformed(ActionEvent e) {
     
      if (panel.points.isEmpty()) {
        random = new Random(1);
      }
     
      double x = (random.nextDouble() * 2 * SIZE) - SIZE;
      double z = (random.nextDouble() * 2 * SIZE) - SIZE;
     
      panel.add(new VectorXYZ(x, 0, z));
     
    }
   
  }
 
  private static class Line {
    public final VectorXZ from;
    public final VectorXZ to;
    public Line(VectorXZ from, VectorXZ to) {
      this.from = from;
      this.to = to;
    }
  }
 
  private static class Arrow extends Line {
    public Arrow(VectorXZ from, VectorXZ to) {
      super(from, to);
    }
  }
   
}
TOP

Related Classes of org.osm2world.core.map_elevation.creation.NNDebugViewer$DebugViewerFrame

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.