坐标系统是GIS图形显示、数据组织分析的基础,建立完善的坐标投影系统对于GIS应用来说是非常重要的。
GIS的坐标系统大致有三种:Plannar Coordinate System(平面坐标系统)、Geographic Coordinate System(地理坐标系统)、Projection Coordinate System(投影坐标系统)。这三者并不是完全独立的,而且各自都有各自的应用特点。如平面坐标系统常常在小范围内不需要投影或坐标变换的情况下使用,在Arcgis中,默认打开数据不知道坐标系统信息的情况下都当作Custom CS处理,也就是平面坐标系统。而地理坐标系统和投影坐标系统又是相互联系的,地理坐标系统是投影坐标系统的基础之一,二者的区别联系在下文详述,下面先搞清楚几个基本的概念
1、椭球面(Ellipsoid)
地图坐标系由大地基准面和地图投影确定,大地基准面是利用特定椭球体对特定地区地球表面的逼近,因此每个国家或地区均有各自的大地基准面,我们通常称谓的北京54坐标系、西安80坐标系实际上指的是我国的两个大地基准面。我国参照前苏联从1953年起采用克拉索夫斯基(Krassovsky)椭球体建立了我国的北京54坐标系,1978年采用国际大地测量协会推荐的IAG 75地球椭球体建立了我国新的大地坐标系--西安80坐标系, 目前GPS定位所得出的结果都属于WGS84坐标系统,WGS84基准面采用WGS84椭球体,它是一地心坐标系,即以地心作为椭球体中心的坐标系。因此相对同一地理位置,不同的大地基准面,它们的经纬度坐标是有差异的。采用的3个椭球体参数如下(源自“全球定位系统测量规范 GB/T 18314-2001”):
椭球体
长半轴
短半轴
Krassovsky
6378245
6356863.0188
IAG 75
6378140
6356755.2882
WGS 84
6378137
6356752.3142
理解:椭球面是用来逼近地球的,应该是一个立的椭圆旋转而成的。
2、大地基准面(Datum)
椭球体与大地基准面之间的关系是一对多的关系,也就是基准面是在椭球体基础上建立的,但椭球体不能代表基准面,同样的椭球体能定义不同的基准面,如前苏联的Pulkovo 1942、非洲索马里的Afgooye基准面都采用了Krassovsky椭球体,但它们的大地基准面显然是不同的。在目前的GIS商用软件中,大地基准面都通过当地基准面向WGS84的转换7参数来定义,即三个平移参数ΔX、ΔY、ΔZ表示两坐标原点的平移值;三个旋转参数εx、εy、εz表示当地坐标系旋转至与地心坐标系平行时,分别绕Xt、Yt、Zt的旋转角;最后是比例校正因子,用于调整椭球大小。北京54、西安80相对WGS84的转换参数至今没有公开,实际工作中可利用工作区内已知的北京54或西安80坐标控制点进行与WGS84坐标值的转换,在只有一个已知控制点的情况下(往往如此),用已知点的北京54与WGS84坐标之差作为平移参数,当工作区范围不大时,如青岛市,精度也足够了。
以(32°,121°)的高斯-克吕格投影结果为例,北京54及WGS84基准面,两者投影结果在南北方向差距约63米(见下表),对于几十或几百万的地图来说,这一误差无足轻重,但在工程地图中还是应该加以考虑的。
输入坐标(度)
北京54 高斯投影(米)
WGS84 高斯投影(米)
纬度值(X)
32
3543664
3543601
经度值(Y)
121
21310994
21310997
理解:椭球面和地球肯定不是完全贴合的,因而,即使用同一个椭球面,不同的地区由于关心的位置不同,需要最大限度的贴合自己的那一部分,因而大地基准面就会不同。
3、高斯投影(Gauss Projection)
(1)高斯-克吕格投影性质
高斯-克吕格(Gauss-Kruger)投影简称“高斯投影”,又名"等角横切椭圆柱投影”,地球椭球面和平面间正形投影的一种。德国数学家、物理学家、天文学家高斯(Carl FriedrichGauss,1777一 1855)于十九世纪二十年代拟定,后经德国大地测量学家克吕格(Johannes Kruger,1857~1928)于 1912年对投影公式加以补充,故名。该投影按照投影带中央子午线投影为直线且长度不变和赤道投影为直线的条件,确定函数的形式,从而得到高斯一克吕格投影公式。投影后,除中央子午线和赤道为直线外,其他子午线均为对称于中央子午线的曲线。设想用一个椭圆柱横切于椭球面上投影带的中央子午线,按上述投影条件,将中央子午线两侧一定经差范围内的椭球面正形投影于椭圆柱面。将椭圆柱面沿过南北极的母线剪开展平,即为高斯投影平面。取中央子午线与赤道交点的投影为原点,中央子午线的投影为纵坐标x轴,赤道的投影为横坐标y轴,构成高斯克吕格平面直角坐标系。
高斯-克吕格投影在长度和面积上变形很小,中央经线无变形,自中央经线向投影带边缘,变形逐渐增加,变形最大之处在投影带内赤道的两端。由于其投影精度高,变形小,而且计算简便(各投影带坐标一致,只要算出一个带的数据,其他各带都能应用),因此在大比例尺地形图中应用,可以满足军事上各种需要,能在图上进行精确的量测计算。
(2)高斯-克吕格投影分带
按一定经差将地球椭球面划分成若干投影带,这是高斯投影中限制长度变形的最有效方法。分带时既要控制长度变形使其不大于测图误差,又要使带数不致过多以减少换带计算工作,据此原则将地球椭球面沿子午线划分成经差相等的瓜瓣形地带,以便分带投影。通常按经差6度或3度分为六度带或三度带。六度带自0度子午线起每隔经差6度自西向东分带,带号依次编为第 1、2…60带。三度带是在六度带的基础上分成的,它的中央子午线与六度带的中央子午线和分带子午线重合,即自 1.5度子午线起每隔经差3度自西向东分带,带号依次编为三度带第 1、2…120带。我国的经度范围西起 73°东至135°,可分成六度带十一个,各带中央经线依次为75°、81°、87°、……、117°、123°、129°、135°,或三度带二十二个。六度带可用于中小比例尺(如 1:250000)测图,三度带可用于大比例尺(如 1:10000)测图,城建坐标多采用三度带的高斯投影。
(3)高斯-克吕格投影坐标
高斯- 克吕格投影是按分带方法各自进行投影,故各带坐标成独立系统。以中央经线投影为纵轴(x), 赤道投影为横轴(y),两轴交点即为各带的坐标原点。纵坐标以赤道为零起算,赤道以北为正,以南为负。我国位于北半球,纵坐标均为正值。横坐标如以中央经线为零起算,中央经线以东为正,以西为负,横坐标出现负值,使用不便,故规定将坐标纵轴西移500公里当作起始轴,凡是带内的横坐标值均加 500公里。由于高斯-克吕格投影每一个投影带的坐标都是对本带坐标原点的相对值,所以各带的坐标完全相同,为了区别某一坐标系统属于哪一带,在横轴坐标前加上带号,如(4231898m,21655933m),其中21即为带号。
(4)高斯-克吕格投影与UTM投影
某些国外的软件如ARC/INFO或国外仪器的配套软件如多波束的数据处理软件等,往往不支持高斯-克吕格投影,但支持UTM投影,因此常有把UTM投影坐标当作高斯-克吕格投影坐标提交的现象。
UTM投影全称为“通用横轴墨卡托投影”,是等角横轴割圆柱投影(高斯-克吕格为等角横轴切圆柱投影),圆柱割地球于南纬80度、北纬84度两条等高圈,该投影将地球划分为60个投影带,每带经差为6度,已被许多国家作为地形图的数学基础。UTM投影与高斯投影的主要区别在南北格网线的比例系数上,高斯-克吕格投影的中央经线投影后保持长度不变,即比例系数为1,而UTM投影的比例系数为0.9996。UTM投影沿每一条南北格网线比例系数为常数,在东西方向则为变数,中心格网线的比例系数为0.9996,在南北纵行最宽部分的边缘上距离中心点大约 363公里,比例系数为 1.00158。 高斯-克吕格投影与UTM投影可近似采用 Xutm=0.9996 * X高斯,Yutm=0.9996 * Y高斯进行坐标转换。以下举例说明(基准面为WGS84):
输入坐标(度)
高斯投影(米)
UTM投影(米)
Xutm=0.9996 * X高斯, Yutm=0.9996 * Y高斯
纬度值(X)
32
3543600.9
3542183.5
3543600.9*0.9996 ≈ 3542183.5
经度值(Y)
121
21310996.8
311072.4
(310996.8-500000)*0.9996+500000 ≈ 311072.4
注:坐标点(32,121)位于高斯投影的21带,高斯投影Y值21310996.8中前两位“21”为带号;坐标点(32,121)位于UTM投影的51带,上表中UTM投影的Y值没加带号。因坐标纵轴西移了500000米,转换时必须将Y值减去500000乘上比例因子后再加500000。
理解:高斯投影的方法就是保持赤道和中央经线不变形,把球面摊平。方法:用一个椭圆柱套住椭球,把它投影到椭圆柱上,然后打开椭圆柱即可。
4、其他
WGS 84 是常用的经纬度的椭球面,也是一个公开的基准面。
正转换:经纬度-->高斯投影坐标。
大地基准面用于高斯投影,或者高斯分带投影,无论是54,80,还是wgs84,都有可能。
在不同的基准面下,同一个点的经纬度不同,投影坐标也不同。
地理坐标网(经纬网)
为了制作和使用地图的方便,高斯-克吕格投影的地图上绘有两种坐标网:地理坐标网和直角坐标网。
在我国1:1万-1:10万地形图上,经纬线只以图廓的形式表现,经纬度数值注记在内图廓的四角,在内外图廓间,绘有黑白相间或仅用短线表示经差、纬差1’的分度带,需要时将对应点相连接,就构成很密的经纬网。在1:20万-1:100万地形图上,直接绘出经纬网,有时还绘有供加密经纬网的加密分割线。纬度注记在东西内外图廓间,经度注记在南北内外图廓间。
直角坐标网(方里网)
直角坐标网是以每一投影带的中央经线作为纵轴(X轴),赤道作为横轴(Y轴)。纵坐标以赤道我0起算,赤道以北为正,以南为负。我国位于北半球,纵坐标都是正值。横坐标本应以中央经线为0起算,以东为正,以南为负,但因坐标值有正有负,不便于使用,所以又规定凡横坐标值均加500公里,即等于将纵坐标轴向西移500公里。横坐标从此纵轴起算,则都成正值。然后,以公里为单位,按相等的间距作平行于纵、横轴的若干直线,便构成了图面上的平面直角坐标网,又叫方里网。
5 Geographic Coordinate System和Projection Coordinate System的区别和联系:
地理坐标系统(Geographic Coordinate System)
1、首先理解地理坐标系(Geographic coordinate system),Geographic coordinate system直译为地理坐标系统,是以经纬度为地图的存储单位的。很明显,Geographic coordinate system是球面坐标系统。我们要将地球上的数字化信息存放到球面坐标系统上,如何进行操作呢?地球是一个不规则的椭球,如何将数据信息以科学的方法存放到椭球上?这必然要求
我们找到这样的一个椭球体。这样的椭球体具有特点:可以量化计算的。具有长半轴,短半轴,偏心率。以下几行便是Krasovsky_1940椭球及其相应参数。
Spheroid: Krasovsky_1940
Semimajor Axis: 6378245.000000000000000000
Semiminor Axis: 6356863.018773047300000000
Inverse Flattening(扁率): 298.300000000000010000
然而有了这个椭球体以后还不够,还需要一个大地基准面将这个椭球定位。在坐标系统描述中,可以看到有这么一行:
Datum: D_Beijing_1954
表示,大地基准面是D_Beijing_1954。
--------------------------------------------------------------------------------
有了Spheroid和Datum两个基本条件,地理坐标系统便可以使用。
完整参数:
Alias:
Abbreviation:
Remarks:
Angular Unit: Degree (0.017453292519943299)
Prime Meridian(起始经度): Greenwich (0.000000000000000000)
Datum(大地基准面): D_Beijing_1954
Spheroid(参考椭球体): Krasovsky_1940
Semimajor Axis: 6378245.000000000000000000
Semiminor Axis: 6356863.018773047300000000
Inverse Flattening: 298.300000000000010000
投影坐标系统(Projection Coordinate System)
2、接下来便是Projection coordinate system(投影坐标系统),首先看看投影坐标系统中的一些参数。
Projection: Gauss_Kruger
Parameters:
False_Easting: 500000.000000
False_Northing: 0.000000
Central_Meridian: 117.000000
Scale_Factor: 1.000000
Latitude_Of_Origin: 0.000000
Linear Unit: Meter (1.000000)
Geographic Coordinate System:
Name: GCS_Beijing_1954
Alias:
Abbreviation:
Remarks:
Angular Unit: Degree (0.017453292519943299)
Prime Meridian: Greenwich (0.000000000000000000)
Datum: D_Beijing_1954
Spheroid: Krasovsky_1940
Semimajor Axis: 6378245.000000000000000000
Semiminor Axis: 6356863.018773047300000000
Inverse Flattening: 298.300000000000010000
从参数中可以看出,每一个投影坐标系统都必定会有Geographic Coordinate System。投影坐标系统,实质上便是平面坐标系统,其地图单位通常为米。
那么为什么投影坐标系统中要存在坐标系统的参数呢?
这时候,又要说明一下投影的意义:将球面坐标转化为平面坐标的过程便称为投影。好了,投影的条件就出来了:
a、球面坐标
b、转化过程(也就是算法)
也就是说,要得到投影坐标就必须得有一个“拿来”投影的球面坐标,然后才能使用算法去投影!
即每一个投影坐标系统都必须要求有Geographic Coordinate System参数。
3、我们现在看到的很多教材上的对坐标系统的称呼很多,都可以归结为上述两种投影。其中包括我们常见的“非地球投影坐标系统”。
__________________
大地坐标(Geodetic Coordinate)
大地测量中以参考椭球面为基准面的坐标。地面点P的位置用大地经度L、大地纬度B和大地高H表示。当点在参考椭球面上时,仅用大地经度和大地纬度表示。大地经度是通过该点的大地子午面与起始大地子午面之间的夹角,大地纬度是通过该点的法线与赤道面的夹角,大地高是地面点沿法线到参考椭球面的距离。
方里网:是由平行于投影坐标轴的两组平行线所构成的方格网。因为是每隔整公里绘出坐标纵线和坐标横线,所以称之为方里网,由于方里线同时又是平行于直角坐标轴的坐标网线,故又称直角坐标网。
在1:1万——1:20万比例尺的地形图上,经纬线只以图廓线的形式直接表现出来,并在图角处注出相应度数。为了在用图时加密成网,在内外图廓间还绘有加密经纬网的加密分划短线(图式中称“分度带”),必要时对应短线相连就可以构成加密的经纬线网。1:2 5万地形图上,除内图廓上绘有经纬网的加密分划外,图内还有加密用的十字线。
我国的1:50万——1:100万地形图,在图面上直接绘出经纬线网,内图廓上也有供加密经纬线网的加密分划短线。
直角坐标网的坐标系以中央经线投影后的直线为X轴,以赤道投影后的直线为Y轴,它们的交点为坐标原点。这样,坐标系中就出现了四个象限。纵坐标从赤道算起向北为正、向南为负;横坐标从中央经线算起,向东为正、向西为负。
虽然我们可以认为方里网是直角坐标,大地坐标就是球面坐标。但是我们在一副地形图上经常见到方里网和经纬度网,我们很习惯的称经纬度网为大地坐标,这个时候的大地坐标不是球面坐标,她与方里网的投影是一样的(一般为高斯),也是平面坐标。
尽管在.NET framework下我们并不需要担心内存管理和垃圾回收(Garbage Collection),但是我们还是应该了解它们,以优化我们的应用程序。同时,还需要具备一些基础的内存管理工作机制的知识,这样能够有助于解释我们日常程序编写中的变量的行为。在本文中我们将深入理解垃圾回收器,还有如何利用静态类成员来使我们的应用程序更高效。
* 更小的步伐 == 更高效的分配
为了更好地理解为什么更小的足迹会更高效,这需要我们对.NET的内存分配和垃圾回收专研得更深一些。
* 图解:
让我们来仔细看看GC。如果我们需要负责"清除垃圾",那么我们需要拟定一个高效的方案。很显然,我们需要决定哪些东西是垃圾而哪些不是。
为了决定哪些是需要保留的,我们首先假设所有的东西都不是垃圾(墙角里堆着的旧报纸,阁楼里贮藏的废物,壁橱里的所有东西,等等)。假设在我们的生活当中有两位朋友:Joseph Ivan Thomas(JIT)和Cindy Lorraine Richmond(CLR)。Joe和Cindy知道它们在使用什么,而且给了我们一张列表说明了我们需要需要些什么。我们将初始列表称之为"根"列表,因为我们将它用作起始点。我们需要保存一张主列表来记录出我们家中的必备物品。任何能够使必备物品正常工作或使用的东西也将被添加到列表中来(如果我们要看电视,那么就不能扔掉遥控器,所以遥控器将被添加到列表。如果我们要使用电脑,那么键盘和显示器就得添加到列表)。
这就是GC如何保存我们的物品的,它从即时编译器(JIT)和通用语言运行时(CLR)中获得"根"对象引用的列表,然后递归地搜索出其他对象引用来建立一张我们需要保存的物品的图表。
根包括:
* 全局/静态指针。为了使我们的对象不被垃圾回收掉的一种方式是将它们的引用保存在静态变量中。
* 栈上的指针。我们不想丢掉应用程序中需要执行的线程里的东西。
* CPU寄存器指针。托管堆中哪些被CPU寄存器直接指向的内存地址上的东西必须得保留。

在以上图片中,托管堆中的对象1、3、5都被根所引用,其中1和5时直接被引用,而3时在递归查找时被发现的。像我们之前的假设一样,对象1是我们的电视机,对象3是我们的遥控器。在所有对象被递归查找出来之后我们将进入下一步--压缩。
* 压缩
我们现在已经绘制出哪些是我们需要保留的对象,那么我们就能够通过移动"保留对象"来对托管堆进行整理。

幸运的是,在我们的房间里没有必要为了放入别的东西而去清理空间。因为对象2已经不再需要了,所以GC会将对象3移下来,同时修复它指向对象1的指针。

然后,GC将对象5也向下移,

现在所有的东西都被清理干净了,我们只需要写一张便签贴到压缩后的堆上,让Claire(指CLR)知道在哪儿放入新的对象就行了。

理解GC的本质会让我们明白对象的移动是非常费力的。可以看出,假如我们能够减少需要移动的物品大小是非常有意义的,通过更少的拷贝动作能够使我们提升整个GC的处理性能。
* 托管堆之外是怎样的情景呢?
作为负责垃圾回收的人员,有一个容易出现入的问题是在打扫房间时如何处理车里的东西,当我们打扫卫生时,我们需要将所有物品清理干净。那家里的台灯和车里的电池怎么办?
在一些情况下,GC需要执行代码来清理非托管资源(如文件,数据库连接,网络连接等),一种可能的方式是通过finalizer来进行处理。
class Sample


在对象创建期间,所有带有finalizer的对象都将被添加到一个finalizer队列中。对象1、4、5都有finalizer,且都已在finalizer队列当中。让我们来看看当对象2和4在应用程序中不再被引用,且系统正准备进行垃圾回收时会发生些什么。

对象2会像通常情况下那样被垃圾回收器回收,但是当我们处理对象4时,GC发现它存在于finalizer队列中,那么GC就不会回收对象4的内存空间,而是将对象4的finalizer移到一个叫做"freachable"的特殊队列中。

有一个专门的线程来执行freachable队列中的项,对象4的finalizer一旦被该线程所处理,就将从freachable队列中被移除,然后对象4就等待被回收。

因此对象4将存活至下一轮的垃圾回收。
由于在类中添加一个finalizer会增加GC的工作量,这种工作是十分昂贵的,而且会影响垃圾回收的性能和我们的程序。最好只在你确认需要finalizer时才使用它。
在清理非托管资源时有一种更好的方法:在显式地关闭连接时,使用IDisposalbe接口来代替finalizer进行清理工作会更好些。
* IDisposable
实现IDisposable接口的类需要执行Dispose()方法来做清理工作(这个方法是IDisposable接口中唯一的签名)。因此假如我们使用如下的带有finalizer的ResourceUser类:
public class ResourceUser
{
~ResourceUser() // THIS IS A FINALIZER
{
// DO CLEANUP HERE
}
} 
我们可以使用IDisposable来以更好的方式实现相同的功能:
public class ResourceUser : IDisposable
{
IDisposable Members
} 
IDisposable被集成在了using块当中。在using()方法中声明的对象在using块的结尾处将调用Dispose()方法,using块之外该对象将不再被引用,因为它已经被认为是需要进行垃圾回收的对象了。
public static void DoSomething()
{
ResourceUser rec = new ResourceUser();
using (rec)
{
// DO SOMETHING
} // DISPOSE CALLED HERE
// DON'T ACCESS rec HERE
} 
我更喜欢将对象声明放到using块中,因为这样可视化很强,而且rec对象在using块的作用域之外将不再有效。这种模式的写法更符合IDisposable接口的初衷,但这并不是必须的。
public static void DoSomething()
{
using (ResourceUser rec = new ResourceUser())
{
// DO SOMETHING
} // DISPOSE CALLED HERE
} 
在类中使用using()块来实现IDisposable接口,能够使我们在清理垃圾对象时不需要写额外的代码来强制GC回收我们的对象。
* 静态方法
静态方法属于一种类型,而不是对象的实例,它允许创建能够被类所共享的方法,且能够达到"减肥"的效果,因为只有静态方法的指针(8 bytes)在内存当中移动。静态方法实体仅在应用程序生命周期的早期被一次性加载,而不是在我们的类实例中生成。当然,方法越大那么将其作为静态就越高效。假如我们的方法很小(小于8 bytes),那么将其作为静态方法反而会影响性能,因为这时指针比它指向的方法所占的空间还大些。
接着来看看例子...
我们的类中有一个公共的方法SayHello():
class Dude
{
private string _Name = "Don";
public void SayHello()
{
Console.WriteLine(this._Name + " says Hello");
}
} 
在每一个Dude类实例中SayHello()方法都会占用内存空间。

一种更高效的方式是采用静态方法,这样我们只需要在内存中放置唯一的SayHello()方法,而不论存在多少个Dude类实例。因为静态成员不是实例成员,我们不能使用this指针来进行方法的引用。
class Dude
{
private string _Name = "Don";
public static void SayHello(string pName)
{
Console.WriteLine(pName + " says Hello");
}
} 

请注意我们在传递变量时栈上发生了些什么(可以参看<第二部分>)。我们需要通过例子的看看是否需要使用静态方法来提升性能。例如,一个静态方法需要很多参数而且没有什么复杂的逻辑,那么在使用静态方法时我们可能会降低性能。
* 静态变量:注意了!
对于静态变量,有两件事情我们需要注意。假如我们的类中有一个静态方法用于返回一个唯一值,而下面的实现会造成bug:
class Counter
{
private static int s_Number = 0;
public static int GetNextNumber()
{
int newNumber = s_Number;
// DO SOME STUFF
s_Number = newNumber + 1;
return newNumber;
}
} 
假如有两个线程同时调用GetNextNumber()方法,而且它们在s_Number的值增加前都为newNumber分配了相同的值,那么它们将返回同样的结果!
我们需要显示地为方法中的静态变量锁住读/写内存的操作,以保证同一时刻只有一个线程能够执行它们。线程管理是一个非常大的主题,而且有很多途径可以解决线程同步的问题。使用lock关键字能让代码块在同一时刻仅能够被一个线程访问。一种好的习惯是,你应该尽量锁较短的代码,因为在程序执行lock代码块时所有线程都要进入等待队列,这是非常低效的。
class Counter
{
private static int s_Number = 0;
public static int GetNextNumber()
{
lock (typeof(Counter))
{
int newNumber = s_Number;
// DO SOME STUFF
newNumber += 1;
s_Number = newNumber;
return newNumber;
}
}
} 
* 静态变量:再次注意了!
静态变量引用需要注意的另一件事情是:记住,被"root"引用的事物是不会被GC清理掉的。我遇到过的一个最烦人的例子:
class Olympics
{
public static Collection<Runner> TryoutRunners;
}
class Runner
{
private string _fileName;
private FileStream _fStream;
public void GetStats()
{
FileInfo fInfo = new FileInfo(_fileName);
_fStream = _fileName.OpenRead();
}
} 
由于Runner集合在Olympics类中是静态的,不仅集合中的对象不会被GC释放(它们都直接被根所引用),而且你可能注意到了,每次执行GetStats()方法时都会为那个文件开放一个文件流,因为它没有被关闭所以也不会被GC释放,这个代码将会给系统造成很大的灾难。假如我们有100000个运动员来参加奥林匹克,那么会由于太多不可回收的对象而难以释放内存。天啦,多差劲的性能呀!
* Singleton
有一种方法可以保证一个类的实例在内存中始终保持唯一,我们可以采用Gof中的Singleton模式。(Gof:Gang of Four,一部非常具有代表性的设计模式书籍的作者别称,归纳了23种常用的设计模式)
public class Earth
{
private static Earth _instance = new Earth();
private Earth() { }
public static Earth GetInstance() { return _instance; }
} 
我们的Earth类有一个私有构造器,所以Earth类能够执行它的构造器来创建一个Earth实例。我们有一个Earth类的静态实例,还有一个静态方法来获得这个实例。这种特殊的实现是线程安全的,因为CLR保证了静态变量的创建是线程安全的。这是我认为在C#中实现singleton模式最为明智的方式。
* .NET Framework 2.0中的静态类
在.NET 2.0 Framework中我们有一种静态类,此类中的所有成员都是静态的。这中特性对于工具类是非常有用的,而且能够节省内存空间,因为该类只存在于内存中的某个地方,不能在任何情况下被实例化。
* 总结一下...
总的来说,我们能够提升GC表现的方式有:
1. 清理工作。不要让资源一直打开!尽可能地保证关闭所有打开的连接,清除所有非托管的资源。当使用非托管对象时,初始化工作尽量完些,清理工作要尽量及时点。
2. 不要过度地引用。需要时才使用引用对象,记住,如果你的对象是活动着的,所有被它引用的对象都不会被垃圾回收。当我们想清理一些类所引用的事物,可以通过将这些引用设置为null来移除它们。我喜欢采用的一种方式是将未使用的引用指向一个轻量级的NullObject来避免产生null引用的异常。在GC进行垃圾回收时,更少的引用将减少映射处理的压力。
3. 少使用finalizer。Finalizer在垃圾回收时是非常昂贵的资源,我们应该只在必要时使用。如果我们使用IDisposable来代替finalizer会更高效些,因为我们的对象能够直接被GC回收而不是在第二次回收时进行。
4. 尽量保持对象和它们的子对象在一块儿。GC在复制大块内存数据来放到一起时是很容易的,而复制堆中的碎片是很费劲的,所以当我们声明一个包含许多其他对象的对象时,我们应该在初始化时尽量让他们在一块儿。
5. 最后,使用静态方法来保持对象的轻便也是可行的。
ArcGIS 9.3无论是从开发角度,还是开发方式和9.2相比都改进、丰富了不少,也兼容9.2ADF应用,通过Web Mapping Application Migration Utility可以将9.2模板应用程序升级到9.3环境中。这里我们先了解9.3 for .Net的开发路线,看看what's new!
1.核心Server APIs--ArcObjects,SOAP,REST
2.ADF开发框架
3.ArcGIS JavaScript APIs,构建纯浏览器的客户端应用,并且可以扩展Microsoft VirtualEarth和Google Maps JavaScript APIs
4.Mobile ADF开发框架
5.丰富的帮助文档(相比9.2全面多了),包括AGS开发和管理,全面支持VS2005和2008
上图圆环从里到外的层次分布指明了各种开发模式之间的依赖关系,其中最引人注目的是REST API、JavaScript API及其扩展,关于REST,Roy Thomas Fielding博士论文有非常系统的论述,但是我们没有时间也仔细研究,IBM developerworks和InfoQ上有一些相关的基础性文章可以作为参考,做AGS REST API开发时再去体会。
Roy Thomas Fielding博士论文
英文:http://www.ics.uci.edu/~fielding/pubs/dissertation/top.htm
中文:http://e2c.91yee.com/columns/
IBM developerworks
Ajax 和 REST,第1部分
跨越边界:REST on Rails
InfoQ
理解REST软件架构
深入浅出REST
JavaScript Applications
JavaScript APIs建立于REST API之上,可以使用AGS服务建立轻量级的,高性能的,纯浏览器的GIS应用,并且可以和其他GIS应用一起整合,构建"mashup"GIS功能。
AGS JavaScript APIs可以Virtual Earth SDK和Google Maps API基于AGS Services的扩展,由此可见微软和Google给WebGIS所带来的革命性的影响,AGS从产品定位上来说,核心还是在于GIS空间编辑、服务、分析和管理,客户端应用从9.2到9.3逐步改进,并和其他地图服务整合一起来满足客户对客户端用户体验的要求。
Web applications
Web applications大家都很熟悉了,里面有一些更新可能是大家比较关心的,首先是对VS2005/2008的兼容,新的应用构建于ASP.NET Ajax平台上,以提升用户的体验和性能。Web application包含了一个公共的Web ADF JavaScript Library,用于客户端组件和服务器端的异步交互,Web ADF JavaScript Library以ASP.NET Ajax JavaScript Library为基础,注意,它和AGS JavaScript APIs是两个不同的js库。
Web Services
GIS Web Service和application web service是gis web服务的两种类型,前者是ESRI标准web服务,可以作为服务发布(arccatalog发布服务的时候可以看到它的url),供ArcMap、AGS SOAP API和REST API使用,后者是通过与ESRI data source的交互,进行gis功能开发与封装,作为web service发布供其他应用调用,这和传统web service开发是一样的,提供各种gis功能接口。
Mobile applications
我一直认为这是今后GIS应用的发展热点之一,mobile applications专为PDAs、smartphones、pocket PCs或Tablet PCs设计,用于创建集中式管理的,高性能的,以GIS为核心的移动客户端应用,支持GPS导航,GIS空间编辑、管理、分析功能,与准实时更新是mobile应用的重点。
Desktop Client and console applications
AGS在这个层面上的应用不算多,但是体现了AGS作为GIS服务供应者的核心地位,目前用户使用AGS更多还是在B/S领域,甚至认为AGS是作为ArcIMS的替代者或升级版本的身份出现的,其实AGS提供的是一种服务,B/S、C/S、Web Service、Mobile都可以作为AGS应用的展现端,AGS目前更多的是应用在B/S架构中,相信以后会出现更全面,更完善的AGS应用,合理设计,充分挖掘AGS SOA架构的潜力。
【转载】原 作 者:Flyingis
1 简要介绍
WMS是OGC标准中比较简单也是比较重要的标准之一。它全称是“Web Map Service”(网络地图服务)。此标准主要定义了用于创建和显示地图图像的三大操作:GetCapabilities(获取服务能力), GetMap(获取地图)和GetFeatureInfo(获取对象信息)。其中GetMap为核心操作,此操作得到一幅地图图像。
2 GetMap请求
GetMap请求类似于在Web上请求一幅图像,但它的请求参数更加复杂。下面是一个样例请求:
返回的图像如下图所示:
其中:
http://: —— 使用的网络协议
webmapping.mgis.psu.edu/ —— 主机域名
geoserver/wms —— 页面或web程序位置
参数 ——
version=1.1.1 —— WMS版本号
request=getmap —— 操作动词,可以为GetCapabilities, GetMap和GetFeatureInfo等
layers=topp:states —— 请求地图所包含的图层名,可以为多层
styles=population —— 指定图层绘制的样式名
SRS=EPSG:4326 —— 指定地图的坐标投影系统代码
bbox=-125,24,-67,50 —— 请求地图的范围(The Bounding Box)
width=400 —— 地图的像素宽度
height=200 —— 地图的像素高度,宽度和高度的不同设置可能会引起返回图像的变形
format=image/png —— 返回地图图像的格式,可以为Image/gif, image/jpg, image/svg+xml等等
如果参数设置错误,将返回一个XML文件来描述错误信息。如下所示:
<ServiceExceptionReport version=”1.1.1“>
<ServiceException code=”">
WIDTH and HEIGHT incorrectly specified
</ServiceException>
</ServiceExceptionReport>
3 GetCapabilities请求
GetCapabilities请求用于查询WMS服务的能力信息,包括支持的服务、支持的格式、空间坐标、地图列表、地图样式等。它主要的目的是使客户端在使用GetMap请求前可以对WMS服务有一个基本的了解,从而可以设置正确的参数。
GetCapabilities请求的样例如下所示:
http://webmapping.mgis.psu.edu/geoserver/wms?version=1.1.1&request=getcapabilities
返回是一个XML文件,包括Service、Capability等部分,详细信息可以查看返回XML文件。
4 GetFeatureInfo请求
GetFeatureInfo用于查询屏幕某点的对象信息,它的样例请求如下所示:
此请求返回一个HTML文档来描述对象,如下所示:
Results for FeatureType ’states’:
——————————————–
the_geom = [GEOMETRY (MultiPolygon) with 153 points]
STATE_NAME = Arizona
STATE_FIPS = 04
SUB_REGION = Mtn
STATE_ABBR = AZ
LAND_KM = 294333.462
WATER_KM = 942.772
PERSONS = 3665228.0
FAMILIES = 940106.0
HOUSHOLD = 1368843.0
MALE = 1810691.0
FEMALE = 1854537.0
WORKERS = 1358263.0
DRVALONE = 1178320.0
CARPOOL = 239083.0
PUBTRANS = 32856.0
EMPLOYED = 1603896.0
UNEMPLOY = 123902.0
SERVICE = 455896.0
MANUAL = 185109.0
P_MALE = 0.494
P_FEMALE = 0.506
SAMP_POP = 468178.0
源自:http://blog.csdn.net/suen/archive/2008/01/15/2044725.aspx 粟卫民
安装完成后需要Post一次。如下:
ArcGis Server账号主要是用于启动ArcSom服务。ArcGIS Container则是用于平时的一些对于Arcgis Server的操作的账户。这里需要注意的是,普通用户是无法启动和操作Arcgis Server的。
当Post完成以后,系统中将会出现agsadmin和agsusers两个用户组,分别代表上述的两种权限账户。我们需要配置账户。如果为了简单,可以将Administrator设置到这两个账户当中,然后用Administrator登陆就可以了。如果为了安全,最后自己设置。这里还需要注意的是,配置好以后,需要重启计算机,才能启动ArcSom服务。
现在需要做的是在ArcCatalog里面配置Arcgis Server。这些东西都很简单,这里就不再多说了,帮助文档里面都写的很清楚。首先添加服务,一般输入本机的主机名,然后添加计算机,还是输入主机名,然后添加输出目录。这里需要注意的是,输出目录的虚拟目录必须为写入权限,不然不能生成图片。除非你用的是MIME模式返回图片。(MIME代表图片流,在IIS里面,可以设置IIS头来返回图片,这样就无需在服务器生成图片文件,从而提高服务器端效率)。
最后需要的就是添加ArcSoc服务器对象。如下面的图例所示:
这里是配置ArcSoc服务是否自动启动,我这里选择的是手工,因为我这里并不是每次开机就启动服务,当然,在服务器上肯定设置为自动:)
这里需要设置地图的mxd文档路径和输出目录。我选择是的用MIME+URL的方式。因为这样比较方便,当然,如果对性能需求比较高,我还是建议用MIME的方式。
这里是设置服务器池模式。主要是分为池和非池管理两种。默认的情况下,如果只是对GIS服务进行浏览和发布的时候,用池的模式。当对服务要编辑的时候用非池的模式。不过我还是建议大家不管哪种模式都用池的管理方式,这样性能是最优化的。因为池的管理方式是初始化就创建了几个SOC对象,每次只是从池里面取出SOC对象并操作,最后放回池里面。而非池则是每次操作SOC的时候都要动态创建SOC对象,这样就增加了很大的开销。当然,如何用池模式管理非池的操作,后面我会给大家做出说明。
这里就是对服务器的一些回收时间和实例进行管理。
以上是转贴刘寓blog的文章,大家在安装上有什么问题可以留言,能解答的我会尽力帮大家。
