1500字范文,内容丰富有趣,写作好帮手!
1500字范文 > GIS算法基础(五)矢量数据向栅格数据的转换(点 线算法实现)

GIS算法基础(五)矢量数据向栅格数据的转换(点 线算法实现)

时间:2022-02-05 06:07:00

相关推荐

GIS算法基础(五)矢量数据向栅格数据的转换(点 线算法实现)

矢量结构数据与栅格结构数据的相互转换,是地理信息系统的基本功能之一,已发展形成了许多高效的转换算法。

源码已经放在github上了,需要朋友自取。

/XiaoZhong233/GIS_ALG

目录

一、矢量点的栅格化

二、矢量线的栅格化

①八方向栅格化

算法思想:

算法实现:

测试:

②全路径栅格化

算法思想

算法实现:

测试结果:

一、矢量点的栅格化

矢量点的栅格化: 实质是将点的坐标x、y换算为栅格行、列号。

注意:栅格的坐标原点是从左上角开始的,行数I向下递增,列数J向左递增

(X0,Y0)代表栅格的原点,dx,dy代表分别代表栅格的长和宽,也就是大小

实际代码中,这个x0,yo因为已知了栅格大小,所以可以求的出来。

在矢量数据向栅格数据转换的过程中,栅格数据可以用二维数组来表达。

/*** * @param point带转化的矢量点* @param xOffset 起始栅格点的x位移量* @param yOffset起始栅格点的y位移量* @return 0-行 1-列*/public int[] transformRasterPoint(Point point,double xOffset,double yOffset) {double x0=size+xOffset+this.xOffset;//栅格起始点坐标double y0=ROW+yOffset+this.yOffset;int[] rowAndColumn = new int[2];//像元大小默认为1rowAndColumn[0] = (int) (1+ (Math.floor(Math.abs((y0-point.getY())/size))));rowAndColumn[1] = (int)(1+(Math.floor(Math.abs((point.getX()-x0))/size)));return rowAndColumn;}

测试结果:

输入:

Raster raster = new Raster(30,30); //创建一个30x30的栅格Point p = new Point(.5, .5); System.out.println(p);int[] a = raster.transformRasterPoint(p, 0, 0);System.out.println(String.format("I=%d,J=%d", a[0],a[1]));

输出:

(0.500000,0.500000)I=30,J=1

二、矢量线的栅格化

①八方向栅格化

八方向栅格法很容易理解,就是已知直线的倾角情况,在每行或每列只有一个像元被涂黑。

算法思想:

一条线段有两个端点:P1(x1,y1)、P2(x2,y2),先分别确定其行列号(I1,J1)及(I2,J2),然后求出这两个端点位置的行数差和列数差。若行数差大于列数差,则逐行求出本行中心线与过这两个端点的直线的交点(X,Y),得到交点行、列号,将交点“涂黑”:Y=yi行中心线,X=(yi-y1)k+x1;式中k=(x2-x1)/(y2-y1),这个公式不看也罢,其实就是两直线求交点的方程若行数差小于或等于列数差,则逐列求出本列中心线与过这两个端点的直线的交点(X,Y),得到交点行、列号,将交点“涂黑” :X=xi行中心线,Y=(xj-x1)k’+y1;式中k’=(y2-y1) /(x2-x1)

算法实现:

public void RasterLine(Point start,Point end,int type,double xOffset,double yOffset) {//开始点与结束点的起始坐标int[] startPoint = transformRasterPoint(start, 0, 0);int[] endPoint = transformRasterPoint(end, 0, 0);//System.out.println(String.format("开始点:(%d,%d)", startPoint[0],startPoint[1]));System.out.println(String.format("结束点:(%d,%d)", endPoint[0],endPoint[1]));//涂黑,开始点与终止点(值设为1)setValue(startPoint[0], startPoint[1]);setValue(endPoint[0], endPoint[1]);Line line = new Line(start, end);//如果是垂直或者水平者直接涂黑if(line.isHorizontal() || Double.doubleToLongBits(start.getX())==Double.doubleToLongBits(end.getX())) {if(line.isHorizontal()) {int i = startPoint[0];int j0 = Math.min(startPoint[1], endPoint[1]);int j1 = Math.max(startPoint[1], endPoint[1]);while(j0!=j1) {setValue(i, j0);j0++;}}else {int i = startPoint[1];int j0 = Math.min(startPoint[0], endPoint[0]);int j1 = Math.max(startPoint[0], endPoint[0]);while(j0!=j1) {setValue(j0, i);j0++;}}return;}//行差与列差int difOfRow = Math.abs(startPoint[0]-endPoint[0]);int difOfColumn = Math.abs(startPoint[1]-endPoint[1]);//若行差大于列差,则逐行求出本行中心线与过两个端点的直线的交点//反之则反之if(difOfRow>difOfColumn) {//求每行中心线int num = Math.min(startPoint[0], endPoint[0]); //用于记录当前行while(num<=Math.max(startPoint[0], endPoint[0])) {//因为只需要求出行,所以设列为1即可Point temPoint=transformVetorPoint(num, 1, 0, 0);//中心线double y = temPoint.getY();//求交点double x=line.getXByY(y);Point result = new Point(x, y);//矢量点转栅格int[] resultRasterPoint=transformRasterPoint(result, 0, 0);//"涂黑"栅格setValue(resultRasterPoint[0], resultRasterPoint[1]);num++;}}else {//求每列中心线int num = Math.min(startPoint[1], endPoint[1]);while(num<Math.max(startPoint[1], endPoint[1])) {Point temPoint = transformVetorPoint(1, num, 0, 0);double x = temPoint.getX();double y = line.getYByX(x);Point result = new Point(x, y);int[] resultRasterPoint = transformRasterPoint(result, 0, 0);setValue(resultRasterPoint[0], resultRasterPoint[1]);num++;}}}

测试:

输入:

p(3,9),q(15,30)组成的线段,在30x30的栅格上显示

输出

这个渲染的代码就不放出来了,有兴趣可以到我的github上看。

②全路径栅格化

算法思想

说白了就是固定行,求列,固定列,求行的过程。

但值得注意的是,书上并没有给出计算行号的过程:

实际上也不难推出,因为求起止行列的过程就是已知tan角求不同边的过程

固定行,求起止列就是求上图中a的过程 a = tana/b

固定列,求起止行就是求b的过程, b=tana * b

因此可以推出

起始行号:

终止行号:

m是栅格的边长,j是当前处理的列,y0是栅格坐标原点在直角坐标系中的纵坐标值

算法实现:

public void RasterLine(Point start,Point end,int type,double xOffset,double yOffset) {//开始点与结束点的起始坐标int[] startPoint = transformRasterPoint(start, 0, 0);int[] endPoint = transformRasterPoint(end, 0, 0);//System.out.println(String.format("开始点:(%d,%d)", startPoint[0],startPoint[1]));System.out.println(String.format("结束点:(%d,%d)", endPoint[0],endPoint[1]));//涂黑,开始点与终止点(值设为1)setValue(startPoint[0], startPoint[1]);setValue(endPoint[0], endPoint[1]);Line line = new Line(start, end);//如果是垂直或者水平者直接涂黑if(line.isHorizontal() || Double.doubleToLongBits(start.getX())==Double.doubleToLongBits(end.getX())) {if(line.isHorizontal()) {int i = startPoint[0];int j0 = Math.min(startPoint[1], endPoint[1]);int j1 = Math.max(startPoint[1], endPoint[1]);while(j0!=j1) {setValue(i, j0);j0++;}}else {int i = startPoint[1];int j0 = Math.min(startPoint[0], endPoint[0]);int j1 = Math.max(startPoint[0], endPoint[0]);while(j0!=j1) {setValue(j0, i);j0++;}}return;}//计算栅格原点在直角坐标系中的坐标double x0=1+xOffset+this.xOffset;double y0=ROW+yOffset+this.yOffset;//△x>=△y,则计算列号,反之则计算行号double difX = Math.abs(start.getX()-end.getX());double difY = Math.abs(start.getY()-end.getY());double k = line.getSlope();if(difX>=difY) {//开始点与结束点的起始坐标if(Double.doubleToLongBits(end.getY())<Double.doubleToLongBits(start.getY())) {startPoint = transformRasterPoint(start, 0, 0);endPoint = transformRasterPoint(end, 0, 0);line = new Line(start,end);}else {startPoint = transformRasterPoint(end, 0, 0);endPoint = transformRasterPoint(start, 0, 0);line = new Line(end,start);}k = line.getSlope();//System.out.println(k);//用于记录当前行int i = startPoint[0];//终止行int j = endPoint[0];//计算起始列号int j0 = (int)Math.floor(((((y0-(i-1)*size-line.getStart().getY())/k)+line.getStart().getX()-x0)/size))+1;//计算终止列号int j1 = (int)Math.floor((((y0-i*size-line.getStart().getY())/k)+line.getStart().getX()-x0)/size)+1;//System.out.println(String.format("s%d,%d", j0,j1));while(i!=j) {//i行从j0-j1涂黑int ja,jb;ja=j0;jb=j1;System.out.println(String.format("%d,%d", j0,j1));while(ja!=jb) {if(ja<jb) {//System.out.println(String.format("i=%d ja=%d", i,ja));setValue(i, ja);ja++;}else {//System.out.println(String.format("i=%d jb=%d", i,jb));setValue(i, jb);jb++;}}i++;//本行终止列号等于下一行的起始列号j0=j1;//计算下一行终止列号j1 = (int)Math.floor((((y0-i*size-line.getStart().getY())/k)+line.getStart().getX()-x0)/size)+1;//System.out.println(String.format("%d,%d", j0,j1));}}else {//System.out.println("第二种");//开始点与结束点的起始坐标if(Double.doubleToLongBits(end.getX())>Double.doubleToLongBits(start.getX())) {startPoint = transformRasterPoint(start, 0, 0);endPoint = transformRasterPoint(end, 0, 0);line = new Line(start,end);}else {startPoint = transformRasterPoint(end, 0, 0);endPoint = transformRasterPoint(start, 0, 0);line = new Line(end,start);}k = line.getSlope();//System.out.println(k);//记录当前列int js = startPoint[1];//记录终止列int je = endPoint[1];//计算起始行号int is = (int)Math.floor(((line.getStart().getX()-x0-(js-1)*size)*k+y0-line.getStart().getY())/size)+1;//计算终止行号int ie = (int)Math.floor(((line.getStart().getX()-x0-js*size)*k+y0-line.getStart().getY())/size)+1;//System.out.println(String.format("first %d,%d", is,ie));while(js!=je) {int ia,ib;//从is-ie行涂黑ia=is;ib=ie;while(ia!=ib) {if(ia<ib) {//System.out.println(ia);setValue(ia, js);ia++;}else {//System.out.println(ib);setValue(ib, js);ib++;}}js++;is=ie;ie = (int)Math.floor(((line.getStart().getX()-x0-js*size)*k+y0-line.getStart().getY())/size)+1;//System.out.println(String.format("%d,%d", is,ie));}}

测试结果:

输入:

p(3,9),q(15,30)组成的线段,在30x30的栅格上显示

输出:

同时,由于输入的线段是相同的,也可以比对一下八方向栅格化和全路径栅格化的栅格化效果。

八方向的特点是每行或每列只有一个栅格被涂黑,所以看起来比较细长。而全路径栅格化,由于计算过程是把所有经过的栅格都”涂黑“了,因此当要以任何方向探测栅格影响的存在或者想要知道矢量可能出现在哪些栅格所覆盖的范围时,就可以用全路径栅格化。

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。