Buy Now 

Free Trial

$695 (Or $395 Upgrade)

Videos

Reviews

Maptitude Mapping Software

Extending Maptitude in .NET

We have just updated the .NET APIs to allow developers to migrate MapPoint desktop applications and add-ons to Maptitude.

Interactive maps generated by Maptitude, the popular Windows mapping technology, are crucial for businesses in a number of fields, including real estate, package delivery, and healthcare. In a word, Maptitude provides businesses with "location." Specifically, it provides an integrated set of products, and services to enable a business to track the precise location of remote assets, thereby reducing operational costs and improving productivity. Whether the asset is a truck, a taxi, or even a field rep, Maptitude can tell you exactly where it is at any time.

Now it is easier than before to add all of the location intelligence functions of Maptitude, including routing and geocoding, in any Windows desktop application written in C# or any other .NET programming languages.

Maptitude has included the GISDK (Geographical Information Systems Developer Kit) for many years. With the updated GISDK .NET APIs, programming Maptitude in .NET has been simplified.

Firstly, the GISDK Extension Engine API lets you extend the Maptitude desktop application itself by writing in-process extensions in C# or any other .NET language, without the need to learn a new programming language.

Secondly, the GISDK Connection API lets you connect a new or existing .NET stand-alone Windows desktop application to Maptitude out-of-process.

Either way, you can program Maptitude in .NET to build custom applications for the desktop, and analyze and share data generated from a wide range of maps, including those that show demographic trends, population density, and sales potential.

There is an additional User Guide for the Routing and Directions API. Please contact Caliper Sales if you would like a copy of this.

Rich Set of Geo-Processing Functions

Whether you use the in-process extension API or the out-of-process connection API, you can access more than 850 GIS functions. These functions include:

  • Opening geographic files in many GIS formats
  • Creating maps in many different geographic projections
  • Geocoding street addresses using your licensed country data packages
  • Geocoding tables of street addresses
  • Reverse geocoding: obtaining information about all the map layers for an input geographic coordinate
  • Selecting (filtering) map features near a geographic coordinate by circle, by shape, or by query
  • Calculating the directions between geographic coordinates by minimizing the travel time
  • Maptitude also offers a rich set of functions for thematic mapping, territory management, and spatial data import from a variety of source formats such as Excel, Access, Txt, and so on.

Offline Mapping Applications

While the GISDK provides a rich set of geo-processing APIs, the Maptitude country packages installed on the user computer include all the geographic data needed by the application. So Maptitude and the GISDK are well-suited for offline usage. No network connectivity is required for the API functionality.

Installation and Licensing Options

When you redistribute applications that you have developed using Maptitude, make sure that the target machines have Maptitude installed as well. Also, note that the Maptitude desktop licensing model prevents you from developing web-based applications.

Programming Examples:

Below are some C# examples. The order in which they are listed is the order of difficulty.

Opening a map:

The following example shows how to open a map and list its contents.


using System;
using System.Collections.Generic;
using System.Text;
using CaliperForm;
/// 
/// Open a map in the tutorial folder, and list its content.
/// 
static void Open_Map() {
    CaliperForm.Connection Conn = new CaliperForm.Connection { MappingServer = "Maptitude" };
    Boolean opened = false;
    try {
        opened = Conn.Open();
        if (opened) {
            // You must declare dk as "dynamic" or the compiler will throw an error
            dynamic dk = Conn.Gisdk;
            string tutorial_folder = dk.Macro("G30 Tutorial Folder") as string;
            // Obtain information about Conn: an array of 
            //  [ "program_path" , "program name" , "program type" , 
            //     build number (integer) , version number (real) , instance number ]
            Object[] program_info = dk.GetProgram();
            string program_name = program_info[1] as string;
            int build_number = (int)program_info[3];
            double version_number = (double)program_info[4];
            // Set the  path that will be used to look for layers used in map files
            string search_path = "c:\\ccdata\\USA (HERE) - 2013 Quarter 4;d:\\ccdata";
            dk.SetSearchPath(search_path);
            // Open a map file in the tutorial folder
            string map_file = tutorial_folder + "BestRout.map";
            var map_options = new OptionsArray();  // you can also use Dictionary or Hashtable 
            map_options["Auto Project"] = "true";
            string data_directory = System.IO.Path.GetDirectoryName(map_file);
            map_options["Force Directory"] = data_directory; // path used to look for layers used in the map 
            string map_name = dk.OpenMap(map_file, map_options) as string;
            if (map_name == null) {
                Console.Out.WriteLine("Cannot open map " + map_file + ". Perhaps some layers cannot be found?");
                return;
            } else {
                Console.Out.WriteLine("map_name = " + map_name);
            }
            // Set the current layer
            dk.SetLayer("County");
            // Get information about the list of layers contained in this map
            dynamic layers = dk.GetMapLayers(map_name, "All");
            dynamic layer_names = layers[0];
            int current_idx = (int)layers[1];
            string current_layer = layers[2] as string;
            dk.CloseMap(map_name);
            Conn.Close();
        }
    } catch (System.Exception error) {
        Console.Out.WriteLine(error.Message);
    }
}

Opening a table:

The following example shows how to open a table and select some records by an SQL-like expression.


using System;
using System.Collections.Generic;
using System.Text;
using CaliperForm;
/// 
/// Open a table in the tutorial folder, and select some rows by an SQL-like expression
/// 
static void Open_Table() {
    CaliperForm.Connection Conn = new CaliperForm.Connection { MappingServer = "Maptitude" };
    Boolean opened = false;
    try {
        opened = Conn.Open();
        if (opened) {
            // You must declare dk as "dynamic" or the compiler will throw an error
            dynamic dk = Conn.Gisdk;
            string tutorial_folder = dk.Macro("G30 Tutorial Folder") as string;
            // Open a table
            string table_name = dk.OpenTable("sales", "ffb", new Object[] { tutorial_folder + "ctsales.bin", null });
            object[] fields = dk.GetFields(table_name, "All");
            var field_names = fields[0] as object[];
            var field_specs = fields[1] as object[];
            // select some records and get record values
            dk.SetView(table_name);
            int num_rows = dk.GetRecordCount(table_name, null);
            string query = "select * where Population > 200000";
            int num_found = dk.SelectByQuery("large towns", "several", query, new Object[] { new Object[] { "Index Limit", 0 } });
            if (num_found > 0) {
                string view_set = table_name + "|large towns";
                object[] sort_order = null;
                object[] options = null;
                string order = "Row";
                string first_record = dk.GetFirstRecord(view_set, null);
                Console.Out.WriteLine(query);
                Console.Out.WriteLine(string.Join(",", field_names));
                foreach (object[] row in dk.GetRecordsValues(view_set, first_record, field_names, sort_order, num_found, order, null)) {
                    string row_values = string.Join(",", row);
                    Console.Out.WriteLine(row_values);
                }
            }
            dk.CloseView(table_name);
            Console.Out.WriteLine();
            Conn.Close();
        }
    } catch (System.Exception error) {
        Console.Out.WriteLine(error.Message);
    }
}

Geocoding Street Addresses:

The following example shows how to geocode a street address.


using System;
using System.Collections.Generic;
using System.Text;
using CaliperForm;
/// 
/// Geocode a street address in the current region.
/// 
static void Geocode_Street_Address() {
    CaliperForm.Connection Conn = new CaliperForm.Connection { MappingServer = "Maptitude" };
    Boolean opened = false;
    try {
        opened = Conn.Open();
        if (opened) {
            // You must declare dk as "dynamic" or the compiler will throw an error
            dynamic dk = Conn.Gisdk;
            string tutorial_folder = dk.Macro("G30 Tutorial Folder") as string;
            // geocode an address 
            dynamic located_coord = null;
            string street_layer_db = null;
            dynamic finder = dk.CreateObject("Data.Finder");
            finder.SetRegion();
            string region_name = finder.GetRegionName();
            // Change the address to be in the current region
            var args = new OptionsArray();
            args["address"] = "200 Beacon Street";
            args["city"] = "Boston MA";
            args["silent"] = true;
            Dictionary result = Cast.ToDictionary(finder.Find("ADDRESS", args));
            // If Success:
            //      result = {"Coord": coord object, ...}
            // If Failure:
            //      result = {"Error": true, "Message": error message }
            if (result != null) {
                foreach (string key in result.Keys) {
                    Console.Out.WriteLine(key + " = " + Convert.ToString(result[key]));
                }
                var coord = result["Coord"] as dynamic;
                if (coord != null) {
                    // Success: convert output lat,lon to doubles
                    double lon = ((double)coord.Lon) / 1000000;
                    double lat = ((double)coord.Lat) / 1000000;
                    located_coord = coord;
                    street_layer_db = result["StreetLayer"] as string;
                    Console.Out.WriteLine("Address: " + result["Address"] as string + ", Location: " + lat + "," + lon);
                } else {
                    // Failure, report error message 
                    var has_errors = result["Error"];
                    var error_message = result["Message"] as string;
                    Console.Out.WriteLine("Error: " + has_errors as string + ", Message: " + error_message);
                }
            }
            Console.Out.WriteLine();
            Conn.Close();
        }
    } catch (System.Exception error) {
        Console.Out.WriteLine(error.Message);
    }
}

Geocoding a table:

The following example shows how to use a table of street addresses to locate records from a table or spreadsheet.


using System;
using System.Collections.Generic;
using System.Text;
using CaliperForm;
/// 
/// Geocode a table of street addresses and produce a geographic layer that can be added to a map.
/// 
static void Geocode_Table() {
    CaliperForm.Connection Conn = new CaliperForm.Connection { MappingServer = "Maptitude" };
    Boolean opened = false;
    try {
        opened = Conn.Open();
        if (opened) {
            // You must declare dk as "dynamic" or the compiler will throw an error
            dynamic dk = Conn.Gisdk;
            string tutorial_folder = dk.Macro("G30 Tutorial Folder") as string;
            string excel_file = tutorial_folder + "Sample Customers United States.xls";
            if (!System.IO.File.Exists(excel_file)) {
                Console.Out.WriteLine("Cannot find tutorial example file: " + excel_file);
                return;
            }
            string sheet_name = "My Customers$";
            string binary_table = tutorial_folder + "My Example Customers.bin";
            string exported_table = dk.Macro("G30 export an Excel sheet", excel_file, sheet_name, binary_table) as string;
            if (exported_table != null) {
                Console.Out.WriteLine("Exported Excel file: " + excel_file + " to: " + exported_table);
                dynamic geo = dk.CreateObject("Data.Geocoder");
                geo.SetRegion();
                string region_name = geo.GetRegionName();
                // Open the exported table
                string table_name = dk.OpenTable("customers", "ffb", new Object[] { exported_table , null });
                int num_records = dk.GetRecordCount(table_name, null);
                Console.Out.WriteLine("Locating " + Convert.ToString(num_records) + 
                                      " records in table " + table_name + " in region " + region_name + "...");
                // Get the input field specifications
                var id_field = dk.GetFieldFullSpec(table_name, "Customer ID") as string;
                var address_field = dk.GetFieldFullSpec(table_name, "Street Address") as string;
                var postal_field = dk.GetFieldFullSpec(table_name, "ZIP Code") as string;
                var city_field = dk.GetFieldFullSpec(table_name,"City") as string;
                var state_field = dk.GetFieldFullSpec(table_name, "State") as string;
                string output_layer_db = tutorial_folder + "Located Customers.dbd";
                var opts = new OptionsArray();
                opts["new_layer_name"] = "Located Customers";
                opts["out_db"] = output_layer_db;
                // First, locate records by street address and postal code, and save the result to "Located Customers.dbd"
                // input_fields = { address_field , address_field_2 , postal_code_field , city_field_or_value , state_field_or_value }
                object[] input_fields = new object[] { address_field, null, postal_field }; 
                Dictionary result = Cast.ToDictionary(geo.LocateView("ADDRESS", table_name + "|", id_field, input_fields, opts));
                // if success: 
                //    result = {"Message":"OK","NotFoundSet":"Address Not Found", 
                //              "LayerName":"Located Customers","NumRecords":4800, 
                //              "NumLocated":..., "OutputLayer":...,"GeocodingLayer":...}
                // else:
                //    result = {"Message":"Error Message","Error":1}
                if ((result != null) && (result["LayerName"] as string != null) && (result["NotFoundSet"] as string != null)) {
                    // Then, locate the records not found by postal code
                    string not_found_set = result["NotFoundSet"] as string;
                    string layer_name = result["LayerName"] as string;
                    int num_not_found = dk.GetRecordCount(layer_name, not_found_set);
                    string street_layer_db = result["GeocodingLayer"] as string;
                    Console.Out.WriteLine(Convert.ToString(num_not_found) + 
                                          " records not found by street address using street layer " + street_layer_db);
                    id_field = dk.GetFieldFullSpec(layer_name, "ID") as string;
                    postal_field = dk.GetFieldFullSpec(layer_name, "ZIP Code") as string;
                    input_fields = new object[] { postal_field };
                    result = Cast.ToDictionary(geo.LocateView("POSTAL_CODE", layer_name + "|" + not_found_set, id_field, input_fields, null));
                    var located_by_postal_code = (int) result["NumLocated"];
                    string postal_layer_db = result["GeocodingLayer"] as string;
                    Console.Out.WriteLine(Convert.ToString(located_by_postal_code) + 
                                          " records located by postal code using postal code layer " + postal_layer_db);
                }
                if (System.IO.File.Exists(output_layer_db)) {
                    Console.Out.WriteLine("Stored output geographic layer to: " + output_layer_db);
                }
            }
            Conn.Close();
        }
    } catch (System.Exception error) {
        Console.Out.WriteLine(error.Message);
    }
}

Selecting features in a circle:

The following example shows how to use select all of the point features on a map that are within a circle about a specific coordinate.


using System;
using System.Collections.Generic;
using System.Text;
using CaliperForm;
/// 
/// Select all landmark point features in a circle near a specific geographic coordinate.
/// 
static void Find_Nearest_Features() {
    CaliperForm.Connection Conn = new CaliperForm.Connection { MappingServer = "Maptitude" };
    Boolean opened = false;
    try {
        opened = Conn.Open();
        if (opened) {
            dynamic dk = Conn.Gisdk;
            // Locate by radius landmark points near located_coord
            dynamic located_coord = dk.Coord((int) (-71.071359 * 1000000.0) , (int)( 42.353844 * 1000000.0)); // Downtown Boston
            Dictionary region_prefs = Cast.ToDictionary(dk.Macro("Get Geocoding Preferences"));
            if (region_prefs == null) {
                Console.Out.WriteLine("Macro 'Get Geocoding Preferences' returned null");
                Conn.Close();
                return;
            }
            string region_file = region_prefs["region_file"] as string;
            if (region_file != null) {
                string data_directory = System.IO.Path.GetDirectoryName(region_file);
                string map_wizard_map_file = data_directory + "\\Map Wizard Maps\\MapWizardUSMap.map";
                // Open the map wizard map witht the layers for this country package
                var map_options = new OptionsArray();
                map_options["Auto Project"] = "true";
                // path used to look for layers used in the map, before other locations usually searched for
                map_options["Force Directory"] = data_directory;
                string map_name = dk.OpenMap(map_wizard_map_file, map_options);
                if (map_name == null) {
                    Console.Out.WriteLine("Cannot open map wizard map file " + map_wizard_map_file + 
                                          ". Perhaps some layers are missing?");
                    Conn.Close();
                    return;
                }
                var search_area = dk.Circle(located_coord, (double)1.0); // 3 Current Map Units (Mile, Kilometers,...)
                string layer_name = "Landmark";
                dk.SetLayer(layer_name);
                var opts = new OptionsArray(); 
                opts["Inclusion"] = "Intersecting";
                opts["Max"] = 50;
                opts["Display"] = "False";
                opts["Auto Redraw"] = "False";
                int n_found = dk.SelectByCircle("Near Coordinate", "several", search_area, opts);
                if (n_found > 0) {
                    string view_set = layer_name + "|Near Coordinate";
                    object[] fields = dk.GetFields(layer_name, "All");
                    var field_names = fields[0] as object[];
                    var field_specs = fields[1] as object[];
                    object[] sort_order = null;
                    object[] options = null;
                    string order = "Row";
                    string first_record = dk.GetFirstRecord(view_set, null);
                    string query = Convert.ToString(n_found) + " " + layer_name + " Features Near Coordinate: " + 
                                   Convert.ToString((double) located_coord.Lat / 1000000.00) + "," + 
                                   Convert.ToString((double) located_coord.Lon / 1000000.00) ;
                    Console.Out.WriteLine(query);
                    Console.Out.WriteLine(string.Join(",", field_names));
                    object[] cells;
                    foreach (object row in dk.GetRecordsValues(view_set, first_record, field_names, sort_order, n_found, order, null)) {
                        cells = row as object[];
                        if (cells != null) {
                            string row_values = string.Join(",", cells);
                            Console.Out.WriteLine(row_values);
                        }

                    }
                } else {
                    Console.Out.WriteLine("No " + layer_name + " Features Found Near Address.");
                }
            }
            Conn.Close();
        }
    } catch (System.Exception error) {
        Console.Out.WriteLine(error.Message);
    }
}

Calculating a route:

The following example shows how to use travel times to find a best route between two addresses.

using System;
using System.Collections.Generic;
using System.Text;
using CaliperForm;
///
/// Calculate the fastest route between 2 addresses
///
static void Calculate_Route()
{
    CaliperForm.Connection Conn = new CaliperForm.Connection { MappingServer = "Maptitude" };
    Boolean opened = false;
    try
    {
        opened = Conn.Open();
        if (opened)
        {
            // You must declare dk as "dynamic" or the compiler will throw an error
            dynamic dk = Conn.Gisdk;
            OptionsArray region_prefs = new OptionsArray(dk.Macro("Get Geocoding Preferences"));
            if (!region_prefs.ContainsKey("region_file")) {
                Console.Out.WriteLine("Region File missing from 'Get Geocoding Preferences'");
                Conn.Close();
                return;
            }
            string region_file = region_prefs["region_file"] as string;
            string map_wizard_map_file = System.IO.Path.GetDirectoryName(region_file) +
                                            "\\Map Wizard Maps\\MapWizardUSMap.map";
            // Open the map wizard map witht the layers for this country package
            var map_options = new OptionsArray();
            map_options["Auto Project"] = "true";
            // path used to look for layers used in the map, before other locations usually searched for
            map_options["Force Directory"] = data_directory;
            string map_name = dk.OpenMap(map_wizard_map_file, map_options);
            if (map_name == null) {
                Console.Out.WriteLine("Cannot open map wizard map file " + map_wizard_map_file
                                      + ". Perhaps some layers are missing?");
                Conn.Close();
                return;
            }
            // geocode an address
            dynamic finder = dk.CreateObject("Data.Finder");
            finder.SetRegion();
            var args = new OptionsArray();
            args["silent"] = true;
            args["address"] = "200 Beacon Street";
            args["city"] = "Boston MA";
            var found_origin = new OptionsArray(finder.Find("ADDRESS", args));
            args["address"] = "100 Seaport Blvd";
            var found_destination = new OptionsArray(finder.Find("ADDRESS", args));
            if (found_origin["Coord"] == null || found_destination["Coord"] == null) {
                Console.Out.WriteLine("Unable to locate origin or destination address.");
                Conn.Close();
                return;
            }

            //Calculate path using the Routing API
            var router = dk.CreateObject("Routing.Router");
            router.Minimize = "Time";
            var options = new OptionsArray();
            string xml_directions_file = dk.Macro("G30 Tutorial Folder") + "Example Directions.xml";
            options["Directions"] = xml_directions_file;
            options["DirectionsField"] = "NAME";
            options["StopDescriptions"] = new string[] { "100 Beacon St" , "200 Seaport Blvd" };
            dynamic path = router.CalculatePath(found_origin["Coord"], found_destination["Coord"],options);
            if (path == null) {
                Console.Out.WriteLine("Router error: {0}", router.ErrorMessage);
                Conn.Close();
                return;
            }
            string map_units = dk.GetMapUnits("Plural");

            Console.Out.WriteLine("Fastest Travel Time Path between two addresses: {0:F2} minutes, {1:F2} {2}.", path.Time, path.Distance, map_units);

            //add annotation
            var annotationOpts = new OptionsArray();
            annotationOpts["Points"] = path.Coords;
            annotationOpts["Line Color"] = dk.ColorRGB(65535, 32768, 0);
            object[] lineStyles = dk.Macro("G30 setup line styles");
            annotationOpts["Line Style"] = lineStyles[1];
            annotationOpts["Line Width"] = 8;
            dk.AddAnnotation("Map|" + map_name, "Polyline", annotationOpts);

            //calculate scope from path points
            dynamic scope = dk.GetArrayScope(path.Coords);
            //back up a little
            scope.Width = scope.Width * 1.05;
            scope.Height = scope.Height * 1.05;
            //zoom map to scope of path
            dk.SetMapScope(map_name, scope);
            dk.RedrawMap(map_name);

            // Dump the directions to the standard output
            if (System.IO.File.Exists(xml_directions_file)) {
                Console.Out.WriteLine("XML Turn by Turn Directions:");
                Console.Out.WriteLine(System.IO.File.ReadAllText(xml_directions_file));
            }
           
            Conn.Close();
        }
    }
    catch (System.Exception error)
    {
        Console.Out.WriteLine(error.Message);
    }
}

FAQs:

• Can I geocode data from spreadsheets?

Yes. You can import and geocode data tables in many common formats, including Excel and CSV. You can geocode by street address, postcodes, city and state, Census FIPS codes, or any other geocoding method included in your country data package.

• How many records can I geocode with the GISDK?

Unlimited!

• How many origin-destination pairs can I route with the GISDK?

Unlimited!

• Can I find the best route using travel times?

Yes. See the "Calculating a Route" example above.

• Can I include intermediate stops (waypoints) in a route?

Yes. As many as you want.

• Can I solve the traveling salesman route problem with multiple stops?

Yes. As many stops as you want. Maptitude can order the stops for you.

• Do your reported travel time take into account traffic?

No.