自己写的点的抽稀(point wedding)算法,类似Douglas-Peuker

自己写的点的抽稀(point wedding)算法

算法思想

类似道格拉斯扑克算法,实现点的抽稀。
将一组二维坐标点,第一步设置预设值,首尾相连,如图,P0连接P6成直线L
在这里插入图片描述
先从后往前计算,P5到L的距离,若距离小于预设值,则去除该点,计算下一个点P4,以此类推;若大于预设值,则P5为L的后端点,并从前端点开始往后计算每个点。

即:首次从后计算每个点到直线距离,小于预设值的点去除,大于预设值的点成为新的端点,并计算顺序改变,直到所有点被遍历过。

已知的算法缺点:效率低(每次都要计算点到直线距离,并再判断,老师说的)

代码实现

这是计算类,用于计算两点之间的距离和三角形的高(传入参数为三边长度,用来得到点到直线距离)

public class calcu {
	//计算两点之间的距离
	public double dist(double x1,double x2,double y1,double y2) {
		double dis=-1;
		double dist=(x2-x1)*(x2-x1)+(y2-y1)*(y2-y1);
		dis=Math.sqrt(dist);
		return dis;
	}
	public double calcuteS(double a,double b,double c) {
		double s =(a+b+c)/2f;       
		double S =  Math.sqrt(s*(s-a)*(s-b)*(s-c));    
		return S;
	}

}

这是读取TXT文档的类,读取数据并分割
数据格式如图
在这里插入图片描述

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;

public class ReadTXT {
	/**
     * 读取文件
     * @param filePath
     * @return
     */
    public static  List  readTxtFile(String filePath) {
        List<String> list = new ArrayList<String>();
        try {
            String encoding = "UTF-8";
            File file = new File(filePath);
            if (file.isFile() && file.exists()) { 
                InputStreamReader read = new InputStreamReader(
                        new FileInputStream(file), encoding);
                BufferedReader bufferedReader = new BufferedReader(read);
                String lineTxt = null;
                while ((lineTxt = bufferedReader.readLine()) != null) {
                    if (!lineTxt.startsWith("#"))
                        list.add(lineTxt);
                }
                read.close();
            } else {
                System.out.println("找不到文件");
            }
        } catch (Exception e) {
            System.out.println("出错了");
            e.printStackTrace();
        }
        return list;
 
    }
    /**
     * 创建二维数组
     * @param list
     * @return
     */
    public static String[][] createArray(String filePath){
        List<String> list = readTxtFile(filePath);
        String array[][] = new String[list.size()][];
        for(int i=0;i<list.size();i++){
            array[i] = new String[2];
            String linetxt=list.get(i);
            String[] myArray = linetxt.replaceAll("\\s+", "@").split("@");
            for(int j=0;j<myArray.length;j++){
                if(j<2){
                    array[i][j]=myArray[j];
                }
            }
        }
        return array;
    }

}

以下为抽稀算法实现

TXT文件目录为:D:\java_workspace\homework2\point.txt

import java.util.Scanner;

import point.ReadTXT;

public class Weending {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		ReadTXT rd=new ReadTXT();
		String array[][] = rd.createArray("D:\\java_workspace\\homework2\\point.txt"); //打开并读取文档
		
		
		// 将文档读取出的数据(String类型)转成double类型,存入二维数组
		double[][] aa=new double[array.length][2];  
		for(int i=0;i<array.length;i++) {
	
			aa[i][0]=Double.parseDouble(array[i][0]);
			aa[i][1]=Double.parseDouble(array[i][1]);
			//System.out.println(aa[i][0]);
		}
		
		//控制台输入预设值
		System.out.println("请输入预设值(小于预设垂线距离的点将会被除掉):");
		Scanner cin=new Scanner(System.in);
		double def;   //预设值 
		
		/*
		 -------------------------------------------------------
		 */

		
		
		def=cin.nextDouble();  //将控制台输入存放入def变量中
		cin.close();   //关闭输入流
		
		
		calcu ca=new calcu(); //创建calcu的对象
		
			int temp=aa.length-2;    
			//temp为从后往前的计算点,temp1位从前往后计算点,为三角形中的位于中间位置的点,
			//另外两个为bg和oe,代表起点和止点,也是三角形上的点。
			int temp1=1;             
			//temp从倒数第二个开始,即aa数组的倒数第二个,aa.length-2;
			//对应的temp从第二个开始(而不是第一个,第一个点为最初的起点bg,为三角形内的另一个点)
			//建立三角形的目的是为了求三角形面积,进而计算顶点即temp(或者temp1)到起止点连线的垂线长度(h)
			int bg=0,oe=aa.length-1;
			
			
			int k=1;
			/*设立k的目的是当某个temp(或者temp1)计算得到的垂线大于预设值def时,则该点会被保留,
			 * 且该点会被重设为终点(或起点),且计算需要从另一个方向开始,这个时候k值加一,从而使循环
			 * 由从后向前变成从前向后(或者从前向后变成从后向前)
			 */

			
	 while (temp>temp1){

				double len=ca.dist(aa[bg][0], aa[oe][0],aa[bg][1], aa[oe][1]);
		
             if (k%2==1) {

			for(int i=0;i < temp;i++) {
				double len1=ca.dist(aa[bg][0], aa[temp][0],aa[bg][1], aa[temp][1]);
				double len2=ca.dist(aa[oe][0], aa[temp][0],aa[oe][1], aa[temp][1]);
				double s=ca.calcuteS(len, len1, len2);
				double h=s/len;
				if (len1==0|len2==0) {
					break;
				}
				if (h>def) {
					oe=temp;
					i=aa.length;
					k++;
					temp=oe-1;
				}else {
					temp=temp-1;
					
					if (temp<=bg) {
						  
						break;
					}
					aa[temp+1][0]=0;
					aa[temp+1][1]=0;			
				}		
		       }
             }else {	
		    	   for (int j = 0; j < oe-bg; j++) {
						double len1=ca.dist(aa[bg][0], aa[temp1][0],aa[bg][1], aa[temp1][1]);
						double len2=ca.dist(aa[oe][0], aa[temp1][0],aa[oe][1], aa[temp1][1]);
						double s=ca.calcuteS(len, len1, len2);
						double h=s/len;
						if (h>def) {
							bg=temp1;
							j=aa.length;
							k++;
							temp1=bg+1;
						}else {
							
							temp1=temp1+1;

							if (temp1>=oe) {
								break;
							}
							aa[temp1-1][0]=0;
							aa[temp1-1][1]=0;				
				}	    	   
			}
             }
          
			}	
			int num=1;
			
			for (int i = 1; i < aa.length; i++) {
				if ((aa[i][0]==0) & (aa[i][1]==0)) {
					
				}else {
					num=num+1;
				}
			}
			//System.out.println(num);
			double[][] aaa=new double[num][2];
		
			aaa[0][0]=aa[0][0];
			aaa[0][1]=aa[0][1];
			aaa[num-1][0]=aa[aa.length-1][0];
			aaa[num-1][1]=aa[aa.length-1][1];
		
			
			int index=1;
			for (int i = 1; i <aa.length; i++) {
				if (aa[i][0]!=0&aa[i][1]!=0) {
					aaa[index][0]=aa[i][0];
					aaa[index][1]=aa[i][1];
					index++;
				}
			}
			System.out.println("除草前的点为:");
			for (int i = 0; i < array.length; i++) {
				System.out.println(array[i][0]+","+array[i][1]);
			}
			System.out.println("除草后的点为:");
			for (int i = 0; i < aaa.length; i++) {
				System.out.println(aaa[i][0]+","+aaa[i][1]);
			}
		


	
	}
}

控制台输入预设值,将会对TXT内坐标点进行抽稀在这里插入图片描述

其中有一步,将数组内需要去除的点,先设为(0,0),之后存储到另一个数组时去掉(0,0)的点,这样就会有一个问题,如果一个点本身就是(0,0)那么它也会被去除,水平有限,没有想到能解决的办法。
我知道,我代码又臭又长… 没办法,初学java,什么都还不会,能成功运行已是不易。望各位轻喷。

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值