Browse our Products
Aspose.GIS for for Python via .NET 25.8 Release Notes
This page contains release notes information for Aspose.GIS for Python via .NET 25.8.
Full List of Issues Covering all Changes in this Release
Key | Summary | Category |
---|---|---|
GISPYTHON-36 | Support of geospatial data reading from GeoPackage (GPKG) | Feature |
GISPYTHON-37 | Support of Tiles in GeoPackage (GPKG) Layers | Feature |
GISPYTHON-40 | Support new Aspose.GIS KmlLayer Class for the support of Format-Specific Features and Non-Destructive Edit | Feature |
GISPYTHON-39 | Support Reading Extended Tags (Region, GroundOverlay, NetworkLink) | Feature |
Public API changes
Following members have been added:
- M:Aspose.Gis.Formats.Kml.KmlDriver.OpenAsKmlLayer(Aspose.Gis.AbstractPath,Aspose.Gis.Formats.Kml.KmlOptions)
- T:Aspose.Gis.Formats.Kml.KmlLayer
- P:Aspose.Gis.Formats.Kml.KmlLayer.RegionList
- P:Aspose.Gis.Formats.Kml.KmlLayer.GroundOverlayList
- P:Aspose.Gis.Formats.Kml.KmlLayer.NetworkLinkList
- P:Aspose.Gis.Formats.Kml.KmlLayer.GeometryType
- P:Aspose.Gis.Formats.Kml.KmlLayer.Driver
- P:Aspose.Gis.Formats.Kml.KmlLayer.SpatialReferenceSystem
- P:Aspose.Gis.Formats.Kml.KmlLayer.Item(System.Int32)
- M:Aspose.Gis.Formats.Kml.KmlLayer.GetEnumerator
- M:Aspose.Gis.Formats.Kml.KmlLayer.Dispose(System.Boolean)
- T:Aspose.Gis.BaseFeatureAttributeCollection
- M:Aspose.Gis.BaseFeatureAttributeCollection.#ctor
- P:Aspose.Gis.BaseFeatureAttributeCollection.Count
- P:Aspose.Gis.BaseFeatureAttributeCollection.IsLocked
- P:Aspose.Gis.BaseFeatureAttributeCollection.Item(System.Int32)
- P:Aspose.Gis.BaseFeatureAttributeCollection.Item(System.String)
- M:Aspose.Gis.BaseFeatureAttributeCollection.Lock
- M:Aspose.Gis.BaseFeatureAttributeCollection.Contains(System.String)
- M:Aspose.Gis.BaseFeatureAttributeCollection.IndexOf(System.String)
- M:Aspose.Gis.BaseFeatureAttributeCollection.Add(Aspose.Gis.FeatureAttribute)
- M:Aspose.Gis.BaseFeatureAttributeCollection.Remove(System.String)
- M:Aspose.Gis.BaseFeatureAttributeCollection.Remove(System.Int32)
- M:Aspose.Gis.BaseFeatureAttributeCollection.GetEnumerator
- M:Aspose.Gis.BaseFeatureAttributeCollection.System#Collections#IEnumerable#GetEnumerator
- P:Aspose.Gis.Formats.Kml.SpecificFields.KmlGroundOverlayInfo.Icon
- T:Aspose.Gis.Formats.Kml.SpecificFields.IconInfo
- M:Aspose.Gis.Formats.Kml.SpecificFields.IconInfo.#ctor(Aspose.Gis.NodeLink)
- P:Aspose.Gis.Formats.Kml.SpecificFields.IconInfo.Href
- T:Aspose.Gis.Formats.Kml.SpecificFields.LinkInfo
- P:Aspose.Gis.Formats.Kml.SpecificFields.LinkInfo.Href
- P:Aspose.Gis.Formats.Kml.SpecificFields.KmlRegionInfo.LatLonAltBox
- T:Aspose.Gis.Formats.Kml.SpecificFields.KmlLatLonAltBox
- P:Aspose.Gis.Formats.Kml.SpecificFields.KmlLatLonAltBox.North
- P:Aspose.Gis.Formats.Kml.SpecificFields.KmlLatLonAltBox.South
- P:Aspose.Gis.Formats.Kml.SpecificFields.KmlLatLonAltBox.East
- P:Aspose.Gis.Formats.Kml.SpecificFields.KmlLatLonAltBox.West
- P:Aspose.Gis.Formats.Kml.SpecificFields.KmlLatLonAltBox.MinAltitude
- P:Aspose.Gis.Formats.Kml.SpecificFields.KmlLatLonAltBox.MaxAltitude
- P:Aspose.Gis.Formats.Kml.SpecificFields.KmlLatLonAltBox.Rotation
- T:Aspose.Gis.NodeLink
- P:Aspose.Gis.NodeLink.NodeName
- P:Aspose.Gis.NodeLink.NodeValue
- M:Aspose.Gis.NodeLink.AsBool
- P:Aspose.Gis.NodeLink.Children
- M:Aspose.Gis.NodeLink.GetAttributes
- M:Aspose.Gis.NodeLink.GetNodeByName(System.String)
- M:Aspose.Gis.NodeLink.GetNodesByName(System.String[])
- M:Aspose.Gis.NodeLink.AsDouble
- M:Aspose.Gis.NodeLink.AsInt
- M:Aspose.Gis.NodeLink.GetNodeContent
- M:Aspose.Gis.NodeLink.ToString
- M:Aspose.Gis.NodeLink.FindNodesByName(System.String)
- M:Aspose.Gis.NodeLink.AddChild(Aspose.Gis.NodeLink)
- T:Aspose.Gis.XmlNodeLink
- P:Aspose.Gis.XmlNodeLink.NameWithoutPrefix
- P:Aspose.Gis.XmlNodeLink.Prefix
- M:Aspose.Gis.XmlNodeLink.FindNodesByName(System.String)
- P:Aspose.Gis.Formats.Kml.KmlLayer.Count
- T:Aspose.Gis.Formats.Kml.SpecificFields.IconInfo
- M:Aspose.Gis.Formats.Kml.SpecificFields.IconInfo.#ctor(Aspose.Gis.NodeLink)
- P:Aspose.Gis.Formats.Kml.SpecificFields.IconInfo.Href
- P:Aspose.Gis.Formats.Kml.SpecificFields.KmlGroundOverlayInfo.Icon
- T:Aspose.Gis.Formats.Kml.SpecificFields.KmlLatLonAltBox
- P:Aspose.Gis.Formats.Kml.SpecificFields.KmlLatLonAltBox.North
- P:Aspose.Gis.Formats.Kml.SpecificFields.KmlLatLonAltBox.South
- P:Aspose.Gis.Formats.Kml.SpecificFields.KmlLatLonAltBox.East
- P:Aspose.Gis.Formats.Kml.SpecificFields.KmlLatLonAltBox.West
- P:Aspose.Gis.Formats.Kml.SpecificFields.KmlLatLonAltBox.MinAltitude
- P:Aspose.Gis.Formats.Kml.SpecificFields.KmlLatLonAltBox.MaxAltitude
- P:Aspose.Gis.Formats.Kml.SpecificFields.KmlLatLonAltBox.Rotation
- P:Aspose.Gis.Formats.Kml.KmlLayer.Features
- P:Aspose.Gis.Formats.Kml.SpecificFields.KmlGroundOverlayInfo.Name
- P:Aspose.Gis.Formats.Kml.SpecificFields.KmlGroundOverlayInfo.Visibility
- T:Aspose.Gis.Formats.Kml.SpecificFields.LinkInfo
- P:Aspose.Gis.Formats.Kml.SpecificFields.LinkInfo.Href
- P:Aspose.Gis.Formats.Kml.SpecificFields.KmlRegionInfo.LatLonAltBox
- T:Aspose.Gis.Formats.Kml.SpecificFields.KmlGroundOverlayInfo
- P:Aspose.Gis.Formats.Kml.SpecificFields.KmlGroundOverlayInfo.LatLonBox
- P:Aspose.Gis.Formats.Kml.SpecificFields.KmlGroundOverlayInfo.DrawOrder
- T:Aspose.Gis.Formats.Kml.SpecificFields.KmlLatLonBox
- P:Aspose.Gis.Formats.Kml.SpecificFields.KmlLatLonBox.North
- P:Aspose.Gis.Formats.Kml.SpecificFields.KmlLatLonBox.South
- P:Aspose.Gis.Formats.Kml.SpecificFields.KmlLatLonBox.East
- P:Aspose.Gis.Formats.Kml.SpecificFields.KmlLatLonBox.West
- P:Aspose.Gis.Formats.Kml.SpecificFields.KmlLatLonBox.MinAltitude
- P:Aspose.Gis.Formats.Kml.SpecificFields.KmlLatLonBox.MaxAltitude
- P:Aspose.Gis.Formats.Kml.SpecificFields.KmlLatLonBox.Rotation
- T:Aspose.Gis.Formats.Kml.SpecificFields.KmlLodSettings
- P:Aspose.Gis.Formats.Kml.SpecificFields.KmlLodSettings.MinLodPixels
- P:Aspose.Gis.Formats.Kml.SpecificFields.KmlLodSettings.MaxLodPixels
- P:Aspose.Gis.Formats.Kml.SpecificFields.KmlLodSettings.MinFadeExtent
- P:Aspose.Gis.Formats.Kml.SpecificFields.KmlLodSettings.MaxFadeExtent
- T:Aspose.Gis.Formats.Kml.SpecificFields.KmlNetworkLinkInfo
- P:Aspose.Gis.Formats.Kml.SpecificFields.KmlNetworkLinkInfo.Link
- P:Aspose.Gis.Formats.Kml.SpecificFields.KmlNetworkLinkInfo.Region
- T:Aspose.Gis.Formats.Kml.SpecificFields.KmlRegionInfo
- P:Aspose.Gis.Formats.Kml.SpecificFields.KmlRegionInfo.Lod
- P:Aspose.Gis.Formats.Kml.SpecificFields.KmlRegionInfo.Id
- T:Aspose.Gis.DynamicFeature
- P:Aspose.Gis.DynamicFeature.Geometry
- M:Aspose.Gis.DynamicFeature.GetAsNode
- M:Aspose.Gis.DynamicFeature.GetValue(System.String)
- M:Aspose.Gis.DynamicFeature.GetValue``1(System.String)
- M:Aspose.Gis.DynamicFeature.GetValuesList``1(System.String,System.String,System.Int32)
- M:Aspose.Gis.DynamicFeature.GetValueOrDefault``1(System.String)
- M:Aspose.Gis.DynamicFeature.GetValueOrDefault(System.String,System.Object)
- M:Aspose.Gis.DynamicFeature.GetValueOrDefault``1(System.String,System.Object)
- M:Aspose.Gis.DynamicFeature.SetValue
1(System.String,
0) - M:Aspose.Gis.DynamicFeature.IsValueNull(System.String)
- M:Aspose.Gis.DynamicFeature.SetValueNull(System.String)
- M:Aspose.Gis.DynamicFeature.UnsetValue(System.String)
- M:Aspose.Gis.DynamicFeature.IsValueSet(System.String)
- M:Aspose.Gis.DynamicFeature.CopyValues(Aspose.Gis.Feature)
- M:Aspose.Gis.DynamicFeature.GetValues(System.Object[],System.Object)
- M:Aspose.Gis.DynamicFeature.GetValuesDump(System.Object)
- M:Aspose.Gis.DynamicFeature.SetValues(System.Object[])
Following members have been removed:
- M:Aspose.Gis.FeatureAttributeCollection.System#Collections#IEnumerable#GetEnumerator
- P:Aspose.Gis.FeatureAttributeCollection.Count
- P:Aspose.Gis.FeatureAttributeCollection.IsLocked
- P:Aspose.Gis.FeatureAttributeCollection.Item(System.Int32)
Usage examples:
GISPYTHON-36. Support of geospatial data reading from GeoPackage (GPKG)
# Initialize variables
open_path = "ianFlooding.gpkg"
layers_count = 0
layer_names = []
tested_feature = None
# Open the GeoPackage dataset
with Dataset.open(open_path, Drivers.geo_package) as dataset:
layers_count = dataset.layers_count
layer_names = []
# Get all layer names
for i in range(dataset.layers_count):
layer_names.append(dataset.get_layer_name(i))
opt = GeoPackageOptions()
# Open the specific layer and get the first feature
with dataset.open_layer("past_track_weds_1pm_est", opt) as layer:
tested_feature = layer[0]
# Assertions (using standard Python assert statements)
assert tested_feature.get_value("stormname") == "GENESIS028"
# Create expected point geometry
expected_point = Point(-46.6, 9.9)
expected_point.spatial_reference_system = SpatialReferenceSystem.wgs84
# Compare geometries (you might need to adjust this based on exact geometry comparison)
assert tested_feature.geometry.equals(expected_point)
assert layers_count == 2
# Check if layer names match expected values
expected_layer_names = ["past_track_weds_1pm_est", "future_track_weds_1pm_est"]
assert set(layer_names) == set(expected_layer_names)
GISPYTHON-37. Support of Tiles in GeoPackage (GPKG) Layers
# Initialize variables
open_path = "ianFlooding.gpkg"
layers_count = 0
layer_names = []
# Open the GeoPackage dataset with explicit casting
with Dataset.open(open_path, Drivers.geo_package) as dataset:
# Cast to GeoPackageDataset to access tile-specific functionality
geopackage_dataset = cast(GeoPackageDataset, dataset)
layers_count = geopackage_dataset.tile_layers_count
layer_names = []
# Get all tile layer names
for i in range(geopackage_dataset.tile_layers_count):
layer_names.append(geopackage_dataset.get_tile_layer_name(i))
# Open the specific tile layer
with geopackage_dataset.open_tile_layer("FL_keys_imagery", GeoPackageOptions()) as layer:
# Get first tile and its extent
tile = layer.get_tile(9, 140, 292)
tile_extent = tile.get_extent()
# Compute hashes for comparison
tile_hash = compute_hash_from_bytes(tile.as_binary())
pngPath1 = "9-140-292.png"
origin_hash = compute_hash(pngPath1)
# Assertions
assert origin_hash == tile_hash
expected_extent = Extent(-9079495.967826376, 2817774.6107047363, -9001224.450862356, 2896046.127668757, None)
assert tile_extent.equals(expected_extent)
# Get second tile (Y axis reverted case)
tile = layer.get_tile(11, 559, 1168)
tile_extent = tile.get_extent()
tile_hash = compute_hash_from_bytes(tile.as_binary())
pngPath2 = "11-559-1168.png"
origin_hash = compute_hash(pngPath2)
assert origin_hash == tile_hash
expected_extent = Extent(-9099063.847067382, 2817774.610704738, -9079495.967826378, 2837342.4899457432, None)
assert tile_extent.equals(expected_extent)
# Final assertions
assert layers_count == 6
expected_layer_names = [
"FL_keys_imagery",
"north_FL_imagery",
"north_surge_weds_1pmest_estimate",
"south_Florida_imagery",
"south_surge_weds_1pmest_estimate",
"surge_highlevel_1pm_est_estimate"
]
assert set(layer_names) == set(expected_layer_names)
def compute_hash(file_path):
sha256 = hashlib.sha256()
with open(file_path, 'rb') as f:
while chunk := f.read(4096):
sha256.update(chunk)
return sha256.digest()
def compute_hash_from_bytes( bytes_data):
sha256 = hashlib.sha256()
sha256.update(bytes_data)
return sha256.digest()
GISPYTHON-40. Support new Aspose.GIS KmlLayer Class for the support of Format-Specific Features and Non-Destructive Edit
# Open KML layer
open_path = AbstractPath.from_local_path("GoogleKmlSample.kml")
with Drivers.kml.open_as_kml_layer(open_path, KmlOptions()) as lyr:
layer = cast(KmlLayer, lyr)
assert layer.count == 20
features = layer.features
# Example with complex feature with CDATA and HTML
feature = features[4]
# Using base attributes operations
desc_length = len(feature.get_value("description"))
assert desc_length == 2818 or desc_length == 2916
assert feature.get_value("name") == "Descriptive HTML"
assert feature.get_value("visibility") == "0"
# Example with feature containing geometry and other attributes
geo_feature = features[5]
# Using base first level attributes operations
# Data extracted from CDATA
expected_desc = "If the <tessellate> tag has a value of 1, the line will contour to the underlying terrain"
assert geo_feature.get_value("description") == expected_desc
assert geo_feature.get_value("name") == "Tessellated"
assert geo_feature.get_value("visibility") == "0"
# Check Geometry
# Using geometry comparison instead of string representation for better reliability
expected_coords = [
(-112.0814237830345, 36.10677870477137, 0),
(-112.0870267752693, 36.0905099328766, 0)
]
# Check if geometry is a LineString with Z coordinates
assert geo_feature.geometry.geometry_type == GeometryType.LINE_STRING
line_string = geo_feature.geometry
assert line_string.has_z == True
# Compare coordinates with tolerance
for i, (expected_x, expected_y, expected_z) in enumerate(expected_coords):
actual_x = line_string[i].x
actual_y = line_string[i].y
actual_z = line_string[i].z
assert math.isclose(actual_x, expected_x, abs_tol=1e-10)
assert math.isclose(actual_y, expected_y, abs_tol=1e-10)
assert math.isclose(actual_z, expected_z, abs_tol=1e-10)
# Check deep attributes
assert math.isclose(float(geo_feature.get_value("latitude")), 36.09825589333556, abs_tol=1e-10)
assert geo_feature.get_value("tessellate") == "1"
# Check unsupported properties using NodeLink API
# Assuming testGroundOverlay is one of the features (adjust index as needed)
test_ground_overlay = layer.ground_overlay_list[0]
# Access LookAt node using NodeLink API
look_at = test_ground_overlay.get_node_by_name("LookAt")
look_at_children = list(look_at.children)
assert len(look_at_children) == 6
# Here are different ways to get value
la_longitude = look_at.get_node_by_name("longitude")
assert math.isclose(la_longitude.as_double(), 15.02468937557116, abs_tol=1e-10)
la_latitude = look_at.get_node_by_name("latitude")
assert math.isclose(la_latitude.as_double(), 37.67395167941667, abs_tol=1e-10)
la_altitude = look_at.get_node_by_name("altitude")
assert la_altitude.as_int() == 0
la_heading = look_at.get_node_by_name("heading")
assert la_heading.node_value == "-16.5581842842829"
la_tilt = look_at.get_node_by_name("tilt")
assert la_tilt.node_value == "58.31228652890705"
la_range = look_at.get_node_by_name("range")
assert la_range.node_value == "30350.36838438907"
GISPYTHON-39.Support Reading Extended Tags (Region, GroundOverlay, NetworkLink)
# Open KML layer
open_path = AbstractPath.from_local_path("GoogleKmlSample.kml")
with Drivers.kml.open_as_kml_layer(open_path, KmlOptions()) as layer:
# Check specific parsed fields
ground_overlays = layer.ground_overlay_list
assert len(ground_overlays) == 1
test_ground_overlay = ground_overlays[0]
# Check Icon HREF
assert test_ground_overlay.icon.href == "http://developers.google.com/kml/documentation/images/etna.jpg"
# Check Name
assert test_ground_overlay.name == "Large-scale overlay on terrain"
# Check LatLonBox coordinates with tolerance
lat_lon_box = test_ground_overlay.lat_lon_box
assert math.isclose(lat_lon_box.north, 37.91904192681665, abs_tol=1e-6)
assert math.isclose(lat_lon_box.south, 37.46543388598137, abs_tol=1e-6)
assert math.isclose(lat_lon_box.east, 15.35832653742206, abs_tol=1e-6)
assert math.isclose(lat_lon_box.west, 14.60128369746704, abs_tol=1e-6)
# Check rotation (note: using abs() for the comparison as in original)
assert math.isclose(abs(lat_lon_box.rotation), 0.1556640799496235, abs_tol=1e-6)