📄 maphelper.cpp
字号:
//////////////////////////////////////////////////////////////////////////
// MapHelper.cpp - Utility routines for working with the MapObjects control
//
#include "stdafx.h"
#include <math.h>
#include <afxctl.h>
#include "maphelper.h"
///////////////////////////////////////////////////////////////////////////
// Data Directory
//
CDataDir::CDataDir()
: m_path("")
{
char szPath[MAX_PATH];
GetCurrentDirectory(MAX_PATH,szPath);
CString currentDir(szPath);
int pos = currentDir.Find("MFC");
if (pos >= 0)
m_path = (currentDir.Left(pos-1)) + TEXT("\\Data");
else
m_path = "";
}
CString CDataDir::GetPath()
{
return m_path;
}
void CDataDir::SetPath(LPCTSTR newPath)
{
m_path = newPath;
}
///////////////////////////////////////////////////////////////////////////
// File name handling
//
CString GetFileDirectory(const CString& path)
{
ASSERT(path.GetLength());
int pos = path.ReverseFind('\\');
if (pos >= 0)
return path.Left(pos);
return "";
}
CString GetFileName(const CString& path)
{
ASSERT(path.GetLength());
int pos = path.ReverseFind('\\');
if (pos >= 0)
return path.Right(path.GetLength() - pos - 1);
return "";
}
CString GetFileExt(const CString& path)
{
ASSERT(path.GetLength());
int pos = path.ReverseFind('.');
if (pos >= 0)
return path.Right(path.GetLength() - pos - 1);
return "";
}
CString GetFileTitle(const CString& path)
{
ASSERT(path.GetLength());
CString strResult = GetFileName(path);
int pos = strResult.ReverseFind('.');
if (pos >= 0)
return strResult.Left(pos);
return strResult;
}
///////////////////////////////////////////////////////////////////////////
// Layer Management
//
void AddLayer(CMap1& map)
{
CString filter(TEXT("ESRI Shapefiles (*.shp)|*.shp|"));
CString allFormats = TEXT("All supported formats|*.shp");
#if 0
// add the image filters to the end of the string
ImageFactory::FormatDescArray formats;
ImageFactory::QueryFormats(formats);
for (int i = 0; i < formats.GetSize(); i++)
{
if (formats[i].m_extensions.GetLength() == 0) continue;
filter += formats[i].m_name + TEXT("|");
filter += formats[i].m_extensions + TEXT("|");
allFormats += TEXT(";") + formats[i].m_extensions;
}
filter = allFormats + TEXT("|") + filter + TEXT("|");
#endif
CFileDialog dlg(TRUE, TEXT(".shp"), 0, OFN_FILEMUSTEXIST | OFN_HIDEREADONLY, filter);
if (dlg.DoModal() == IDOK)
{
CString ext = GetFileExt(dlg.GetPathName());
if (ext.CompareNoCase(TEXT("shp")) == 0)
AddLayer(map, dlg.GetPathName());
else
AddImageLayer(map, dlg.GetPathName());
}
}
void AddLayer(CMap1& map, const CString& path, COLORREF color, LPDISPATCH renderer)
{
// Establish connection to data
CMoDataConnection conn;
if (!conn.CreateDispatch(TEXT("MapObjects2.DataConnection")))
throw "unable to create MapObjects2.DataConnection";
conn.SetDatabase(GetFileDirectory(path));
if (!conn.Connect())
throw "unable to connect to database";
// Add layer specified by path
CMoLayers layers(map.GetLayers());
CMoMapLayer layer;
if (!layer.CreateDispatch(TEXT("MapObjects2.MapLayer")))
throw "unable to create MapObjects2.MapLayer";
CMoGeoDataset geoDataset(conn.FindGeoDataset(GetFileTitle(path)));
layer.SetGeoDataset(geoDataset);
if (color != -1) // Set color if specified
{
CMoSymbol layerSymbol(layer.GetSymbol());
layerSymbol.SetColor(color);
}
if (renderer)
layer.SetRenderer(renderer);
layers.Add(layer);
}
void AddLabelLayer(CMap1& map, const CString& path, LPCTSTR labelField, COLORREF color)
{
// Establish connection to data
CMoDataConnection conn;
if (!conn.CreateDispatch(TEXT("MapObjects2.DataConnection")))
throw "unable to create MapObjects2.DataConnection";
conn.SetDatabase(GetFileDirectory(path));
if (!conn.Connect())
throw "unable to connect to database";
// Add layer specified by path
CMoLayers layers(map.GetLayers());
CMoMapLayer layer;
if (!layer.CreateDispatch(TEXT("MapObjects2.MapLayer")))
throw "unable to create MapObjects2.MapLayer";
CMoGeoDataset geoDataset(conn.FindGeoDataset(GetFileTitle(path)));
layer.SetGeoDataset(geoDataset);
// Setup label renderer
CMoLabelRenderer lr;
lr.CreateDispatch("MapObjects2.LabelRenderer");
lr.SetField(labelField);
lr.SetDrawBackground(FALSE);
CMoTextSymbol sym(lr.GetSymbol(0));
CFontHolder font(0);
const FONTDESC fd = { sizeof(FONTDESC), OLESTR("Arial"), FONTSIZE(12), FW_NORMAL, ANSI_CHARSET, FALSE, FALSE, FALSE };
//font.InitializeFont(&fd, sym.GetFont());
font.InitializeFont(&fd);
LPFONTDISP pFontDisp = font.GetFontDispatch();
sym.SetFont(pFontDisp);
if (pFontDisp)
pFontDisp->Release();
if (color != -1)
sym.SetColor(color);
sym.SetVerticalAlignment(moAlignBottom);
sym.SetHorizontalAlignment(moAlignLeft);
layer.SetRenderer(lr);
layers.Add(layer);
}
void AddImageLayer(CMap1& map, const CString& path)
{
// Establish connection to data
CMoDataConnection conn;
if (!conn.CreateDispatch(TEXT("MapObjects2.DataConnection")))
throw "unable to create MapObjects2.DataConnection";
conn.SetDatabase(GetFileDirectory(path));
if (!conn.Connect())
throw "unable to connect to database";
// Add image layer
CMoLayers layers(map.GetLayers());
CMoImageLayer image;
if (!image.CreateDispatch(TEXT("MapObjects2.ImageLayer")))
throw "unable to create MapObjects2.ImageLayer";
image.SetFile(path);
layers.Add(image);
}
void AddSDELayer(CMap1& map, LPCTSTR server, LPCTSTR user,
LPCTSTR password, LPCTSTR db, COLORREF color)
{
// Establish connection to data
CMoDataConnection conn;
if (!conn.CreateDispatch(TEXT("MapObjects2.DataConnection")))
throw "unable to create MapObjects2.DataConnection";
conn.SetServer(server);
conn.SetUser(user);
conn.SetPassword(password);
conn.SetDatabase(db);
if (!conn.Connect())
throw "unable to connect to database";
// Add layer specified by path
CMoLayers layers(map.GetLayers());
CMoMapLayer layer;
if (!layer.CreateDispatch(TEXT("MapObjects2.MapLayer")))
throw "unable to create MapObjects2.MapLayer";
CMoGeoDataset geoDataset(conn.FindGeoDataset(db));
layer.SetGeoDataset(geoDataset);
if (color != -1) // Set color if specified
{
CMoSymbol layerSymbol(layer.GetSymbol());
layerSymbol.SetColor(color);
}
layers.Add(layer);
}
//
// All layer objects support the GetLayerType method.
// Each object's dispatch ID for the property is different
// though. Given the object's dispatch pointer, lookup
// the dispatch ID for the LayerType property then call
// Invoke to get the layer type.
//
short GetLayerType(CMoLayers& layers, short layerNum)
{
USES_CONVERSION;
short layerType = -1;
LPCOLESTR lpOleStr = T2COLE(TEXT("LayerType"));
DISPID dispID = -1;
COleDispatchDriver dd(layers.Item(COleVariant(layerNum)));
if (SUCCEEDED(LPDISPATCH(dd)->GetIDsOfNames(IID_NULL,
(LPOLESTR*)&lpOleStr, 1, 0, &dispID)))
{
dd.GetProperty(dispID, VT_I2, &layerType);
}
return layerType;
}
//
// Works with Redlands sample data
//
LPDISPATCH CreateStreetRenderer()
{
CMoSymbol sym;
CMoValueMapRenderer vr;
VERIFY(vr.CreateDispatch("MapObjects2.ValueMapRenderer"));
vr.SetField(TEXT("CFCC"));
vr.SetSymbolType(moLineSymbol);
vr.SetValueCount(6);
vr.SetValue(0, TEXT("A11"));
sym.AttachDispatch(vr.GetSymbol(0));
sym.SetColor(moBlue);
sym.SetSize(9);
vr.SetValue(1, TEXT("A15"));
sym.AttachDispatch(vr.GetSymbol(1));
sym.SetColor(moBlue);
sym.SetSize(9);
vr.SetValue(2, TEXT("A20"));
sym.AttachDispatch(vr.GetSymbol(2));
sym.SetColor(moNavy);
sym.SetSize(5);
vr.SetValue(3, TEXT("A21"));
sym.AttachDispatch(vr.GetSymbol(3));
sym.SetColor(moNavy);
sym.SetSize(5);
vr.SetValue(4, TEXT("A31"));
sym.AttachDispatch(vr.GetSymbol(4));
sym.SetColor(moBrown);
sym.SetSize(2);
vr.SetValue(5, TEXT("A63"));
sym.AttachDispatch(vr.GetSymbol(5));
sym.SetColor(moRed);
sym.SetSize(5);
sym.AttachDispatch(vr.GetDefaultSymbol());
sym.SetColor(moGray);
sym.SetSize(2);
LPDISPATCH(vr)->AddRef();
return LPDISPATCH(vr);
}
///////////////////////////////////////////////////////////////////////////
// Zoom and Pan
//
void ZoomIn(CMap1& map)
{
CMoRectangle r(map.TrackRectangle());
if (LPDISPATCH(r))
map.SetExtent(r);
}
void ZoomOut(CMap1& map)
{
CMoRectangle r(map.GetExtent());
ASSERT(LPDISPATCH(r));
r.ScaleRectangle(1.5);
map.SetExtent(r);
}
void ZoomFull(CMap1& map)
{
CMoRectangle r(map.GetFullExtent());
ASSERT(LPDISPATCH(r));
map.SetExtent(r);
}
void Pan(CMap1& map)
{
map.Pan();
}
void Resize(CMap1& map, int cx, int cy, int border)
{
if (map.m_hWnd)
map.SetWindowPos(0, border, border, cx - border, cy - border, SWP_NOZORDER);
}
///////////////////////////////////////////////////////////////////////////
// Conversion
//
double DegreesToMiles(double x1, double y1, double x2, double y2)
{
// H. Andoyer: [Annuaire du Bureau des Longitudes, 1950, Paris, p. 145]
if (x1 == x2 && y1 == y2)
return 0;
double a = 6378137; // Use GRS 80 spheroid
double f = 0.003352813; // 1 / 298.257
double F = (DEG2RAD(y1) + DEG2RAD(y2)) / 2.0;
double G = (DEG2RAD(y1) - DEG2RAD(y2)) / 2.0;
double l = (DEG2RAD(x1) - DEG2RAD(x2)) / 2.0;
double sF2 = pow(sin(F),2);
double cF2 = pow(cos(F),2);
double sG2 = pow(sin(G),2);
double cG2 = pow(cos(G),2);
double sL2 = pow(sin(l),2);
double cL2 = pow(cos(l),2);
double S = sG2*cL2 + cF2*sL2;
double C = cG2*cL2 + sF2*sL2;
double omega = atan(sqrt(S/C));
double rho = sqrt(S*C) / omega;
double D = 2*a*omega;
double H1 = (3*rho - 1) / (2*C);
double H2 = (3*rho + 1) / (2*S);
double m = D*(1 + f*(H1*sF2*cG2 - H2*cF2*sG2));
return m * 0.0006214;
}
///////////////////////////////////////////////////////////////////////////
// Miscellaneous
//
LPDISPATCH GetIDispatch(CMap1& map)
{
LPDISPATCH pDispatch = 0;
LPUNKNOWN pUnknown = map.GetControlUnknown();
if (pUnknown)
pUnknown->QueryInterface(IID_IDispatch, (void**)&pDispatch);
return pDispatch;
}
double GetAspectRatio(CMap1& map)
{
CMoRectangle r(map.GetExtent());
return (double)r.GetWidth() / (double)r.GetHeight();
}
//
// Use ratio of map to window to calculate map point
//
LPDISPATCH ToMapPoint(CMap1& map, long x, long y)
{
ASSERT(map.m_hWnd);
CRect client;
map.GetClientRect(&client);
CMoRectangle bounds(map.GetExtent());
double mapX = bounds.GetLeft() + (double)x * bounds.GetWidth() / (double)client.Width();
double mapY = bounds.GetTop() - (double)y * bounds.GetHeight() / (double)client.Height();
CMoPoint mapPoint;
mapPoint.CreateDispatch(TEXT("MapObjects2.Point"));
mapPoint.SetX(mapX);
mapPoint.SetY(mapY);
LPDISPATCH(mapPoint)->AddRef(); // Client is responsible for release
return mapPoint;
}
void FromMapPoint(CMap1& map, CMoPoint& pt, long& x, long& y)
{
ASSERT(map.m_hWnd);
CRect client;
map.GetClientRect(&client);
CMoRectangle bounds(map.GetExtent());
x = (long)MULDIV((pt.GetX() - bounds.GetLeft()), client.Width(), bounds.GetWidth());
y = (long)MULDIV((bounds.GetTop() - pt.GetY()), client.Height(), bounds.GetHeight());
}
double ToMapDistance(CMap1& map, long x)
{
ASSERT(map.m_hWnd);
CRect client;
map.GetClientRect(&client);
CMoRectangle bounds(map.GetExtent());
return (double)x * bounds.GetWidth() / (double)client.Width();
}
long FromMapDistance(CMap1& map, double& mapX)
{
ASSERT(map.m_hWnd);
CRect client;
map.GetClientRect(&client);
CMoRectangle bounds(map.GetExtent());
return (long)MULDIV(mapX, client.Width(), bounds.GetWidth());
}
///////////////////////////////////////////////////////////////////////////
// Geodatasets
//
void SetValue(CMoFields& fields, LPCTSTR name, VARIANT& value)
{
// Find the field
CMoField field(fields.Item(COleVariant(name)));
// Set the field value
field.SetValue(value);
}
void SetValue(CMoFields& fields, LPCTSTR name, const LONG value)
{
VARIANT v;
v.vt = VT_I4;
v.lVal = value;
SetValue(fields, name, v);
}
void SetValue(CMoFields& fields, LPCTSTR name, const double value)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -