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 ();
                }

            }

        }

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