MapInfo开发心得——数据篇【转】

 
上一篇文章介绍了一个简单的地图缩放工具的制作,接下来需要介绍一下地图数据读取及加载的设计。
首先,地图上的数据是来自数据库并自动生成的,我在这里并没有采用MapInfo的ADO.NET,而是采用本身系统的查询接口再加上自定义实体来生成地图图元,并插入MapInfo的Session中的临时表中以展示。
考虑到程序的扩展性,我将数据获取、图元展示、地图展示等分离开来,尽量做到灵活易懂。
数据获取接口,我只定义了一个方法:
Code
<!--

Code highlighting produced by Actipro CodeHighlighter (freeware)
http://www.CodeHighlighter.com/

-->    /**//// <summary>
    
/// 数据提供接口,定义了获取数据的基本方法
    
/// </summary>

    public interface IDataProvider
    
{
        
/**//// <summary>
        
/// 获取所有数据主方法
        
/// </summary>
        
/// <returns>获取到的实体列表</returns>

        List<AbstractEntity> GetData ();
    }

这个方法返回List<自定义抽象实体>,这个List表示多个需要展示的图元集合。
所以最重要的是AbstractEntity了。
在该抽象实体中,我定义了两个属性X和Y,用来表示图元的座标:
公用属性
<!--

Code highlighting produced by Actipro CodeHighlighter (freeware)
http://www.CodeHighlighter.com/

-->        /**//// <summary>
        
/// 地图横向座标X(经度)
        
/// </summary>

        public double X
        
{
            
get
            
{
                
return this._x;
            }

            
set
            
{
                
this._x = value;
            }

        }

        
/**//// <summary>
        
/// 地图纵向座标Y(纬度)
        
/// </summary>

        public double Y
        
{
            
get
            
{
                
return this._y;
            }

            
set
            
{
                
this._y = value;
            }

        }

然后就是定义一大堆抽象方法了:

抽象方法
<!--

Code highlighting produced by Actipro CodeHighlighter (freeware)
http://www.CodeHighlighter.com/

-->        /**//// <summary>
        
/// 获取该子类实例化在地图上的显示样式
        
/// </summary>
        
/// <returns></returns>

        public abstract CompositeStyle GetMapStyle ();
        
/**//// <summary>
        
/// 获取该子类实例在地图上显示的图元形状
        
/// </summary>
        
/// <param name="coordSys"></param>
        
/// <returns></returns>

        public abstract FeatureGeometry GetFeature ( CoordSys coordSys );
        
/**//// <summary>
        
/// 构造该子类在地图表中的自定义字段
        
/// </summary>
        
/// <remarks>
        
/// 不应包含X、Y、Key字段
        
/// 字段名“MI_Geometry”和“MI_Style”和“MI_Key”为保留字段名
        
/// </remarks>
        
/// <returns>自定义列列表</returns>

        public abstract List<Column> CreateCustomColumn ();
        
/**//// <summary>
        
/// 填充Command对象中Parameters的值。只需填充除父类外的自定义属性
        
/// </summary>
        
/// <remarks>该方法只允许被父类调用</remarks>
        
/// <param name="command">MICommand对象引用</param>

        protected abstract void FillCommand ( ref MICommand command );
        
/**//// <summary>
        
/// 构造该子类在地图上显示的标注图层
        
/// </summary>
        
/// <returns>如不需显示标注图层,返回NULL</returns>

        public abstract IMapLayer CreateLabelLayer ();
        
/**//// <summary>
        
/// 获取该子类在地图数据表表名
        
/// </summary>
        
/// <returns></returns>

        public abstract string GetTableName ();
        
/**//// <summary>
        
/// 获取子类在地图上图层的名称
        
/// </summary>
        
/// <returns>数据在图层上的名称</returns>

        public abstract string GetLayerName ();
        
/**//// <summary>
        
/// 获取该实体的唯一标识
        
/// </summary>
        
/// <returns></returns>

        public abstract string GetKey ();
        
/**//// <summary>
        
/// 构造该图形被点击后在地图上弹出的附加控件
        
/// </summary>
        
/// <param name="key">被点击图形的唯一标识,该标识由Entity中GetKey获取</param>
        
/// <returns></returns>

        public abstract System.Windows.Forms.Control SelectionTips(string key);

从上面代码可以看出,在同一个List<AbstractEntity>中,只要把不同的子类对象装到List中,在地图上显示的所有图元都可以不相同!
以下展示了其中一个子类的重写:
Code
<!--

Code highlighting produced by Actipro CodeHighlighter (freeware)
http://www.CodeHighlighter.com/

-->        public override  MapInfo.Styles.CompositeStyle GetMapStyle ()
        
{
            Color cc 
= Color.FromArgb(200, GetValueColor(this.Value));
            SimpleInterior siStyle 
= new SimpleInterior(2, cc);
            SimpleLineStyle lineStyle 
= new SimpleLineStyle ( new LineWidth () );
            AreaStyle aStyle 
= new AreaStyle ( lineStyle, siStyle );
            CompositeStyle style 
= new CompositeStyle ( aStyle );
            
return style;
        }

        
public override sealed List<MapInfo.Data.Column> CreateCustomColumn ()
        
{
            MapInfo.Data.Column c 
= new MapInfo.Data.Column ( "value", MapInfo.Data.MIDbType.Double );
            List
<MapInfo.Data.Column> list = new List<MapInfo.Data.Column> ();
            list.Add ( c );
            
return list;
        }

        
protected override sealed void FillCommand ( ref MapInfo.Data.MICommand command )
        
{
            command.Parameters[
"value"].Value = this._value;
        }

        
public override MapInfo.Geometry.FeatureGeometry GetFeature ( MapInfo.Geometry.CoordSys coordSys )
        
{
            
//构造一个边长100米的矩形
            MapInfo.Geometry.Rectangle dr = new MapInfo.Geometry.Rectangle ( coordSys, new DPoint ( this.X, this.Y ), 100d, 100d, DistanceUnit.Meter, DistanceType.Spherical );
            FeatureGeometry fg 
= new MapInfo.Geometry.Rectangle ( coordSys, dr );
            
return fg;
        }

其中CreateCustomColumn和FillCommand方法是比较重要的,我们来分析一下:
由于现在我使用MapInfo中临时表来插入图元数据,并需要插入一些适当的值到自定义列中,于是在CreateCustomColumn中,我由子类提供一个列列表,以便构造Command对象时使用,并使用FillCommand方法把适当的值插入。这样,子类也具有了在临时图元表中插入自定义值的可能。在地图获取到数据后,只要把所有的数据转换成MapInfo可识别的图元,并插入到临时图元表中,那么所有需要的图元都将出现在地图上了!

 

填充数据到临时图元表中
<!--

Code highlighting produced by Actipro CodeHighlighter (freeware)
http://www.CodeHighlighter.com/

-->        /**//// <summary>
        
/// 把数据填充到地图表中
        
/// </summary>
        
/// <param name="table">地图数据表实例,必须实现GetFeature和GetMapStyle方法</param>
        
/// <param name="coordSys">地图座标系统</param>
        
/// <param name="entityList">数据</param>

        public static void InsertTable ( Table table,CoordSys coordSys, List<AbstractEntity> entityList )
        
{
            
//创建连接对象
            MIConnection connection = new MIConnection ();
            connection.Open ();
            
//Comm对象
            MICommand cmd;
            
try
            
{
                
foreach ( AbstractEntity entity in entityList )
                
{
                    cmd 
= connection.CreateCommand ();
                    
//使用各个实体构造Comm对象
                    entity.PrepareCommand ( table.Alias, ref cmd, entity.GetFeature ( coordSys ), entity.GetMapStyle () );
                    cmd.Prepare ();
                    
int nchanged = cmd.ExecuteNonQuery ();
                    cmd.Dispose ();
                }

            }

            
catch ( Exception ex )
            
{
                
throw new Exception ( "InsertTable Error " + ex.Message, ex );
            }

            
finally
            
{
                
if ( connection.State == System.Data.ConnectionState.Open )
                
{
                    connection.Close ();
                }

            }

        }

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章