部分源码选自GDAL库的官方网址:www.gdal.org,其余的代码为笔者自己编写。
 // readfile.cpp : 定义控制台应用程序的入口点。
//
/*
part of the codes were cite from: http://www.gdal.org/gdal_tutorial.html
and remaining of code were created :by www.cnblogs.com/AmatVictorialCuram/‎
and please mark the site if you cite the program fo commercial of publication.
*/
#include "stdafx.h"
#include <iostream>
#include "gdal.h"
#include "gdal_priv.h"
/**/
#include <iomanip>
#include <fstream>
using namespace std;
/**/
int minLabel(int a,int b); int maxLabel(int a,int b); double csd(int *Parea,int length); int main()
{
/*
part of the codes were cite from: http://www.gdal.org/gdal_tutorial.html
and remaining of code were created :by www.cnblogs.com/AmatVictorialCuram/‎
and please mark the site if you cite the program fo commercial of publication.
*/
const char *pszFilename="E:\\tif/fragstats/sample.tif";
GDALDataset *poDataset; GDALAllRegister(); poDataset = (GDALDataset *) GDALOpen( pszFilename, GA_ReadOnly );
if( poDataset == NULL )
{
cout<<"file read error!"<<endl;;
}
double adfGeoTransform[]; printf( "Driver: %s/%s\n",
poDataset->GetDriver()->GetDescription(),
poDataset->GetDriver()->GetMetadataItem( GDAL_DMD_LONGNAME ) ); printf( "Size is %dx%dx%d\n",
poDataset->GetRasterXSize(), poDataset->GetRasterYSize(),
poDataset->GetRasterCount() ); if( poDataset->GetProjectionRef() != NULL )
printf( "Projection is `%s'\n", poDataset->GetProjectionRef() ); if( poDataset->GetGeoTransform( adfGeoTransform ) == CE_None )
{
printf( "Origin = (%.6f,%.6f)\n",
adfGeoTransform[], adfGeoTransform[] ); printf( "Pixel Size = (%.6f,%.6f)\n",
adfGeoTransform[], adfGeoTransform[] );
} GDALRasterBand *poBand;
int nBlockXSize, nBlockYSize;
int bGotMin, bGotMax;
double adfMinMax[]; poBand = poDataset->GetRasterBand( );
poBand->GetBlockSize( &nBlockXSize, &nBlockYSize );
printf( "Block=%dx%d Type=%s, ColorInterp=%s\n",
nBlockXSize, nBlockYSize,
GDALGetDataTypeName(poBand->GetRasterDataType()),
GDALGetColorInterpretationName(
poBand->GetColorInterpretation()) ); adfMinMax[] = poBand->GetMinimum( &bGotMin );
adfMinMax[] = poBand->GetMaximum( &bGotMax );
if( ! (bGotMin && bGotMax) )
GDALComputeRasterMinMax((GDALRasterBandH)poBand, TRUE, adfMinMax); printf( "Min=%.3fd, Max=%.3f\n", adfMinMax[], adfMinMax[] ); if( poBand->GetOverviewCount() > )
printf( "Band has %d overviews.\n", poBand->GetOverviewCount() ); if( poBand->GetColorTable() != NULL )
printf( "Band has a color table with %d entries.\n",
poBand->GetColorTable()->GetColorEntryCount() );
/*****
Reading Raster Data
*****/
float *pafScanline;
int nXSize = poBand->GetXSize();
int nYSize=poBand->GetYSize(); //读取图像的nXSize*nYSize数据
pafScanline = (float*) CPLMalloc(sizeof(float)*nXSize*nYSize);//创建指针
poBand->RasterIO(
GF_Read,//第一个参数表示要读入数据还是写入数据
, ,//nXOff, nYOff表示读取或者写入图像数据的起始坐标图像的左上角坐标为(0,0)
nXSize, nYSize,/*nXSize, nYSize表示读取或者写入图像数据的窗口大小,nXSize表示宽度,
nYSize表示高度,均使用像素为单位,该宽度和高度是从第二个和第三个参数处开始计算。
这两个参数和第二第三个参数一起表示就是,读取和写入图像的窗口位置和大小。*/
pafScanline, //指向存储数据的一个指针
nXSize, nYSize,//指定缓冲区的大小
GDT_Float32,
, );
// poBand->RasterIO( GF_Read, 0, 0, nXSize, nYSize, pafScanline, nXSize, nYSize, GDT_Float32, 0, 0 );
cout<<"列数:nXSize="<<nXSize<<endl;
cout<<"行数:nYSize="<<nYSize<<endl;
//system("pause"); //创建nXSize*nYSize的float数组
float **data=new float *[nXSize];//每列有nXSize列,data数组的大小与dataLabel数组的大小相同,类型不同
int **dataLabel=new int *[nXSize];//创建标签数组,有nYSize行,nXSize列
int t=,i=,j=;
for(int i=;i<nYSize;i++)//nYSize行
{
dataLabel[i]=new int [nXSize];
data[i] = new float [nXSize];
} cout<<"输出元数据数组data:"<<endl;
for(int i=;i<nYSize;i++)
{
for(int j=;j<nXSize;j++)
{
data[i][j]=pafScanline[t++];
cout<<setw()<<data[i][j];
}
cout<<endl;
}
cout<<endl;
//system("pause");
cout<<"输出标签数组dataLabel数组:"<<endl;
for(int i=;i<nYSize;i++)
{
cout<<endl;
for(int j=;j<nXSize;j++)
{
dataLabel[i][j]=nYSize*nXSize;
cout<<setw()<<dataLabel[i][j];
}
}
//system("pause");
cout<<endl;
cout<<"联通区域标记算法开始:"<<endl;
dataLabel[][]=;//把左上角的第一个标签赋值为1
int indexcolor=;
for(i=;i<nYSize;i++)
{
for(j=;j<nXSize;j++)
{
if(i==)
{
if(j==)
continue;
if(data[i][j]==data[i][j-])
dataLabel[i][j]=dataLabel[i][j-];
else
{
dataLabel[i][j]=++indexcolor;
}
continue;
}
if(j==)
{
if(data[i][j]==data[i-][j])
{
if(dataLabel[i-][j]<dataLabel[i][j])
dataLabel[i][j]=dataLabel[i-][j];
}
if(data[i][j]==data[i-][j+])
{
if(dataLabel[i-][j+]<dataLabel[i][j])
dataLabel[i][j]=dataLabel[i-][j+];
}
if(dataLabel[i][j]==nYSize*nXSize)
{
dataLabel[i][j]=++indexcolor;
}
continue;
}
//if(edgeCheckL(i,j) && data[i][j]==data[i][j-1])//左边的,
if(j> && data[i][j]==data[i][j-])
{
if(dataLabel[i][j-]<dataLabel[i][j])
dataLabel[i][j]=dataLabel[i][j-]; }
//if(edgeCheckLU(i,j) && data[i][j]==data[i-1][j-1])//左上角的
if((i> && j>)&& data[i][j]==data[i-][j-])
{
if(dataLabel[i-][j-]<dataLabel[i][j])
dataLabel[i][j]=dataLabel[i-][j-];
}
//if(edgeCheckU(i,j) && data[i][j]==data[i-1][j])//上面的
if(i> && data[i][j]==data[i-][j])
{
if(dataLabel[i-][j]<dataLabel[i][j])
dataLabel[i][j]=dataLabel[i-][j];
}
//if(edgeCheckUR(i,j) && data[i][j]==data[i-1][j+1])//右上角的
if((i> && j<nYSize-) && data[i][j]==data[i-][j+])
{
if(dataLabel[i-][j+]<dataLabel[i][j])
dataLabel[i][j]=dataLabel[i-][j+];
}
if(dataLabel[i][j]==nYSize*nXSize)
dataLabel[i][j]=++indexcolor;
}
}
//system("pause");
cout<<endl;
cout<<"输出第一次标记数组"<<endl<<endl;
for(i=;i<nYSize;i++)
{
for(j=;j<nXSize;j++)
{
cout<<setw()<<dataLabel[i][j];
}
cout<<endl;
}
//system("pause");
cout<<"合并首次生成的标签数组。。。。"<<endl<<endl; //合并:像素值相同,但是标签不同,就把标签值大的变为小的。
for(i=;i<nYSize;i++)//行
{
for(j=;j<nXSize;j++)//列
{
if(i==)//第0行,只判左边的!
{
if(j==)//第一个元素
{
j=;//跳过第一个元素,直接从第二个元素:data[0][1]判断
//判断并执行合并:
if(data[i][j-]==data[i][j] && dataLabel[i][j-]!=dataLabel[i][j])//像素值相同 && 标签不同:合并!
{
//把所有的大标签替换为当前两个标签中的一个较小的值
//执行一次遍历
//cout<<"第"<<i<<"行"<<"第"<<j<<"列:"<<"第"<<++replace<<"次替换"<<endl;
for(int m=;m<nYSize;m++)
{
for(int n=;n<nXSize;n++)
{//把大的标签替换为小的标签
if(dataLabel[m][n]==maxLabel(dataLabel[i][j],dataLabel[i][j-]))
{
dataLabel[m][n]=minLabel(dataLabel[i][j],dataLabel[i][j-]);
}
}
}
}
}
}
else//非0行
{
if(j==)//第0列,但不是第一行的:只判断上、右上两个方向
{
if(data[i-][j]==data[i][j] && dataLabel[i-][j]!=dataLabel[i][j])//像素值相同 && 标签不同:合并!
{
//把所有的大标签替换为当前两个标签中的一个较小的值
//执行一次遍历
//cout<<"第"<<i<<"行"<<"第"<<j<<"列:"<<"第"<<++replace<<"次替换"<<endl;
for(int m=;m<nYSize;m++)
{
for(int n=;n<nXSize;n++)
{//把大的标签替换为小的标签
if(dataLabel[m][n]==maxLabel(dataLabel[i][j],dataLabel[i-][j]))
{
dataLabel[m][n]=minLabel(dataLabel[i][j],dataLabel[i-][j]);
}
}
}
}
if(data[i-][j+]==data[i][j] && dataLabel[i-][j=]!=dataLabel[i][j])//像素值相同 && 标签不同:合并!
{
//把所有的大标签替换为当前两个标签中的一个较小的值
//执行一次遍历
//cout<<"第"<<i<<"行"<<"第"<<j<<"列:"<<"第"<<++replace<<"次替换"<<endl;
for(int m=;m<nYSize;m++)
{
for(int n=;n<nXSize;n++)
{//把大的标签替换为小的标签
if(dataLabel[m][n]==maxLabel(dataLabel[i][j],dataLabel[i-][j+]))
{
dataLabel[m][n]=minLabel(dataLabel[i][j],dataLabel[i-][j+]);
}
}
}
}
}
else if(j==nYSize-)//非0行且最后一列的:判断左、左上、上三个方向
{
if(data[i][j-]==data[i][j] && dataLabel[i][j-]!=dataLabel[i][j])//像素值相同 && 标签不同:合并!
{
//把所有的大标签替换为当前两个标签中的一个较小的值
//执行一次遍历
//cout<<"第"<<i<<"行"<<"第"<<j<<"列:"<<"第"<<++replace<<"次替换"<<endl;
for(int m=;m<nYSize;m++)
{
for(int n=;n<nXSize;n++)
{//把大的标签替换为小的标签
if(dataLabel[m][n]==maxLabel(dataLabel[i][j],dataLabel[i][j-]))
{
dataLabel[m][n]=minLabel(dataLabel[i][j],dataLabel[i][j-]);
}
}
}
}
if(data[i-][j-]==data[i][j] && dataLabel[i-][j-]!=dataLabel[i][j])//像素值相同 && 标签不同:合并!
{
//把所有的大标签替换为当前两个标签中的一个较小的值
//执行一次遍历
//cout<<"第"<<i<<"行"<<"第"<<j<<"列:"<<"第"<<++replace<<"次替换"<<endl;
for(int m=;m<nYSize;m++)
{
for(int n=;n<nXSize;n++)
{//把大的标签替换为小的标签
if(dataLabel[m][n]==maxLabel(dataLabel[i][j],dataLabel[i-][-]))
{
dataLabel[m][n]=minLabel(dataLabel[i][j],dataLabel[i-][j-]);
}
}
}
}
if(data[i-][j]==data[i][j] && dataLabel[i-][j]!=dataLabel[i][j])//像素值相同 && 标签不同:合并!
{
//把所有的大标签替换为当前两个标签中的一个较小的值
//执行一次遍历
//cout<<"第"<<i<<"行"<<"第"<<j<<"列:"<<"第"<<++replace<<"次替换"<<endl;
for(int m=;m<nYSize;m++)
{
for(int n=;n<nXSize;n++)
{//把大的标签替换为小的标签
if(dataLabel[m][n]==maxLabel(dataLabel[i][j],dataLabel[i-][j]))
{
dataLabel[m][n]=minLabel(dataLabel[i][j],dataLabel[i-][j]);
}
}
}
} }
else//非0行且(既不是第一列,也不是最后一列的):判断左、左上、上、右上四个方向
{
if(data[i][j-]==data[i][j] && dataLabel[i][j-]!=dataLabel[i][j])//像素值相同 && 标签不同:合并!
{
//把所有的大标签替换为当前两个标签中的一个较小的值
//执行一次遍历
//cout<<"第"<<i<<"行"<<"第"<<j<<"列:"<<"第"<<++replace<<"次替换"<<endl;
for(int m=;m<nYSize;m++)
{
for(int n=;n<nXSize;n++)
{//把大的标签替换为小的标签
if(dataLabel[m][n]==maxLabel(dataLabel[i][j],dataLabel[i][j-]))
{
dataLabel[m][n]=minLabel(dataLabel[i][j],dataLabel[i][j-]);
}
}
}
}
if(data[i-][j-]==data[i][j] && dataLabel[i-][j-]!=dataLabel[i][j])//像素值相同 && 标签不同:合并!
{
//把所有的大标签替换为当前两个标签中的一个较小的值
//执行一次遍历
//cout<<"第"<<i<<"行"<<"第"<<j<<"列:"<<"第"<<++replace<<"次替换"<<endl;
for(int m=;m<nYSize;m++)
{
for(int n=;n<nXSize;n++)
{//把大的标签替换为小的标签
if(dataLabel[m][n]==maxLabel(dataLabel[i][j],dataLabel[i-][-]))
{
dataLabel[m][n]=minLabel(dataLabel[i][j],dataLabel[i-][j-]);
}
}
}
}
if(data[i-][j]==data[i][j] && dataLabel[i-][j]!=dataLabel[i][j])//像素值相同 && 标签不同:合并!
{
//把所有的大标签替换为当前两个标签中的一个较小的值
//执行一次遍历
//cout<<"第"<<i<<"行"<<"第"<<j<<"列:"<<"第"<<++replace<<"次替换"<<endl;
for(int m=;m<nYSize;m++)
{
for(int n=;n<nXSize;n++)
{//把大的标签替换为小的标签
if(dataLabel[m][n]==maxLabel(dataLabel[i][j],dataLabel[i-][j]))
{
dataLabel[m][n]=minLabel(dataLabel[i][j],dataLabel[i-][j]);
}
}
}
}
if(data[i-][j+]==data[i][j] && dataLabel[i-][j+]!=dataLabel[i][j])//像素值相同 && 标签不同:合并!
{
//把所有的大标签替换为当前两个标签中的一个较小的值
//执行一次遍历
//cout<<"第"<<i<<"行"<<"第"<<j<<"列:"<<"第"<<++replace<<"次替换"<<endl;
for(int m=;m<nYSize;m++)
{
for(int n=;n<nXSize;n++)
{//把大的标签替换为小的标签
if(dataLabel[m][n]==maxLabel(dataLabel[i][j],dataLabel[i-][j+]))
{
dataLabel[m][n]=minLabel(dataLabel[i][j],dataLabel[i-][j+]);
}
}
}
}
}
} }
}
t=;
//system("pause");
cout<<"输出合并后的标签数组dataLabel:"<<endl;
for(i=;i<nYSize;i++)
{
for(j=;j<nXSize;j++)
{
if(dataLabel[i][j]>t)
{
t++;
}
cout<<setw()<<dataLabel[i][j]; }
cout<<endl;
}
cout<<endl<<"t="<<t<<endl;
cout<<"联通区域标记算法结束end!!!"<<endl;
//system("pause");
int max=;
for(int i=;i<nYSize;i++)
{
for(int j=;j<nXSize;j++)
{
if(dataLabel[i][j]>max)
{
max=dataLabel[i][j];
}
}
}
cout<<"maxLabel="<<max<<endl;
int *Pid=new int [max+];
int *Parea=new int [max+];
for(i=;i<max+;i++)
{
Pid[i]=i;
Parea[i]=;
}
/////////////////////////////
for(int i=;i<nYSize;i++)
{
for(int j=;j<nXSize;j++)
{
Parea[dataLabel[i][j]]++;
}
}
t=max+;
for(i=;i<t;i++)
{ cout<<"dataLabel为"<<i<<"的面积为:"<<Parea[i]<<endl;
} double Xi=,Si=;
int NPatch=;
for(i=;i<t;i++)
{
if(Parea[i]!=)
{
NPatch++;
Xi=Xi+Parea[i];//求出板块总面积
}
/*cout<<"NPatch="<<NPatch<<endl;
cout<<"Xi="<<Xi<<endl;*/
}
cout<<"NPatch="<<NPatch<<endl;
//cout<<"Xi="<<Xi<<endl;
Xi=Xi/NPatch;//面积平均数
cout<<"Initial Value:Xi="<<Xi<<endl;
cout<<"Initial Value:Si="<<Si<<endl;
//计算出所有
for(i=;i<t;i++)
{
if(Parea[i]!=)
{
Si=Si+((Parea[i]-Xi)*(Parea[i]-Xi))/NPatch;
}
}
cout<<"方差="<<Si<<endl;
Si=sqrt(Si);
cout<<"Standard Deviation(标准差)="<<Si<<endl;
cout<<endl; /****输出内容写出到文件当中****/
ofstream ocout;
//ocout.open("result.csv");
//ocout.open("result.txt");
ocout.open("result.csv");
/****将计算出的结果输出到屏幕****/
ocout<<"PatchID"<<","<<"Area"<<","<<"CSD"<<endl;
for(i=;i<t;i++)
{
if(Parea[i]!=)
{ //ocout<<"Patch: Label="<<i<<setw(4)<<" Area="<<Parea[i]<<setw(10)<<"CSD="<<(Parea[i]-Xi)/Si<<endl;
ocout<<i<<",";
ocout<<Parea[i]<<",";
ocout<<(Parea[i]-Xi)/Si<<","<<endl;
}
}
/*******后面的这一部分没有太大的实质性用处,可有可无**********/
const char *pszFormat = "GTiff";
GDALDriver *poDriver;
char **papszMetadata; poDriver = GetGDALDriverManager()->GetDriverByName(pszFormat); if( poDriver == NULL )
exit( ); papszMetadata = poDriver->GetMetadata();
if( CSLFetchBoolean( papszMetadata, GDAL_DCAP_CREATE, FALSE ) )
printf( "Driver %s supports Create() method.\n", pszFormat );
if( CSLFetchBoolean( papszMetadata, GDAL_DCAP_CREATECOPY, FALSE ) )
printf( "Driver %s supports CreateCopy() method.\n", pszFormat ); /*释放读取文件用的指针*/
CPLFree(pafScanline);
//关闭文件
GDALClose((GDALDatasetH)poDataset);
free(dataLabel);
free(data);
free(Parea);
free(Pid);
//
ocout.close();
}
int minLabel(int a,int b)
{
return (a>b)?b:a;
}
int maxLabel(int a,int b)
{
return (a<b)?b:a;
}
double csd(int *Parea,int length)
{
return ;
}

C++调用GDAL库读取并输出tif文件,并计算斑块面积输出景观指数:CSD的更多相关文章

  1. GDAL库——读取图像并提取基本信息

    GDAL库是一个跨平台的栅格地理数据格式库,包括读取.写入.转换.处理各种栅格数据格式(有些特定的格式对一些操作如写入等不支持).它使用了一个单一的抽象数据模型就支持了大多数的栅格数据.这里有GDAL ...

  2. [原创]java WEB学习笔记41:简单标签之带属性的自定义标签(输出指定文件,计算并输出两个数的最大值 demo)

    本博客为原创:综合 尚硅谷(http://www.atguigu.com)的系统教程(深表感谢)和 网络上的现有资源(博客,文档,图书等),资源的出处我会标明 本博客的目的:①总结自己的学习过程,相当 ...

  3. 基于GDAL库,读取.grd文件(以海洋地形数据为例)C++版

    技术背景 海洋地形数据主要是通过美国全球地形起伏数据(GMT)获得,数据格式为grd(GSBG)二进制数据,打开软件通过是Surfer软件,surfer软件可进行数据的编辑处理,以及进一步的可视化表达 ...

  4. 基于GDAL库,读取.nc文件(以海洋表温数据为例)C++版

    对于做海洋数据处理的同学,会经常遇到nc格式的文件,nc文件的格式全称是NetCDF,具体的详细解释请查询官网[https://www.unidata.ucar.edu/software/netcdf ...

  5. 使用C#版本的gdal库打开hdf文件

    作者:朱金灿 来源:http://blog.csdn.net/clever101 最近应同事的请求帮忙研究下使用C#版的gdal库读取hdf文件,今天算是有一点成果,特地做一些记录. 首先是编译C#版 ...

  6. GDAL C#读取shp中文属性值乱码问题

    GDAL的C#版本读取shp中,如果属性值中含有中文,读出来有可能是乱码的问题,根据SWIG生成的C#代码调试发现问题所在,在Ogr.cs文件中有这么一个函数,代码如下: internal stati ...

  7. 浅析GDAL库C#版本支持中文路径问题

    GDAL库对于C#的支持问题还是蛮多的,对于中文路径的支持就是其中之一(另一个就是通过OGR库获取图形的坐标信息). 关于C#支持中文路径,看过我之前博客的应该都不陌生,如果使用的是我修改过的GDAL ...

  8. GDAL库调试(包括跨语言调试)

    很多时候都需要调试GDAL库,尤其是像学习GDAL库中的某些算法是如何实现的时候,调试就必不可少了. 首先说明用C++的调试.以VS2008为例进行说明. 编译DEBUG版本的GDAL库,这个可以参考 ...

  9. 转 mysql查询结果输出到文件

    mysql查询结果输出到文件   mysql查询结果导出/输出/写入到文件 方法一:直接执行命令:mysql> select count(1) from table  into outfile ...

随机推荐

  1. JavaEE系列之(二)commons-fileupload实现文件上传、下载

    一.文件上传概述     实现Web开发中的文件上传功能,需要两步操作:     1.在Web页面中添加上传输入项 <form action="#" method=" ...

  2. 销售订单行上行号LINE_SHIPMENT_OPTION_NUMBER

     销售订单行上行号:LINE_SHIPMENT_OPTION_NUMBER 取值: ( 1) Line块的块级触发器POST-QUERY调用: OE_LINE.Post_Query;(来自于库OE ...

  3. 剑指 offer set 4 矩形覆盖

    总结 1. 斐波那契数列的变形题, 但是稍有隐晦, 有点意思 2. 求解 f(3) 时, 最后一块矩形可以竖着放, 也可以两块矩形横着放, 分别对应于 f(2) 和 f(1) ------------ ...

  4. 进程控制之fork函数

    一个现有进程可以调用fork函数创建一个新进程. #include <unistd.h> pid_t fork( void ); 返回值:子进程中返回0,父进程中返回子进程ID,出错返回- ...

  5. Tfs服务器迁移(更改IP)后客户端(vs2013)配置方法

    一.前言 公司开发项目需要进驻客户现场,局域网中的tfs代码服务器有时会有修改ip的情况发生.服务器ip修改后在vs2013中更改服务器ip地址非常麻烦,有些时候需要将代码重新进行映射.多次试验后将可 ...

  6. WPF 之 利用Visibility属性进行Item模板切换

    前台Xaml如下: <Grid.Resources> <xx:AccountStatusToVisibility x:Key="AccountStatusToVisibil ...

  7. Design Mode 之 行为模式

    行为型模式,共十一种:策略模式.模板方法模式.观察者模式.迭代子模式.责任链模式.命令模式.备忘录模式.状态模式.访问者模式.中介者模式.解释器模式. 看看这11中模式的关系,大致可分为四类:(1) ...

  8. L - Abbott's Revenge(比较复杂的bfs)

    Time Limit:3000MS     Memory Limit:0KB     64bit IO Format:%lld & %llu Submit Status Practice UV ...

  9. ProgressBar的Indeterminate属性

    Indeterminate ProgressBar默认是白色的,如果容器的背景也是白色的,这样就根本看不到Progressbar. 简单解决方案: 用style属性设定反转的颜色. <Progr ...

  10. js的时间操作方法

    1.js获取系统时间格式为YYYY-MM-DD HH:MM:SS 1 function curDateTime(){ 2 var d = new Date(); 3 var year = d.getY ...