设为首页 | 加入收藏
首 页
|平台简介|通知公告|行业信息|人才服务|专家库|知识产权|展会交流|项目库
会员登录 用户名: 密码: 忘记密码?
 
 
当前位置:首 页 >>  信息内容页
求凸包Swing演示程序
  发布时间:2012年12月6日  来源:javw学习室  作者:admin  阅读人次:3643

  求凸包java演示程序:

  import java.awt.*;

  import java.awt.event.*;

  import javax.swing.*;

  import javax.swing.event.*;

  import javax.swing.border.*;

  import java.util.*;

  /*

  * 直线类

  */

  class Line {

  Point p1, p2;

  Line(Point p1, Point p2) {

  this.p1 = p1;

  this.p2 = p2;

  }

  void draw(Graphics g) {

  g.drawLine(p1.x, p1.y, p2.x, p2.y);

  }

  public String toString() {

  return "(" + p1.x + ", " + p1.y + ") -> (" + p2.x + ", " + p2.y + ")";

  }

  }

  /*

  * 凸包接口

  */

  interface TuBao {

  void setPointList(java.util.List< Point> pts);

  java.util.List< Line> eval();

  }

  /*

  * 暴力法求凸包

  */

  class BaoLiTuBao implements TuBao {

  java.util.List< Point> pts = null;

  java.util.List< Line> lines = new ArrayList< Line>();

  public void setPointList(java.util.List< Point> pts) {

  this.pts = pts;

  }

  public java.util.List< Line> eval() {

  lines.clear();

  if (pts == null) { return lines; }

  int n = pts.size();

  int a, b, c, cc, l, r;

  for (int i = 0; i < n; i++) {

  for (int j = i+1; j < n; j++) {

  a = pts.get(j).y - pts.get(i).y;

  b = pts.get(i).x - pts.get(j).x;

  c = pts.get(i).x * pts.get(j).y -pts.get(i).y * pts.get(j).x;

  l = r = 0;

  int k;

  for (k = 0; k < n; k++) {

  cc = a * pts.get(k).x + b * pts.get(k).y;

  if (cc > c) l++;

  else if (cc < c) r++;

  if (l * r != 0) break;

  }

  if (k == n) {

  lines.add(new Line(pts.get(i), pts.get(j)));

  }

  }

  }

  return lines;

  }

  }

  /*

  * 分治法求凸包

  */

  class QuickTuBao implements TuBao {

  java.util.List< Point> pts = null;

  java.util.List< Line> lines = new ArrayList< Line>();

  public void setPointList(java.util.List< Point> pts) {

  this.pts = pts;

  }

  //求凸包,结果存入lines中

  public java.util.List< Line> eval() {

  lines.clear();

  if (pts == null || pts.isEmpty()) { return lines; }

  java.util.List< Point> ptsLeft = new ArrayList< Point>();

  java.util.List< Point> ptsRight = new ArrayList< Point>();

  //按x坐标对pts排序

  Collections.sort(pts, new Comparator< Point>() {

  public int compare(Point p1, Point p2) {

  return p1.x-p2.x;

  }

  });

  Point p1 = pts.get(0); //最左边的点

  Point p2 = pts.get(pts.size()-1); //最右边的点

  Point p3 = null;

  int area = 0;

  for (int i = 1; i < pts.size(); i++) {

  p3 = pts.get(i);

  area = getArea(p1, p2, p3);

  if (area > 0) {

  ptsLeft.add(p3);

  } else if (area < 0) {

  ptsRight.add(p3);

  }

  }

  d(p1, p2, ptsLeft);

  d(p2, p1, ptsRight);

  return lines;

  }

  private void d(Point p1, Point p2, java.util.List< Point> s) {

  //s集合为空

  if (s.isEmpty()) {

  lines.add(new Line(p1, p2));

  return;

  }

  //s集合不为空,寻找Pmax

  int area = 0;

  int maxArea = 0;

  Point pMax = null;

  for (int i = 0; i < s.size(); i++) {

  area = getArea(p1, p2, s.get(i));

  if (area > maxArea) {

  pMax = s.get(i);

  maxArea = area;

  }

  }

  //找出位于(p1, pMax)直线左边的点集s1

  //找出位于(pMax, p2)直线左边的点集s2

  java.util.List< Point> s1 = new ArrayList< Point>();

  java.util.List< Point> s2 = new ArrayList< Point>();

  Point p3 = null;

  for (int i = 0; i < s.size(); i++) {

  p3 = s.get(i);

  if (getArea(p1, pMax, p3) > 0) {

  s1.add(p3);

  } else if (getArea(pMax, p2, p3) > 0) {

  s2.add(p3);

  }

  }

  //递归

  d(p1, pMax, s1);

  d(pMax, p2, s2);

  }

  // 三角形的面积等于返回值绝对值的二分之一

  // 当且仅当点p3位于直线(p1, p2)左侧时,表达式的符号为正

  private int getArea(Point p1, Point p2, Point p3) {

  return p1.x * p2.y + p3.x * p1.y + p2.x * p3.y -

  p3.x * p2.y - p2.x * p1.y - p1.x * p3.y;

  }

  }

  /*

  * 绘制点及凸包的面板

  */

  class DrawPanel extends JPanel {

  public static final int WIDTH = 640;

  public static final int HEIGHT = 480;

  public static final int BORDER = 100;

  java.util.List< Point> pts = new ArrayList< Point>();

  TuBao tuBao = null;

  int n;

  public DrawPanel() {

  setPreferredSize(new Dimension(WIDTH, HEIGHT));

  setBorder(new LineBorder(Color.RED));

  n = 100;

  }

  public void setN(int n) { this.n = n; }

  public void setTuBao(TuBao tuBao) {

  this.tuBao = tuBao;

  tuBao.setPointList(pts);

  }

  public void randPoints() {

  pts.clear();

  Random rd = new Random(new Date().getTime());

  for (int i = 0; i < n; i++) {

  pts.add(new Point(rd.nextInt(WIDTH-BORDER*2)+BORDER,

  rd.nextInt(HEIGHT-BORDER*2)+BORDER));

  }

  }

  public void paintComponent(Graphics g) {

  super.paintComponent(g);

  Color c = g.getColor();

  g.setColor(Color.red);

  for (Point pt : pts) {

  g.fillOval(pt.x, pt.y, 5, 5);

  }

  g.setColor(c);

  if (tuBao == null) return;

  for (Line line : tuBao.eval()) {

  line.draw(g);

  }

  tuBao = null;

  }

  }

  /*

  * 主窗体

  */

  public class GetTuBao extends JFrame {

  DrawPanel drawPanel;

  JSlider sd;

  JLabel lb;

  TuBao baoLiTuBao = new BaoLiTuBao();

  TuBao quickTuBao = new QuickTuBao();

  public GetTuBao() {

  setTitle("凸包问题演示");

  JPanel menu = new JPanel();

  menu.setLayout(new FlowLayout(FlowLayout.LEFT));

  sd = new JSlider(JSlider.HORIZONTAL, 0, 100, 100);

  sd.setMajorTickSpacing(20);

  sd.setMinorTickSpacing(10);

  sd.setPaintTicks(true);

  lb = new JLabel("100");

  JButton btnRand = new JButton("随机点");

  JButton btnBaoLi = new JButton("暴力法");

  JButton btnQuick = new JButton("快包法");

  menu.add(sd);

  menu.add(lb);

  menu.add(btnRand);

  menu.add(btnBaoLi);

  menu.add(btnQuick);

  drawPanel = new DrawPanel();

  add(BorderLayout.NORTH, menu);

  add(BorderLayout.CENTER, drawPanel);

  pack();

  setResizable(false);

  sd.addChangeListener(new ChangeListener() {

  public void stateChanged(ChangeEvent e) {

  lb.setText(String.valueOf(sd.getValue()));

  drawPanel.setN(sd.getValue());

  }

  });

  btnRand.addActionListener(new ActionListener() {

  public void actionPerformed(ActionEvent e) {

  drawPanel.randPoints();

  repaint();

  }

  });

  btnBaoLi.addActionListener(new ActionListener() {

  public void actionPerformed(ActionEvent e) {

  drawPanel.setTuBao(baoLiTuBao);

  repaint();

  }

  });

  btnQuick.addActionListener(new ActionListener() {

  public void actionPerformed(ActionEvent e) {

  drawPanel.setTuBao(quickTuBao);

  repaint();

  }

  });

  setVisible(true);

  }

  public static void main(String[] args) {

  try {

  UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");

  } catch(Exception e) {

  e.printStackTrace();

  }

  EventQueue.invokeLater(new Runnable() {

  public void run() {

  GetTuBao getTuBao = new GetTuBao();

  }

  });

  }

  }

打印本页 | 关闭窗口
版权所有 2010-2013 贵州省信息技术服务业协会
协会地址:贵州省贵阳市花溪大道北段14号6楼
联系电话:0851-6829448  黔ICP备10201172号-3
技术支持:贵州博虹科技有限公司 电话:0851-5706777