以下是我做的“转换”按钮 的点击事件,想实现将已经加载在Scene控件中的面要素,按照面要素属性表中我设置的ZValue字段作为拉伸告诉,进行拉伸,但拉伸后没有侧面,而且控件的界面并不刷新,必须得重新加载shp文件才会显示,请问有人知道问题出在哪里了吗,求指点。
private void btnChange_Click(object sender, EventArgs e)
{
List<IFeature> newFeatures = new List<IFeature>(); //创建一个新的列表,用于存储新创建的要素。
try
{
ISceneGraph scenegraph = axSceneControl1.SceneGraph; //从场景控件中获取场景图。
IScene scene = (IScene)axSceneControl1.Scene; //将场景控件中的场景转换为IScene接口。
ILayer layer = scene.Layer[0]; //获取场景中的第一个图层。
if (layer == null)
{
MessageBox.Show("未找到图层!");
return;
}
IFeatureLayer featureLayer = layer as IFeatureLayer; //将图层转换为IFeatureLayer接口。
IFeatureClass featureClass = featureLayer.FeatureClass; //获取要素图层的要素类。
IQueryFilter queryFilter = new QueryFilterClass(); //创建一个查询过滤器。
int zValueFieldIndex = featureClass.Fields.FindField("ZValue"); //查找名为"ZValue"的字段在要素类中的索引。
IFeatureCursor featureCursor = featureClass.Search(queryFilter, true); //使用查询过滤器查询要素类,返回要素游标。
IFeature feature = featureCursor.NextFeature(); //获取要素游标的下一个要素。
while (feature != null)
{
double zValue = Convert.ToDouble(feature.get_Value(zValueFieldIndex)); //获取要素的"ZValue"字段值,并将其转换为双精度浮点数。
IGeometry geometry = feature.ShapeCopy; //获取要素的几何形状副本。
if (geometry.GeometryType == esriGeometryType.esriGeometryPolygon) //检查几何形状是否为多边形类型。
{
IPolygon polygon = geometry as IPolygon; //将几何形状转换为IPolygon接口。
IZ iz = (IZ)polygon;
iz.SetConstantZ(zValue);
IFeature newFeature = featureClass.CreateFeature(); //创建一个新的要素。
newFeature.Shape = polygon; //将新要素的几何形状设置为多边形。
newFeature.Store(); //将新要素保存到要素类中。
newFeatures.Add(newFeature); //将新要素添加到新要素列表中。
}
feature = featureCursor.NextFeature(); //获取要素游标的下一个要素。
}
System.Runtime.InteropServices.Marshal.ReleaseComObject(featureCursor); //释放要素游标的COM对象。
axSceneControl1.SceneGraph.RefreshViewers(); //刷新场景控件的视图。
}
catch (Exception ex)
{
MessageBox.Show("拉伸失败" + ex.Message);
}
}
我又对代码进行了修改,但又遇到一个问题
private void btnChange_Click(object sender, EventArgs e)
{
// 获取ArcScene控件
IScene scene = (IScene)axSceneControl1.Scene;
// 获取场景中的图层
IMap map = scene as IMap;
ILayer layer = null;
for (int i = 0; i < map.LayerCount; i++)
{
layer = map.get_Layer(i);
if (layer is IFeatureLayer && layer.Valid)
{
// 检查图层是否为HaveZ图层
IFeatureLayer featureLayer = (IFeatureLayer)layer;
IFeatureClass featureClass = featureLayer.FeatureClass;
if (featureClass != null && featureClass.ShapeType == esriGeometryType.esriGeometryPolygon)
{
// 获取要素类的ZValue字段索引
int zValueFieldIndex = featureClass.FindField("ZValue");
// 获取要素游标
IFeatureCursor featureCursor = featureClass.Search(null, true);
IFeature feature = featureCursor.NextFeature();
// 创建新的要素类
IWorkspaceFactory workspaceFactory = new ShapefileWorkspaceFactory();
IFeatureWorkspace featureWorkspace = (IFeatureWorkspace)workspaceFactory.OpenFromFile("C:\\Users\\Administrator\\Desktop\\具有Z值的少数shp1", 0);
IFields fields = featureClass.Fields;
IFeatureClass newFeatureClass = featureWorkspace.CreateFeatureClass("NewFeatureClass", fields, null, null, esriFeatureType.esriFTSimple, "Shape", "");
// 创建拉伸对象
IGeometryEnvironment geometryEnvironment = new GeometryEnvironmentClass();
IExtrude extrude = (IExtrude)geometryEnvironment;
while (feature != null)
{
// 获取原始几何形状
IGeometry geometry = feature.Shape;
// 检查几何形状是否为多边形
if (geometry.GeometryType == esriGeometryType.esriGeometryPolygon)
{
IPolygon polygon = (IPolygon)geometry;
// 获取ZValue字段值
double zValue = Convert.ToDouble(feature.get_Value(zValueFieldIndex));
// 使用ITopologicalOperator接口将多边形拉伸为多面体
IMultiPatch multiPatch = extrude.ExtrudeFromTo(0, zValue, polygon) as IMultiPatch;
// 创建新要素
IFeature newFeature = newFeatureClass.CreateFeature();
newFeature.Shape = multiPatch;
// 复制原始要素的属性到新要素
for (int j = 0; j < fields.FieldCount; j++)
{
if (j != zValueFieldIndex)
{
newFeature.set_Value(i, feature.get_Value(i));
}
}
// 插入新要素
newFeature.Store();
}
// 获取下一个要素
feature = featureCursor.NextFeature();
}
// 释放资源
System.Runtime.InteropServices.Marshal.ReleaseComObject(featureCursor);
}
}
}
// 刷新场景
scene.SceneGraph.Invalidate(layer, true, false);
}
上面的代码运行到
// 创建新要素
IFeature newFeature = newFeatureClass.CreateFeature();
newFeature.Shape = multiPatch;
会报错要素的几何类型与要素类的几何类型不匹配,我应该做一些什么调整呢
我按照类型不匹配的错误进行了修改,在创建新要素时,创建了一个IGeometry,但在运行到复制原始要素的属性到新要素时,又报错Fields is not editable,这应该怎么修改呢。尝试了之后,似乎是因为创建新要素类型的问题,是不是有可以编辑的要素类,或者是定义使用问题?
private void btnChange_Click(object sender, EventArgs e)
{
try
{
// 获取ArcScene控件
IScene scene = (IScene)axSceneControl1.Scene;
// 获取场景中的图层
IMap map = scene as IMap;
ILayer layer = null;
for (int i = 0; i < map.LayerCount; i++)
{
layer = map.get_Layer(i);
if (layer is IFeatureLayer && layer.Valid)
{
// 检查图层是否为HaveZ图层
IFeatureLayer featureLayer = (IFeatureLayer)layer;
IFeatureClass featureClass = featureLayer.FeatureClass;
if (featureClass != null && featureClass.ShapeType == esriGeometryType.esriGeometryPolygon)
{
// 获取要素类的ZValue字段索引
int zValueFieldIndex = featureClass.FindField("ZValue");
// 获取要素游标
IFeatureCursor featureCursor = featureClass.Search(null, true);
IFeature feature = featureCursor.NextFeature();
// 创建新的要素类
IWorkspaceFactory workspaceFactory = new ShapefileWorkspaceFactory();
IFeatureWorkspace featureWorkspace = (IFeatureWorkspace)workspaceFactory.OpenFromFile("C:\\Users\\Administrator\\Desktop\\具有Z值的少数shp1", 0);
IFields fields = featureClass.Fields;
IFeatureClass newFeatureClass = featureWorkspace.CreateFeatureClass("NewFeatureClass", fields, null, null, esriFeatureType.esriFTSimple, "Shape", "");
// 创建拉伸对象
IGeometryEnvironment geometryEnvironment = new GeometryEnvironmentClass();
IExtrude extrude = (IExtrude)geometryEnvironment;
while (feature != null)
{
// 获取原始几何形状
IGeometry geometry = feature.Shape;
// 检查几何形状是否为多边形
if (geometry.GeometryType == esriGeometryType.esriGeometryPolygon)
{
IPolygon polygon = (IPolygon)geometry;
// 获取ZValue字段值
double zValue = Convert.ToDouble(feature.get_Value(zValueFieldIndex));
// 使用ITopologicalOperator接口将多边形拉伸为多面体
IMultiPatch multiPatch = extrude.ExtrudeFromTo(0, zValue, polygon) as IMultiPatch;
// 创建新要素
IFeature newFeature = newFeatureClass.CreateFeature();
IGeometry newGeometry = multiPatch as IPolygon;
newFeature.Shape = newGeometry;
// 复制原始要素的属性到新要素
for (int j = 0; j < fields.FieldCount; j++)
{
if (j != zValueFieldIndex)
{
newFeature.set_Value(j, feature.get_Value(j));
}
}
// 插入新要素
newFeature.Store();
}
// 获取下一个要素
feature = featureCursor.NextFeature();
}
// 释放资源
System.Runtime.InteropServices.Marshal.ReleaseComObject(featureCursor);
}
}
}
// 刷新场景
scene.SceneGraph.Invalidate(layer, true, false);
}
catch(Exception ex)
{
MessageBox.Show("拉伸失败" + ex.Message);
}
}
找到原因了哈哈,字段中的ID和Object这两个字段是自动生成不可更改的,所以我设置了一个判定字段是否可以编辑,不能编辑就直接跳过,但是又有了新的问题。下面这个是修改之后的完整代码。
private void btnChange_Click(object sender, EventArgs e)
{
try
{
// 获取ArcScene控件
IScene scene = (IScene)axSceneControl1.Scene;
// 获取场景中的图层
IMap map = scene as IMap;
ILayer layer = null;
for (int i = 0; i < map.LayerCount; i++)
{
layer = map.get_Layer(i);
if (layer is IFeatureLayer && layer.Valid)
{
// 检查图层是否为HaveZ图层
IFeatureLayer featureLayer = (IFeatureLayer)layer;
IFeatureClass featureClass = featureLayer.FeatureClass;
if (featureClass != null && featureClass.ShapeType == esriGeometryType.esriGeometryPolygon)
{
// 获取要素类的ZValue字段索引
int zValueFieldIndex = featureClass.FindField("ZValue");
// 获取要素游标
IFeatureCursor featureCursor = featureClass.Search(null, true);
IFeature feature = featureCursor.NextFeature();
// 创建新的要素类
IWorkspaceFactory workspaceFactory = new ShapefileWorkspaceFactory();
IFeatureWorkspace featureWorkspace = (IFeatureWorkspace)workspaceFactory.OpenFromFile("C:\\Users\\Administrator\\Desktop\\具有Z值的少数shp1", 0);
IFields fields = featureClass.Fields;
IFeatureClass newFeatureClass = featureWorkspace.CreateFeatureClass("NewFeatureClass", fields, null, null, esriFeatureType.esriFTSimple, "Shape", "");
// 创建拉伸对象
IGeometryEnvironment geometryEnvironment = new GeometryEnvironmentClass();
IExtrude extrude = (IExtrude)geometryEnvironment;
while (feature != null)
{
// 获取原始几何形状
IGeometry geometry = feature.Shape;
// 检查几何形状是否为多边形
if (geometry.GeometryType == esriGeometryType.esriGeometryPolygon)
{
IPolygon polygon = (IPolygon)geometry;
// 获取ZValue字段值
double zValue = Convert.ToDouble(feature.get_Value(zValueFieldIndex));
// 使用ITopologicalOperator接口将多边形拉伸为多面体
IMultiPatch multiPatch = extrude.ExtrudeFromTo(0, zValue, polygon) as IMultiPatch;
// 创建新要素
IFeature newFeature = newFeatureClass.CreateFeature();
IGeometry newGeometry = multiPatch as IPolygon;
newFeature.Shape = newGeometry;
// 复制原始要素的属性到新要素
for (int j = 0; j < fields.FieldCount; j++)
{
IField field = fields.get_Field(j);
if (field.Editable)
{
if (j != zValueFieldIndex)
{
// 如果是 ZValue 字段,设置新要素的值
newFeature.set_Value(j, feature.get_Value(j));
}
else
{
// 如果是 ZValue 字段,设置新要素的值
newFeature.set_Value(j, zValue);
}
}
}
// 插入新要素
newFeature.Store();
}
// 获取下一个要素
feature = featureCursor.NextFeature();
}
// 释放资源
System.Runtime.InteropServices.Marshal.ReleaseComObject(featureCursor);
}
}
}
// 刷新场景
scene.SceneGraph.Invalidate(layer, true, false);
}
catch(Exception ex)
{
MessageBox.Show("拉伸失败" + ex.Message);
}
}
问题出现在
IFeatureClass newFeatureClass = featureWorkspace.CreateFeatureClass("NewFeatureClass", fields, null, null, esriFeatureType.esriFTSimple, "Shape", "");
这行代码会报错,这又是什么原因导致的呢
我打了断点进行调试之后,发现是第一次点击按钮后,面要素并没有拉伸为三维,是我的将多边形拉伸为多面体那行代码不起作用吗,应该怎么修改呢
我又对代码进行了修改,思路是先创立底面和顶面,在通过IRing连接,但出现了未登录系统这个重来没遇过的问题,这应该怎么解决
private void btnChange_Click(object sender, EventArgs e)
{
IScene scene = axSceneControl1.Scene;
for (int i = 0; i < scene.LayerCount; i++)
{
ILayer layer = scene.get_Layer(i);
IFeatureLayer featureLayer = (IFeatureLayer)layer;
if (featureLayer.Name == "HaveZ")
{
IFeatureClass featureClass = featureLayer.FeatureClass;
IFeatureCursor cursor = featureClass.Search(null, false);
IFeature feature = cursor.NextFeature();
while (feature!=null)
{
IGeometry geometry = feature.Shape;
if (geometry is IPolygon)
{
IPolygon polygon = (IPolygon)geometry;
double zValue = Convert.ToDouble(feature.get_Value(feature.Fields.FindField("ZValue")));
IGeometryCollection multiPatch = new MultiPatchClass();
IPointCollection points = (IPointCollection)polygon;
//底部面
IGeometry bottomFace = polygon; //设置底部面为与要素相同的面要素
//创建顶部面
IPointCollection topRing = new RingClass();
for (int j = 0; j < points.PointCount; j++)
{
IPoint point = points.get_Point(j);
point.Z = zValue; // 顶部面的 Z 值为 "ZValue" 字段的值
topRing.AddPoint(point);
}
((IRing)topRing).Close();
multiPatch.AddGeometry((IGeometry)topRing);
//连接底部与顶部面
for (int k = 0; k < points.PointCount; k++)
{
IPoint point1 = points.get_Point(k);
IPoint point2 = points.get_Point((k + 1) % points.PointCount);
IPointCollection sideRing = new RingClass();
sideRing.AddPoint(point1);
sideRing.AddPoint(point2);
sideRing.AddPoint(point1); //形成闭环
IGeometryCollection triangleStrip = new TriangleStripClass();
// 创建底部面的副本
IClone bottomFaceClone = (IClone)bottomFace;
IGeometry bottomFaceCopy = (IGeometry)bottomFaceClone.Clone();
triangleStrip.AddGeometry(bottomFaceCopy); // 使用底部面
triangleStrip.AddGeometry((IGeometry)topRing);
triangleStrip.AddGeometry((IGeometry)sideRing);
multiPatch.AddGeometry((IGeometry)triangleStrip);
}
// 创建新要素并添加到图层
IFeatureBuffer featureBuffer = featureClass.CreateFeatureBuffer();
featureBuffer.Shape = (IGeometry)multiPatch;
featureBuffer.set_Value(featureClass.Fields.FindField("ZValue"), zValue); // 设置 Z 值属性
IFeatureCursor insertCursor = featureClass.Insert(true);
insertCursor.InsertFeature(featureBuffer);
insertCursor.Flush();
}
feature = cursor.NextFeature();
}
}
}
IActiveView pActiveView = (IActiveView)scene;
pActiveView.PartialRefresh(esriViewDrawPhase.esriViewGeography, null, null);
}