使用Element对象模拟车辆动态行驶

ArcEngine中也提供了支持模拟车辆动态行驶的方法,其主要原理是:首先获取得到车辆行驶的路径IPolyline对象,通过IConstructGeometryCollection接口将IPolyline对象按指定大小拆分得到沿行驶路径分布的众多IPoint对象,主要获取每个IPoint对象的坐标信息,使用一个IMarkerElement对象来在地图上表示车辆,表示车辆的图片通过IPictureMarkerSymbol接口来设置,其位置则通过各个IPoint对象表示;或者也可以直接通过IPictureElement对象来设计,但是IPictureElement对象无法设定车头行驶方向。最后根据车辆行驶车速通过一个时间控件逐点按时不断刷新Element对象,达到模拟车辆动态行驶的效果。

其C#实现代码如下:

    
  private void timer1_Tick(object sender, EventArgs e)
        {
            try
            {
                //清空所有标记
                pGraphicsContainer.DeleteAllElements();
                double pPointX = 0, pPointY = 0;
                IPoint pPoint = new PointClass();
                IRgbColor pColor = new RgbColorClass();
                IPictureMarkerSymbol pPictureMarkerSymbol = new PictureMarkerSymbolClass();
                IMarkerElement pMarkerElement = new MarkerElementClass();
                ITextElement pTextElement = new TextElementClass();
                ITextSymbol pTextSymbol = new TextSymbolClass();
                IEnvelope pEnvelop = axMainMap.ActiveView.Extent;
                foreach (IPointCollection pPointCol in pPointColList)
                {
                    double pAngle = 0;                    //记录车头方向
                    //当前路径到达终点则保留终点位置标记
                    if (num > pPointCol.PointCount - 1)
                        pPoint = pPointCol.get_Point(pPointCol.PointCount - 1);
                    else
                    {
                        pPoint = pPointCol.get_Point(num++);
                        //根据路径方向计算车头方向,单位为°
                        if (num != 1)
                        {
                            IPoint pFoward = pPointCol.get_Point(num - 2);  //记录行驶的前一结点
                            if (pFoward.X - pPoint.X == 0)
                                pAngle = 90;
                            else
                                pAngle = Math.Atan((pFoward.Y - pPoint.Y) / (pFoward.X - pPoint.X))*60;
                        }
                    }
                    //方法一:创建IPictureElement,支持图片同步缩放
                    //IPictureElement pPictureElement = new JpgPictureElementClass();
                    //pPictureElement.ImportPictureFromFile(".//...//func.jpg");
                    //pPictureElement.SavePictureInDocument = true;
                    //pPictureElement.MaintainAspectRatio = false;
                    //IElement pEle = pPictureElement as IElement;
                    //创建Polygon对象
                    //IEnvelope pEnv = new EnvelopeClass();
                    //pEnv.PutCoords(pPoint.X - 10, pPoint.Y - 10, pPoint.X + 60, pPoint.Y + 40);
                    //pEle.Geometry = (IGeometry)pEnv;
                    //方法二:禁止图片同步缩小
                    pPictureMarkerSymbol.Size = 10;
                    //设置位图透明颜色
                    pColor.Red = 255;
                    pColor.Green = 255;
                    pColor.Blue = 255;
                    pPictureMarkerSymbol.BitmapTransparencyColor = pColor;
                    pPictureMarkerSymbol.CreateMarkerSymbolFromFile(esriIPictureType.esriIPictureBitmap, strRootPath + "\\LtMonitor\\Car.bmp");
                    //设置x,y偏移量
                    pPictureMarkerSymbol.YOffset = 2;
                    //设置车头方向
                    pPictureMarkerSymbol.Angle = pAngle;
                   
                    //设置标记位置
                    pMarkerElement.Symbol = pPictureMarkerSymbol;
                    ((IElement)pMarkerElement).Geometry = pPoint;
                    pGraphicsContainer.AddElement((IElement)pMarkerElement, 0); 
                    //加载车名称标记
                    pTextElement.Text = "汽车";
                    //设置文本标记大小
                    pTextSymbol.Size = 6;
                    //设置字体颜色
                    pColor.Red = 255;
                    pColor.Green = 0;
                    pColor.Blue = 0;
                    pTextSymbol.Color = pColor;
                    pTextElement.Symbol = pTextSymbol;
                    //用于计算视图范围
                    pPointX += pPoint.X;
                    pPointY += pPoint.Y;
                    //设置文本标记位置
                    pPoint.Y = pPoint.Y - 20;
                    pPoint.X = pPoint.X + 5;
                    ((IElement)pTextElement).Geometry = pPoint;
                    //向Element容器中加载IElement对象
                    pGraphicsContainer.AddElement((IElement)pTextElement, 0);
                }
                //如果导航点超出视图范围,则将移动地图
                if (pPointX / pPointColList.Count > pEnvelop.XMax - 50)
                {
                    pPoint.X = pPointX / pPointColList.Count;
                    pPoint.Y = pPointY / pPointColList.Count;
                    pEnvelop.CenterAt(pPoint);
                    axMainMap.Extent = pEnvelop;
                }
                //局部刷新
                axMainMap.ActiveView.PartialRefresh(esriViewDrawPhase.esriViewGraphics, null, null);
            }
            catch { }
        }
       //提取行驶路径的点信息,等距划分,距离为1米
        private void MakeMultiPoint(IGeometry pGeometry, int nPoints, ref IPointCollection pGeoCol)
        {
            if (pGeometry.GeometryType == esriGeometryType.esriGeometryPolyline)
            {
                IGeometryCollection pGeometryCollection;
                IConstructGeometryCollection pCGeometryCollection = new GeometryBagClass();
                //等距均分
                //pCGeometryCollection.ConstructDivideEqual((IPolyline)pGeometry, nPoints - 1, esriConstructDivideEnum.esriDivideIntoPolylines);
                //以定值划分,0.001的单位为Km
                pCGeometryCollection.ConstructDivideLength((IPolyline)pGeometry,0.001,true,esriConstructDivideEnum.esriDivideIntoPolylines);
                IEnumGeometry pEnumGeometry = (IEnumGeometry)pCGeometryCollection;
                pGeometryCollection = new MultipointClass();
                IPolyline pPolyline = (IPolyline)pEnumGeometry.Next();
                object Missing = Type.Missing;
                //提取指定值划分后的点信息
                pGeometryCollection.AddGeometry(pPolyline.FromPoint, ref Missing, ref Missing);
                while (pPolyline != null)
                {
                    pGeometryCollection.AddGeometry(pPolyline.ToPoint, ref Missing, ref Missing);
                    pPolyline = (IPolyline)pEnumGeometry.Next();
                }
                pGeoCol = (IPointCollection)pGeometryCollection;
            }
        }


        以上代码尚存在一个问题:车辆的文本标注与车辆图片之间的距离随地图的缩放而产生变化,目前还没有发现能够同时支持图片和文本的Element对象,如果有就很好解决了!MakeMultiPoint()函数将车辆行驶路径按1m的距离拆分,并从IPolyLine对象中得到IPointCollecntion对象,Timer控件响应时,首先删除上次标记,再添加本状态下的标记,保证每次响应时一条路径上只有一个标记代表车辆行驶。

你可能感兴趣的:(ArcEngine)