Zones, zone, vector, vertex, What is it ?

Basics

In addition to the matrix information WolfArray, it is necessary to have a way to work with vector data. This is the purpose of the classes Zones, zone, vector, and wolfvertex.

It is the combination of these classes that provides a coherent set, even though the classes can be used individually in specific scripts.

The most fundamental information is wolfvertex, which contains 2D or 3D coordinates in the attributes x, y, and z.

wolfvertex instances are then assembled to form line segments and, by extension, polylines and polygons. Unlike the Fortran code, which has a segment class, in Python, vertices are stored in the myvertices attribute of the vector class.

To create a polygon, it is not mandatory to have a duplicated vertex. The closed attribute indicates whether the vector should be considered closed or not. If the last vertex is not identical to the first, the vector will behave like a polyline.

A zone is a class used to organize multiple vectors. These are stored in the myvectors attribute.

A Zones is a class used to organize multiple instances of zone, in the myzones attribute.

Unlike a shapefile, the storage mode proposed here does not force the use of only one type of data. It is therefore possible to combine polylines and polygons in the same object.

Formats

The default writing format is .vec, which is a text file containing only the X and Y coordinates.

It is also possible to write a .vecz file that includes the Z coordinate.

The .vec and .vecz formats are compatible with the Fortran code and the historical WOLF interface written in VisualBasic6. In Python, it is also possible to write the information in JSON format.

An import/export filter for the .shp, .gpkg, and .gdb formats is provided through Geopandas <https://geopandas.org/en/stable/>_.

An import filter for .dxf is also available thanks to the ezdxf <https://ezdxf.readthedocs.io/en/stable/>_ package.

Interaction with Shapely

Shapely https://shapely.readthedocs.io/en/stable/manual.html_ is a powerful and widely used 2D geometry library (GEOS, PostGIS…).

It is used internally by the vector class for certain operations. For example, it is possible to obtain a LineString via .linestring or a Polygon via .polygon.

For efficiency reasons, Wolf routines can prepare <https://shapely.readthedocs.io/en/stable/reference/shapely.prepare.html#shapely.prepare>_ Shapely geometries to take advantage of the associated computational acceleration.

[1]:
from wolfhece.PyVertexvectors import Zones, zone, vector, wolfvertex

Create a wolfvertex

[ ]:
pt1 = wolfvertex(10., 20.) # Z coordinate is not mandatory
pt2 = wolfvertex(30., 40.)

print(pt1.z) # Z coordinate is -99999. by default
-99999.0
[ ]:
# List all attributes/routines of the class wolfvertex - remove the __ methods and the _ methods
print([attr for attr in dir(pt1) if not attr.startswith('__') and not attr.startswith('_')])
['addvalue', 'as_shapelypoint', 'copy', 'dist2D', 'dist3D', 'getcoords', 'getvalue', 'in_use', 'is_like', 'limit2bounds', 'rotate', 'values', 'x', 'y', 'z']

A wolfvertex can store associated values in addition to its coordinates.

To achieve this, you can use the addvalue and getvalue methods.

[5]:
pt1.addvalue('added_value', 1.)
pt1.addvalue('string', 'for the test')

print(pt1.getvalue('added_value')) # 1.0
print(pt1.getvalue('string')) # for the test
1.0
for the test

We can retrieve a numpy vector with coordinates by getcoords.

[6]:
pt1.getcoords()
[6]:
array([ 1.0000e+01,  2.0000e+01, -9.9999e+04])

We can test 2 wolfvertex by is_like (test only x,y,z)

[9]:
print(pt2.is_like(pt1)) # True if the two vertices are in the same zone

pt3 = pt1.copy() # Copy the vertex
print(pt3.is_like(pt1)) # True if the two vertices are in the same zone
False
True

Create a vector

A vector is a list of wolfvertex instances…

[ ]:
import numpy as np

x = np.linspace(0, 10, 100)
y = np.sin(x)

vert = [wolfvertex(x[i], y[i]) for i in range(len(x))]

vect = vector(name = 'test')
vect.add_vertex(vert)

print(vect)
print(vect.nbvertices) # 100

print(vect.xmin, vect.xmax) # -99999.0 -99999.0
print(vect.ymin, vect.ymax) # -99999.0 -99999.0

# By default, the vector does not set the min/max values of the vertices. We need to set them manually.
# This is done by the find_minmax() method.
vect.find_minmax()
print(vect.xmin, vect.xmax) # 0.0 10.0
print(vect.ymin, vect.ymax) # -0.9993845576124357 0.9996923408861117
test
100
-99999.0 -99999.0
-99999.0 -99999.0
0.0 10.0
-0.9993845576124357 0.9996923408861117

Plot a vector

We can plot a vector in a Matplotlib Axis.

[15]:
import matplotlib.pyplot as plt

fig, ax = plt.subplots()
vect.plot_matplotlib(ax)
../_images/tutorials_zones_zone_vector_vertex_15_0.png

Create a zone

A zone is a list of vector instances

[ ]:
x = np.linspace(0, 10, 100)
y = np.cos(x)

# We can also create a vector from a numpy array.
# The array must be 2D with the first column being the x coordinates and the second column being the y coordinates. shape (n, 2) or (n, 3) if z is present.
# We can also use the add_vertices_from_array() method to add vertices from a numpy array.
vect2 = vector(name = 'test2', fromnumpy=np.vstack((x, y)).T) # Create a vector from a numpy array
vect2.find_minmax()

print(vect2.xmin, vect2.xmax) # 0.0 10.0
print(vect2.ymin, vect2.ymax) # -0.9999471661761239 1.0

z1 = zone(name = 'zone1') # Create a zone from the vector
z1.add_vector(vect, forceparent=True) # Add the vector to the zone
z1.add_vector(vect2, forceparent=True) # Add the vector to the zone

# The forceparent argument is used to force the zone to be the parent of the vector.
# So, if a vector want to use the zone instance, it can do it with its `parentzone` attribute.

assert vect.parentzone == z1 # The vector is in the zone
assert vect2.parentzone == z1 # The vector is in the zone

# Regarding the extent of the zone, we can set it manually or let the zone calculate it from the vectors.
z1.find_minmax() # Calculate the min/max values of the zone from the vectors
print(z1.xmin, z1.xmax) # 0.0 10.0
print(z1.ymin, z1.ymax) # -0.9999471661761239 1.0

0.0 10.0
-0.9999471661761239 1.0
0.0 10.0
-0.9999471661761239 1.0

Plot a zone

[22]:
fig, ax = plt.subplots()
z1.plot_matplotlib(ax) # Plot the zone with the vectors
../_images/tutorials_zones_zone_vector_vertex_19_0.png

Create a Zones

A Zones instance is a list of zone instances

[23]:
z2 = zone(name = 'zone2') # Create a zone from the vector

vect3 = vect.move(2., 1., inplace=False) # Move a copy of the vector to a new position
vect4 = vect2.move(0.5, 0.5, inplace=False) # Move a copy of the vector to a new position

z2.add_vector(vect3, forceparent=True) # Add the vector to the zone
z2.add_vector(vect4, forceparent=True) # Add the vector to the zone
z2.find_minmax() # Calculate the min/max values of the zone from the vectors

zones = Zones()
zones.add_zone(z1, forceparent=True) # Add the zone to the list of zones
zones.add_zone(z2, forceparent=True) # Add the zone to the list of zones
zones.find_minmax() # Calculate the min/max values of the zones from the vectors

print(zones.xmin, zones.xmax) # 0.0 10.0
print(zones.ymin, zones.ymax) # -0.9999471661761239 1.0
0.0 12.0
-0.9999471661761239 1.9996923408861118

Plot a Zones

[25]:
fig, ax = plt.subplots()
zones.plot_matplotlib(ax) # Plot the zone with the vectors
plt.show() # Show the plot
../_images/tutorials_zones_zone_vector_vertex_23_0.png

Save a Zones to file

[ ]:
# zones.saveas('test.vec')  # Save the zones in a .vec file
# zones.saveas('test.vecz') # Save the zones in a .vecz file (Z values included)
# zones.saveas('test.shp')  # Save the zones in a .shp file (Shapefile format)