Alternate solution to implement use case "Map and Market".
Posted: Wed Aug 30, 2017 2:48 pm
Use case : Displaying the active region for medical experts using the use case of "Map & Market" of Demo Center.
1. We have table in access database to store the zip code details with following fields.
3. We are adding the BaseLayer of Active region in the map.
Detailed Implementation :
--------------------------------------------------------------------------------
- We are having structure (GeoItem) to store the data which are fetched from the access database, with following properties.
------------------------------------------------------
MMProvider.cs
------------------------------------------------------
TileRenderer.cs (this class is inherited from ITiledProvider of Ptv.XServer.Controls.Map.Layers.Tiled which is present in Ptv.XServer.Controls.Map.dll assembly)
-------------------------------------------------------------------
We have two properties and one function as follows
- We have code for SelectionCanvas.cs same as given in Demo Center demo.
- We are adding BaseLayer in map as follows.
- Issue is that it takes so long time to display the region for large number of zip code.
- Is there any alternate way to implement usecase like "Map and Market" of Demo center ?
1. We have table in access database to store the zip code details with following fields.
- ZipCode (type : Double)
- XMIN (type : Double)
- YMIN (type : Double)
- XMAX (type : Double)
- YMAX (type : Double)
- WKB_GEOMETRY (type : Long binary data)
- XCoordinate (type : Double)
- YCoordinate (type : Double)
3. We are adding the BaseLayer of Active region in the map.
Detailed Implementation :
--------------------------------------------------------------------------------
- We are having structure (GeoItem) to store the data which are fetched from the access database, with following properties.
- byte[] Wkb
- object Id
- double XMin
- double YMin
- double XMax
- double YMax
- double XCoord
- double YCoord
- Dictionary<string, object> Atributes;
------------------------------------------------------
Code: Select all
public interface IGeoProvider
{
IEnumerable<GeoItem> QueryBBox(double xmin, double ymin, double xmax, double ymax, string[] attributes);
}
------------------------------------------------------
Code: Select all
public IEnumerable<GeoItem> QueryBBox(double xmin, double ymin, double xmax, double ymax, string[] attributes)
{
// Query to get the geo items from Ole database.
String queryForActiveRegion = "SELECT *
"FROM Germany_5_digit_postcode as tGeo " +
"WHERE ZipCode in ( <Here we have list of more than 4000 zip codes> );
// initializing the command by query and the connection
using (var command = new OleDbCommand(queryForActiveRegion, Connection))
{
// executing the query so that we can get the geoItem result from the access database
using (var dataReader = command.ExecuteReader())
{
// reading the data from the reader
while (dataReader.Read())
{
// storing the data in GeoItem structure
var geoItem = new GeoItem
{
Wkb = (byte[])dataReader[0],
XMin = Convert.ToDouble(dataReader[1]),
YMin = Convert.ToDouble(dataReader[2]),
XMax = Convert.ToDouble(dataReader[3]),
YMax = Convert.ToDouble(dataReader[4]),
XCoord = Convert.ToDouble(dataReader[5]),
YCoord = Convert.ToDouble(dataReader[6])
};
geoItem.Atributes = new Dictionary<string, object>();
geoItem.Atributes["COLOR"] = dataReader[8];
}
else // this means that no attribute needed for the geoitem
{
// do nothing
}
// returing geoItem
yield return geoItem;
}
}
}
}
-------------------------------------------------------------------
We have two properties and one function as follows
- public IGeoProvider Provider { get; set; }
- public GdiTheme Theme { get; set; }
- public string CacheId{ get { return "TileRenderer"; }}
- public int MinZoom{get { return 0; }}
- public int MaxZoom{get { return 19; }}
Code: Select all
public Stream GetImageStream(int x, int y, int zoom)
{
using (var bmp = new Bitmap(256, 256))
{
var rect = GeoTransform.TileToPtvMercatorAtZoom(x, y, zoom);
Func<double, double, Point> mercatorToImage =
(
mercatorX, mercatorY) => new Point(
x = (int)((mercatorX - rect.Left) / (rect.Right - rect.Left) * 256),
y = 256 + (int)-((mercatorY - rect.Top) / (rect.Bottom - rect.Top) * 256)
);
using (var graphics = Graphics.FromImage(bmp))
{
var result = Provider.QueryBBox(rect.Left, rect.Top, rect.Right, rect.Bottom, Theme.RequiredFields);
foreach (var item in result)
{
var path = WkbToGdi.Parse(item.Wkb, mercatorToImage);
var style = Theme.Mapping(item);
if (style.Fill != null)
graphics.FillPath(style.Fill, path);
if (style.Outline != null)
graphics.DrawPath(style.Outline, path);
}
}
var stream = new MemoryStream();
bmp.Save(stream, ImageFormat.Png);
stream.Seek(0, SeekOrigin.Begin);
return stream;
}
}
- We are adding BaseLayer in map as follows.
Code: Select all
MMProvider provider = new MMProvider
{
Connection = oleDbConnection,
IdColumn = "IntId",
GeometryColumn = "WKB_GEOMETRY",
XMinColumn = "XMIN",
YMinColumn = "YMIN",
XMaxColumn = "XMAX",
YMaxColumn = "YMAX",
XCoordColumn = "XCoord",
YCoordColumn = "YCoord",
ActiveRegionZipCodes = activeRegionZipCodes
};
// getting the color for AK-Region so that we can apply that color for the same
System.Drawing.Color[] palette =
{
System.Drawing.ColorTranslator.FromHtml("#009EE3"),
System.Drawing.Color.LightGray
};
// getting the GdiTheme which has the color as well as the outlining specification; so that we can apply those specifications to AK-Region
var theme = new GdiTheme
{
RequiredFields = new[] { "COLOR" }, // need to fetch the field kk_kat
Mapping = gdiStyle => new GdiStyle
{
Fill = new System.Drawing.SolidBrush(palette[System.Convert.ToInt16(gdiStyle.Atributes["COLOR"]) - 1]),
Outline = System.Drawing.Pens.Black,
}
};
// creating the tileRenderer object using the MMProvider and GdiTheme; so that we can use the tile rendered to create tile canvas
var tileRenderer = new TileRenderer
{
Provider = provider,
Theme = theme,
};
// the collection of selected elements so that it will help us to color the AK-Region using those points
var selectedRegions = new ObservableCollection<System.Windows.Media.Geometry>();
// insert layer with two canvases
var activeRegionLayer = new BaseLayer("AK-Region")
{
CanvasCategories = new[] { CanvasCategory.Content, CanvasCategory.SelectedObjects },
CanvasFactories = new BaseLayer.CanvasFactoryDelegate[]
{
m => new TiledCanvas(m, tileRenderer) { IsTransparentLayer = true },
m => new SelectionCanvas(m, provider, selectedRegions)
},
Opacity = .5,
};
// insert the active region layer above the Background layer of map
ptvMap.Layers.Insert(ptvMap.Layers.IndexOf(ptvMap.Layers["Background"]), activeRegionLayer);
- Is there any alternate way to implement usecase like "Map and Market" of Demo center ?