Using MapXtreme .Net

Hello! I want to share with you my experience with such an SDK as MapXtreme .Net from Pitney Bowes. As they said on the website:
MapInfo MapXtreme for .Net is a suite of GIS software developers in the Microsoft .Net environment that allows you to integrate mapping and GIS functions into business applications.

Installation


The first step was to set up the machine to work. Install MS VisualStudio 2015 from the developer's site (it works on MSVS2010, I haven’t tried the version below).

Download the installation package from the developer's site . The trial version 7.1 for 60 days is available on the download portal (version 8 is available for purchase, the difference between them is palpable, but affects MapXtreme architecture. The main operations have remained unchanged).

It is also necessary to download a world map, otherwise why do we even need a GIS, right? For MapXtreme, the ADC WorldMap Version 7.1 card is suitable .

Put it in that order, since MapXtreme requires .Net.

Documentation


The library is very large with many features, but to get to them you need documentation, and MapXtreme has problems with it. After installation in the directory with the SDK you can find
MapXtreme Developers Reference
MapXtreme Version 8.0 Developer Guide

The materials themselves contain examples at the captain's level of evidence, or are completely absent. On the Internet, this library also does not contain many explanatory resources. The best was on the site of the developer . However, about six months ago, they closed her access and began to send everyone to tech support.

By the way, a few words about her darling:

image

There were 3-4 calls to them for help, and all the time they told me:
“We passed your request to our developers”
“Send your source code to us, we do not understand your problem”, etc.

A guide is also provided for the card, which is helpful. It describes all the tags and TPIA values ​​that can be set.

Development


If you installed everything correctly, then when creating a new project, VisualStudio will have the MapXtreme project type available (I have version 8.0, because we bought a license).

image

Select the Windows Form App. If new elements have not appeared in the ToolBox, open the menu item
Tools → Choose ToolBox Items ...

And in the window that appears, select the tools we need:

image

So, we have all installed, configured and are ready to write code MapXtreme provides ready-made components for creating an application. You can immediately make the MapXteme toolbar by adding the ToolStrip component to the main form, which stores the buttons we need.

image

In order to use the buttons we have chosen, we map the MapControl property to the name of our MapControl type element. My name is mapControl1, it may differ for you. Or write in the form constructor

private void Form1_Load(object sender, EventArgs e)
{
    addrectangleToolStripButton1.MapControl = mapControl1;
    ....
}

If everything is done correctly, then you should succeed like this:

image

“I did everything right, I chose a drawing tool, but nothing works for me! Why?"

To solve this problem, you need to select the layer on which we will draw and make it mutable. By default, all layers on mapControl are immutable.

We can solve our problem by means of MapXtreme by pressing the “Layer Control” button and ticking the right places.

image

Or do it directly in code:

var layerTemp = mapControl1.Map.Layers["wldcty25"];            
LayerHelper.SetInsertable(layerTemp, true);//дает возможность рисовать на слое инструментами
LayerHelper.SetEditable(layerTemp, true);  //делает наш слой изменяемым

I note that you can only draw on the “upper” layer, that is, to draw an object now, we need to move our “wldcty25” layer up:

image

Or write in code:

mapControl1.Map.Layers.Move(lastPosition, nextPosition);

As a result, our first object is drawn:

image

As I said earlier, any setting can be set through the interface. However, the customer is most often finicky and needs more flexible / accessible configuration elements, so I will not talk about how to configure anything through MapXtreme components. I will show how to do this through code.

I want to start with style. The main class responsible for the design is CompositeStyle . In MapXtreme, we can style both the layer and the object. I note that the style of the layer overlaps the style of the object.

SimpleLineStyle border;//стиль линейного объекта
border= new SimpleLineStyle(<ширина линии в единицах MapXtreme>, <код стиля линии>,  <цвет линии>)
SimpleInterior interior;//стиль внутренней области объекта
interior = new SimpleInterior(<код стиля>, <цвет переднего плана>,<цвет фона>)
AreaStyle polygon;//стиль который используя предыдущие два задает стиль для площадного объекта
polygon = new AreaStyle(border, interior);
SimpleLineStyle line;//стиль линейного объекта
line = new SimpleLineStyle(<ширина линии в единицах MapXtreme>, <код стиля линии>, <цвет линии>)
BasePointStyle point;//стиль точечного объекта
point = new SimpleVectorPointStyle(<код стиля>, <цвет точки>, <размер точки>)
CompositeStyle compStyle;//стиль применяемый к слою
compStyle = CompositeStyle(polygon, line, null, point);

Apply the resulting style to the layer:

FeatureOverrideStyleModifier fosm;
fosm = new FeatureOverrideStyleModifier(parStyleName, parStyleAlias, compStyle);
myLayer.Modifiers.Append(featureOverrideStyleModifier);

Apply the resulting style to the object:

Feature feature = null;
feature = new Feature(<класс описывающий наш объект>, compStyle);

Object Creation


To create a multiline or multipolygon, first create the source data:

//задаем первую часть мультиобъекта
DPoint[] pts1 = new DPoint[5];
pts1[0] = new DPoint(-20, 10);//произвольные координаты точек взятые для примера
pts1[1] = new DPoint(10, 15);
pts1[2] = new DPoint(15, -10);
pts1[3] = new DPoint(-10, -10);
pts1[4] = new DPoint(-20, 10);
//задаем вторую часть мультиобъекта
DPoint[] pts2 = new DPoint[5];
pts2[0] = new DPoint(-40, 50);
pts2[1] = new DPoint(60, 45);
pts2[2] = new DPoint(65, -40);
pts2[3] = new DPoint(25, 20);
pts2[4] = new DPoint(-40, 50);
//LineString создаем из массива элементов DPoint
LineString lineString1 = new LineString(coordSys, pts1);
LineString lineString2 = new LineString(coordSys, pts2);

Using the code above, create:

- multipolygon

//Ring в заданной системе координат coordSys создается через LineString 
Ring ring1 = new Ring(coordSys, lineString1);
Ring ring2 = new Ring(coordSys, lineString2);
Ring[] rng1 = new Ring[2];
rng1[0] = ring2;
rng1[1] = ring1;
//MultiPolygon состоит из массива Ring
MultiPolygon multiPol = new MultiPolygon(coordSys, rng1);

- multiline

//Curve в заданной системе координат coordSys создается через LineString 
Curve curve4 = new Curve(coordSys, lineString1);
Curve curve5 = new Curve(coordSys, lineString2);
Curve[] crv = new Curve[2];
crv[0] = curve5;
crv[1] = curve4;
//MultiCurve состоит из массива Curve 
MultiCurve mc = new MultiCurve(coordSys, crv);

Work with map projection


Receiving:

CoordSys сoordSys= mapControl1.Map.GetDisplayCoordSys();

Creating and changing the current coordinate system:

CoordSys cs = Session.Current.CoordSysFactory.CreateCoordSys("EPSG:3395", CodeSpace.Epsg); 
mapControl1.Map.SetDisplayCoordSys(cs);

In fact, there are a lot of overloaded constructors, but usually two are enough, since in practical tasks it is necessary to work in three to four coordinate systems.

I haven’t said anything yet about working with bitmap images. She is also here. However, if you change the coordinate system, then your image is unlikely to be converted if you do not register a trace. line:

mapControl1.Map.RasterReprojectionMethod = ReprojectionMethod.Always;    
/**
*ReprojectionMethod имеет три состояния
*        None = 0, //запрет на изменение растра
*        Always = 1,//изменять всегда
*        Optimized = 2//так и не понял зачем нужен, в моей практике он ничем не отличался от 
*        предыдущего
*/

Personally, I only worked with GeoTiff. MapXtreme does not work directly with images. In order for everything to be good, the system needs a * .tab file that will contain a raster description, a coordinate system, and the coordinates of the angles.

I never found how to make * .tab for a raster using MapXtreme tools, the Internet didn’t give any hints either, and I had to write a method myself that would create this file:

private string CreateTabFile(List parImageCoordinate)//список координат углов
{
    NumberFormatInfo nfi = new CultureInfo("en-US", false).NumberFormat;
    var ext = m_fileName.Split(new Char[] { '.' });
    var fileExt = ext[ext.GetLength(0) - 1];
    string fileTabName = m_fileName.Substring(0, m_fileName.Length - fileExt.Length) + "TAB";
    StreamWriter sw = new StreamWriter(fileTabName);
    string header = "!table\n!version 300\n!charset WindowsCyrillic\n \n";
    sw.WriteLine(header);
    string definitionTables = "Definition Table\n  ";
    definitionTables += "File \"" + m_fileName + "\"\n  ";
    definitionTables += "Type \"RASTER\"\n  ";
    for (var i = 0; i < parImageCoordinate.Count; i++)
    {
        definitionTables += "(" + parImageCoordinate[i].Longitude.ToString("N", nfi) + "," + parImageCoordinate[i].Latitude.ToString("N", nfi) + ") ";
        definitionTables += "(" + parImageCoordinate[i].PixelColumn.ToString() + "," + parImageCoordinate[i].PixelRow.ToString() + ") ";
        definitionTables += "Label \"Точка " + (i + 1).ToString() + " \",\n  ";
     }
     definitionTables = definitionTables.Substring(0, definitionTables.Length - 4);
     definitionTables += "\n  ";
     definitionTables += "CoordSys Earth Projection 1, 104\n  ";
     definitionTables += "Units \"degree\"\n";
     sw.WriteLine(definitionTables);
     string metaData = "begin_metadata\n";
     metaData += "\"\\IsReadOnly\" = \"FALSE\"\n";
     metaData += "\"\\MapInfo\" = \"\"\n";
     string hash;
     using (MD5 md5Hash = MD5.Create())
     {
         hash = GetMd5Hash(md5Hash, m_fileName);
     }
      metaData += "\"\\MapInfo\\TableID\" = \"" + hash + "\"\n";
      metaData += "end_metadata\n";
      sw.WriteLine(metaData);
      sw.Close();
      return fileTabName;
}

GetMd5Hash method taken from MSDN . So, now our mapControl1 is ready to work with the raster.

That's all for now. It came out and voluminous, probably. Why did you decide to write? Because I did not find good content on this issue either on the hub or in the ru / e segment of the Internet.

Also popular now: