我认为这个问题是ArcGis Server ADF Javascript Library的BUG?!

问题起源于前几天我一直研究的问题,就是用户在客户端选择一个圆,然后在服务端做空间分析,选择出圆里边所有的点,比如乡镇,村庄等(当然,实际上我使用美国地图测试)。但是经过测试发现,选择出来的点数除了偶尔正确之外,大多数都是不正确的,起初我还怀疑是ADF的问题,又直接通过AO搜索,问题同样存在,为此郁闷了好久。昨天,我终于找到问题的所在了。因为昨天我写心得《ADF Toolbar与Map的客户端和服务端交互过程分析》时大概研究了ESRI.ADF.UI.Map.debug.js的内容,发现如下内容:

MapDragCircle = MapCircle = ESRI.ADF.MapTools.Circle = function(mapid, mode, showLoading, cursor, vectorToolbarState) {
var map = $find(mapid);
var onComplete = Function.createDelegate(map, function(geom) {
  var geomString = geom.get_center().toString(':') + ':' + geom.get_width()*2;
  this.doCallback('EventArg=Circle&coords='+geomString+'&'+mapid+'_mode='+mode,this);
});
map.getGeometry(ESRI.ADF.Graphics.ShapeType.Circle,onComplete,function(){map.__activeToolMode=null;},ESRI.ADF.MapTools.lineColor,ESRI.ADF.MapTools.fillColor,cursor, true);
map.__activeToolMode = mode;
};

注意这行代码:

  var geomString = geom.get_center().toString(':') + ':' + geom.get_width()*2;

什么意思呢? 意思就是说你在MapCircleEventArgs得到的那个MapRadius并不是半径,而是一个4倍于半径的值。真正的半径值应该是“geom.get_width() / 2”。到底是不是真正这样呢? 我写了一个测试代码,就是以中点和MapCircleEventArgs.MapRadius构造一个正方形和原来在Javascript端画的圆形做叠加,ADF代码如下:

    public void ServerAction(ToolEventArgs args)
    {
        try
        {
            //PointSelector.SelectByAO(args);
            ESRI.ArcGIS.ADF.Web.UI.WebControls.Map map = (ESRI.ArcGIS.ADF.Web.UI.WebControls.Map)args.Control;
            ESRI.ArcGIS.ADF.Web.UI.WebControls.MapCircleEventArgs circleArgs = (ESRI.ArcGIS.ADF.Web.UI.WebControls.MapCircleEventArgs)args;
            ESRI.ArcGIS.ADF.ArcGISServer.PointN centerPointN = ESRI.ArcGIS.ADF.Web.DataSources.ArcGISServer.Converter.FromAdfPoint(circleArgs.MapCenter);
            double radius = circleArgs.MapRadius;
            //
            // 以圆中点和半经构造一个正方型。
            //
            ESRI.ArcGIS.ADF.ArcGISServer.PointN[] fivePoint = new ESRI.ArcGIS.ADF.ArcGISServer.PointN[5];
            fivePoint[0] = new ESRI.ArcGIS.ADF.ArcGISServer.PointN();
            fivePoint[0].X = centerPointN.X - radius;
            fivePoint[0].Y = centerPointN.Y + radius;
            fivePoint[0].SpatialReference = centerPointN.SpatialReference;
            fivePoint[1] = new ESRI.ArcGIS.ADF.ArcGISServer.PointN();
            fivePoint[1].X = centerPointN.X + radius;
            fivePoint[1].Y = centerPointN.Y + radius;
            fivePoint[1].SpatialReference = centerPointN.SpatialReference;
            fivePoint[2] = new ESRI.ArcGIS.ADF.ArcGISServer.PointN();
            fivePoint[2].X = centerPointN.X + radius;
            fivePoint[2].Y = centerPointN.Y - radius;
            fivePoint[2].SpatialReference = centerPointN.SpatialReference;
            fivePoint[3] = new ESRI.ArcGIS.ADF.ArcGISServer.PointN();
            fivePoint[3].X = centerPointN.X - radius;
            fivePoint[3].Y = centerPointN.Y - radius;
            fivePoint[3].SpatialReference = centerPointN.SpatialReference;
            fivePoint[4] = new ESRI.ArcGIS.ADF.ArcGISServer.PointN();
            fivePoint[4].X = fivePoint[0].X;
            fivePoint[4].Y = fivePoint[0].Y;
            fivePoint[4].SpatialReference = centerPointN.SpatialReference;
            ESRI.ArcGIS.ADF.ArcGISServer.Ring[] rings = new ESRI.ArcGIS.ADF.ArcGISServer.Ring[1];
            rings[0] = new ESRI.ArcGIS.ADF.ArcGISServer.Ring();
            rings[0].PointArray = fivePoint;
            ESRI.ArcGIS.ADF.ArcGISServer.PolygonN poly = new ESRI.ArcGIS.ADF.ArcGISServer.PolygonN();
            poly.RingArray = rings;
            poly.SpatialReference = centerPointN.SpatialReference;
            poly.HasID = false;
            poly.HasM = false;
            poly.HasZ = false;
            //////////////
            ESRI.ArcGIS.ADF.ArcGISServer.RgbColor fillColor = new ESRI.ArcGIS.ADF.ArcGISServer.RgbColor();
            fillColor.Red = 0;
            fillColor.Blue = 255;
            fillColor.Green = 0;
            fillColor.AlphaValueSpecified = true;
            fillColor.AlphaValue = 128;
            ESRI.ArcGIS.ADF.ArcGISServer.SimpleFillSymbol fillSym = new ESRI.ArcGIS.ADF.ArcGISServer.SimpleFillSymbol();
            fillSym.Style = ESRI.ArcGIS.ADF.ArcGISServer.esriSimpleFillStyle.esriSFSSolid;
            fillSym.Color = fillColor;
            ESRI.ArcGIS.ADF.ArcGISServer.RectangleElement newRect = new ESRI.ArcGIS.ADF.ArcGISServer.RectangleElement();
            newRect.Rectangle = poly;
            newRect.Symbol = fillSym;
            ///////
            IMapFunctionality mapFunc = map.GetFunctionality("USA_Base");
            ESRI.ArcGIS.ADF.Web.DataSources.ArcGISServer.MapResourceBase realMapRes =
                (ESRI.ArcGIS.ADF.Web.DataSources.ArcGISServer.MapResourceBase)mapFunc.Resource;
            ESRI.ArcGIS.ADF.ArcGISServer.MapDescription mapDesc = realMapRes.MapDescription;
            mapDesc.CustomGraphics = new ESRI.ArcGIS.ADF.ArcGISServer.GraphicElement[] { newRect};
            map.RefreshResource("USA_Base");
        }
        catch (System.Exception ex)
        {
         
        }
    }

大家请看图,如果使用原来的ADF Javascript Library的代码,就是getWidth() * 2,则得出的图


如果使用getWidth()/2值,则得出图:




如果我的分析没有错的话,那么这个问题就应该是BUG了。不过听说现在9.3版本不允许使用自己的代码了,所以解决方法只有两个了:
1、自己编写那个MapDragCricle代码。
2、在ADF Server端,做double realRadius = MapCircleEventArgs.MapRadius / 2。
posted @ 2009-10-15 22:25  鹰王  阅读(677)  评论(2)    收藏  举报