学习AE摄像机动画

    掌握摄像机动画技巧之前,还是需要学习摄像机的工作原理,熟悉摄像机工具。

“轨道摄像机工具”其实就是旋转工具

用摄像机制作动画,主要对摄像机位置和目标兴趣点制作动画。用“轨道摄像机工具”时,只对摄像机位置起作用,不对目标兴趣点起作用。

“XY轴轨道摄像机工具”就是在XY轴方向上下左右移动,“Z轴轨道摄像机工具”实际上就是推拉的工具,他们改变摄像机位置和目标兴趣点。

是下面三个工具的结合。用这个工具,按住左键时,它就相当于“轨道摄像机工具”;按住中键,它就相当于“XY轴轨道摄像机工具”;按住右键,它就相当于“Z轴轨道摄像机工具”。

 


摄像机分为两种,单点摄像机(自由摄像机)和两点摄像机。

两点摄像机:目标兴趣点和位置

如何将两点摄像机转换为单点摄像机?

1.选择摄像机,右击

2.变换——自动定向

选择“关”

现在,制作一个简单的动画,穿越的效果。

1.用单点摄像机制作。制作之后,发现物体太大了。选择“摄像机”图层,按AA,会出现如图:调整“缩放”

制作好之后,我们发现摄像机运动死板。右击摄像机图层,变换——自动定向,将“沿路径方向设置”勾上。

选择图片图层,变换——自动定向,选择“朝向目标兴趣点”

 


现在,我们来学习摄像机动画,充分应用空白对象和父子关系。

1.输入文字“ZXW”

2.新建摄像机,选择“摄像机”图层,按R,调整“旋转”,会发现目标点不好控制。

于是,我们旋转摄像机,又不想影响目标点的话,通过空白对象和父子关系来控制位置。

3.新建空白对象。拖拽摄像机拾取链到空白对象,建立父子关系。

4.选择空白对象,按R,进行旋转,可以达到我们想要的效果。

5.将图片图层拉到时间线上,转换为三维,平铺,使其与文字切合。切换到左视图,调整位置。

6.新建照明图层,聚光灯,调整灯光位置。

这时,我们会发现,除了灯光位置发生变化,其目标点也会发生变化。按住CTRL键,移动灯光位置,来解决。

7.聚光灯,没有一束光一束光的效果,需要一个LUX插件。新建固态层,添加LUX插件特效。

8.摄像机进行旋转。新建空白对象,打开三维空间,与摄像机建立父子关系,旋转空白对象X轴90度。这时,摄像机旋转90度。

旋转空白对象2圈,这时,我们看见摄像机俯视旋转2圈。

我们最终制作的效果是,有平视到俯视后,旋转两圈,再由俯视到平视。用两个空白对象控制摄像机动画。

将第一个空白对象命名为“X轴”,第二个空白对象命名为“Y轴”,两个空白对象建立父子关系。

 

第二篇:AE 学习积累

创建或则打开shapefile

IWorkspace ipws;

IWorkspaceFactory ipwsf = new ShapefileWorkspaceFactoryClass(); ipws = ipwsf.OpenFromFile(folder, 0);

IFeatureWorkspace ifeatws;

ifeatws = ipws as IFeatureWorkspace;

IFields pFields = new FieldsClass();

IField pField = new FieldClass();

IFieldsEdit pFieldsEdit = pFields as IFieldsEdit;

IFieldEdit pFieldEdit = pField as IFieldEdit;

IGeometryDef ipGeodef = new GeometryDefClass();

IGeometryDefEdit ipGeodefEdit = ipGeodef as IGeometryDefEdit; // IGeoDataset geoDataset = featureClass as IGeoDataset; ISpatialReference ipSpatialRef;

ISpatialReferenceFactory spatialReferenceFactory = new SpatialReferenceEnvironmentClass();

IProjection projection = spatialReferenceFactory.CreateProjection

((int)esriSRProjectionType.esriSRProjection_GaussKruger); //土地利用中只采用高斯克吕格

ISpheroid pspheroid = spatialReferenceFactory.CreateSpheroid ((int)esriSRSpheroidType.esriSRSpheroid_Krasovsky1940); //在土地利用矢量数据交换格式中,采用克拉索夫斯基椭球。 ILinearUnitEdit lunitedit = new LinearUnitClass();

double unit = 1;

switch (m_headfile.Unit_VCT.ToUpper())

{

case "M":

lunitedit.DefineEx(" ", " ", " ", "M", ref unit); break;

case "MM":

unit = 0.001 * unit;

lunitedit.DefineEx(" ", " ", " ", "MM", ref unit); break;

case "CM":

unit = 0.01 * unit;

lunitedit.DefineEx(" ", " ", " ", "CM", ref unit); break;

case "DM":

unit = unit * 0.1;

lunitedit.DefineEx(" ", " ", " ", "M", ref unit);

break;

default:

lunitedit.DefineEx(" ", " ", " ", "M", ref unit); break;

}

ILinearUnit lunit = lunitedit as ILinearUnit;

IParameter[] parameter = new IParameter[5];

parameter[0] =

spatialReferenceFactory.CreateParameter((int)esriSRParameterType.esriSRParameter_FalseEasting);//esriSRParameterType.esriSRParameter_FalseEasting parameter[0].Value = 500000.000000;

parameter[1] =

spatialReferenceFactory.CreateParameter((int)esriSRParameterType.esriSRParameter_FalseNorthing);//esriSRParameterType.esriSRParameter_FalseNorthing parameter[1].Value = 0;

parameter[2] =

spatialReferenceFactory.CreateParameter((int)esriSRParameterType.esriSRParameter_CentralMeridian);

parameter[2].Value = m_headfile.Meridinan;

parameter[3] =

spatialReferenceFactory.CreateParameter((int)esriSRParameterType.esriSRParameter_ScaleFactor);

parameter[3].Value = m_headfile.Scale;

parameter[4] =

spatialReferenceFactory.CreateParameter((int)esriSRParameterType.esriSRParameter_LongitudeOfOrigin);

parameter[4].Value = 0;

IProjectedCoordinateSystem proCoord = new

ProjectedCoordinateSystemClass();

IProjectedCoordinateSystemEdit proCoordEdit = proCoord as IProjectedCoordinateSystemEdit;

IGeographicCoordinateSystem pGCS = CreateGCS();

pGCS.SetDomain(m_headfile.MinX, m_headfile.MaxX, m_headfile.MinY, m_headfile.MaxY);

IGeographicCoordinateSystem2 pGCS2 = pGCS as

IGeographicCoordinateSystem2;

pGCS2.set_LeftLongitude(true, 114);

pGCS2.set_RightLongitude(true, 120);

object name1 = "Kass-Crug";

object alias = "UTM";

object abbreviation = "Trans_Merc";

object remarks = "Transverse Mercator is the projection";

object usage = "";

object GCS = pGCS;

object lineUnit = lunit;

object pProject = projection;

object para = parameter;

proCoordEdit.Define(ref name1, ref alias, ref abbreviation, ref remarks, ref usage, ref GCS, ref lineUnit,

ref pProject, ref para);

/*IUnknownCoordinateSystem proCoord = new

UnknownCoordinateSystemClass();*/

//proCoord.SetDomain(m_headfile.MinX, m_headfile.MaxX,

m_headfile.MinY, m_headfile.MaxY);

//proCoord.set_CentralMeridian(true, m_headfile.Meridinan);

proCoord.ScaleFactor = m_headfile.Scale;

proCoord.SetDomain(-10000, 10000,-10000, 10000);

/* proCoord.set_CentralMeridian(true, m_headfile.Meridinan);*/ ipSpatialRef = (ISpatialReference)proCoord;

ipGeodefEdit.GeometryType_2 = shapeType;

////////////声明结束/////////////////////////////////////// ipGeodefEdit.HasM_2 = false;

ipGeodefEdit.HasZ_2 = false;

ipGeodefEdit.SpatialReference_2 = ipSpatialRef;

pFieldEdit.Name_2 = "Shape";

pFieldEdit.Type_2 = esriFieldType.esriFieldTypeGeometry;

pFieldEdit.GeometryDef_2 = ipGeodef;

pFieldsEdit.AddField(pField);

///////////////////////////////////////////////////////////////////设置

shape文件的基本属性

featureClass = ifeatws.CreateFeatureClass(name, pFields, null, null, esriFeatureType.esriFTSimple, "Shape", "");

其中中间一段为设置空间参考,也可以设置为unknown,参考spatialreference.

创建地理坐标系统系统

public IGeographicCoordinateSystem CreateGCS()

{

ISpatialReferenceFactory spatialReferenceFactory = new

SpatialReferenceEnvironmentClass();

//Create a geographic coordinate system using the available geographic

//coordinate systems. These can be found in the esriGeometry esriSRGeoCSType

//enumeration.

IGeographicCoordinateSystemEdit pGCS = new

GeographicCoordinateSystemClass();

IDatum pDatum =

spatialReferenceFactory.CreateDatum((int)esriSRDatumType.esriSRDatum_Krasovksy1940);

IUnit pUnit =

spatialReferenceFactory.CreateUnit((int)esriSRUnitType.esriSRUnit_Meter); string name = "Xiaobao";

string alias = "xiaobao GCS";

string abbreviation = "UserDefined";

string remarks = "HAHA";

string usage = "Suitable for the China";

IPrimeMeridianEdit primEdid = new PrimeMeridianClass(); IPrimeMeridian pprimemeridian=primEdid as IPrimeMeridian; double meridian =117;

primEdid.DefineEx("","","","",ref meridian);

IAngularUnitEdit pAngularunitEdit = new AngularUnitClass(); double radiusperdegree=0.008726646;

pAngularunitEdit.DefineEx("", "", "", "", ref radiusperdegree); IAngularUnit pAngularunit = pAngularunitEdit as IAngularUnit;

pGCS.DefineEx(name, alias, abbreviation, remarks, usage, pDatum, pprimemeridian, pAngularunit);

return (IGeographicCoordinateSystem)pGCS;

}

获得ITable中的row

IQueryFilter pQueryfielter = new QueryFilterClass();

ICursor pCursor = pTable.Search(pQueryfielter,false);

IRow pRow = pCursor.NextRow();

其中pTable为已经获得的ITable,可以从IFeatureclass转换而来也可以打开 mdb而生成

从ACCESS打开一个工作空间

Public IWorkspace open_pGDB_Workspace(string database)

{

IPropertySet propertySet = new

ESRI.ArcGIS.esriSystem.PropertySetClass();

propertySet.SetProperty("DATABASE", database); IWorkspaceFactory workspaceFactory = new

ESRI.ArcGIS.DataSourcesGDB.AccessWorkspaceFactoryClass(); return workspaceFactory.Open(propertySet, 0); }

钩子的利用:

在AE 开发中,可以利用钩子把mapcontrol给传到由ITool或者ICommond继承的命令或者工具里,传进去的钩子就是hook,类型是一个object,实际上就是一个mapcontrol,可以用强制转换为MapControl

ICommand GTCStandard;

if (!Match.ImageMatch.m_isAlive)

{

GTCStandard = new MatchTool();

GTCStandard.OnCreate(axMapControl1.GetOcx()); if (GTCStandard != null)

axMapControl1.CurrentTool = (ITool)GTCStandard; 上面的代码是在主框架中将钩子传给由basetool或者 basecommond继承而来的命令或者工具。

这样还有一个利用就是,在由命令或者工具里生成的form,可以把钩子先传到form里,要是mapcontrol的currenttool不是这个命令,可以在form ,声明一个mapcontrol,将钩子转换为mapcontrol,然后把当前命令置为想要变成的命令。

查找指定定字段的位置

int GetFieldNum(string name,IFields pFields)

{

for(int i=0;i<pFields.FieldCount;i++)

{

if(pFields.get_Field(i).Name==name)

return i;

}

}

[国家标准]图幅号转换

//'*********************************************** //' 图名解析与合成——国标

//' , 0205

//' , 0207

//' Chengdu KODY Co. Ltd.

//' 0307 VC->VB(将原来的VC版程序改成VB代码)

//'成都 KODY Co. Ltd.

//'*********************************************** //' Description:

//' 根据图名解析图廓左下角经纬度坐标

//' Examples:

//' 图名规范执行国标,例如1:50,000地形图图幅编号:J50E015008,其中:

//' J50是1:1,000,000图幅编号,J代表从赤道(A)起按纬度4°的编号,50代表从经度180°起自西向东按经度6°的编号;

//' E是比例尺代码,代表1:50,000;

//' 015代表在J50图幅内自北向南第15行(每行10′); //' 008代表在J50图幅内自西向东第8列(每列15′); //' Parameters:

//' filename - 输入,图幅文件名,可能带有后缀 //' B, L - 输出,图幅左下角经纬度坐标 //' DeltaB, DeltaL, - 输出,图幅经纬度坐标跨度 //' Notes:

//' 得到的经度为[0,360)度,东经均大于180度,没有等于360的 //' Return Value:

//' false - 不能正确解析图名,可能不符合图幅命名规范 //' true - 正常执行

public bool FileName2BL_standard(string fileName, ref double B,

ref double L,

ref double deltaB,

ref double deltaL)

{

long row, col;

long bigrow, bigcol;

string Code;

string mFileName, temp;

long a, bb, c, d;

double addlongitude, addlatitude;

long pos, iIndex;

string sTemp, mStr;

if ((fileName == "") | (fileName == null)) {

return false;

}

mFileName = fileName.ToLower();

pos = 0;

if (mFileName.Length < 10)

{

return false;

}

mStr = mFileName.Substring(0, 1);

bigrow = System.Convert.ToInt16(mStr);

mStr = mFileName.Substring(1, 2);

bigcol = System.Convert.ToInt16(mStr);

Code = mFileName.Substring(3, 1);

mStr = mFileName.Substring(4, 3);

row = System.Convert.ToInt16(mStr);

mStr = mFileName.Substring(7, 3);

col = System.Convert.ToInt16(mStr);

switch (Code.ToUpper())

{

case "B": // 1:250000

addlongitude = 1.5;// //'1 addlatitude = 1.0; break;

case "C": //1:200000

addlongitude = 1.5; // '1 addlatitude = 1.0;// '1 break;

case "D":// 1:100000 度30' //'1度 度30' 度

addlongitude = 0.5; //'30' addlatitude = 1.0 / 3.0; //'20' break;

case "E": //1:50000

addlongitude = 0.25; //'15' addlatitude = 1.0 / 6.0; //'10' break;

case "F":// 1:25000

addlongitude = 0.125; //'7'30" addlatitude = 1.0 / 12.0;

addlongitude = 0.0625; addlatitude = 1.0 / 24.0;

addlongitude = 0.03125; addlatitude = 1.0 / 48.0;

addlongitude = 0.03125; addlatitude = 1.0 / 48.0;

}

a = (bigrow - 97) + 1;

bb = bigcol;

c = row;

d = col;

L = (bb - 1.0) * 6.0 + (d - 1.0) * addlongitude;

B = (a - 1.0) * 4.0 + (4.0 / addlatitude - c) * addlatitude;

deltaL = addlongitude;

deltaB = addlatitude;

}

//'5' break; case "G":// 1:10000 //3'45" //2'30" break; case "H"://1:5000 //1'52.5" //1'15" break; case "I": //1:2000 //1'52.5" //1'15" break; default: return false; break; //if (bb >= 30) bb = bb - 30; //保证在东经 return true;

在 ITable中找到指定值所在记录行

private IRow FindMatchRecord(ITable pTable, object valve, int fieldnum) {

try

{

IQueryFilter pQueryFilter = new QueryFilterClass(); ICursor pCursor = pTable.Search(pQueryFilter, false); IRow pRow = pCursor.NextRow();

while (pRow != null && pRow.get_Value(fieldnum) != valve) {

pRow = pCursor.NextRow();

}

return pRow;

}

catch (Exception e)

{

MessageBox.Show(e.Message);

Dispose(true);

return null;

}

}

在Fields找到制定字段名字所在位置 (指定类型(Shape)) private int GetFiledNum(IFields pFields, string name)

{

try

{

for (int i = 0; i < pFields.FieldCount; i++) {

if (pFields.get_Field(i).Name == name) return i;

}

return -1;

}

catch (Exception e)

{

MessageBox.Show(e.Message);

Dispose(true);

return -1;

}

}

private int GetFieldNum(IFields pFields, esriFieldType type)

{

try

{

for (int i = 0; i < pFields.FieldCount; i++)

{

if (pFields.get_Field(i).Type == type)

{

return i;

}

}

return -1;

}

catch (System.Exception e)

{

MessageBox.Show(e.Message);

return -1;

}

}

关于ArcEngine开发程序中关闭时内存泄漏的问题

一、AE9.0和9.1中解决办法

在AE9.0和9.1中,就出现了Arc Engine开发程序中关闭时内存泄漏的问题,弹出个错误,让人十分不爽.后来查找相关资料,需要在关闭窗体时,加一个函数。 private void frmMain_Closing(object

AE学习积累

sender, System.ComponentModel.CancelEventArgs e) {

ESRI.ArcGIS.Utility.COMSupport.AOUninitialize.Shutdown();

}

二、在AE9.2中解决方法

后来听说在AE9.1的补丁中,不需要加这么句,我也试过,不知道真的改了没有。

这些天在用AE9.2,我晕了ESRI还没有解决这个问题。我仍用上面的语句,编译通过,但发现有个警告,提示上面的方法已经过时。根据提示,改了类库了。 private void Form1_FormClosing(object sender, FormClosingEventArgs e)

{

ESRI.ArcGIS.ADF.COMSupport.AOUninitialize.Shutdown();

}

判断线段左右多边形

/// <summary>

/// 找到线段的左右多边形,但线段为悬挂线,返回的rightpolygon为包含悬挂线的多边形

/// </summary>

/// <param name="pPolyline"></param>

/// <param name="pFeatureClass"></param>

/// <param name="rightPolygon"></param>

/// <param name="leftPolygon"></param>

/// <returns></returns>

private bool GetRightLeftPolygon(IPolyline pPolyline, IFeatureClass pFeatureClass,

ref IFeature rightPolygon, ref IFeature leftPolygon)

{

int right = 0;

int left = 0;

try

{

ISpatialFilter pSpatialFilter = new SpatialFilterClass(); pSpatialFilter.Geometry = pPolyline;

pSpatialFilter.GeometryField = pFeatureClass.ShapeFieldName;

if (0 == rel)

{

pSpatialFilter.SpatialRel =

esriSpatialRelEnum.esriSpatialRelWithin;

}

if (1 == rel)

{

pSpatialFilter.SpatialRel =

esriSpatialRelEnum.esriSpatialRelRelation;

pSpatialFilter.SpatialRelDescription ="*T*******"; }

IFeatureCursor pFeatureCursor =

pFeatureClass.Search(pSpatialFilter, false);

IFeature pFeature = pFeatureCursor.NextFeature();

int n = 0;

while(pFeature!=null)

{

if (IsRightGeometry(pPolyline,

(IPolygon)pFeature.Shape))

{

rightPolygon = pFeature;

right++;

}

else

{

leftPolygon = pFeature;

left++;

}

pFeature = pFeatureCursor.NextFeature();

n++;

}

if(0==n)

{

pSpatialFilter.SpatialRel =

esriSpatialRelEnum.esriSpatialRelWithin;

pFeatureCursor = pFeatureClass.Search(pSpatialFilter,

false);

pFeature = pFeatureCursor.NextFeature();

if (pFeature == null)

return false;

if (IsRightGeometry(pPolyline,

(IPolygon)pFeature.Shape))

{

rightPolygon = pFeature;

right++;

n++;

}

else

{

leftPolygon = pFeature;

left++;

n++;

}

}

return true;

}

catch (Exception e)

{

MessageBox.Show(e.Message);

return false;

}

}

/// <summary>

/// 通过线段法线端点是否在多边形内来判断是否是右多边形

/// </summary>

/// <param name="pPolyline"></param>

/// <param name="pPolygon"></param>

/// <returns></returns>

private bool IsRightGeometry(IPolyline pPolyline,IPolygon pPolygon) {

object missing=Type.Missing;

ILine normal = new LineClass();

double len = pPolyline.Length / 2;

pPolyline.QueryNormal(esriSegmentExtension.esriNoExtension,len, false, 0.5, normal);

bool isright=false;

IPoint pt1 = normal.ToPoint;

IPoint outpoint=new PointClass();

double hitdistance=0;

int hitIndex=0;

int hitsegmentindex=0;

double x=0;

pPolygon.QueryPointAndDistance(esriSegmentExtension.esriExtendEmbedded,pt1,false,outpoint,ref hitdistance,

ref x,ref isright); //判断法线端点是否在多边形内,在的为右多边形,不在为左多边形

if (isright)

return true;

else

return false;

}

////

上面代码是先前写的,在空间搜索上,很容易漏掉一些。后来尝试了多种方法,觉得一种组合是最好的,先严后宽。先写出一个可能会漏掉,但不会超出的过滤函数,再写一个可能超出但不会漏掉的。其实如果数据ok的话,这里面的一种方法就可以搞定了。但是为了加强程序强度,不要因为数据的质量而出错,当然,觉得的错误数据那就没有办法了,比如一条根本就没有打断的线,无能为力阿

严的方法就是先空间过滤搜索,然后把用Topo操作,将polyline和多边形做相交,然后比较交出来的几何物体与与原polyline长度的差,在很小范围内的就是那条公共边了。

松的方法是先空间过滤,同样求交,但这次根据交点的个数来判断。但要排除包含情况,不是悬挂线的包含,是大图幅中包含岛的边给选上了,以下是改进的两个空间过滤方法。其他的步骤不变

private int GetRightLeftPolygon(IPolyline pPolyline, IFeatureClass

pFeatureClass,IQueryFilter pQueryFilter,

ref IFeature rightPolygon, ref IFeature leftPolygon)

{

int right = 0;

int left = 0;

try

{

IGeometry mapGeo = (IGeometry)pPolyline;

ITopologicalOperator pTopop =

(ITopologicalOperator)pPolyline;

string whereClaues = "";

whereClaues = " NOT ((XMIN > " + mapGeo.Envelope.XMax.ToString() + ") OR ";

whereClaues = whereClaues + " (XMAX < " +

mapGeo.Envelope.XMin.ToString() + ") OR ";

whereClaues = whereClaues + " (YMIN > " +

mapGeo.Envelope.YMax.ToString() + ") OR ";

whereClaues = whereClaues + " (YMAX < " +

mapGeo.Envelope.YMin.ToString() + "))";

ISpatialFilter pSpatialFilter = new SpatialFilterClass(); pSpatialFilter.Geometry = pPolyline;

pSpatialFilter.WhereClause = whereClaues;

pSpatialFilter.GeometryField = pFeatureClass.ShapeFieldName;

pSpatialFilter.SearchOrder =

esriSearchOrder.esriSearchOrderAttribute;

pSpatialFilter.SpatialRel =

esriSpatialRelEnum.esriSpatialRelRelation;

pSpatialFilter.SpatialRelDescription = "*********"; IQueryFilter filter = new QueryFilterClass();

filter.WhereClause = whereClaues;

IFeatureCursor pFeatureCursor = pFeatureClass.Search(filter, false);

// int count =

pFeatureClass.FeatureCount(filter);

IFeature pFeature = pFeatureCursor.NextFeature();

int n = 0;

while (pFeature != null)

{

Application.DoEvents();

IGeometry otherGeo = pFeature.Shape;

IGeometry intersect = pTopop.Intersect(otherGeo, esriGeometryDimension.esriGeometry1Dimension);

if (!intersect.IsEmpty)

{

IPolyline intersectPolyline = (IPolyline)intersect; if (Math.Abs(intersectPolyline.Length -

pPolyline.Length) < 1)

{

if (IsRightGeometry(pPolyline,

(IPolygon)otherGeo))

{

rightPolygon = pFeature;

right++;

}

else

{

leftPolygon = pFeature;

left++;

}

n++;

}

}

pFeature = pFeatureCursor.NextFeature();

}

if (n == 0)

{

// MessageBox.Show("Fuck");

pFeatureCursor = pFeatureClass.Search(filter, false);

pFeature = pFeatureCursor.NextFeature();

while (pFeature != null)

{

IGeometry otherGeo = pFeature.Shape;

IRelationalOperator pRelOp =

(IRelationalOperator)otherGeo;

if (!pRelOp.Within(pPolyline))

{

IGeometry pIntersect = pTopop.Intersect(otherGeo,

esriGeometryDimension.esriGeometry1Dimension);

IPolyline tempPolyLine = (IPolyline)pIntersect; IPointCollection pIntersectPointColl =

(IPointCollection)pIntersect;

if (pIntersectPointColl.PointCount >=

2&&tempPolyLine.Length>0.05)

{

if (IsRightGeometry(pPolyline,

(IPolygon)pFeature.Shape))

{

rightPolygon = pFeature;

right++;

n++;

}

else

{

leftPolygon = pFeature;

left++;

n++;

}

}

}

pFeature = pFeatureCursor.NextFeature();

}

}

// if (0 == n) //如果漏

掉启用另外一种方案

// {

// pSpatialFilter.WhereClause =

pQueryFilter.WhereClause;

// pSpatialFilter.SpatialRelDescription = "FTF******"; // pFeatureCursor = pFeatureClass.Search(pSpatialFilter, false);

// pFeature = pFeatureCursor.NextFeature();

// if (IsRightGeometry(pPolyline,

(IPolygon)pFeature.Shape))

// {

// rightPolygon = pFeature;

// right++;

// n++;

// }

// else

// {

// leftPolygon = pFeature;

// left++;

// n++;

// }

// pFeature = pFeatureCursor.NextFeature();

//

// }

if (n == 0) 悬挂线情况

{

pSpatialFilter.SpatialRel =

esriSpatialRelEnum.esriSpatialRelWithin;

while (pFeature != null)

{

if (IsRightGeometry(pPolyline,

(IPolygon)pFeature.Shape))

{

rightPolygon = pFeature;

right++;

n++;

}

else

{

leftPolygon = pFeature;

left++;

n++;

}

pFeature = pFeatureCursor.NextFeature();

}

} //

if (n > 2 || right > 1 || left > 1)

{

m_writer.WriteLine(n.ToString()+"topo寻找左右多边形错误");

}

if (n == 0)

{

m_writer.WriteLine("没有找到多边形");

}

Marshal.ReleaseComObject(pFeatureCursor);

return n;

}

catch (Exception e)

{

m_writer.WriteLine(DateTime.Now.ToString() + ":" + e.Message);

return 0;

}

}

ArcEngine 图层渲染

1.Feature的基本渲染方法 Feature的常用的绘制方法包括:

1.简单绘制

2.唯一值绘制/多字段唯一值绘制

3.点密度/多字段点密度绘制

4.数据分级绘制

5.质量图(饼图/直方图)

6.按比例尺渲染

7.比例符号渲染

1.简单渲染

简单渲染是ArcEngine的默认渲染,我们打开一个FeatureClass,建立一个atureLayer的时候,如果没有给 FeatureLayer设置Renderer那么使用的就是简单渲染。简单渲染对整个图层中的所有Feature 使用同一种方式显示。 简单渲染在ArcEngine中用ISimpleRenderer来表示。 ISimpleRenderer的使用方式如下: //假设layer是一个IFeatureLayer,获取IGeoFeatureLayer IGeoFeatureLayer geoLayer=layer as IGeoFeatureLayer; //构造

SimpleRenderer ISimpleRenderer renderer=new SimpleRendererClass(); renderer.description="简单的渲染一下"; renderer.Label="符号的标签"; //假设sym是一个和该图层中Geometry类型对应的符号; renderer.Symbol=sym; //为图层设置渲染,注意需要刷新该图层。 geoLayer.Renderer=renderer;

2.独立值/多字段独立值渲染

独立值/多字段独立值渲染,根据Feature的某一个字段的数据或某几个字段的组合结果来确定符号。 具有相同值或相同组合值的Feature,使用一样的符号。在使用多个字段的使用,每个字段的取值之间 使用分割符来连接。字段的取值顺序和在Renderer中设置的一样。 基本使用方式如下: //假设layer是一个IFeatureLayer,获取IGeoFeatureLayer IGeoFeatureLayer geoLayer=layer as IGeoFeatureLayer; //构造一个UniqueValueRenderer IUniqueValueRenderer renderer=new UniqueValueRendererClass(); //假设使用两个字段来渲染 renderer.FieldCount=2; //假设YSLX字段表示要素类型 //假设YSYT字段表示要数用途 renderer.set_Field(0,"YSLX");

renderer.set_Field(1,"YSYT"); //字段之间使用 | 来连接(默认取值) renderer.FieldDelimiter="|"; //设置默认符号

renderer.DefaultSymbol=defaultSymbol; renderer.DefaultLabel="默认Label"; //添加值 renderer.addValue("房屋|民居","民居房屋",MJSymbol); renderer.addValue("房屋|商业用地","商业用地",SYSymbol); ... //还可以通过set_Symbol,set_Heading、set_Value来修改上述设置。

geoLayer.Renderer=renderer.

3.点密度/多字段点密度

点密度图通过在Feature的图形上打点来表示数据的数多,点越密集表示数据量越大。 还可以使用多字段的点密度图。这个使用同一个Feature上就可以显示几种不同的点。 注意点密度图有一个特殊的地方: 点密度图使用的符号是面状符号。而其中有需要包括点状符号。

接口使用如下:

IDotDensityRenderer renderer=new DotDensityRendererClass (); IRendererFields flds=(IRendererFields)renderer;

flds.AddField("MJ ","面积");

flds.AddField("RK","人口");

IDotDensityFillSymbol ddSym=new DotDensityFillSymbolClass(); ISymbolArray symArray=(ISymbolArray)ddSym;

symArray.AddSymbol(mjSymbol);

symArray.AddSymbol(rkSymbol);

ddSym.Outline =(ILineSymbol)outlineSymbol ;

ddSym.DotSize =10 ;

ddSym.FixedPlacement=true;

renderer.DotDensitySymbol =ddSym;

renderer.DotValue=20 ;

renderer.MaintainSize=this.m_dotdensityParam .MaintainSize ; IGeoFeatureLayer geoLayer=(IGeoFeatureLayer)layer ;

geoLayer.Renderer =(IFeatureRenderer)renderer;

4.数据分级绘制(使用IClassBreaksRenderer)

5.饼图/直方图(使用IChartRenderer)

6.按比例尺渲染(使IScaleDependentRenderer)

7.比例符号渲染(使用 IProportionalSymbolRenderer )

2.图例的使用 图例的使用通过ILegendInfo接口。每个Renderer都实现了该接口,但是有时候该实现不好用, 所以也可以自己实现该接口。实现过程是比较简单的。

3.渲染层次 使用ILevelRender 接口。该接口可以指定一 当前的Level(-1)表示绘制全部。 然后 提供一个符号数组 ,注意每个符号要指定Level .如果不指定就默认为0。

4.透明度控制 透明度控制使用 ITransparencyRenderer 接口。该接口允许指定一个字段,字段取值用来表示透明度 注意 透明度的取值在0--100之间。

5.数据正规化 数据正规化用 IDataNormalization 接口来表示。该接口提供了几种正规化表示方法。

6. 部分渲染 部分渲染通过使用IDataExclusion 来实现。该接口允许提供过滤语句来过滤掉不需要渲染的Feature。 同时也可以给他们制定特殊的符号。同时控制是否显示 7.旋转控制 旋转控制通过使用IRotationRenderer 接口来表示。该接口要求提供旋转角度的字段。同时要求提供旋转的 方法。

8.数据样本 IDataSampling 没有使用过。

9.外表关联

ITable dispTable=((IDisplayTable)feaLayer).DisplayTable ;//图层 ITable attTable;

//外表

IMemoryRelationshipClassFactory fac=new

MemoryRelationshipClassFactoryClass ();

IRelationshipClass

relClass=fac.Open("JZMJ",(IObjectClass)dispTable,"ZDDJH",

IObjectClass)attTable,"G03", "Forward","Backward",

RelCardinality.esriRelCardinalityOneToOne);

IDisplayRelationshipClass dispRelClass=feaLayer as

IDisplayRelationshipClass ;

dispRelClass.DisplayRelationshipClass(relClass,esriJoinType.esriLeftInnerJoin);

10.统计分析

ITableHistogram tableHistogram=new BasicTableHistogramClass (); tableHistogram.Table =((IDisplayTable)layer).DisplayTable ;

tableHistogram.Field =fieldName ; object valueArray=null, freq=null; IBasicHistogram basicHistogram=(IBasicHistogram)tableHistogram; basicHistogram.GetHistogram(out valueArray,out freq); IClassify classify=null;

int breakNum=6; //分类方法

switch(ClassifyMethod )

{

case ClassifyMethodName.lsClassifyMethodEqualInterval:

{

EqualIntervalClass eq=new EqualIntervalClass ();

eq.Classify (valueArray,freq,ref breakNum);

classify=(IClassify)eq; break;

}

case ClassifyMethodName.lsClassifyMethodStandardDeviation: {

StandardDeviationClass sd=new StandardDeviationClass (); IStatisticsResults stat= histogram as IStatisticsResults ; classify=sd as IClassify;

classify.SetHistogramData (valueArray,freq);

IDeviationInterval di=sd as IDeviationInterval ;

di.DeviationInterval=1;

di.Mean=stat.Mean;

di.StandardDev=stat.StandardDeviation;

classify.Classify (ref breakNum); break;

}

case ClassifyMethodName.lsClassifyMethodQuantile:

{

Quantile qc=new QuantileClass ();

qc.Classify (valueArray,freq,ref breakNum);

classify=qc as IClassify ;

break;

}

case ClassifyMethodName.lsClassifyMethodNaturalBreaks:

{

NaturalBreaksClass nb=new NaturalBreaksClass ();

nb.Classify (valueArray,freq,ref breakNum);

classify=nb as IClassify ; break;

}

case ClassifyMethodName.lsClassifyMethodDefinedInterval: {

DefinedIntervalClass di=new DefinedIntervalClass ();

di.IntervalRange =this.m_classBreaksParam .Interval ; di.Classify (valueArray,freq,ref breakNum);

classify=di as IClassify ;

break;

}

default:

{

EqualIntervalClass eq=new EqualIntervalClass ();

eq.Classify (valueArray,freq,ref breakNum);

classify=(IClassify)eq;

break;

}

}

object o=classify.ClassBreaks ;

System.Array breakArray= o as System.Array;

现在breakArray中就是统计后的数据了

由featureclasss或者table来获得workspaceedit

IDataset pDataSet = DLTBTable as IDataset;

IWorkspace tempWorkSpace = pDataSet.Workspace;

IWorkspaceEdit pWorkEdit = tempWorkSpace as IWorkspaceEdit; 在featurlclass中有featruedataset,可以转化成IDataset

C#制作鹰眼全过程(带注释)

xMapControl1是主控件

要看清楚事件响应

1.鹰眼地图资源载入

private void axMapControl1_OnMapReplaced(object sender, IMapControlEvents2_OnMapReplacedEvent e)

{

//当主地图显示控件的地图更换时,鹰眼中的地图也跟随更换

axMapControl2.LoadMxFile(axMapControl1.DocumentFilename); axMapControl2.Extent = axMapControl2.FullExtent;

}

2.绘制鹰眼矩形框

private void axMapControl1_OnExtentUpdated(object sender,

IMapControlEvents2_OnExtentUpdatedEvent e)

{

// 得到新范围

IEnvelope pEnv = (IEnvelope)e.newEnvelope;

IGraphicsContainer pGra = axMapControl2.Map as IGraphicsContainer;

IActiveView pAv = pGra as IActiveView;

//在绘制前,清除axMapControl2中的任何图形元素

pGra.DeleteAllElements();

IRectangleElement pRectangleEle = new RectangleElementClass(); IElement pEle = pRectangleEle as IElement;

pEle.Geometry = pEnv;

//设置鹰眼图中的红线框

IRgbColor pColor = new RgbColorClass();

pColor.Red = 255;

pColor.Green = 0;

pColor.Blue = 0;

pColor.Transparency = 255;

//产生一个线符号对象

ILineSymbol pOutline = new SimpleLineSymbolClass(); pOutline.Width = 2;

pOutline.Color = pColor;

//设置颜色属性

pColor = new RgbColorClass();

pColor.Red = 255;

pColor.Green = 0;

pColor.Blue = 0;

pColor.Transparency = 0;

//设置填充符号的属性

IFillSymbol pFillSymbol = new SimpleFillSymbolClass();

pFillSymbol.Color = pColor;

pFillSymbol.Outline = pOutline;

IFillShapeElement pFillShapeEle = pEle as IFillShapeElement;

pFillShapeEle.Symbol = pFillSymbol;

pGra.AddElement((IElement)pFillShapeEle, 0);

pAv.PartialRefresh(esriViewDrawPhase.esriViewGraphics, null, null);

}

3. 实现互动

private void axMapControl2_OnMouseDown(object sender, IMapControlEvents2_OnMouseDownEvent e)

{

IPoint pPt=new PointClass ();

pPt.PutCoords (e.mapX ,e.mapY );

//改变主控件的视图范围

axMapControl1 .CenterAt (pPt );

}

利用UID获取图层集合

每种元素都有自己的UID,在IMap里有一个接口getlayers,是通过UID获得,就是不知道这个是否能够穿越group这一关。。。。。。有空试试

1.符号库条目接口

IStyleGalleryItem:

IStyleGalleryItem是ServerStyleGalleryItem类的接口

包括属性有

类别:Category

编号:ID

名称:Name

符号:Item

2.IStyleGalleryClass接口

IStyleGalleryClass是各个符号类别的接口,现在符号类别是固定的包括点,线,面,颜色,填充等十多种。

利用此借口可以增加新的符号,编辑符号,得到类别名称和描述等功能。 特别是利用Preview函数可以生成内存图片。

3.IStyleGallery接口

是符号库接口可以向符号文件增加新的符号并具有修改,删除等功能,并可以载入符号问件,载入指定的符号文件中的指定类别

public static System.Drawing.Bitmap StyleGalleryItemToBmp( int iWidth,

int iHeight,

ESRI.ArcGIS.Display.IStyleGalleryClass mStyleGlyCs, ESRI.ArcGIS.Display.IStyleGalleryItem mStyleGlyItem) {

//建立符合规格的内存图片

Bitmap bmp = new Bitmap(iWidth,iHeight);

Graphics gImage = Graphics.FromImage(bmp);

//建立对应的符号显示范围

ESRI.ArcGIS.Display.tagRECT rect = new ESRI.ArcGIS.Display.tagRECT(); rect.right = bmp.Width;

rect.bottom = bmp.Height;

//生成预览

System.IntPtr hdc = new IntPtr();

hdc = gImage.GetHdc();

//在图片上绘制符号

mStyleGlyCs.Preview(mStyleGlyItem.Item,hdc.ToInt32(),ref rect); gImage.ReleaseHdc(hdc);

gImage.Dispose();

return bmp;

}

1.

using ESRI.ArcGIS.Display;

2.

IStyleGallery pStyleGallery = new

ESRI.ArcGIS.Display.ServerStyleGalleryClass();

IStyleGalleryStoragepStyleGalleryStorage;

pStyleGalleryStorage = pStyleGallery as

ESRI.ArcGIS.Display.IStyleGalleryStorage;

//增加符号文件

pStyleGalleryStorage.AddFile(CurrentStyleFile);

//根据当前符号的类别和文件得到符号的枚举循环子

//符号类别包括Fill Symbol,Line Symbol等

ESRI.ArcGIS.Display.IEnumStyleGalleryItemmEnumStyleItem;

mEnumStyleItem =

pStyleGallery.get_Items(CurrentStyleGalleryClass,CurrentStyleFile,""); //得到符号文件类别的各个条目,增加到一个Combox中

ESRI.ArcGIS.esriSystem.IEnumBSTR pEnumBSTR =

this.pStyleGallery.get_Categories(this.CurrentStyleGalleryClass); pEnumBSTR.Reset();

string Category = "";

Category = pEnumBSTR.Next();

while(Category != null)

{

this.cbxCategory.Items.Add(Category);

Category = pEnumBSTR.Next();

}

3.

//得到各个符号并转化为图片

mEnumStyleItem.Reset();

mStyleItem = mEnumStyleItem.Next();

int ImageIndex =0;

while(mStyleItem != null)

{

//调用另一个类的方法将符号转化为图片

bmpB =

StyleGalleryItemView.StyleGalleryItemToBmp(32,32,mStyleClass,mStyleItem);

bmpS =

StyleGalleryItemView.StyleGalleryItemToBmp(16,16,mStyleClass,mStyleItem);

Largeimage.Images.Add(bmpB);

Smallimage.Images.Add(bmpS);

lvItem = new ListViewItem(new

string[]{mStyleItem.Name,mStyleItem.ID.ToString(),mStyleItem.Category},ImageIndex);

this.lvSymbolView.Items.Add(lvItem);

mStyleItem = mEnumStyleItem.Next();

ImageIndex++;

}

//必须采用此方式进行释放,第二次才能正常读取

System.Runtime.InteropServices.Marshal.ReleaseComObject(mEnumStyleItem);

GIS中的坐标系定义与转换

1. 椭球体、基准面及地图投影

GIS 中的坐标系定义是GIS系统的基础,正确定义GIS系统的坐标系非常重要。GIS中的坐标系定义由基准面和地图投影两组参数确定,而基准面的定义则由特定 椭球体及其对应的转换参数确定,因此欲正确定义GIS系统坐标系,首先必须弄清地球椭球体(Ellipsoid)、大地基准面(Datum)及地图投影 (Projection)三者的基本概念及它们之间的关系。

基 准面是利用特定椭球体对特定地区地球表面的逼近,因此每个国家或地区均有各自的基准面,我们通常称谓的北京54坐标系、西安80坐标系实际上指的是我国的 两个大地基准面。我国参照前苏联从19xx年起采用克拉索夫斯基

(Krassovsky)椭球体建立了我国的北京54坐标系,19xx年采用国际大地测量 协会推荐的1975地球椭球体建立了我国新的大地坐标系--西安80坐标系,目前大地测量基本上仍以北京54坐标系作为参照,北京54与西安80坐标之间 的转换可查阅国家测绘局公布的对照表。 WGS1984基准面采用WGS84椭球体,它是一地心坐标系,即以地心作为椭球体中心,目前GPS测量数据多以WGS1984为基准。

上述3个椭球体参数如下:

椭 球体与基准面之间的关系是一对多的关系,也就是基准面是在椭球体基础上建立的,但椭球体不能代表基准面,同样的椭球体能定义不同的基准面,如前苏联的 Pulkovo 1942、非洲索马里的Afgooye基准面都采用了Krassovsky椭球体,但它们的基准面显然是不同的。

地图投影是将地图从球面转换到平面的数学变换,如果有人说:该点北京54坐标值为X=4231898,Y=21655933,实际上指的是北京54基准面下的投影坐标,也就是北京54基准面下的经纬度坐标在直角平面坐标上的投影结果。

2. GIS中基准面的定义与转换

虽 然现有GIS平台中都预定义有上百个基准面供用户选用,但均没有我们国家的基准面定义。假如精度要求不高,可利用前苏联的Pulkovo 1942基准面

(Mapinfo中代号为1001)代替北京54坐标系;假如精度要求较高,如土地利用、海域使用、城市基建等GIS系统,则需要自定义基 准面。

GIS 系统中的基准面通过当地基准面向WGS1984的转换7参数来定义,转换通过相似变换方法实现,具体算法可参考科学出版社19xx年出版的《城市地理信息 系统标准化指南》第76至86页。假设Xg、Yg、Zg表示WGS84地心坐标系的三坐标轴,Xt、Yt、Zt表示当地坐标系的三坐标轴,那么自定义基准 面的7参数分别为:三个平移参数ΔX、ΔY、ΔZ表示两坐标原点的平移值;三个旋转参数εx、εy、εz表示当地坐标系旋转至与地心坐标系平行时,分别绕 Xt、Yt、Zt的旋转角;最后是比例校正因子,用于调整椭球大小。

MapX中基准面定义方法如下:

Datum.Set(Ellipsoid, ShiftX, ShiftY, ShiftZ, RotateX, RotateY, RotateZ, ScaleAdjust, PrimeMeridian)

其中参数: Ellipsoid为基准面采用的椭球体;

ShiftX, ShiftY, ShiftZ为平移参数;

RotateX, RotateY, RotateZ为旋转参数;

ScaleAdjust为比例校正因子,以百万分之一计;

PrimeMeridian为本初子午线经度,在我国取0,表示经度从格林威治起算。

美 国国家测绘局(National Imagery and Mapping Agency)公布了世界大多数国家的当地基准面至WGS1984基准面的转换3参数(平移参数),可从

http://164.214.2.59/GandG/wgs84dt/dtp.html 下载,其中包括有香港Hong Kong 1963基准面、台湾 Hu-Tzu-Shan 基准面的转换3参数,但是没有中国大陆的参数。

实 际工作中一般都根据工作区内已知的北京54坐标控制点计算转换参数,如果工作区内有足够多的已知北京54与WGS84坐标控制点,可直接计算坐标转换的7 参数或3参数;当工作区内有3个已知北京54与WGS84坐标控制点时,可用下式计算WGS84到北京54坐标的转换参数(A、B、C、D、E、F): x54 = AX84 + BY84 + C,y54 = DX84 + EY84 + F,多余一点用作检验;在只有一个已知控制点的情况下(往往如此),用已知点的北京54与WGS84坐标之差作为平移参数,当工作区范围不大时精度也足够 了。

从Mapinfo 中国的URL(.cn/download)可下载到包含北京54、西安80坐标系定义的 Mapinfow.prj文件,其中定义的北京54基准面参数为:(3,24,-123,-94,-0.02,0.25,0.13,1.1,0),西安 80基准面参数为:(31,24,-123,-94,-0.02,0.25,0.13,1.1,0),文件中没有注明其参数的来源,我发现它们与 Mapinfo参考手册附录G"定义自定义基准面"中的一个例子所列参数相同,因此其可靠性值得怀疑,尤其从西安80与北京54采用相同的7参数来看,至 少西安80的基准面定义肯定是不对的。因此,当系统精度要求较高时,一定要对所采用的参数进行检测、验证,确保坐标系定义的正确性。

3. GIS中地图投影的定义

我 国的基本比例尺地形图(1:5千,1:1万,1:2.5万,1:5万,1:10万,1:25万,1:50万,1:100万)中,大于等于50万的均采用高 斯-克吕格投影

(Gauss-Kruger),又叫横轴墨卡托投影(Transverse Mercator);小于50万的地形图采用正轴等角割园锥投影,又叫兰勃特投影(Lambert Conformal Conic);海上小于50万的地形图多用正轴等角园柱投影,又叫墨卡托投影(Mercator),我国的GIS系统中应该采用与我国基本比例尺地形图系 列一致的地图投影系统。

在MapX中坐标系定义由基准面、投影两部分参数组成,方法如下:

CoordSys.Set(Type, [Datum], [Units], [OriginLongitude],

[OriginLatitude],

[StandardParallelOne], [StandardParallelTwo], [Azimuth],

[ScaleFactor],

[FalseEasting], [FalseNorthing], [Range], [Bounds], [AffineTransform])

其中参数:Type表示投影类型,Type为1时地图坐标以经纬度表示,它是必选参数,它后面的参数都为可选参数;

Datum为大地基准面对象,如果采用非地球坐标(NonEarth)无需定义该参数; Units为坐标单位,如Units为7表示以米为单位;

OriginLongitude、OriginLatitude分别为原点经度和纬度;

StandardParallelOne、StandardParallelTwo为第一、第二标准纬线; Azimuth为方位角,斜轴投影需要定义该参数;

ScaleFactor为比例系数;

FalseEasting, FalseNorthing为东伪偏移、北伪偏移值;

Range为地图可见纬度范围;

Bounds为地图坐标范围,是一矩形对象,非地球坐标(NonEarth)必须定义该参数;

AffineTransform为坐标系变换对象。

相应高斯-克吕格投影、兰勃特投影、墨卡托投影需要定义的坐标系参数序列如下:

高斯-克吕格:投影代号(Type),基准面(Datum),单位(Unit),

中央经度(OriginLongitude),原点纬度(OriginLatitude),

比例系数(ScaleFactor),

东伪偏移(FalseEasting),北纬偏移(FalseNorthing)

兰勃特: 投影代号(Type),基准面(Datum),单位(Unit),

中央经度(OriginLongitude),原点纬度(OriginLatitude),

标准纬度1(StandardParallelOne),标准纬度2(StandardParallelTwo), 东伪偏移(FalseEasting),北纬偏移(FalseNorthing)

墨卡托: 投影代号(Type),基准面(Datum),单位(Unit),

原点经度(OriginLongitude),原点纬度(OriginLatitude),

标准纬度(StandardParallelOne)

在 城市GIS系统中均采用6度或3度分带的高斯-克吕格投影,因为一般城建坐标采用的是6度或3度分带的高斯-克吕格投影坐标。高斯-克吕格投影以6度或

3 度分带,每一个分带构成一个独立的平面直角坐标网,投影带中央经线投影后的直线为X轴(纵轴,纬度方向),赤道投影后为Y轴(横轴,经度方向),为了防止 经度方向的坐标出现负值,规定每带的中央经线西移500公里,即东伪偏移值为500公里,由于高斯-克吕格投影每一个投影带的坐标都是对本带坐标原点的相 对值,所以各带的坐标完全相同,因此规定在横轴坐标前加上带号,如(4231898,21655933)其中21即为带号,同样所定义的东伪偏移值也需要 加上带号,如21带的东伪偏移值为21500000米。

假如你的工作区位于21带,即经度在120度至126度范围,该带的中央经度为123度,采用Pulkovo 1942基准面,那么定义6度分带的高斯-克吕格投影坐标系参数为:(8,1001,7,123,0,1,21500000,0)。

那 么当精度要求较高,实测数据为WGS1984坐标数据时,欲转换到北京54基准面的高斯-克吕格投影坐标,如何定义坐标系参数呢?你可选择WGS

1984(Mapinfo中代号104)作为基准面,当只有一个已知控制点时(见第2部分),根据平移参数调整东伪偏移、北纬偏移值实现WGS84到北京 54的转换,如:(8,104,7,123,0,1,21500200,-200),也可利用 AffineTransform坐标系变换对象,此时的转换系数(A、B、C、D、E、F)中A、B、D、E为0,只有X、Y方向的平移值C、F ;当有3个已知控制点时,可利用得到的转换系数(A、B、C、

D、E、F)定义 AffineTransform坐标系变换对象,实现坐标系的转换,如:(8,104,7,123,0,1,21500000,0, map.AffineTransform),其中AffineTransform定义为AffineTransform.set(7,A、B、C、D、 E、F)(7表示单位米);当然有足够多已知控制点时,直接求定7参数自定义基准面就行了。

自定义IActiveViewEvents(用于监听activew事件)

using System;

using System.Collections.Generic;

using System.ComponentModel;

using System.Data;

using System.Drawing;

using System.Text;

using System.Windows.Forms;

namespace EngineWiringEventsCSharp

{

public partial class Form1 : Form

{

// ***** SECTION (Start): Declare Event Handlers

//

// Notes:

// Variables are prefixed with an 'm_' denoting that they are member variables.

// This means they are global in scope for this class. private

ESRI.ArcGIS.Carto.IActiveViewEvents_AfterDrawEventHandler

m_ActiveViewEventsAfterDraw;

private

ESRI.ArcGIS.Carto.IActiveViewEvents_AfterItemDrawEventHandler m_ActiveViewEventsAfterItemDraw;

private

ESRI.ArcGIS.Carto.IActiveViewEvents_ContentsChangedEventHandler m_ActiveViewEventsContentsChanged;

private

ESRI.ArcGIS.Carto.IActiveViewEvents_ContentsClearedEventHandler m_ActiveViewEventsContentsCleared;

private

ESRI.ArcGIS.Carto.IActiveViewEvents_FocusMapChangedEventHandler m_ActiveViewEventsFocusMapChanged;

private

ESRI.ArcGIS.Carto.IActiveViewEvents_ItemAddedEventHandler

m_ActiveViewEventsItemAdded;

private

ESRI.ArcGIS.Carto.IActiveViewEvents_ItemDeletedEventHandler

m_ActiveViewEventsItemDeleted;

private

ESRI.ArcGIS.Carto.IActiveViewEvents_ItemReorderedEventHandler m_ActiveViewEventsItemReordered;

private

ESRI.ArcGIS.Carto.IActiveViewEvents_SelectionChangedEventHandler m_ActiveViewEventsSelectionChanged;

private

ESRI.ArcGIS.Carto.IActiveViewEvents_SpatialReferenceChangedEventHandler m_ActiveViewEventsSpatialReferenceChanged;

private

ESRI.ArcGIS.Carto.IActiveViewEvents_ViewRefreshedEventHandler m_ActiveViewEventsViewRefreshed;

// ***** SECTION (End): Declare Event Handlers

// m_map is set to be global in scope because it will be used for both the AddHandler and RemoveHandler

private ESRI.ArcGIS.Carto.IMap m_map;

public Form1()

{

InitializeComponent();

}

private void btnStep1_Click(object sender, EventArgs e) {

// It is important to perfom the Explict Cast or else the wiring up of the Events with the

// AddHandler will not function properly. Also the if the Explict Cast is not performed

// when the RemoveHandler's are called a diconnected RCW error will result.

m_map = (ESRI.ArcGIS.Carto.IMap)

axMapControl1.ActiveView.FocusMap; // Explict Cast

TextBox3.Clear();

// ***** SECTION (Start): Set up the event handlers for all of the IActiveViewEvents

//

// Notes:

// You set the member IActiveViewEvents_XXXXXXXXX variables to the EventHandler

// for the specific events you want to capture.

//Create an instance of the delegate, add it to AfterDraw event

m_ActiveViewEventsAfterDraw = new

ESRI.ArcGIS.Carto.IActiveViewEvents_AfterDrawEventHandler(OnActiveViewEventsAfterDraw);

((ESRI.ArcGIS.Carto.IActiveViewEvents_Event)(m_map)).AfterDraw += m_ActiveViewEventsAfterDraw;

//Create an instance of the delegate, add it to AfterItemDraw event

m_ActiveViewEventsAfterItemDraw = new

ESRI.ArcGIS.Carto.IActiveViewEvents_AfterItemDrawEventHandler(OnActiveViewEventsItemDraw);

((ESRI.ArcGIS.Carto.IActiveViewEvents_Event)(m_map)).AfterItemDraw += m_ActiveViewEventsAfterItemDraw;

//Create an instance of the delegate, add it to

ContentsChanged event

m_ActiveViewEventsContentsChanged = new

ESRI.ArcGIS.Carto.IActiveViewEvents_ContentsChangedEventHandler(OnActiveViewEventsContentsChanged);

((ESRI.ArcGIS.Carto.IActiveViewEvents_Event)(m_map)).ContentsChanged += m_ActiveViewEventsContentsChanged;

//Create an instance of the delegate, add it to

ContentsCleared event

m_ActiveViewEventsContentsCleared = new

ESRI.ArcGIS.Carto.IActiveViewEvents_ContentsClearedEventHandler(OnActiveViewEventsContentsCleared);

((ESRI.ArcGIS.Carto.IActiveViewEvents_Event)(m_map)).ContentsCleared += m_ActiveViewEventsContentsCleared;

//Create an instance of the delegate, add it to

FocusMapChanged event

m_ActiveViewEventsFocusMapChanged = new

ESRI.ArcGIS.Carto.IActiveViewEvents_FocusMapChangedEventHandler(OnActiveViewEventsFocusMapChanged);

((ESRI.ArcGIS.Carto.IActiveViewEvents_Event)(m_map)).FocusMapChanged += m_ActiveViewEventsFocusMapChanged;

//Create an instance of the delegate, add it to ItemAdded event

m_ActiveViewEventsItemAdded = new

ESRI.ArcGIS.Carto.IActiveViewEvents_ItemAddedEventHandler(OnActiveViewEventsItemAdded);

((ESRI.ArcGIS.Carto.IActiveViewEvents_Event)(m_map)).ItemAdded += m_ActiveViewEventsItemAdded;

//Create an instance of the delegate, add it to ItemDeleted event

m_ActiveViewEventsItemDeleted = new

ESRI.ArcGIS.Carto.IActiveViewEvents_ItemDeletedEventHandler(OnActiveViewEventsItemDeleted);

((ESRI.ArcGIS.Carto.IActiveViewEvents_Event)(m_map)).ItemDeleted += m_ActiveViewEventsItemDeleted;

//Create an instance of the delegate, add it to ItemReordered event

m_ActiveViewEventsItemReordered = new

ESRI.ArcGIS.Carto.IActiveViewEvents_ItemReorderedEventHandler(OnActiveViewEventsItemReordered);

((ESRI.ArcGIS.Carto.IActiveViewEvents_Event)(m_map)).ItemReordered += m_ActiveViewEventsItemReordered;

//Create an instance of the delegate, add it to

SelectionChanged event

m_ActiveViewEventsSelectionChanged = new

ESRI.ArcGIS.Carto.IActiveViewEvents_SelectionChangedEventHandler(OnActiveViewEventsSelectionChanged);

((ESRI.ArcGIS.Carto.IActiveViewEvents_Event)(m_map)).SelectionChanged += m_ActiveViewEventsSelectionChanged;

//Create an instance of the delegate, add it to

SpatialReferenceChanged event

m_ActiveViewEventsSpatialReferenceChanged = new

ESRI.ArcGIS.Carto.IActiveViewEvents_SpatialReferenceChangedEventHandler(OnActiveViewEventsSpatialReferenceChanged);

((ESRI.ArcGIS.Carto.IActiveViewEvents_Event)(m_map)).SpatialReferenceChanged += m_ActiveViewEventsSpatialReferenceChanged;

//Create an instance of the delegate, add it to ViewRefreshed event

m_ActiveViewEventsViewRefreshed = new

ESRI.ArcGIS.Carto.IActiveViewEvents_ViewRefreshedEventHandler(OnActiveViewEventsViewRefreshed);

((ESRI.ArcGIS.Carto.IActiveViewEvents_Event)(m_map)).ViewRefreshed += m_ActiveViewEventsViewRefreshed;

// ***** SECTION (End): Set up the event handlers for all of the IActiveViewEvents

}

private void btnStep3_Click(object sender, EventArgs e) {

// ***** SECTION (Start): Remove Event Handlers

// Notes:

// Remove the event handlers that were wired up previously

((ESRI.ArcGIS.Carto.IActiveViewEvents_Event)(m_map)).AfterDraw -= m_ActiveViewEventsAfterDraw;

((ESRI.ArcGIS.Carto.IActiveViewEvents_Event)(m_map)).AfterItemDraw -= m_ActiveViewEventsAfterItemDraw;

((ESRI.ArcGIS.Carto.IActiveViewEvents_Event)(m_map)).ContentsChanged -= m_ActiveViewEventsContentsChanged;

((ESRI.ArcGIS.Carto.IActiveViewEvents_Event)(m_map)).ContentsCleared -= m_ActiveViewEventsContentsCleared;

((ESRI.ArcGIS.Carto.IActiveViewEvents_Event)(m_map)).FocusMapChanged -= m_ActiveViewEventsFocusMapChanged;

((ESRI.ArcGIS.Carto.IActiveViewEvents_Event)(m_map)).ItemAdded -= m_ActiveViewEventsItemAdded;

((ESRI.ArcGIS.Carto.IActiveViewEvents_Event)(m_map)).ItemDeleted -= m_ActiveViewEventsItemDeleted;

((ESRI.ArcGIS.Carto.IActiveViewEvents_Event)(m_map)).ItemReordered -= m_ActiveViewEventsItemReordered;

((ESRI.ArcGIS.Carto.IActiveViewEvents_Event)(m_map)).SelectionChanged -= m_ActiveViewEventsSelectionChanged;

((ESRI.ArcGIS.Carto.IActiveViewEvents_Event)(m_map)).SpatialReferenceChanged -= m_ActiveViewEventsSpatialReferenceChanged;

((ESRI.ArcGIS.Carto.IActiveViewEvents_Event)(m_map)).ViewRefreshed -= m_ActiveViewEventsViewRefreshed;

// ***** SECTION (End): Remove Event Handlers

}

// ***** SECTION (Start): Custom Functions that you write to add additionaly functionality for the events

//Event handler

private void

OnActiveViewEventsAfterDraw(ESRI.ArcGIS.Display.IDisplay Display, ESRI.ArcGIS.Carto.esriViewDrawPhase phase)

{

// Add your code here

//System.Windows.Forms.MessageBox.Show("AfterDraw"); TextBox3.Text = TextBox3.Text + "\r\n" + "AfterDraw"; }

//Event handler

private void OnActiveViewEventsItemDraw(short Index, ESRI.ArcGIS.Display.IDisplay Display,

ESRI.ArcGIS.esriSystem.esriDrawPhase phase)

{

// Add your code here

//System.Windows.Forms.MessageBox.Show("ItemDraw"); TextBox3.Text = TextBox3.Text + "\r\n" + "ItemDraw"; }

//Event handler

private void OnActiveViewEventsContentsChanged()

{

// Add your code here

//System.Windows.Forms.MessageBox.Show("ContentsChanged");

TextBox3.Text = TextBox3.Text + "\r\n" + "ContentsChanged"; }

//Event handler

private void OnActiveViewEventsContentsCleared()

{

// Add your code here

//System.Windows.Forms.MessageBox.Show("ContentsCleared");

TextBox3.Text = TextBox3.Text + "\r\n" + "ContentsCleared"; }

//Event handler

private void OnActiveViewEventsFocusMapChanged()

{

// Add your code here

//System.Windows.Forms.MessageBox.Show("FocusMapChanged");

TextBox3.Text = TextBox3.Text + "\r\n" + "FocusMapChanged"; }

//Event handler

private void OnActiveViewEventsItemAdded(object Item) {

// Add your code here

//System.Windows.Forms.MessageBox.Show("ItemAdded"); TextBox3.Text = TextBox3.Text + "\r\n" + "ItemAdded"; }

//Event handler

private void OnActiveViewEventsItemDeleted(object Item) {

// Add your code here

//System.Windows.Forms.MessageBox.Show("ItemDeleted"); TextBox3.Text = TextBox3.Text + "\r\n" + "ItemDeleted"; }

//Event handler

private void OnActiveViewEventsItemReordered(object Item, int toIndex)

{

// Add your code here

//System.Windows.Forms.MessageBox.Show("AfterDraw"); TextBox3.Text = TextBox3.Text + "\r\n" + "AfterDraw"; }

//Event handler

private void OnActiveViewEventsSelectionChanged()

{

// Add your code here

//System.Windows.Forms.MessageBox.Show("SelectionChanged");

TextBox3.Text = TextBox3.Text + "\r\n" + "SelectionChanged"; }

//Event handler

private void OnActiveViewEventsSpatialReferenceChanged() {

// Add your code here

//System.Windows.Forms.MessageBox.Show("SpatialReferenceChanged"); TextBox3.Text = TextBox3.Text + "\r\n" +

"SpatialReferenceChanged";

}

//Event handler

private void

OnActiveViewEventsViewRefreshed(ESRI.ArcGIS.Carto.IActiveView view, ESRI.ArcGIS.Carto.esriViewDrawPhase phase, object data,

ESRI.ArcGIS.Geometry.IEnvelope envelope)

{

// Add your code here

//System.Windows.Forms.MessageBox.Show("ViewRefreshed"); TextBox3.Text = TextBox3.Text + "\r\n" + "ViewRefreshed"; }

fit to display(和arcgis中功能相同)

private void btnDisplay_Click(object sender, EventArgs e)

{

try

{

IRasterGeometryProc pRasterGeoProc = new

RasterGeometryProcClass();

pRasterGeoProc.Reset(m_OperatorLayer.Raster);

double Active_XMax = m_hookhelper.ActiveView.Extent.XMax; double Active_XMin = m_hookhelper.ActiveView.Extent.XMin; double Active_YMax = m_hookhelper.ActiveView.Extent.YMax; double Active_YMin = m_hookhelper.ActiveView.Extent.YMin; double centx = (Active_XMax + Active_XMin) / 2;

double centy = (Active_YMax + Active_YMin) / 2;

Active_XMax = centx + m_hookhelper.ActiveView.Extent.Width / 4;

Active_XMin = centx - m_hookhelper.ActiveView.Extent.Width / 4;

Active_YMax = centy + m_hookhelper.ActiveView.Extent.Height / 4;

Active_YMin = centy - m_hookhelper.ActiveView.Extent.Height / 4;

IRasterProps pRasterProps = m_OperatorLayer.Raster as IRasterProps;

double XMax = pRasterProps.Extent.XMax;

double XMin = pRasterProps.Extent.XMin;

double YMax = pRasterProps.Extent.YMax;

double YMin = pRasterProps.Extent.YMin;

IPoint frompt1 = new PointClass();

IPoint frompt2 = new PointClass();

IPoint frompt3 = new PointClass();

IPoint frompt4 = new PointClass();

IPoint topt1 = new PointClass();

IPoint topt2 = new PointClass();

IPoint topt3 = new PointClass();

IPoint topt4 = new PointClass();

frompt1.PutCoords(XMin, YMin);

frompt2.PutCoords(XMin, YMax);

frompt3.PutCoords(XMax, YMax);

frompt4.PutCoords(XMax, YMin);

topt1.PutCoords(Active_XMin, Active_YMin);

topt2.PutCoords(Active_XMin, Active_YMax);

topt3.PutCoords(Active_XMax, Active_YMax);

topt4.PutCoords(Active_XMax, Active_YMin);

IPointCollection fromColl = (IPointCollection)new

PolygonClass();

IPointCollection toColl = (IPointCollection)new

PolygonClass();

fromColl.AddPoint(frompt1, ref missing, ref missing); fromColl.AddPoint(frompt2, ref missing, ref missing); fromColl.AddPoint(frompt3, ref missing, ref missing);

fromColl.AddPoint(frompt4, ref missing, ref missing); toColl.AddPoint(topt1, ref missing, ref missing);

toColl.AddPoint(topt2, ref missing, ref missing);

toColl.AddPoint(topt3, ref missing, ref missing);

toColl.AddPoint(topt4, ref missing, ref missing);

pRasterGeoProc.Warp(fromColl, toColl,

esriGeoTransTypeEnum.esriGeoTransPolyOrder1, m_OperatorLayer.Raster); ControlsMapFullExtentCommand fullcmd = new

ControlsMapFullExtentCommand();

fullcmd.OnClick();

m_hookhelper.ActiveView.Refresh();

}

catch (Exception s)

{

MessageBox.Show("请选择图层");

}

IESRISpatialReferenceGEN(输出空间信息,如geodatabase里的GDB_Spatialrefs里的srtext.

}

IEsriSpatialReference为用文本写进空间信息

FeatureDataConverterClass

用来快速转换Featureclass,table,geodatabase的一个专门的转换类

FeatureClass导出Raster

private void btnExport_Click(object sender, EventArgs e)

{

try

{

SaveFileDialog dlg = new SaveFileDialog();

dlg.FileOk += new CancelEventHandler(dlg_FileOk);

dlg.Filter = "(*.tif)|*.tif|(*.img)|*.img";

dlg.ShowDialog();

IFeatureLayer pFeatuerLayer = m_OperatorLayer as

IFeatureLayer;

if (pFeatuerLayer != null && txtExport.Text != null)

{

IFeatureClass pFeatureClass = pFeatuerLayer.FeatureClass; IConversionOp pConversionOP = new

RasterConversionOpClass() as IConversionOp;

IRasterAnalysisEnvironment pRasterAnaly = pConversionOP

as IRasterAnalysisEnvironment;

IFeatureClassDescriptor pFeatureClassDescriptor = new

FeatureClassDescriptorClass();

IWorkspace

pWorkspace=GetRasterWorkspace(txtExport.Text);

pRasterAnaly.OutWorkspace = pWorkspace;

int x=9;

object t1 = x as object;

pFeatureClassDescriptor.Create(pFeatureClass, null,

"OBJECTID");

IGeoDataset pGeoDataset = pFeatureClassDescriptor as

IGeoDataset;

pRasterAnaly.SetCellSize(esriRasterEnvSettingEnum.esriRasterEnvValue, ref

t1);

int x2 = 0;

object t2=x2 as object;

object extent=pGeoDataset.Extent as object;

pRasterAnaly.SetExtent(esriRasterEnvSettingEnum.esriRasterEnvValue, ref

extent , ref t2);

pConversionOP.ToRasterDataset(pGeoDataset, "IMAGINE

Image", pWorkspace, txtExport.Text);

}

}

catch(Exception s)

{

MessageBox.Show(s.Message);

}

}

ISpatialFilter的利用

在arcgis中,有效的利用ISpatialFilter能够提高共建搜索的效率。在使用的感觉上来说,低维的几何对象一般当spatialfilter里的geometry,感觉就是目标对象,搜索的目标对象,而featureclass,使用serach函数的,为搜索源对象,这样定义SpatialRelDescription使用九交模型时候,quereygeometry与requestgeometry比较明确,丢进spatial去的geometry为querygeometry,而featureclass里的geometry为requestgeometery。返回 IFeautureCursor为搜索的对象

高维的几何对象为featureclass

搜索多边形包含或者和线是否为多边形边界线时候

SpatialRelDescription ="*T*******"

点在多边形内

SpatialRelDescription = "**F******"

影像配准

配准

影像图配准主要包括以下几个方面

1.打开影像图

2.配准

3.影像图入库/保存

1.打开影像图的代码以前已经写过了。

2.配准

配准 主要使用IGeoReference这个接口来完成工作。

还有使用ActiveView来进行坐标转换,将MapControl中鼠标的点击位置 转换为 地图和影像图上的坐标。

下面介绍IGeoReference接口

首先RasterLayer实现了这个接口

CanGeoRef 监测该图层是否可以做配准

PointsTransform 将鼠标的位置 转换为栅格文件上的相对坐标。

Rectify 将纠正的结果保存为一个新的栅格文件 相当于另存为

Register 纠正的结果生成World文件 和栅格文件保存在同一个目录下

Reset 取消纠正 但是Register 之前的操作不能恢复。

最重要的是下面三个

Shift 一点纠正 就是平移

TwoPointsAdjust 两点配准 有一定的缩放

Warp 三点或以上配准

注意事项

1.每次Register是一个标志阶段

这每次配准的过程中 必须把上次Register 以来的所有配准点数据都使用上。 例如:

首先Register了

然后 1.使用了一点平移

2.接下来 又接受了一个点 这个时候就要使用 两点配准。

3.接下来 又接受了一个点 这个时候就要使用 三点配准了。

2.配准一般还有一个附加的功能

就是 让用户保存每次的配准过程 并且 提供每次配准过程的精度。这个需要自己补充。 注意,就是先前的配准的点要按顺序保存下来,在以后的配准需要使用的

当影像配准使用fit to display功能后,不是很好能够去匹配,因为已经有四个点,再加点没有意义,所以配准的时候先reset,然后通过影像的extent和fit to display之前的extent进行坐标的相对变换,这样当前的frompoints就转换到真正的影像位置了

贴代码

private IPointCollection GetRelativelyPoints(IEnvelope

secExtent,IPointCollection fromPointColl,IEnvelope firstExtent)

{

IPointCollection tempPointColl=(IPointCollection)new

PolygonClass();

for (int i = 0; i < fromPointColl.PointCount; i++)

{

IPoint pt = fromPointColl.get_Point(i);

double delt_x = pt.X - secExtent.XMin;

double delt_y = pt.Y - secExtent.YMin;

delt_x = delt_x * (firstExtent.Width / secExtent.Width);//比例

delt_y = delt_y * (firstExtent.Height / secExtent.Height); IPoint temppt = new PointClass();

temppt.PutCoords(firstExtent.XMin + delt_x, firstExtent.YMin + delt_y);

tempPointColl.AddPoint(temppt, ref missing, ref missing); }

return tempPointColl;

}

金字塔

金字塔需要IRasterPyramids接口,需要从IRasterDataSet得到。而 IRasterDataset则通过RasterWorkspaceFactory打开一个workspace然后打开一个rasterworkspace

private void SetPyramid(IRasterLayer pRasterLayer)

{

if (pRasterLayer.PyramidPresent)

return;

string filepath = pRasterLayer.FilePath;

int n = filepath.LastIndexOf("\\");

string folder = filepath.Substring(0, n);

IWorkspaceFactory workspaceFactory = new

RasterWorkspaceFactoryClass();

IRasterWorkspace rasterWorkspace =

(IRasterWorkspace)workspaceFactory.OpenFromFile(folder, 0);

IRasterDataset pRasterDataset =

rasterWorkspace.OpenRasterDataset(pRasterLayer.Name);

IRasterPyramid pRasterPyramid = (IRasterPyramid)pRasterDataset; if (!pRasterPyramid.Present)

pRasterPyramid.Create();

}

ArcSDE空间数据库中SDE用户使用探讨

ArcSDE作为空间数据库解决方案,应用非常广泛,本短文将尝试描述SDE的工作机制,简要说明空间数据

库中SDE用户的使用方法。

ArcSDE如何工作

ArcSDE属于中间件技术,其本身并不能够存储空间数据,它的作用可以理解为数据库的“空间扩展”。在

基于Oracle的ArcSDE空间数据库中,ArcSDE保存了一系列Oracle对象,用于管理空间信息。这些对象统称

为资料档案库(Repository),包含空间数据字典和ArcSDE软件程序包。ArcSDE需要SDE用户管理空间资

料档案库,这类似于Oracle中需要SYS用户管理数据字典。Oracle的数据字典存储在SYSTEM表空间中;相

应地,在存储ArcSDE空间资料档案库的时候,也需要使用特定的表空间。通常,为了方便起见,默认使用

名称也是SDE的表空间管理空间数据字典。

ArcSDE的工作机制中,SDE用户负责ArcSDE与Oracle的交互,通过维护SDE模式下的空间数据字典以及运行

其模式中的程序包,来保证空间数据库的读/写一致性。在ArcSDE服务启动的过程中,SDE用户通过Oracle

验证,并且创建和维护一个Oracle会话连接,连接的程序便是giomgr,即ArcSDE服务器管理进程,该进程

一直存在,负责监听用户连接请求,分配相应的gsrvr管理进程(见注1),进行空间数据字典的维护。

ArcSDE的安全性

ArcSDE的安全机制完全依赖于Oracle,空间数据库用户(包括SDE),需要Oracle的用户密码才能够访问

空间数据,ArcSDE本身并不保存任何认证信息。

在Oracle中,SDE用户的最小系统权限设置要求是:

Create procedure / Create table / Create sequence / Create trigger / Create session

由此可见,SDE亦属于Oracle数据库中的普通权限用户。

对于Oracle来说,虽然SDE属于非DBA用户,但是在ArcSDE架构中,SDE的地位比较特殊,是ArcSDE管理员

。只有SDE可以完成一些特定的工作:比如启动/停止ArcSDE服务;终止某些用户连接;压缩多版本数据库

等。SDE用户虽然不是一个真正的Oracle DBA用户,但是在ArcSDE工作过程中,软件会进行一些特定的对

象权限操作。因此,应该将SDE用户等同于Oracle DBA用户处理,就像SYS或者SYSTEM一样,必须严格保护

其密码。

在ArcSDE空间数据库中,从权限管理级别上,可以把用户分成两大类:

1、 空间数据库管理员,只有并且只能是SDE

2、 空间数据库一般用户,包括创建、浏览空间数据的除SDE外的其它oracle用户 使用SDE用户,强烈推

荐遵循两个原则:

SDE用户不用于加载空间数据

SDE存储资料档案库的表空间不用于存放空间数据

SDE用户的特殊对象权限

SDE用户作为Oracle数据库的一般用户,可以创建自己的表或者存储过程;作为ArcSDE空间数据库管理员

,在对象权限设置中,ArcSDE会自动授予SDE一些对象权限。SDE用户需要这些对象权限,以保证ArcSDE

Geodatabase的完整性。空间数据库的一般用户在创建新的Geodatabase对象的时候,ArcSDE将这些新建对

象的权限授予SDE用户。比如ACTC用户创建一个名称为Country的Geodatabase的要素类,此时数据库中同

时生成Country(即B表,Business Table)的相应支撑表,即F表(Feature Table)和S表(Spatial

Index Table)。这时候,SDE用户将自动获取得到Country、F表和S表这几个表的Select权限。当用户将

Country注册为版本,此时ACTC模式下生成记录编辑信息的A表(Additions Table)和D表(Deletions

Table)。这时候,SDE用户获得该A表和D表的Select / Insert / Update / Delete权限。在这些对象权

限授予过程中,ACTC用户并未获取任何通知信息。

在ArcGIS Desktop的空间数据库连接中,并没有体现出来SDE用户的这些对象权限,如果使用SDE用户进行

空间数据库连接,只能够观察到上例中的Country表,其它的支撑表都被过滤掉了。如果需要完整查看SDE

用户被授予的对象权限,可以通过Oracle的USER_TAB_PRIVS_RECD视图获取。 SDE用户完成哪些特定工作

在空间数据库中,作为管理员的SDE完成一般用户不能完成的操作,以下举例说明:

1、 启动/停止ArcSDE服务

只有SDE能够与Oracle完成交互,启动或停止ArcSDE的服务。操作为:

sdemon –o start / shutdown (启动/停止)

这时候需要提交SDE用户密码。

2、 终止某个空间用户连接

在空间数据库连接中,有时候出连接进程挂起或者非法连接的时候,可以使用SDE终止其连接。操作为:

首先,从连接列表中获取该连接的信息

sdemon –o info –I users

在获取到需要终止的连接ID后,使用kill命令

sdemon –o kill –t < 连接 ID>

<连接ID> 完成此项操作需要提交SDE用户密码。

3、 压缩多版本数据库(Multi-versioned Geodatabase)

在ArcSDE Geodatabase中,随着数据编辑工作的进行,SDE空间资料档案库中相应元数据表、以及用户模

式中的A表和D表的记录逐渐增加,会影响空间数据的访问效率,因此经常需要进行数据库版本的压缩工作

。在确定数据库不存在任何锁定后,便可以进行压缩工作,操作为:

sdeversion –o compress –u sde

完成此项操作需要提交SDE用户密码。

作为ArcSDE管理员,SDE还要完成其它一些工作。比如,在控制空间数据的数据段、索引段存储的时候,

SDE用户可以使用sdedbtune命令来提高数据库效率。

注1:这是传统的ArcSDE应用服务器连接(Application-server connection)的工作方式,在这种方式中

,ArcSDE服务器进程(giomgr)分配名为gsrvr的进程来全面负责客户机与服务器的元数据通信。ArcSDE

8.1版本之后,出现新的连接方式,即直接连接方式(Direction-connection),在这种连接方式中,

gsrvr进程功能嵌入到客户机连接应用程序中,如ArcCatalog或其它ESRI软件产品。此种方式下,Gsrvr的

功能由客户端连接应用程序完成。

测试环境:ArcSDE 9.0,Oracle 9.2.0.4.0,Windows NT

参考:

1、 Config_tuning_GD_oracle

2、 Understanding ArcSDE

3、 网站:S

SDE命令使用举例

1、sdeservice命令

sdeservice命令是ArcSDE众多命令行中的一个,只能使用于Windows操作系统中。这个命令可以改变SDE用

户的密码。ArcSDE是作为后台程序运行的,在Windows操作系统中,所有后台运行的程序都是作为相应的

Windows服务(windows services)而存在的。这些Windows服务的信息是存储在Windows操作系统的注册

表中的。

ArcSDE服务信息同样也存储在Windows注册表中。必须使用sdeservice命令才能创建支持ArcSDE的注册表

信息。这个命令里提供了ArcSDE服务启动所需要的信息(比如说license)以及Windows系统中需要运行的

命令(当ArcSDE服务启动时,需要运行的程序)。

创建ArcSDE服务的时候,必须指定SDE用户的密码。这个密码是加密存储在注册表里的。有了这个密码,

系统注册表中的其它ArcSDE服务信息可以自动启动。Giomgr进程以SDE用户登陆到数据库中,使用的密码

便是上面我们提到的存储在注册表中的SDE用户密码。

有时候,我们可能需要更改ArcSDE服务的某些配置信息。虽然这些修改可以通过注册表编辑器来实现,但

使用sdeservice命令来进行注册表修改是最安全的方法。当然,需要提醒的是,有一些记录(例如ArcSDE

管理员密码是加密存储的)只能通过sdeservice命令来修改。

通常,数据库管理员要定期修改SDE用户的密码。这时仅仅在数据库中或者Windows操作系统中修改SDE用

户密码是无法启动ArcSDE服务的,还必须在注册表中修改这个密码。如果没有这一步操作,ArcSDE服务肯

定是无法启动的。要想改变注册表中的这个密码,可以使用下图中给出的sdeservice –o modify命令来

修改。这个命令可以用于修改SDEHOME目录、SDE用户、License服务器和NLS 语言。一旦SDE用户密码在数

据库和注册表中都经过修改,这时我们便可以启动ArcSDE服务了。

(图1)

sdeservice –o modify –r

<SDEHOME|SDE_DBA_PASSWORD|LICENSE_SERVER|NLS_LANG>

-p <old_DB_ASMIN_password> -v <new_value> [-i <service>] [-q]

2、sdemon命令

sdemon命令是ArcSDE命令行工具中尤为常用的一个。Sdemon命令通常是在管理ArcSDE服务的时候使用。打

开命令行窗口后,键入sdemon命令,然后按回车。这时便可见以下画面: 图片 1 与其它的命令行操作相比,sdemon命令行的参数是比较少的。下面分别描述以上几个sdemon操作的功能:

sdemon –o status 显示ArcSDE服务的状态

sdemon –o start 启动ArcSDE服务

sdemon –o shutdown 关闭ArcSDE服务

sdemon –o pause 暂停ArcSDE服务,禁止新的连接

sdemon –o resume 在暂停后重新允许与ArcSDE服务连接

sdemon –o info 提供ArcSDE服务和当前连接的信息,其中,users提供了所有使用应用服务器连接的用

户的连接信息;config提供了ArcSDE服务配置的所有信息;stats显示当时ArcSDE服务的连接情况;locks

显示当前所有锁定的layers、state、table、objects信息;vars显示ArcSDE服务所在主机上所有相应的

环境变量的设置

sdemon –o kill -t <{all | pid}> 将与ArcSDE服务的连接断开,其中,all表示断开所有的连接;pid

表示将进程号为该ID号的连接断开

需要指出的是,sdemon命令行只能对应用服务器连接(三级连接)有监听作用,因为只有这些连接是由

giomgr进程(ArcSDE服务器的专用进程)为它们分配指定的gsrvr进程监控的。二级连接(或称为直接连

接)中,gsrvr进程的功能已经嵌入到客户端软件中,ArcSDE服务和这样的连接没有直接的交互。这样的

二级连接可以通过后台数据库直接管理。

其它常用的sde命令行还有,sdelayer、sdetable、sdeimport等等,具体信息可以查看ArcSDE帮助中的

Administrator Command Reference

删除layer注意事项

调用map.deleteLayer()其实只是在mapcontrol里把layer给删掉了。如果layer是一个datalayer,则ae程序并没有对调用文件进行解锁,你根本无法在外面对ae程序使用过的文件进行任何操作。你再次从ae里打开这个layer时候,信息也是上次调用时候的。

为了消除这种情况,必须调用IDatalayer2.disconnect();释放掉打开文件后在该文件夹形成工作空间,其实一切都是这个工作空间的错,也就是一般意义的上的缓存。

超出游标最大数

如果不是AE,而在其他程序里,这个问题应该和数据库的连接设置有关。但是如果是在AE程序里出现这个错误,很有可能是因为在同一个数据库打开了两个游标,这两个游标不管是两张表的还是一张表的,都会出现如此问题。只有调用c#里的 Marshal.releasecomobject才能解决问题。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。

IGeometry的赋值不仅仅是赋值

声明 IPoint pt=null;然后不断给pt赋值,你会发现内存不断的在增长。自己感到奇怪,不就是一个赋值吗,我下一次赋的值不是把上次所赋的位置所占据了吗,不应该在申请新的内存空间阿。但事实上不是,自己猜度出,在arcgis里,IGeometry重载的复制操作符,只是把

这次赋值操作压栈,当前的值是这次赋给的值,而以前的值则被压栈,不明白这个机制有什么作用。查到从IGeometry继承的对象都有setempty函数,用于清栈的。

ArcSde里游标问题

这两天做图幅计算的功能,涉及到ArcSde里多张表的操作,但是数据库总会莫名其妙的报一些错误,比如什么“致命通信双工错误”,”NetWork I/O error”,还有无法跟新行。自己一开始还以为这些是oracle的错误,后来仔细想想,自己在做VCT的输出时候,打开表的次数,凭率还是速度都比这个快,可是没有遇到这样的错误。仔细想想,前几天遇到了相同的另外一个怪问题,也是和Arcsde里的游标数有关,一旦在arcsde里打开两个游标,就如同埋下一颗定时炸弹,随时都可能出问题,而且让人摸不着头脑,也许这个是需要SDE改进的地方吧

过两天试试本地数据库会不会出现这种情况,没有了Network,你还报那样的错误,那我就服了you

反正,在AE开发时候,切忌,申请了一个cursor就要记得退出函数时释放,在c#里是marshal.realeseComobject,c++里应该是delete吧。这个就跟c++ 里new和delete一样,而且还有严重,当你使用新的一个游标时候,最好不要同时存在另一个游标

线状地物打断

DBMS和ACCESS在拷贝界线的时候不要打开工作空间编辑状态

private void SetPolylineToLinesegment(IWorkspace pWorkspace,IQueryFilter pQueryFilter)

{

IFeatureWorkspace pFeatWS = (IFeatureWorkspace)pWorkspace;

IFeatureClass fcDWDD = GTCUtil.dbUtil.openFeatureClass(pFeatWS, "DWDD");

string whereclause = pQueryFilter.WhereClause;

if (!GTCUtil.dbUtil.deleteFeaturesFromQueryFilter(fcDWDD as ITable, pQueryFilter))

{

return;

}

// 将XZDW--线状地物所有目标拷入DWDD--线状地物打断

IFeatureClass fcXZDW = GTCUtil.dbUtil.openFeatureClass(pFeatWS, "XZDW");

GTCUtil.dbUtil.copyFeaturesSameStruction(fcDWDD, fcXZDW,

whereclause);

/// 将XZJX--行政界线QSJX--权属界线DLJX--地类界线加入

//copy "行政界线"

IFeatureClass XZJXFeatClass =

GTCUtil.dbUtil.openFeatureClass(pFeatWS, "XZJX");

GTCUtil.dbUtil.copyFeaturesFromQueryFilter(fcDWDD, XZJXFeatClass, "");

//copy "权属界线"

IFeatureClass QSJXFeatClass =

GTCUtil.dbUtil.openFeatureClass(pFeatWS, "QSJX");

GTCUtil.dbUtil.copyFeaturesFromQueryFilter(fcDWDD, QSJXFeatClass, "");

//copy "地类界线"

IFeatureClass DLJXFeatClass =

GTCUtil.dbUtil.openFeatureClass(pFeatWS, "DLJX");

GTCUtil.dbUtil.copyFeaturesFromQueryFilter(fcDWDD, DLJXFeatClass, "");

/// 对DWDD--线状地物打断进行自打断

Application.DoEvents();

GTCEditor.SpecialEditor.LinesSelfBreak(fcDWDD, whereclause);

//删除多余的线

string strWcDelLine = "SZTF = ''";

IQueryFilter filter=new QueryFilterClass();

filter.WhereClause= strWcDelLine;

GTCUtil.dbUtil.deleteFeaturesFromQueryFilter(fcDWDD as ITable, filter);

}

static public IFeatureClass openFeatureClass(IFeatureWorkspace

featureWorkspace, String nameOfFeatureClass)

{

return featureWorkspace.OpenFeatureClass(nameOfFeatureClass); }

删除要素,同图幅,以前的

static public bool deleteFeaturesFromQueryFilter(ITable targetTable, IQueryFilter queryFilter)

{

IDataset dataset = targetTable as IDataset;

IWorkspace workspace = dataset.Workspace;

IWorkspaceEdit workspaceEdit = workspace as IWorkspaceEdit; bool isBeginEdited = workspaceEdit.IsBeingEdited(); //如果工作空间已经打开则不需要再次打开,也不需要关闭 if (!isBeginEdited)

{

workspaceEdit.StartEditing(false);

workspaceEdit.StartEditOperation();

}

try

{

ICursor cursor = targetTable.Search(queryFilter, false); ITableWrite tableWrite = targetTable as ITableWrite; IRow row = cursor.NextRow();

ISet set = new SetClass();

while(row != null)

{

Application.DoEvents();

set.Add((object)row);

//set = new SetClass();

row = cursor.NextRow();

}

tableWrite.DeleteRows(set);

if (!isBeginEdited)

{

workspaceEdit.StopEditOperation();

workspaceEdit.StopEditing(true);

}

}

catch (Exception e)

{

MessageBox.Show("删除出错" + e.Message);

workspaceEdit.AbortEditOperation();

if (!isBeginEdited&&workspaceEdit.IsBeingEdited()) {

workspaceEdit.StopEditOperation();

workspaceEdit.StopEditing(true);

}

return false;

}

return true;

}

#region “把源表记录添加到指定FeatureClass(两个表结构一样)”

static public void copyFeaturesSameStruction(IFeatureClass targetFC,

IFeatureClass sourceFC, string strWC)

{

if (targetFC == null)

{

MessageBox.Show("添加记录失败"); return;

}

if (sourceFC == null)

{

}

{

}

&&workspaceEdit.IsBeingEdited()) {

isBeginEdited =

}

{

workspaceEdit.StartEditing(

workspaceEdit.StartEditOperation(); }

queryFilter.WhereClause = strWC;

false); MessageBox.Show("添加记录失败"); return; if (targetFC.ShapeType != sourceFC.ShapeType) MessageBox.Show("两个FeatureClass数据结构不一样"); return; IDataset dataset = targetFC as IDataset; IWorkspace workspace = dataset.Workspace; IWorkspaceEdit workspaceEdit = workspace as IWorkspaceEdit; IObjectClassInfo2 iObjClaInfo = targetFC as IObjectClassInfo2; bool isBeginEdited = iObjClaInfo.CanBypassEditSession(); //如果工作空间已经打开则不需要再次打开,也不需要关闭 if (!isBeginEdited true; if(!isBeginEdited) false); IFields fields = sourceFC.Fields; int fieldCount = fields.FieldCount; IField field; IQueryFilter queryFilter = new QueryFilterClass(); IFeatureCursor sourceCursor = sourceFC.Search(queryFilter,

try

{

IFeatureCursor targetCursor = targetFC.Insert(true);

IFeatureBuffer targetBuffer = targetFC.CreateFeatureBuffer();

IFeature sourceFeature = sourceCursor.NextFeature(); while (sourceFeature != null)

{

//targetBuffer.Shape = sourceFeature.Shape;

for (int i = 0; i < fieldCount; i++)

{

Application.DoEvents();

field = fields.get_Field(i);

int fieldTargetIndex =

targetBuffer.Fields.FindField(field.Name);

if (fieldTargetIndex == -1)

continue;

if (!field.Editable||sourceFeature.get_Value(i) == DBNull.Value)

continue;

targetBuffer.set_Value(fieldTargetIndex,

sourceFeature.get_Value(i));

}

targetCursor.InsertFeature(targetBuffer);

targetCursor.Flush();

sourceFeature = sourceCursor.NextFeature();

}

if (!isBeginEdited)

{

workspaceEdit.StopEditOperation();

workspaceEdit.StopEditing(true);

}

}

catch (Exception e)

{

MessageBox.Show("添加出错" + e.Message);

//workspaceEdit.AbortEditOperation();

if (!isBeginEdited && workspaceEdit.IsBeingEdited()) {

workspaceEdit.StopEditOperation();

workspaceEdit.StopEditing(false);

}

return;

}

}

#endregion

#region 拷贝Feature到目标层去

static public void copyFeaturesFromQueryFilter(IFeatureClass targerFeatClass, IFeatureClass sourceFeatClass, string strWC)

{

if (targerFeatClass.ShapeType != sourceFeatClass.ShapeType) {

MessageBox.Show("目标层和来源层的类型不同");

return;

}

IFeatureCursor insertfeatCursor = targerFeatClass.Insert(true); IFeatureBuffer insertFeatBuffer =

targerFeatClass.CreateFeatureBuffer();

IQueryFilter queryfilter = new QueryFilterClass();

queryfilter.WhereClause = strWC;

IFeatureCursor sourceCursor = sourceFeatClass.Search(queryfilter, false);

IFeature sourceFeature = sourceCursor.NextFeature();

while (sourceFeature != null)

{

Application.DoEvents();

insertFeatBuffer.Shape = sourceFeature.Shape;

insertfeatCursor.InsertFeature(insertFeatBuffer);

insertfeatCursor.Flush();

sourceFeature = sourceCursor.NextFeature();

}

}

#endregion

//线自打断,并且属性可以继承

static public void LinesSelfBreak(IFeatureClass sourceFeatClass, string strWc)

{

if (sourceFeatClass.ShapeType !=

esriGeometryType.esriGeometryPolyline)

{

System.Windows.Forms.MessageBox.Show("目标层不是一个线层.");

return;

}

IQueryFilter queryFilter = new QueryFilterClass();

queryFilter.WhereClause = strWc;

IFeatureCursor featCursor = sourceFeatClass.Search(queryFilter, false);

IFeatureConstruction featureConstruction = new

FeatureConstructionClass();

IDataset dataset = sourceFeatClass as IDataset;

IWorkspace workspace = dataset.Workspace;

IWorkspaceEdit workspaceEdit = workspace as IWorkspaceEdit;

if (workspaceEdit.IsBeingEdited() != true)

{

workspaceEdit.StartEditing(false);

workspaceEdit.StartEditOperation();

}

try

{

featureConstruction.PlanarizeLinesFromCursor(null, sourceFeatClass, featCursor, -1);

workspaceEdit.StopEditOperation();

workspaceEdit.StopEditing(true);

}

catch (Exception e)

{

System.Windows.Forms.MessageBox.Show("线打断出错. " + e.Message);

workspaceEdit.AbortEditOperation();

}

}

获得工作空间的属性

/// <summary>

///

/// </summary>

/// <param name="pWorkspace">传入的工作空间</param>

/// <param name="server"></param>

/// <param name="instance"></param>

/// <param name="user"></param>

/// <param name="password"></param>

/// <param name="database"></param>

/// <param name="version"></param>

/// <returns>1为DBMS数据库,2为本地数据库,如ACCESS</returns>

public int GetWorkspaceProperty(IWorkspace pWorkspace, out string server, out string instance, out string user,

out string password, out string database, out string version)

{

server = "";

instance = "";

user = "";

password = "";

database = "";

version = "";

int type=0;

IPropertySet propertySet = pWorkspace.ConnectionProperties; object ns = null;

object vs = null;

propertySet.GetAllProperties(out ns, out vs);

object[] names = (object[])ns;

object[] values = (object[])vs;

for(int i=0;i<names.Length;i++)

{

string tn = names[i].ToString();

string tv = values[i].ToString();

if(Regex.IsMatch(tn,"SERVER",RegexOptions.IgnoreCase)) {

server = tv;

}

if(Regex.IsMatch(tn,"INSTANCE",RegexOptions.IgnoreCase)) {

instance = tv;

}

if(Regex.IsMatch(tn,"DATABASE",RegexOptions.IgnoreCase)) {

if (tv.Contains("\\"))

type = 2;

else

type = 1;

}

if(Regex.IsMatch(tn,"AUTHENTICATION_MODE",RegexOptions.IgnoreCase)) {

}

if(Regex.IsMatch(tn,"USER",RegexOptions.IgnoreCase)) {

user = tv;

}

if(Regex.IsMatch(tn,"PASSWORD",RegexOptions.IgnoreCase)) {

password = tv;

}

if(Regex.IsMatch(tn,"VERSION",RegexOptions.IgnoreCase)) {

version = tv;

}

}

return type;

}

相关推荐