📄 mapchange.java
字号:
import java.awt.*;
import java.awt.event.*;
import java.io.*;
import javax.swing.*;
public class mapChange extends Canvas implements ActionListener {
//声明参数变量
//图形用户界面
Frame f, f2;
ScrollPane sro;
Panel panel;
MenuBar mb;
Menu mf, me, mh, mc;
CheckboxMenuItem cmi;
//文件指针(矢量,栅格写,栅格读)
RandomAccessFile rf, rfs, rfb;
//文件地址
String path;
//矢量数据,arcnum为弧段数,k[i][j]为第i条弧段的第j个数据,x[i][j]为第i条弧段的第j个节点的x坐标,y类似
int arcnum = 0;
int[][] k;
double[][] x, y;
//是否显示栅格图像
boolean sta = false;
//栅格过度数据(二维数组记录栅格中每一像原的属性)
int[][] at;
//最终栅格数据(以宽度为一像素的线记录栅格图像,是对二维数组的压缩)
//lnum为线的数目,stx、sty,endx、endy为始末节点坐标,ln为线的属性)
int lnum = 0;
int[] stx, sty, endx, endy, ln;
//矢量图的显示大小,和栅格的大小(或者叫精度)
double size=1, sgsize=1;
//以颜色区分不同多边形
Color[] col;
boolean again;
//本类的默认构造,生成图形用户界面,并对事件进行监听
public mapChange(){
f = new Frame("地图格式转换");
f.setSize(1000, 900<Toolkit.getDefaultToolkit().getScreenSize().height-30?900:Toolkit.getDefaultToolkit().getScreenSize().height-30);
f.setBackground(Color.lightGray);
f.addWindowListener(new WindowAdapter(){public void windowClosing (WindowEvent e) {
System.exit(0);
}});
setBackground(Color.white);
sro = new ScrollPane();
sro.add(this);
f.add(sro);
mb = new MenuBar();
mf = new Menu("文件");
me = new Menu("编辑");
mh = new Menu("帮助");
f.setMenuBar(mb);
mb.add(mf);
mb.add(me);
mb.add(mh);
mf.add(new MenuItem("打开矢量文件"));
mf.add(new MenuItem("保存栅格文件"));
mf.add(new MenuItem("打开栅格文件"));
mf.addSeparator();
mf.add(new MenuItem("退出"));
me.add(new MenuItem("刷新"));
mc = new Menu("放缩");
mc.add(new MenuItem("默认"));
mc.add(new MenuItem("50%"));
mc.add(new MenuItem("200%"));
mc.addSeparator();
mc.add(new MenuItem("自定义"));
mc.addActionListener(this);
me.add(mc);
me.add(new MenuItem("矢量转栅格"));
me.addSeparator();
cmi = new CheckboxMenuItem("显示矢量图", true);
me.add(cmi);
mh.add(new MenuItem("关于"));
mf.addActionListener(this);
mh.addActionListener(this);
me.addActionListener(this);
f.setVisible(true);
col = new Color[50];
for (int i=1; i<50; i++) {
col[i] =new Color ((i*i)%256, (i*100)%256, (i*20)%256);
}
}
//菜单事件监听
public void actionPerformed(ActionEvent e) {
if (e.getActionCommand()=="打开矢量文件") {
FileDialog fd = new FileDialog(f, "打开矢量文件");
fd.setFile("*.e00");
fd.setVisible(true);
path = fd.getDirectory() + fd.getFile();
sta = false;
try {
rf = new RandomAccessFile (path,"r");
arcnum = readin();
again = true;
repaint();
}
catch (IOException ioe){
System.out.println (ioe);
}
catch (Exception fe) {
System.out.println (fe);
}
}
else if (e.getActionCommand() == "保存栅格文件") {
FileDialog fds = new FileDialog (f, "保存栅格文件", 1);
fds.setFile("*.bin");
fds.setVisible(true);
String spath = fds.getDirectory() + fds.getFile() + ".bin";
try {
rfs = new RandomAccessFile (spath, "rw");
rfs.seek(0);
rfs.writeInt(lnum);
rfs.writeInt((int)(1000*sgsize));
rfs.writeInt((int)(830*sgsize));
for (int i=0; i<lnum; i++) {
rfs.writeInt(stx[i]);
rfs.writeInt(sty[i]);
rfs.writeInt(endx[i]);
rfs.writeInt(endy[i]);
rfs.writeInt(ln[i]);
}
rfs.close();
}
catch (IOException ioe){
System.out.println (ioe);
}
catch (Exception fe) {
System.out.println (fe);
}
}
else if (e.getActionCommand()=="200%") {
size = 2;
again = true;
repaint();
}
else if (e.getActionCommand()=="50%") {
size = 0.5;
again = true;
repaint();
}
else if (e.getActionCommand()=="默认") {
size = 1;
again = true;
repaint();
}
else if (e.getActionCommand()=="自定义") {
ratio();
}
else if (e.getActionCommand()=="打开栅格文件") {
FileDialog fdr = new FileDialog (f, "打开栅格文件");
fdr.setFile("*.bin");
fdr.setVisible(true);
String rpath = fdr.getDirectory()+fdr.getFile();
try {
rfb = new RandomAccessFile (rpath, "r");
rfb.seek(0);
lnum = rfb.readInt();
sgsize = size = rfb.readInt()/1000.0;
rfb.readInt();
stx = new int[lnum];
sty = new int[lnum];
endx = new int[lnum];
endy = new int[lnum];
ln = new int[lnum];
for (int i=0; i<lnum; i++) {
stx[i] = rfb.readInt();
sty[i] = rfb.readInt();
endx[i] = rfb.readInt();
endy[i] = rfb.readInt();
ln[i] = rfb.readInt();
}
rfb.close();
}
catch (IOException ioe){
System.out.println (ioe);
}
catch (Exception fe) {
System.out.println (fe);
}
sta = true;
arcnum = 0;
again = true;
repaint();
}
else if (e.getActionCommand()=="矢量转栅格") {
if (rf == null) {
JOptionPane.showMessageDialog(f, "请先打开矢量文件!", "错误", 2);
}
else {
try {
rf.seek(0);
sta = true;
change();
lnum = reduce();
repaint();
}
catch (IOException ioe){
System.out.println (ioe);
}
catch (Exception fe) {
System.out.println (fe);
}
}
}
else if (e.getActionCommand() == "关于")
f.add(new about());
else if (e.getActionCommand() == "刷新")
repaint();
else if (e.getActionCommand()=="退出") {
if (rf != null) {
try {
rf.close();
}
catch (IOException ioe) {}
}
System.exit(0);
}
}
//读取e00文件数据
public int readin() {
try{rf.seek(0);}
catch(Exception e){}
String linestr = "";
String[] parts;
arcnum = 0;
k = new int[100][7];
x = new double[100][];
y = new double[100][];
int j, n=0;
//寻找数据初始位置
try {
while (! linestr.equals("ARC 2")){
linestr = rf.readLine();
}
}
catch (IOException ioe) {}
catch (Exception e)
{return 0;}
//将文件内容读入内存
try {
while (true) {
j = 0;
linestr = rf.readLine();
parts = linestr.split(" ");
for (int i=0; i<parts.length; i++) {
if (parts[i].length() != 0 )
k[n][j++] = Integer.parseInt(parts[i]);
}
//遇到结束符终止循环
if (k[n][0] == -1)
break;
//为数组开辟内存空间,用到才开,节省内存
x[n] = new double[k[n][6]];
y[n] = new double[k[n][6]];
//读入节点坐标
for (int i=0; i<(int)(k[n][6]/2); i++) {
linestr = rf.readLine();
parts = linestr.split(" ");
x[n][i*2] = Double.parseDouble(parts[1]);
y[n][i*2] = Double.parseDouble(parts[2]);
x[n][i*2+1] = Double.parseDouble(parts[3]);
y[n][i*2+1] = Double.parseDouble(parts[4]);
}
if (k[n][6]%2 == 1) {
linestr = rf.readLine();
parts = linestr.split(" ");
x[n][k[n][6]-1] = Double.parseDouble(parts[1]);
y[n][k[n][6]-1] = Double.parseDouble(parts[2]);
}
n++;
}
}
catch (IOException ioe) {
System.out.println (ioe);
}
catch (Exception e) {
System.out.println (e);
}
//返回弧段总数
return n;
}
//绘图程序,repaint()方法调用
public void paint(Graphics g) {
//设置画布大小
this.setSize((int)(1000*size), (int)(830*size));
//判断栅格文件是否存在,是否要求绘出
if (sta & lnum!=0) {
//1:1比例绘出栅格图像
if (sgsize == size)
for (int i=0; i<lnum; i++) {
if (ln[i] == 0)
g.setColor(Color.WHITE);
else
g.setColor(col[ln[i]]);
g.drawLine(stx[i], sty[i], endx[i], endy[i]);
}
//栅格图像显示比例与原始比例不同时,画线改为以对应比例绘出矩形
else
for (int i=0; i<lnum; i++) {
if (ln[i] == 0)
g.setColor(Color.WHITE);
else
g.setColor(col[ln[i]]);
g.fillRect((int)(stx[i]*size/sgsize), (int)(sty[i]*size/sgsize), (int)((endx[i]-stx[i]+1)*size/sgsize+0.99), (int)(size/sgsize+0.99));
}
}
//判断是否要求绘出矢量图像,是否以读入矢量文件
if (cmi.getState() & arcnum!=0) {
g.setColor(Color.BLACK);
//遍历所有弧段,根据组成弧段的点的坐标安规定比例两点连线
for (int n=0; n<arcnum; n++)
for (int i=1; i<k[n][6]; i++)
g.drawLine((int)((x[n][i-1]/5000-100)*size),(int)((830-y[n][i-1]/5000)*size),(int)((x[n][i]/5000-100)*size),(int)((830-y[n][i]/5000)*size));
}
if (again) {
sro.validate();
again = false;
}
return;
}
//将矢量图像转换为当前比例下的栅格文件(每栅格对应一像素),将结果记入二维数组
//转换使用边界代数法,具体过程见说明文档
public void change() {
at = new int[(int)(1000*size)][(int)(830*size)];
for (int m=0; m<1000*size; m++)
for (int n=0; n<830*size; n++)
at[m][n] = 0;
int s, l;
int[] ix, iy;
double xMax;
sgsize = size;
for (int n=0; n<arcnum; n++) {
ix = new int[k[n][6]];
iy = new int[k[n][6]];
for (int i=0; i<k[n][6]; i++) {
ix[i] = (int)((x[n][i]/5000-100)*sgsize);
iy[i] = (int)((830-y[n][i]/5000)*sgsize);
}
for (int i=1; i<k[n][6]; i++) {
if (iy[i]>iy[i-1]) {
for (s = iy[i-1]; s<iy[i]; s++) {
if (iy[i]-iy[i-1] == 1)
for (l=0; l<=(ix[i-1]+ix[i])/2; l++)
at[l][s] += (k[n][5] - k[n][4]);
else {
xMax = ix[i-1] + 1.0*(ix[i]-ix[i-1])/(iy[i]-iy[i-1])*(s-iy[i-1]);
for (l=0; l<=xMax; l++)
at[l][s] += k[n][5] - k[n][4];
}
}
}
else if (iy[i]<iy[i-1]) {
for (s=iy[i]; s<iy[i-1]; s++) {
if (iy[i-1]-iy[i] == 1)
for (l=0; l<=(ix[i-1]+ix[i])/2; l++)
at[l][s] += (k[n][4] - k[n][5]);
else {
xMax = ix[i] + (ix[i]-ix[i-1])*1.0/(iy[i]-iy[i-1])*(s-iy[i]);
for (l=0; l<=xMax; l++)
at[l][s] += k[n][4] - k[n][5];
}
}
}
}
}
}
//对生成的二维数组的栅格数据进行压缩,以提高绘图和缩放的效率,并且大大减小数据量
//具体压缩方法见说明文档
public int reduce() {
stx = new int[(int)(10000*size)];
sty = new int[(int)(10000*size)];
endx = new int[(int)(10000*size)];
endy = new int[(int)(10000*size)];
ln = new int[(int)(10000*size)];
int i;
int num=0, point;
stx[0] = 0;
sty[0] = 0;
point = 0;
for (int j=0; j<830*size; j++) {
for (i=0; i<1000*size; i++) {
if (num != at[i][j]) {
ln[point] = num;
endx[point] = i-1;
endy[point++] = j;
stx[point] = i;
sty[point] = j;
num = at[i][j];
}
}
endx[point] = i-1;
endy[point] = j;
ln[point++] = num;
stx[point] = 0;
sty[point] = (j+1);
}
return point-1;
}
//自定义图像比例时,接受数据的窗口
public void ratio() {
//生成图形用户界面
Label lab;
JButton but;
final TextField text;
Panel pan;
f2 = new Frame("图像比例");
lab = new Label("%");
text = new TextField("100");
but = new JButton("确定");
but.addActionListener(new ActionListener() {
//按钮事件监听(关闭此窗口,且修改数据,重载paint方法)
public void actionPerformed (ActionEvent evt) {
size = Double.parseDouble(text.getText())/100;
f2.setVisible(false);
again = true;
repaint();
return;
}
});
pan = new Panel();
pan.setBackground(Color.LIGHT_GRAY);
pan.add(text);
pan.add(lab);
pan.add(but);
f2.add(pan);
f2.setSize(200, 100);
f2.setLocation(250, 200);
f2.setVisible(true);
}
//main主函数,程序从这里开始运行
public static void main (String[] args) {
new mapChange();
}
}
//“关于”的窗口,介绍一些软件信息
class about extends JFrame{
JPanel p1, p2;
Label l1, l2, l3;
JLabel l4;
ImageIcon img;
public about() {
p1 = new JPanel();
p2 = new JPanel();
l1 = new Label("地图格式转换");
l2 = new Label("mapChange 版本:v2.31");
l3 = new Label("开发: 刘明超(00612068)");
p1.setLayout(new GridLayout(3,1));
p1.add(l1);
p1.add(l2);
p1.add(l3);
img = new ImageIcon("1.jpg");
l4 = new JLabel(img);
p2 = new JPanel();
p2.add(l4);
p1.setBackground(Color.WHITE);
p2.setBackground(Color.WHITE);
this.setLayout(new GridLayout(1,2));
this.add(p2);
this.add(p1);
this.setTitle("关于 mapChange");
this.setSize(350,200);
this.setLocation(270, 150);
this.setVisible(true);
}
public static void main(String[] args) {
new about();
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -