从零开始:AE二次开发中获取A点到B点的最佳路径(4)

在本文档中主要内容是:代码实现创建的几何网络最短路径分析的代码。参考资料为: ArcGIS Engine 10开发手册。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using ESRI.ArcGIS.Geodatabase;
using ESRI.ArcGIS.DataSourcesGDB;
using ESRI.ArcGIS.NetworkAnalysis;
using ESRI.ArcGIS.Carto;
using ESRI.ArcGIS.Geometry;
using ESRI.ArcGIS.Display;
using ESRI.ArcGIS.Controls;

namespace 阵地部署辅助决策预案系统_3._10_.Services.MapDevelopClass
{
    /// <summary>
    /// 网络分析,包括几何网络分析和无向网络分析
    /// </summary>
    class NetWorkAnalysis
    {
        #region  Geometric Network 几何网络分析,用于:A.寻找 连通的/不连通的管线 B.上/下游追踪 C.寻找环路 D.寻找通路 E.爆管分析

        #region 获取工作区间
        /// <summary>
        /// 打开个人数据库,获取工作区
        /// </summary>
        /// <param name="_pGDBName"></param>
        /// <returns></returns>
        public IWorkspace GetWorkspace(String _pGDBName)
        {
            IWorkspaceFactory pWsFac = new AccessWorkspaceFactoryClass();
            IWorkspace pWs = pWsFac.OpenFromFile(_pGDBName, 0);
            return pWs;
        }
        #endregion

        #region 创建几何网络
        /// <summary>
        /// 创建几何网络,其中要素类和几何网络名可根据需要进行修改
        /// </summary>
        /// <param name="_pWorkspace"></param>
        /// <param name="_pFeatureDatasetName"></param>
        /// <param name="_pGeometricName"></param>
        public void CreateGeometricNetwork(IWorkspace _pWorkspace, IFeatureDatasetName _pFeatureDatasetName, String _pGeometricName)
        {
            INetworkLoader2 pNetworkLoader = new NetworkLoaderClass();
            // 创建网络的名称
            pNetworkLoader.NetworkName = _pGeometricName;
            // 创建网络的类型
            pNetworkLoader.NetworkType = esriNetworkType.esriNTUtilityNetwork;
            // 设置要素集名称
            pNetworkLoader.FeatureDatasetName = (IDatasetName)_pFeatureDatasetName;
            // 检查要建立几何网络的数据,每一个要素只能参与一个网络,PrimaryLine 是要素集中的线要素
            if (pNetworkLoader.CanUseFeatureClass("PrimaryLine") ==
            esriNetworkLoaderFeatureClassCheck.esriNLFCCValid)
            {
                pNetworkLoader.AddFeatureClass("PrimaryLine",
                esriFeatureType.esriFTComplexEdge, null, false);
            }
            //Feeder是数据集中的点要素
            if (pNetworkLoader.CanUseFeatureClass("Feeder") ==
            esriNetworkLoaderFeatureClassCheck.esriNLFCCValid)
            {
                pNetworkLoader.AddFeatureClass("Feeder", esriFeatureType.esriFTSimpleJunction,
                null, false);
            }
            // 数据中没有enable字段,所以用false。如果用true的话,就要进行相关的设置
            INetworkLoaderProps pNetworkLoaderProps = (INetworkLoaderProps)pNetworkLoader;
            pNetworkLoader.PreserveEnabledValues = false;
            String defaultAncillaryRoleFieldName =  pNetworkLoaderProps.DefaultAncillaryRoleField;
            esriNetworkLoaderFieldCheck ancillaryRoleFieldCheck =  pNetworkLoader.CheckAncillaryRoleField("Feeder",  defaultAncillaryRoleFieldName);
            switch (ancillaryRoleFieldCheck)
            {
                case esriNetworkLoaderFieldCheck.esriNLFCValid:
                case esriNetworkLoaderFieldCheck.esriNLFCNotFound:
                    pNetworkLoader.PutAncillaryRole("Feeder",
                    esriNetworkClassAncillaryRole.esriNCARSourceSink,
                    defaultAncillaryRoleFieldName);
                    break;
                default:
                    Console.WriteLine(
                    "The field {0} could not be used as an ancillary role field.",
                    defaultAncillaryRoleFieldName);
                    break;
            }
            pNetworkLoader.SnapTolerance = 0.02;
            // 给几何网络添加权重
            pNetworkLoader.AddWeight("Weight", esriWeightType.esriWTDouble, 0);
            // 将权重和PrimaryLine数据中的SHAPE_Length字段关联
            pNetworkLoader.AddWeightAssociation("Weight", "PrimaryLine", "SHAPE_Length");
            // 构建网络
            pNetworkLoader.LoadNetwork();
        }
        #endregion


        #region 代码创建几何网络的最短路径分析
        /// <summary>
        /// 求解最短路径,使用方式如: SolvePath(axMapControl1.Map, GetGeometricNetwork(pFtDataset, "TestGeometric"), "Weight", pPointC, 1000, ref pPolyline, ref s); GetGeometricNetwork是自定义的获取几何网络名的方法
        /// </summary>
        /// <param name="_pMap">MapControl中的Map</param>
        /// <param name="_pGeometricNetwork"></param>
        /// <param name="_pWeightName"></param>
        /// <param name="_pPoints"></param>
        /// <param name="_pDist"></param>
        /// <param name="_pPolyline"></param>
        /// <param name="_pPathCost"></param>
        public void SolvePath(IMap _pMap, IGeometricNetwork _pGeometricNetwork, string _pWeightName, IPointCollection _pPoints, double _pDist, ref IPolyline _pPolyline, ref double _pPathCost)
        {
            try
            { // 这4个参数其实就是一个定位Element的指标
                int intEdgeUserClassID;

                int intEdgeUserID;

                int intEdgeUserSubID;

                int intEdgeID;

                IPoint pFoundEdgePoint;

                double dblEdgePercent;

                ITraceFlowSolverGEN pTraceFlowSolver = new TraceFlowSolverClass() as ITraceFlowSolverGEN;

                INetSolver pNetSolver = pTraceFlowSolver as INetSolver;

                //操作是针对逻辑网络的,INetwork是逻辑网络

                INetwork pNetwork = _pGeometricNetwork.Network;

                pNetSolver.SourceNetwork = pNetwork;

                INetElements pNetElements = pNetwork as INetElements;

                int pCount = _pPoints.PointCount;
                //定义一个边线旗数组
                IEdgeFlag[] pEdgeFlagList = new EdgeFlagClass[pCount];

                IPointToEID pPointToEID = new PointToEIDClass();

                pPointToEID.SourceMap = _pMap;

                pPointToEID.GeometricNetwork = _pGeometricNetwork;

                pPointToEID.SnapTolerance = _pDist;

                for (int i = 0; i < pCount; i++)
                {
                    INetFlag pNetFlag = new EdgeFlagClass() as INetFlag;

                    IPoint pEdgePoint = _pPoints.get_Point(i);
                    //查找输入点的最近的边线
                    pPointToEID.GetNearestEdge(pEdgePoint, out intEdgeID, out pFoundEdgePoint, out dblEdgePercent);

                    pNetElements.QueryIDs(intEdgeID, esriElementType.esriETEdge, out intEdgeUserClassID, out intEdgeUserID, out intEdgeUserSubID);


                    pNetFlag.UserClassID = intEdgeUserClassID;

                    pNetFlag.UserID = intEdgeUserID;

                    pNetFlag.UserSubID = intEdgeUserSubID;

                    IEdgeFlag pTemp = (IEdgeFlag)(pNetFlag as IEdgeFlag);
                    pEdgeFlagList[i] = pTemp;
                }
                pTraceFlowSolver.PutEdgeOrigins(ref pEdgeFlagList);

                INetSchema pNetSchema = pNetwork as INetSchema;

                INetWeight pNetWeight = pNetSchema.get_WeightByName(_pWeightName);

                INetSolverWeightsGEN pNetSolverWeights = pTraceFlowSolver as INetSolverWeightsGEN;

                pNetSolverWeights.FromToEdgeWeight = pNetWeight;//开始边线的权重

                pNetSolverWeights.ToFromEdgeWeight = pNetWeight;//终止边线的权重

                object[] pRes = new object[pCount - 1];

                //通过FindPath得到边线和交汇点的集合
                IEnumNetEID pEnumNetEID_Junctions;

                IEnumNetEID pEnumNetEID_Edges;

                pTraceFlowSolver.FindPath(esriFlowMethod.esriFMConnected,
                 esriShortestPathObjFn.esriSPObjFnMinSum,
                 out pEnumNetEID_Junctions, out pEnumNetEID_Edges, pCount - 1, ref pRes);
                //计算元素成本
                _pPathCost = 0;
                for (int i = 0; i < pRes.Length; i++)
                {
                    double m_Va = (double)pRes[i];

                    _pPathCost = _pPathCost + m_Va;
                }

                IGeometryCollection pNewGeometryColl = _pPolyline as IGeometryCollection;//QI

                ISpatialReference pSpatialReference = _pMap.SpatialReference;

                IEIDHelper pEIDHelper = new EIDHelperClass();

                pEIDHelper.GeometricNetwork = _pGeometricNetwork;

                pEIDHelper.OutputSpatialReference = pSpatialReference;

                pEIDHelper.ReturnGeometries = true;

                IEnumEIDInfo pEnumEIDInfo = pEIDHelper.CreateEnumEIDInfo(pEnumNetEID_Edges);

                int Count = pEnumEIDInfo.Count;

                pEnumEIDInfo.Reset();

                for (int i = 0; i < Count; i++)
                {
                    IEIDInfo pEIDInfo = pEnumEIDInfo.Next();

                    IGeometry pGeometry = pEIDInfo.Geometry;

                    pNewGeometryColl.AddGeometryCollection(pGeometry as IGeometryCollection);
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }
        }

        /// <summary>
        /// 获得需要的几何网络
        /// </summary>
        /// <param name="_pFeatureDataset"></param>
        /// <param name="_pGeometricName"></param>
        /// <returns></returns>
        IGeometricNetwork GetGeometricNetwork(IFeatureDataset _pFeatureDataset, string _pGeometricName)
        {
            INetworkCollection pNetworkCollection = _pFeatureDataset as INetworkCollection;


            return pNetworkCollection.get_GeometricNetworkByName(_pGeometricName);

        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="axMapControl1"></param>
        /// <param name="pGC"></param>
        public void SolvePathTest(AxMapControl axMapControl1 ,IGraphicsContainer pGC,string workspacfile,string DataSetName,string NetwrokName,IMultipoint pmulti)
        {
            IWorkspace pWs = GetMDBWorkspace(workspacfile);

            IFeatureWorkspace pFtWs = pWs as IFeatureWorkspace;

            IFeatureDataset pFtDataset = pFtWs.OpenFeatureDataset(DataSetName);

            double s = 0;

            IPolyline pPolyline = new PolylineClass();

            SolvePath(axMapControl1.Map, GetGeometricNetwork(pFtDataset, NetwrokName), "Weight", pPointC, 1000, ref pPolyline, ref s);

            IRgbColor pColor = new RgbColorClass();
            pColor.Red = 255;
            IElement pElement = new LineElementClass();
            ILineSymbol linesymbol = new SimpleLineSymbolClass();
            linesymbol.Color = pColor as IColor;
            linesymbol.Width = 100;

            pElement.Geometry = pPolyline;

            pGC.AddElement(pElement, 2);

            axMapControl1.ActiveView.PartialRefresh(esriViewDrawPhase.esriViewGraphics, null, null);
        }

        /// <summary>
        /// 打开个人数据库
        /// </summary>
        /// <param name="_pGDBName"></param>
        /// <returns></returns>
         IWorkspace GetMDBWorkspace(String _pGDBName)
        {
            IWorkspaceFactory pWsFac = new AccessWorkspaceFactoryClass();

            IWorkspace pWs = pWsFac.OpenFromFile(_pGDBName, 0);

            return pWs;
        }

         IPointCollection GetPoints(IMultipoint PMulit)
         {
             IPointCollection pPoints;
             PMulit = new MultipointClass();
             pPoints = PMulit as IPointCollection;
             return pPoints;
         }
        #endregion

        #endregion



    }
}
其中几何网络名,featureSet,featureclass需要自己定义和创建,几何网络如何不是必须在程序后台创建的话,我建议在ArcCatalog中建好之后存储到GDB中。

以上的代码这是几何网络的分析,并不是无向网络的分析。无向网络的创建也分为两种,通过Catalog创建和通过代码创建。无向网络Network DataSet的分析与几何网络稍微不太一样。具体代码如下: 

#region Network DataSet 无向网络分析,用于:A.最短路径 B.物流输送 C.临近设施分析 D.服务区分析 E.选址分析

        /// <summary>
        /// 代码创建几何网络
        /// </summary>
         /// <param name="_pWsName">个人数据库的路径</param>
         /// <param name="_pDatasetName">要素数据集的路径</param>
         /// <param name="_pNetName">建立网络的名称</param>
         /// <param name="_pFtName">参与网络的要素类</param>
         public void CreateNetworkDataset(string _pWsName, string _pDatasetName, string _pNetName, string _pFtName)
         {
             
            IDENetworkDataset2 pDENetworkDataset = new DENetworkDatasetClass();

            pDENetworkDataset.Buildable = true;

            IWorkspace pWs = GetMDBWorkspace(_pWsName);

            IFeatureWorkspace pFtWs = pWs as IFeatureWorkspace;

            IFeatureDataset pFtDataset = pFtWs.OpenFeatureDataset(_pDatasetName);

            // 定义空间参考,负责会出错
            IDEGeoDataset pDEGeoDataset = (IDEGeoDataset)pDENetworkDataset;

             IGeoDataset pGeoDataset = pFtDataset as IGeoDataset;

            pDEGeoDataset.Extent = pGeoDataset.Extent;

             pDEGeoDataset.SpatialReference = pGeoDataset.SpatialReference;



            // 网络数据集的名称
            IDataElement pDataElement = (IDataElement)pDENetworkDataset;

            pDataElement.Name = _pNetName;



            // 参加建立网络数据集的要素类
            INetworkSource pEdgeNetworkSource = new EdgeFeatureSourceClass();
            pEdgeNetworkSource.Name = _pFtName;

            
            pEdgeNetworkSource.ElementType = esriNetworkElementType.esriNETEdge;

            // 要素类的连通性
            IEdgeFeatureSource pEdgeFeatureSource = (IEdgeFeatureSource)pEdgeNetworkSource;
            pEdgeFeatureSource.UsesSubtypes = false;

           

            pEdgeFeatureSource.ClassConnectivityGroup = 1;

            pEdgeFeatureSource.ClassConnectivityPolicy =esriNetworkEdgeConnectivityPolicy.esriNECPEndVertex;


           
            //不用转弯数据
            pDENetworkDataset.SupportsTurns = false;

          
            IArray pSourceArray = new ArrayClass();
            pSourceArray.Add(pEdgeNetworkSource);


            pDENetworkDataset.Sources = pSourceArray;

            //网络数据集的属性设置

            IArray pAttributeArray = new ArrayClass();

            // Initialize variables reused when creating attributes:
            IEvaluatedNetworkAttribute pEvalNetAttr;
            INetworkAttribute2 pNetAttr2;
            INetworkFieldEvaluator pNetFieldEval;
            INetworkConstantEvaluator pNetConstEval;


      
            pEvalNetAttr = new EvaluatedNetworkAttributeClass();
            pNetAttr2 = (INetworkAttribute2)pEvalNetAttr;
            pNetAttr2.Name ="Meters";
            pNetAttr2.UsageType = esriNetworkAttributeUsageType.esriNAUTCost;
            pNetAttr2.DataType = esriNetworkAttributeDataType.esriNADTDouble;
            pNetAttr2.Units = esriNetworkAttributeUnits.esriNAUMeters;
            pNetAttr2.UseByDefault = false;


            pNetFieldEval = new NetworkFieldEvaluatorClass();
            pNetFieldEval.SetExpression("[METERS]", "");
            //方向设置
            pEvalNetAttr.set_Evaluator(pEdgeNetworkSource,
                esriNetworkEdgeDirection.esriNEDAlongDigitized, (INetworkEvaluator)pNetFieldEval);
            pEvalNetAttr.set_Evaluator(pEdgeNetworkSource,
                esriNetworkEdgeDirection.esriNEDAgainstDigitized, (INetworkEvaluator)
                pNetFieldEval);

            pNetConstEval = new NetworkConstantEvaluatorClass();
            pNetConstEval.ConstantValue = 0;
            pEvalNetAttr.set_DefaultEvaluator(esriNetworkElementType.esriNETEdge,
                (INetworkEvaluator)pNetConstEval);
            pEvalNetAttr.set_DefaultEvaluator(esriNetworkElementType.esriNETJunction,
                (INetworkEvaluator)pNetConstEval);
            pEvalNetAttr.set_DefaultEvaluator(esriNetworkElementType.esriNETTurn,
                (INetworkEvaluator)pNetConstEval);

            // 一个网络数据集可以有多个属性,我只添加了一个
            pAttributeArray.Add(pEvalNetAttr);

            pDENetworkDataset.Attributes = pAttributeArray;
          

            // 创建网络数据集,注意在创建几何网络的时候会锁定相应的要素类,因此不要用ArcMap或者catalog等打开参相应的数据

          INetworkDataset pNetworkDataset = Create(pFtDataset, pDENetworkDataset);

             
            //建立网络

            INetworkBuild pNetworkBuild = (INetworkBuild)pNetworkDataset;

            
            pNetworkBuild.BuildNetwork(pGeoDataset.Extent);

         }
      
         /// <summary>
         /// 创建无向网络
         /// </summary>
         /// <param name="_pFeatureDataset"></param>
         /// <param name="_pDENetDataset"></param>
         /// <returns></returns>
         public INetworkDataset Create(IFeatureDataset _pFeatureDataset, IDENetworkDataset2 _pDENetDataset)
         {
             IFeatureDatasetExtensionContainer pFeatureDatasetExtensionContainer = (IFeatureDatasetExtensionContainer)_pFeatureDataset;

             IFeatureDatasetExtension pFeatureDatasetExtension = pFeatureDatasetExtensionContainer.FindExtension
                 (esriDatasetType.esriDTNetworkDataset);

             IDatasetContainer2 pDatasetContainer2 = (IDatasetContainer2)pFeatureDatasetExtension;

             IDEDataset pDENetDataset = (IDEDataset)_pDENetDataset;

             INetworkDataset pNetworkDataset = (INetworkDataset)pDatasetContainer2.CreateDataset
                 (pDENetDataset);


             return pNetworkDataset;
         }

         /// <summary>
         /// _pFtClass参数为Stops的要素类,_pPointC是用鼠标点的点生成的点的集合,最后一个参数是捕捉距离
         /// </summary>
         /// <param name="_pNaContext"></param>
         /// <param name="_pFtClass"></param>
         /// <param name="_pPointC"></param>
         /// <param name="_pDist"></param>
         public void NASolve(INAContext _pNaContext, IFeatureClass _pFtClass, IPointCollection _pPointC, double _pDist)
         {
             INALocator pNAlocator = _pNaContext.Locator;
             for (int i = 0; i < _pPointC.PointCount; i++)
             {
                 IFeature pFt = _pFtClass.CreateFeature();

                 IRowSubtypes pRowSubtypes = pFt as IRowSubtypes;

                 pRowSubtypes.InitDefaultValues();

                 pFt.Shape = _pPointC.get_Point(i) as IGeometry;

                 IPoint pPoint = null;

                 INALocation pNalocation = null;

                 pNAlocator.QueryLocationByPoint(_pPointC.get_Point(i), ref pNalocation, ref pPoint, ref _pDist);

                 INALocationObject pNAobject = pFt as INALocationObject;

                 pNAobject.NALocation = pNalocation;

                 int pNameFieldIndex = _pFtClass.FindField("Name");

                 pFt.set_Value(pNameFieldIndex, pPoint.X.ToString() + "," + pPoint.Y.ToString());

                 int pStatusFieldIndex = _pFtClass.FindField("Status");

                 pFt.set_Value(pStatusFieldIndex, esriNAObjectStatus.esriNAObjectStatusOK);

                 int pSequenceFieldIndex = _pFtClass.FindField("Sequence");

                 pFt.set_Value(_pFtClass.FindField("Sequence"), ((ITable)_pFtClass).RowCount(null));

                 pFt.Store();

             }
         }


         /// <summary>
         /// 获取网络数据集
         /// </summary>
         /// <param name="_pFeatureWs"></param>
         /// <param name="_pDatasetName"></param>
         /// <param name="_pNetDatasetName"></param>
         /// <returns></returns>
         INetworkDataset GetNetDataset(IFeatureWorkspace _pFeatureWs, string _pDatasetName, string _pNetDatasetName)
         {

             ESRI.ArcGIS.Geodatabase.IDatasetContainer3 pDatasetContainer = null;

             ESRI.ArcGIS.Geodatabase.IFeatureDataset pFeatureDataset = _pFeatureWs.OpenFeatureDataset(_pDatasetName);
             ESRI.ArcGIS.Geodatabase.IFeatureDatasetExtensionContainer pFeatureDatasetExtensionContainer = pFeatureDataset as ESRI.ArcGIS.Geodatabase.IFeatureDatasetExtensionContainer; // Dynamic Cast
             ESRI.ArcGIS.Geodatabase.IFeatureDatasetExtension pFeatureDatasetExtension = pFeatureDatasetExtensionContainer.FindExtension(ESRI.ArcGIS.Geodatabase.esriDatasetType.esriDTNetworkDataset);
             pDatasetContainer = pFeatureDatasetExtension as ESRI.ArcGIS.Geodatabase.IDatasetContainer3; // Dynamic Cast

             ESRI.ArcGIS.Geodatabase.IDataset pNetWorkDataset = pDatasetContainer.get_DatasetByName(ESRI.ArcGIS.Geodatabase.esriDatasetType.esriDTNetworkDataset, _pNetDatasetName);

             return pNetWorkDataset as ESRI.ArcGIS.Geodatabase.INetworkDataset; // Dynamic Cast
         }


         public void LoadNetDataSet(AxMapControl axMapControl1, INASolver pNASolveClass, INALayer pNALayer)
         {
             IWorkspace pWs = GetMDBWorkspace(@".\data\Geometric.mdb");

             IFeatureWorkspace pFtWs = pWs as IFeatureWorkspace;

             INetworkDataset pNetWorkDataset = GetNetDataset(pFtWs, "network", "network_ND");

             pNASolveClass = new NARouteSolverClass();

             loadNet(axMapControl1.Map, pNetWorkDataset);

             

             pNALayer = GetNaLayer(pNASolveClass,  GetSolverContext(pNASolveClass, pNetWorkDataset));

             axMapControl1.Map.AddLayer(pNALayer as ILayer);
         }



         /// <summary>
         /// 加载NetworkDataset到Map中
         /// </summary>
         /// <param name="_pMap"></param>
         /// <param name="_pNetworkDataset"></param>
         void loadNet(IMap _pMap, INetworkDataset _pNetworkDataset)
         {
             INetworkLayer pNetLayer = new NetworkLayerClass();

             pNetLayer.NetworkDataset = _pNetworkDataset;

             _pMap.AddLayer(pNetLayer as ILayer);
         }

         /// <summary>
         /// 获取网络分析上下文,这个接口是网络分析中很重要的一个
         /// </summary>
         /// <param name="_pNaSolver"></param>
         /// <param name="_pNetworkDataset"></param>
         /// <returns></returns>
         public INAContext GetSolverContext(INASolver _pNaSolver, INetworkDataset _pNetworkDataset)
         {
             //Get the Data Element

             IDatasetComponent pDataComponent = _pNetworkDataset as IDatasetComponent;

             IDEDataset pDeDataset = pDataComponent.DataElement;

             INAContextEdit pContextEdit = _pNaSolver.CreateContext(pDeDataset as IDENetworkDataset, _pNaSolver.Name) as INAContextEdit;

             //Prepare the context for analysis based upon the current network dataset schema.
             pContextEdit.Bind(_pNetworkDataset, new GPMessagesClass());
             return pContextEdit as INAContext;
         }
         /// <summary>
         /// 获取NALayer
         /// </summary>
         /// <param name="_pNaSover"></param>
         /// <param name="_pNaContext"></param>
         /// <returns></returns>

         INALayer GetNaLayer(INASolver _pNaSover, INAContext _pNaContext)
         {
             return _pNaSover.CreateLayer(_pNaContext);
         }
      

        #endregion
由于我使用的是MVVM框架,所以稍微修改了下ArcGIS Engine10开发手册中的代码,不过经过测试,还是可以正常使用的。


  • 2
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值