weixin_45543529 2023-11-02 12:21 采纳率: 50%
浏览 22
已结题

二维GIS数据面要素矢量拉伸三维代码

以下是我做的“转换”按钮 的点击事件,想实现将已经加载在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);
            }
        }

img

我又对代码进行了修改,但又遇到一个问题

 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", "");

这行代码会报错,这又是什么原因导致的呢

img

我打了断点进行调试之后,发现是第一次点击按钮后,面要素并没有拉伸为三维,是我的将多边形拉伸为多面体那行代码不起作用吗,应该怎么修改呢
我又对代码进行了修改,思路是先创立底面和顶面,在通过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);
        }
  • 写回答

14条回答 默认 最新

  • 专家-赤兔[在线] 全栈领域优质创作者 2023-11-02 12:31
    关注
    获得0.60元问题酬金

    引自强大而免费的微信小程序:皆我百晓生

    根据你提供的代码,有几个问题需要修正:

    1. 你在创建新的要素时,只是将其形状设置为原始多边形的形状,但没有为其设置Z值。你需要使用GeometryEnvironment类的SetZ方法为新要素设置Z值。

    2. 在循环中创建新要素后,需要使用IGraphicsLayer接口的AddElement方法将新要素添加到图层中。

    3. 在刷新视图之前,需要使用ISceneViewer接口的LockView和UnlockView方法锁定和解锁场景视图。

    修改后的代码如下所示:

    private void btnChange_Click(object sender, EventArgs e)
    {
        try
        {
            IScene scene = axSceneControl1.Scene;
            ILayer layer = scene.Layer[0];
            if (layer == null)
            {
                MessageBox.Show("未找到图层!");
                return;
            }
            IFeatureLayer featureLayer = layer as IFeatureLayer;
            IFeatureClass featureClass = featureLayer.FeatureClass;
            int zValueFieldIndex = featureClass.Fields.FindField("ZValue");
            IFeatureCursor featureCursor = featureClass.Search(null, true);
            
            IGraphicsContainer graphicsContainer = layer as IGraphicsContainer;
            graphicsContainer.DeleteAllElements(); // 移除之前的要素
            
            ISceneViewer sceneViewer = axSceneControl1.SceneGraph.ActiveViewer;
            sceneViewer.LockView();
            
            IFeature feature = featureCursor.NextFeature();
            while (feature != null)
            {
                double zValue = Convert.ToDouble(feature.get_Value(zValueFieldIndex));
                IGeometry geometry = feature.ShapeCopy;
                if (geometry.GeometryType == esriGeometryType.esriGeometryPolygon)
                {
                    IPolygon polygon = geometry as IPolygon;
                    
                    IGeometry newGeometry = GeometryEnvironment.Instance.CreateScaledPolygon(polygon, zValue, zValue, zValue);
                    
                    IElement element = new PolygonElementClass
                    {
                        Geometry = newGeometry
                    };
                    
                    graphicsContainer.AddElement(element, 0);
                }
                feature = featureCursor.NextFeature();
            }
            
            sceneViewer.UnlockView();
            axSceneControl1.SceneGraph.RefreshViewers();
            
            System.Runtime.InteropServices.Marshal.ReleaseComObject(featureCursor);
        }
        catch (Exception ex)
        {
            MessageBox.Show("拉伸失败" + ex.Message);
        }
    }
    

    请确保你通过zValueFieldIndex正确地找到了“ZValue”字段在要素类中的索引。如果仍然遇到问题,请提供更多的详细信息,以便我能够更好地帮助你。

    评论 编辑记录

报告相同问题?

问题事件

  • 系统已结题 11月10日
  • 修改了问题 11月8日
  • 修改了问题 11月5日
  • 修改了问题 11月5日
  • 展开全部

悬赏问题

  • ¥15 phython如何实现以下功能?查找同一用户名的消费金额合并—
  • ¥15 孟德尔随机化怎样画共定位分析图
  • ¥18 模拟电路问题解答有偿速度
  • ¥15 CST仿真别人的模型结果仿真结果S参数完全不对
  • ¥15 误删注册表文件致win10无法开启
  • ¥15 请问在阿里云服务器中怎么利用数据库制作网站
  • ¥60 ESP32怎么烧录自启动程序
  • ¥50 html2canvas超出滚动条不显示
  • ¥15 java业务性能问题求解(sql,业务设计相关)
  • ¥15 52810 尾椎c三个a 写蓝牙地址