Examples

The examples provided assume you have imported sample data. Before getting started with examples, please import the Maptek_PythonSDK_SampleData_20200101.maptekobj file by:

  1. FileImport (or HomeImport) in PointStudio or Vulcan GeologyCore, or
  2. Using the SDK in the first example

All examples provided on this page have been demonstrated using Maptek PointStudio 2020 or above.

Importing a maptekobj file

This example will show how to import the provided sample dataset Maptek_PythonSDK_SampleData_20200101.maptekobj into your current maptekdb project. The following snippet has been written to mimic the same result that would occur if importing this data using HomeImport within the software.

from mapteksdk.project import Project
import mapteksdk.data.io as io
proj = Project() # Connect to default project

# Use the path you have saved Maptek_PythonSDK_SampleData_20200101.maptekobj
path_to_maptekobj = "F:/Python SDK Help/Maptek_PythonSDK_SampleData_20200101.maptekobj"

# This will import the maptekobj file which may contain an arbitrary
# number of objects within. These will not automatically be assigned
# a project path.
object_id = io.import_maptekobj(path_to_maptekobj)

# Assign all of the imported data to a path
for id in proj.get_children(object_id).ids():
    # Move each child found in the imported data into the scrapbook container
    # Project().rename_object can be used for moving objects
    proj.rename_object(
        id, # The ObjectID representing the current object
        "scrapbook/{}".format(id.name), # New path to assign
        overwrite=True # Replace any existing data at this path
    )

Check the contents of the project have been imported:

Checking existence of an object

The following snippet shows how to check if an object exists and if it does, a valid is returned for it.

from mapteksdk.project import Project
proj = Project() # Connect to default project

# The Project().find_object() function will return an
# ObjectID if an object exists. If it doesn't, None
# will be returned.
if proj.find_object("/scrapbook/surfaces/Pit model"):
    print("it exists!")

# Expected output:
# >>> it exists!

Checking existence of a container

A container in a Maptek project is like a folder on your file system. It can contain sub-containers and objects. The following snippet will verify data from the example above has been imported into /scrapbook/scans and /scrapbook/surfaces.

from mapteksdk.project import Project
from mapteksdk.data import VisualContainer
proj = Project() # Connect to default project

scans_container = proj.find_object("/scrapbook/scans")
# Verify it is a VisualContainer using the ObjectID.is_a() function
if scans_container and scans_container.is_a(VisualContainer):
    print("/scrapbook/scans is a VisualContainer!")

surfaces_container = proj.find_object("/scrapbook/surfaces")
# Verify it is a VisualContainer using the ObjectID.is_a() function
if surfaces_container and surfaces_container.is_a(VisualContainer):
    print("/scrapbook/surfaces is a VisualContainer!")

Listing contents of a container

As a container may contain an arbitrary number of objects, it is useful to be able to list its content. The following snippet will list the names of the objects immediately below /scrapbook/scans/set1.

from mapteksdk.project import Project
proj = Project() # Connect to default project

for name in proj.get_children("scrapbook/scans/set1/").names():
    print("name: {}".format(name))

# Expected output:
# >>> name: points1of4
# >>> name: points2of4
# >>> name: points3of4
# >>> name: points4of4

Listing all objects in all containers

The above snippet demonstrated the Project.get_children() function which queries the direct children within a container. Another function available that will seek our all children within all containers from a given starting point is Project.get_descendants(). When a path is requested, the use of "" indicates the root of the project. In this example, "scrapbook" will be used to get all of the objects imported earlier.

from mapteksdk.project import Project
proj = Project() # Connect to default project

for child_name, child in proj.get_descendants("scrapbook"):
    print("name: {}, path: {}, type: {}".format(
        child_name,
        child.path, # ObjectID.path property.
        child.type_name # The name of type of object.
    ))

# Project().get_children() and Project().get_descendants() return
# a ChildView (mapteksdk.data.ChildView) type.
# This can be used like:
#    for name, id in proj.get_descendants("path" or ObjectID)
#       (name is a string, id is an ObjectID)
# or
#    for id in proj.get_descendants().ids()
#       (results as list of ObjectID)
# or
#    for name in proj.get_descendants().names()
#       (results as list of string)

 

Listing only containers (or object of type)

The example above will list all contents. However you might want to get a list of PointSet objects that exist under that path, or VisualContainer objects within the project. This can be done by applying a type check in the following snippet.

from mapteksdk.project import Project
from mapteksdk.data import VisualContainer, PointSet
proj = Project() # Connect to default project

print("List of all VisualContainer objects in project with count of children")
container_list = [item for item in proj.get_descendants().ids()
                 if item.is_a(VisualContainer)]
for container in container_list:
    print("path: {}, count of children: {}".format(
        container.path,
        len(proj.get_children(container))
    ))

print("\nList of all PointSet objects in project")
pointset_list = [item for item in proj.get_descendants().ids()
                 if item.is_a(PointSet)]
for pointset in pointset_list:
    print("path: {}".format(pointset.path))

 

Listing contents of a selection

The SDK can be used to query the objects currently selected by the user. This can be useful if requiring the user to select an object of a specific type to do an operation against.

from mapteksdk.project import Project
proj = Project() # Connect to default project

# Ensure user has made a selection
selection = proj.get_selected()
while len(selection) == 0:
    input("Please selection one or more objects and press any key to continue.")
    selection = proj.get_selected()

# get_selection() returns a list of ObjectID
# ObjectIDs are useful for getting names, paths, parents, icon names
# and use within several project functions

print("You have selected these objects:")
for item in selection:
    print("  name: {}, path: {}, type: {}, icon name: {}".format(
        item.name,
        item.path,
        item.type_name,
        item.icon_name))

# Example output:
# >>> You have selected these objects:
# >>>  name: Pit model toes and crests, path: /scrapbook/surfaces/Pit model toes and crests, type
# >>>  name: legends, path: /legends, type: VisualContainer, icon name: StandardContainerClosed
# >>>  name: actual toes and crests, path: /scrapbook/surfaces/Pit model toes and crests/actual tork
# >>>  name: Pit model, path: /scrapbook/surfaces/Pit model, type: Surface, icon name: FacetNetwo
# >>>  name: points3of4, path: /scrapbook/scans/set1/points3of4, type: PointSet, icon name: Point

Listing a specific type from a selection

The following example will filter the user's selection to include only PointSet and Surface objects from the total selection.

This example uses a newer feature from 1.1. To make this example work with 1.0, the part item.is_a(types_to_find) can be changed to any(item.is_a(ty) for ty in types_to_find).

from mapteksdk.project import Project
# Import some data types to work with for this example:
from mapteksdk.data import VisualContainer, Surface, PointSet, EdgeNetwork
proj = Project() # Connect to default project

def get_selection_of_types(types_to_find=[]):
    # Keep specified types from selection. If no specific type requested, return selection.
    selection = proj.get_selected()

    if types_to_find:
        # Keep the items that are of the specified type(s)
        selection[:] = [item for item in selection if item.is_a(types_to_find)]

    return selection

if __name__ == "__main__":
    # Specify the types to find from selection
    types_to_find = (PointSet, Surface)
    # Filter existing selection to PointSet and Surface objects
    selection = get_selection_of_types(types_to_find)
    # Test for valid selection of PointSet or Surface objects
    while not selection:
        input("Please make a selection of the following types and press any key to continue: {}".format(
            ",".join(t.__name__ for t in types_to_find) if types_to_find else "Any type of object" ))
        selection = get_selection_of_types(types_to_find)
    
    print("You have selected the following {} objects:".format(
        ", ".join(t.__name__ for t in types_to_find) if types_to_find else ""))

    for item in selection:
        print("  name: {}, path: {}, type: {}".format(
            item.name,
            item.path,
            item.type_name))

# Example output:
# >>> Please make a selection of the following types and press any key to continue: PointSet,Surface
# >>> You have selected the following PointSet, Surface objects:
# >>>  name: Pit model, path: /scrapbook/surfaces/Pit model, type: Surface
# >>>  name: points1of4, path: /scrapbook/scans/set1/points1of4, type: PointSet
# >>>  name: points2of4, path: /scrapbook/scans/set1/points2of4, type: PointSet
# >>>  name: points3of4, path: /scrapbook/scans/set1/points3of4, type: PointSet
# >>>  name: points4of4, path: /scrapbook/scans/set1/points4of4, type: PointSet

Accessing ObjectID properties

The ObjectID class is used in many places throughout the SDK and can used in many of the same functions that accept a path string to an object. Instances of ObjectID are normally returned when querying the Project class for object information, selections, etc. Referring to an ObjectID is useful when objects are assigned multiple paths or no path at all (orphan).

from mapteksdk.project import Project
proj = Project() # Connect to default project

path = "scrapbook/surfaces/Pit model"
example_object = proj.find_object(path)
# If the object has been found it will be returned as an ObjectID
# ObjectID <mapteksdk.data.ObjectID>
if example_object:
    print("Object properties for {}:".format(path))
    print(("  Name: {}\n  Icon name: {}\n  Path: {}\n  Parent path: {}"
           "\n  String ID: {}\n  Handle: {}\n  Is hidden: {}\n  Type name: {}"
           "\n  Exists: {}\n  Is orphan: {}").format(
        example_object.name,
        example_object.icon_name,
        example_object.path, # Note: Primary path only if it has multiple
        example_object.parent.path,
        example_object,
        example_object.native_handle,
        example_object.hidden, # Note: use of hidden objects must be explicitly enabled
        proj.type_name(example_object),
        example_object.exists,
        example_object.is_orphan # Note: An orphan is an object without a path
        ))
else:
    print("{} not found".format(path))

# Example output:
# >>> Object properties for scrapbook/surfaces/Pit model:
# >>>  Name: Pit model        
# >>>  Icon name: FacetNetwork
# >>>  Path: /scrapbook/surfaces/Pit model
# >>>  Parent path: /scrapbook/surfaces
# >>>  String ID: OID(I27, C0, T146)
# >>>  Handle: 41095346599755803
# >>>  Is hidden: False
# >>>  Type name: Surface
# >>>  Exists: True
# >>>  Is orphan: False

Opening an object for read-only access

The following example demonstrates opening an existing object for reading using the Project.read() function with context management.

from mapteksdk.project import Project
from mapteksdk.data import Surface
proj = Project() # Connect to default project

path = "scrapbook/surfaces/Pit model"
# Project().find_object() will return an ObjectID if found
if proj.find_object(path):
    # Project().read(path or ObjectID) provides read-only access to an object.
    # Attempting changes on read-only arrays will result in exceptions.
    with proj.read(path) as surface:
        print("Point count: {}\nFacet count: {}\nEdge count: {}".format(
            surface.point_count,
            surface.facet_count,
            surface.edge_count
        ))

# Example output:
# Point count: 64268
# Facet count: 127778
# Edge count: 192047

Opening an object for read and write

The following example demonstrates opening an existing object for editing using the Project.edit() function with context management. In this example, half of the points within the surface are coloured red.

from mapteksdk.project import Project
from mapteksdk.data import Surface
import math
proj = Project() # Connect to default project
        
path = "scrapbook/surfaces/Pit model"
if proj.find_object(path):
    # Project().edit(path) provides edit access to an object with context management.
    # Once leaving he context of the 'with' statement, the object is saved.
    with proj.edit(path) as surface:
        # Make half of the points on surface red [Red,Green,Blue,Alpha]
        first_half = math.floor(surface.point_count / 2)
        surface.point_colours[first_half:] = [255, 0, 0, 255]

Creating a new object and opening for read and write

The following example demonstrates how to create a new object in the Project, of a specific type. This is done using the Project.new() function. This example will create a Polyline object and make all of its Edges (lines) blue and store it under '/cad/zigzag line'.

from mapteksdk.project import Project
from mapteksdk.data import Polyline
import numpy as np
proj = Project() # Connect to default project

path = "/cad/zigzag line"
# Project().new(path, Type) provides creation and edit access to a new object
# of the specified type with context management. The object is stored in the
# project when exiting the scope of the with statement.  
with proj.new(path, Polyline, overwrite=True) as zigzag:
    # Create a blue zigzag line
    zigzag.points = np.array([[0, 0, 0], [10, 10, 0], [20, 0, 0], [30, 10, 0],
                              [40, 0, 0], [50, 10, 0]])
    zigzag.point_colours = [0,0,255]

if proj.find_object(path):
    print("Saved {}".format(path))
    

Renaming an object

Objects can be renamed by using the Project.rename_object() function. This is done by providing an absolute path to an object and a new name for it (either with a new absolute path or by name only, excluding its path - demonstrated in this example).

This example renames 'scrapbook/surfaces/Pit model' to 'Pit model 2' then changes it back to its original name.

from mapteksdk.project import Project
proj = Project() # Connect to default project

# It is possible for an object to exist with multiple paths in a project,
# so the Project().rename() function is used for renaming and/or moving an object.

path = "scrapbook/surfaces/Pit model"
try:
  proj.rename_object(path, "Pit model 2", overwrite=True)
  found_at = proj.find_object("/scrapbook/surfaces/Pit model 2")
  print("Object now called: {}".format(found_at.name))
  proj.rename_object(found_at, "Pit model")
  print("Object renamed back to: {}".format(found_at.name))
except ReferenceError:
  print("Object not found at: {}".format(path))

# Example output:
# Object now called: Pit model 2
# Object renamed back to: Pit model

Moving an object within a project

The Project.rename_object() function can be used to rename objects as well as move them. The reason this function has multiple uses is because it is possible for an object to contain multiple paths. Therefore when moving it, you are really re-assigning one of (though normally its only) destination path(s).

This example moves an existing object, then moves it back to its original parent container.

from mapteksdk.project import Project
proj = Project() # Connect to default project

# It is possible for an object to exist with multiple paths in a project,
# so the Project().rename() function is used for renaming and/or moving an object.

# The main difference is to move an object, you define an absolute path
# in the 'new_name' parameter.
old_path = "scrapbook/surfaces/Pit model"
new_path = "/surfaces/Pit model"
if proj.find_object(old_path):
  proj.rename_object(old_path, new_path)
  found_at = proj.find_object(new_path)
  print("Object now exits here: {}".format(found_at.path))
  proj.rename_object(found_at, old_path)
  print("Object moved back to: {}".format(found_at.path))
else:
  raise ReferenceError("Source object not found at: {}".format(old_path))
 

Copying an object

The Project.copy_object() function provides an efficient way to make copies of objects within the project.

from mapteksdk.project import Project
proj = Project() # Connect to default project

path = "/scrapbook/surfaces/Pit model"
copy_to = "/scrapbook/surfaces/copies/Pit model (copy)"
item_to_copy = proj.find_object(path)
if item_to_copy:
  # Project().copy_object() allows convenient copying of project objects
  # by using a path or ObjectID as source and a path as destination.
  # An ObjectID for the new copy is returned from the function.
  copied = proj.copy_object(item_to_copy, copy_to, overwrite=True)
  print("Made a copy of \n '{}'\n to '{}'".format(item_to_copy.path, copied.path))
else:
  raise ReferenceError("Source object not found at: {}".format(path))

# Example output:
# >>> Made a copy of
# >>>  '/scrapbook/surfaces/Pit model'
# >>>  to '/scrapbook/surfaces/copies/Pit model (copy)'

Deleting an object

The Project.delete() function can be used to delete objects from the project.

from mapteksdk.project import Project
proj = Project() # Connect to default project

path = "scrapbook/surfaces/Pit model"
item_to_delete = proj.find_object(path)
# Project().delete() allows deletion of an object. Note that
# if deleting a container, you may leave 'orphan' child objects in the
# project that no longer have a parent path available.

if item_to_delete:
    # Temporarily copy the object to put back when finished.
    copy = proj.copy_object(path, path + "(temp copy)")

    proj.delete(path)
    print("Verify if anything found at path {}? {}".format(
        path, proj.find_object(path) != None ))

    if proj.rename_object(copy, "Pit model"):
        print("Restored original {}".format(copy.path))
else:
  raise ReferenceError("Source object not found at: {}".format(path))

# Example output:
# >>> Verify if anything found at path scrapbook/surfaces/Pit model? False
# >>> Restored original scrapbook/surfaces/Pit model

Deleting contents of a container

The Project.delete_container_contents() function can be used to clear all objects within a container. The example below first creates some copies of data into '/surfaces/' then deletes it.

from mapteksdk.project import Project
proj = Project() # Connect to default project

container_to_purge = "/surfaces/"
# Populate the scrapbook container with some copies
# of another object to then delete
item = proj.find_object("/scrapbook/surfaces/Pit model")
if item:
    for i in range(5): # create 5 copies, copy1, copy2, etc
        proj.copy_object(item, "{}{}{}".format(
           container_to_purge, "copy", i))
    
    print("{} has {} children now.".format(
        container_to_purge,    
        len(proj.get_children(container_to_purge))))
    
    print("Deleting children from {}".format(container_to_purge))
    proj.delete_container_contents(container_to_purge)
    
    print("{} has {} children now.".format(
        container_to_purge,    
        len(proj.get_children(container_to_purge))))
else:
  raise ReferenceError("Source object not found for creating some junk data")

# Example output:
# >>> /surfaces/ has 5 children now.
# >>> Deleting children from /surfaces/
# >>> /surfaces/ has 0 children now.

Determining object type

Within the project contents you may see objects of several types. Depending on the name of an object is not a suitable way to infer its type. The following example demonstrates how to query the type of the data you are interacting with.

import mapteksdk.data as datatype
from mapteksdk.project import Project
proj = Project() # Connect to default project

selection = proj.get_selected()
if selection:
    for item in selection:
        print("'{}' is a {}, displayed with icon: {}".format(
            item.path,
            item.type_name,
            item.icon_name or "Unknown",
        ))

        try:
            with proj.read(item) as reader:
                pass
        except TypeError:
            print("  - Note: This object is not yet supported properly by the SDK")
else:
    print("You have not selected anything.")  

# Example output:
# >>> '/scrapbook/other types/legend' is a NumericColourMap, displayed with icon: ColourMapNumeric1D
# >>> '/surfaces' is a StandardContainer displayed with icon: StandardContainerClosed
# >>> '/cad/zigzag line' is a Polyline, displayed with icon: EdgeChain
# >>> '/scrapbook/surfaces/Pit model toes and crests/actual toes and crests' is a EdgeNetwork, displayed with icon: EdgeNetwork
# >>> '/scrapbook/other types/ellipsoid' is a Ellipsoid, displayed with icon: Ellipsoid
# >>>  - Note: This object is not yet supported properly by the SDK
# >>> '/scrapbook/surfaces/Pit model' is a Surface, displayed with icon: FacetNetwork
# >>> '/scrapbook/scans/set1/points2of4' is a PointSet, displayed with icon: PointSet
# >>> '/scrapbook/other types/3d text' is a Text3D, displayed with icon: Text3D

Checking if an object is supported by SDK version

The Maptek database has support for hundreds of data types. Not all of these are available for creation and modification through the SDK, even if they can be seen, copied, renamed or deleted within the project contents. In some cases before attempting to work with data you may need to verify that it is fully supported by the version of the SDK you are using as well as the dependencies or application it is being used with.

from mapteksdk.project import Project
proj = Project() # Connect to default project

# As this SDK works across multiple products and a project may contain a
# significant number of data types yet to be exposed via the SDK or
# available in certain contexts. Therefore some objects that can be
# found may not be supported directly for reading, writing or editing.

# Via Project() functions these objects can be moved/renamed, etc, but
# will be unsupported by read(), edit() and new()

# Objects that are unsupported will raise TypeError when they are opened for
# read or edit. There is no way to create a new object of an unsupported type
# as there is is no type to refer to.

def is_read_supported(project, item):
  try:
      with project.read(item):
        return True
  except TypeError:
    return False

# Check object exists and get its ObjectID
path = "/scrapbook/other types/ellipsoid"
item = proj.find_object(path)
# Check if it is of an unsupported type
if item:
  if is_read_supported(proj, item):
    print("{} is supported by the SDK and the current application.".format(
      item.path
    ))
  else:
    print("{} is either not supported for reading or editing by the SDK" \
          " or the reference DLLs used in this context.".format(
        item.path
    ))
else:
  raise ReferenceError("Source object not found at: {}".format(path))

Note:  If you have a use case or need for additional data not yet supported, please contact support. There is ongoing development to add SDK support for more data types. The underlying architecture contains several hundred data types, however not all of them are generally applicable for this context.