Additionally, the Model class has the following methods:
#Complementary to method add_attribute, there is also
#Model.attribute_exists(self, attr_name: str) -> bool
assert model.attribute_exists("POSITION") == True
#Model.get_attribute(self, attr_name: str) -> Attribute
position_attr = model.get_attribute("POSITION")
Note that the property Model.metadata returns a copy. Updating it won't affect the metadata stored inside the model. If you wish to update the metadata, use the Model.set_metadata method:
#@property
#Model.metadata(self) -> dict
model.metadata["description"] = "A new description"
assert model.metadata["description"] != "A new description"
#updating the metadata
#Model.set_metadata(self, metadata: dict) -> None
model.set_metadata({ "description": "A new description" })
assert model.metadata["description"] == "A new description"
It is possible to check what is the geometry type of the Model. Note that models do not support mixing geometry types. If you need this feature, consider splitting your geometry into several Models.
#@property
#Model.geom_type(self) -> int
geometry_type_code = model.geom_type
Attributes
A unique name identifies each attribute. There are a few names that are commonly used for certain types of attributes:
Name
Description
POSITION
coordinates of the vertex positions
NORMAL
normal buffer
COLOR
vertex color
Metacity does not utilize indices for geometry reuse, all data is stored "as is" in sequential order.
If everything works as intended, a user should rarely work directly withAttributes. Occasionally, it might be useful to be able to access the Attribute API:
Parsing Lines is very similar to parsing points, although the main difference is the data gets stored as individual segments duplicating inner vertices.
from metacity.geometry import Attribute
lines = Attribute()
#Insert 2D line string using push_line2D method:
#Attribute.push_line2D(self, line: List[float]) -> None
lines.push_line2D([0, 0, \
1, 1, \
1, 2])
#in the example above, the vertices get internally stored as:
#input: a - b - c
#stored values: [0, 0, 0, 1, 1, 0, 1, 1, 0, 1, 2, 0]
# [a - b, b - c]
# every 3rd zero is padding for 3D data, inner vertex si duplicated
#Similar for 3D points
#Attribute.push_line3D(self, line: List[float]) -> None
lines.push_line3D([0, 0, 0, \
1, 1, 0.5, \
1, 2, 1])
#@property
#Attribute.geom_type(self) -> int:
assert lines.geom_type == 2
Polygons are automatically triangulated, the API also supports polygons with holes:
from metacity.geometry import Attribute
triangles = Attribute()
#Insert simple 2D polygon using push_polygon3D method:
#Attribute.push_polygon2D(self, polygon: List[List[float]]) -> None
triangles.push_polygon2D([[0, 0, \
0, 1, \
1, 1, \
0, 1]])
#The structure draws from GeoJSON specs,
#the List[List[float]] can be interpreted as [[polygon], [hole], [hole] ...]
#Insert 2D polygon with a hole in the middle:
triangles.push_polygon2D([[0, 0, \
0, 1, \
1, 1, \
0, 1],\
[0.25, 0.25, \
0.25, 0.75, \
0.75, 0.75, \
0.75, 0.25])
#All works equivalently for 3D:
#Attribute.push_polygon3D(self, polygon: List[List[float]]) -> None
triangles.push_polygon3D([[0, 0, 1, \
0, 1, 1, \
1, 1, 1, \
0, 1, 1]])
#@property
#Attribute.geom_type(self) -> int:
assert triangles.geom_type == 3
Internally, Attribute keeps track of the first assigned type (points, lines, or polygons) and checks all future assignments against it. If the type does not match, an exception gets raised.
For the encoding explanation, see Attribute . The geom_type property of the Model class always returns the type of the POSITION attribute.
Attributes work similarly to . The Attribute API allows parsing of various data. All data is stored inside as if it was 3D data (2D data gets padded by zeroes).