| | mmartin 04-12-2007, 12:50 PM Hello community.
Any ideas on how to draw a polygon on a geodatamap of zip codes, have
the user select the area,trap the zips in the shape and export to a dataset? Particularly not sure how to activate and use the toolbar drawing functions...programmactialy
I am using mappoint 2006 in visual studio 2005 via activex, VB.net:roll:
Best
M. Martin Paul Larson 04-17-2007, 02:24 PM First off, you'll need to change the zipcode map to a pushpin map. This is because the QueryShape() method does not work on demographic or area maps.
Programmatically triggering the DrawFreeformShape tool can be done by adding this class to your application:
Public Class xMapPointGUI
Private hwMPC As IntPtr = IntPtr.Zero
Private hwMessageFrame As IntPtr
Private Const WM_COMMAND As Int32 = &H111
Private Const WM_MAPPOINT_BEGIN_SCRIBBLE As Int32 = 58205
Private Const WM_MAPPOINT_BEGIN_LINE As Int32 = 58206
Private Const WM_MAPPOINT_BEGIN_ARROW As Int32 = 58207
Private Const WM_MAPPOINT_BEGIN_FREEFORM As Int32 = 58208
Private Const WM_MAPPOINT_BEGIN_RECTANGLE As Int32 = 58209
Private Const WM_MAPPOINT_BEGIN_OVAL As Int32 = 58210
Private Const WM_MAPPOINT_BEGIN_MEASURE As Int32 = &HE370
Private Const WM_MAPPOINT_BEGIN_RADIUS As Int32 = &HE372
Private Const WM_MAPPOINT_BEGIN_TEXTBOX As Int32 = 58211
Private Const WM_MAPPOINT_DRAW_PUSHPIN As Int32 = 58202
Private Declare Auto Function FindWindowEx Lib "user32" Alias "FindWindowEx" (ByVal hwParent As IntPtr, ByVal hwChildAfter As IntPtr, ByVal strClassName As String, ByVal strWindowCaption As String) As IntPtr
Private Declare Auto Function GetParentWindow Lib "user32" Alias "GetParent" (ByVal hwChild As IntPtr) As IntPtr
Private Declare Auto Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal hWnd As IntPtr, ByVal wMsg As Int32, ByVal wParam As Int32, ByVal lParam As Int32) As Int32
Public Event MPCError(ByVal strErrorMsg As String)
Public Sub New(ByRef MPC As AxMapPoint.AxMappointControl)
If MPC.Handle.ToInt32 = 0 Then
RaiseEvent MPCError("MapPointControl was not initialized before calling xMapPointGui.New()")
Exit Sub
End If
hwMPC = GetParentWindow(FindWindowEx(MPC.Handle, IntPtr.Zero, vbNullString, vbNullString))
Dim hwTemp = FindWindowEx(hwMPC, IntPtr.Zero, vbNullString, "")
hwMessageFrame = FindWindowEx(hwTemp, IntPtr.Zero, vbNullString, "")
End Sub
Public Sub BeginScribbleTool()
SendMessage(hwMessageFrame, WM_COMMAND, WM_MAPPOINT_BEGIN_SCRIBBLE, 0)
End Sub
Public Sub BeginLineTool()
SendMessage(hwMessageFrame, WM_COMMAND, WM_MAPPOINT_BEGIN_LINE, 0)
End Sub
Public Sub BeginArrowTool()
SendMessage(hwMessageFrame, WM_COMMAND, WM_MAPPOINT_BEGIN_ARROW, 0)
End Sub
Public Sub BeginFreeFormTool()
SendMessage(hwMessageFrame, WM_COMMAND, WM_MAPPOINT_BEGIN_FREEFORM, 0)
End Sub
Public Sub BeginRectangleTool()
SendMessage(hwMessageFrame, WM_COMMAND, WM_MAPPOINT_BEGIN_RECTANGLE, 0)
End Sub
Public Sub BeginOvalTool()
SendMessage(hwMessageFrame, WM_COMMAND, WM_MAPPOINT_BEGIN_OVAL, 0)
End Sub
Public Sub BeginRadiusTool()
SendMessage(hwMessageFrame, WM_COMMAND, WM_MAPPOINT_BEGIN_RADIUS, 0)
End Sub
Public Sub BeginTextBoxTool()
SendMessage(hwMessageFrame, WM_COMMAND, WM_MAPPOINT_BEGIN_TEXTBOX, 0)
End Sub
Public Sub BeginMeasureTool()
SendMessage(hwMessageFrame, WM_COMMAND, WM_MAPPOINT_BEGIN_MEASURE, 0)
End Sub
Public Sub BeginDrawPushPinTool()
SendMessage(hwMessageFrame, WM_COMMAND, WM_MAPPOINT_DRAW_PUSHPIN, 0)
End Sub
End Class
You can instantiate the class object by calling
Dim mpGUI As xMapPointGUI
...
mpGUI = New xMapPointGUI(Me.AxMapPointControl1)
To trigger the freeform tool, call
mpGui.BeginFreeFormTool()
After the user draws the shape, use the mappoint api QueryShape() method to find all pushpins within the shape and return them as a recordset. Then iterate through the recordset and use your favorite ADO.Net method to export the recordset items to a dataset.
HTH
Paul mmartin 04-17-2007, 06:40 PM Hi Paul,
Thanks very much for your reply. So, I understand then that a
GeoMapRegion.geoMapNorthAmerica could be used with Push pins put in for all the zip codes, to then query and put into the dataset?
Also, I implemented the class and executed it, but I'm not sure what's supposed to happen? Does this activate the toolbar freeform shape or some other function?. Not sure what it's doing once it executes the SendMessage(hwMessageFrame, WM_COMMAND, WM_MAPPOINT_BEGIN_FREEFORM, 0) ....? I simply brough up a map, and executed a button firing the mpGUI.BeginFreeFormTool() (I guess I'm not quite sure what the difference is between using this and the tool bar freeform command?)
Thanks again..michael Paul Larson 04-17-2007, 07:46 PM Yes - your understanding is correct.
And, yes, the method activates the freeform tool. Just as if the user had clicked the freeform toolbar button. This was to answer your question about activating the drawing toolbar items programmatically.
Were you instead looking for how to programmatically actually draw a shape? Dazzer 04-18-2007, 03:46 AM The adding of the pushpins can slow this process down quite considerably, Particularly if you shape is quite large.
One method i've implemented for this in the past is to plot all zip codes (post codes in my case in the uk) on a map with pushpins, then using the well documented CalcPos function, retrieve and store, in a database of choice, the latitude and longitude of those pushpins along with there zip code.
Once you have this data you don't need to use the pushpins in future. You can plot your shape and using any number of point in polygon algorithms ( Point in Polygon Strategies (http://www.acm.org/pubs/tog/editors/erich/ptinpoly/) ) work out which postcodes are within your polygon, (personally i go for a 'Ray' algorithm where I project a line from outside the shape to infinity counting the number of times the line crosses a boundary). mmartin 04-18-2007, 08:36 AM Thanks Paul,
Yes, this is exactly what I needed. I fixed something (I didn't have an active map in the sub I was calling the beginfreeform sub from) and now it works just as required. Thanks again..Michael (The code below is just and example of my test that worked)
Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
Dim objmap As MapPoint.Map
AxMappointControl1.NewMap(MapPoint.GeoMapRegion.ge oMapNorthAmerica)
objmap = AxMappointControl1.ActiveMap
AxMappointControl1.Toolbars.Item(1).Visible = True
AxMappointControl1.Toolbars.Item(2).Visible = True
AxMappointControl1.Toolbars.Item(3).Visible = True
AxMappointControl1.Toolbars.Item(4).Visible = True
mpGUI = New xmappointGUI(AxMappointControl1)
mpGUI.BeginFreeFormTool()
End Sub Paul Larson 04-18-2007, 04:14 PM Great - glad it works for ya.
Just an FYI, the toolbars don't need to be visible in order for the xMappointGUI class to work. It's fine to leave them visible, though.
-Paul | |