odblab 0.1.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- odblab/__init__.py +3 -0
- odblab/core/__init__.py +7 -0
- odblab/core/database.py +228 -0
- odblab/core/load.py +87 -0
- odblab/core/util.py +114 -0
- odblab/icons/file-exit.svg +1 -0
- odblab/icons/frame-first.svg +1 -0
- odblab/icons/frame-last.svg +1 -0
- odblab/icons/frame-next.svg +1 -0
- odblab/icons/frame-pause.svg +1 -0
- odblab/icons/frame-play.svg +1 -0
- odblab/icons/frame-previous.svg +1 -0
- odblab/icons/utilities-print.svg +1 -0
- odblab/icons/view-colormap.svg +1 -0
- odblab/icons/view-deformation.svg +1 -0
- odblab/icons/view-mirror.svg +1 -0
- odblab/icons/view-region.svg +1 -0
- odblab/icons/view-render-style.svg +1 -0
- odblab/icons/views-autofit.svg +1 -0
- odblab/icons/views-back.svg +1 -0
- odblab/icons/views-bottom.svg +1 -0
- odblab/icons/views-front.svg +1 -0
- odblab/icons/views-isometric.svg +1 -0
- odblab/icons/views-left.svg +1 -0
- odblab/icons/views-right.svg +1 -0
- odblab/icons/views-rotateccw.svg +1 -0
- odblab/icons/views-rotatecw.svg +1 -0
- odblab/icons/views-top.svg +1 -0
- odblab/scripts/odb2npz.py +303 -0
- odblab/scripts/rst2npz.py +148 -0
- odblab/viewer/__init__.py +14 -0
- odblab/viewer/__main__.py +16 -0
- odblab/viewer/border.py +46 -0
- odblab/viewer/infoBlock.py +62 -0
- odblab/viewer/legend.py +88 -0
- odblab/viewer/mainWindow.py +407 -0
- odblab/viewer/meshView.py +208 -0
- odblab/viewer/renderStyles.py +8 -0
- odblab/viewer/renderable.py +47 -0
- odblab/viewer/spectrums.py +113 -0
- odblab/viewer/triad.py +60 -0
- odblab/viewer/util.py +55 -0
- odblab/viewer/view.py +26 -0
- odblab/viewer/viewport.py +342 -0
- odblab/viewer/views.py +15 -0
- odblab-0.1.0.dist-info/METADATA +18 -0
- odblab-0.1.0.dist-info/RECORD +49 -0
- odblab-0.1.0.dist-info/WHEEL +4 -0
- odblab-0.1.0.dist-info/licenses/LICENSE +674 -0
odblab/__init__.py
ADDED
odblab/core/__init__.py
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
from odblab.core.database import Database as Database
|
|
2
|
+
from odblab.core.util import computeMagnitude as computeMagnitude
|
|
3
|
+
from odblab.core.util import computePrincipal as computePrincipal
|
|
4
|
+
from odblab.core.util import computeEquivalentStress as computeEquivalentStress
|
|
5
|
+
from odblab.core.util import autoComputeMagnitude as autoComputeMagnitude
|
|
6
|
+
from odblab.core.util import autoComputeInvariants as autoComputeInvariants
|
|
7
|
+
from odblab.core.load import load as load
|
odblab/core/database.py
ADDED
|
@@ -0,0 +1,228 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import numpy as np
|
|
3
|
+
from numpy import ndarray as Array
|
|
4
|
+
from numpy.ma import MaskedArray
|
|
5
|
+
from dataclasses import dataclass
|
|
6
|
+
from collections.abc import Sequence, Mapping, Collection, Callable
|
|
7
|
+
from typing import Literal
|
|
8
|
+
|
|
9
|
+
@dataclass(frozen=True)
|
|
10
|
+
class Database:
|
|
11
|
+
"""
|
|
12
|
+
A data container for extracted finite element analysis mesh and results.
|
|
13
|
+
This container holds the finite element mesh, node/element sets, and temporal field output data.
|
|
14
|
+
|
|
15
|
+
Notes
|
|
16
|
+
-----
|
|
17
|
+
Do not instantiate this class directly. Use `odblab.load` instead.
|
|
18
|
+
"""
|
|
19
|
+
nodes: Array
|
|
20
|
+
elements: MaskedArray
|
|
21
|
+
types: Array
|
|
22
|
+
nodeSets: dict[str, Array]
|
|
23
|
+
elementSets: dict[str, Array]
|
|
24
|
+
times: Array
|
|
25
|
+
nodeHeaders: Array
|
|
26
|
+
centroidHeaders: Array
|
|
27
|
+
nodeData: Array
|
|
28
|
+
centroidData: Array
|
|
29
|
+
path: str
|
|
30
|
+
|
|
31
|
+
def __post_init__(self) -> None:
|
|
32
|
+
"""Post dataclass object initialization."""
|
|
33
|
+
for array in (
|
|
34
|
+
self.nodes, self.elements, self.types, self.times, self.nodeHeaders, self.centroidHeaders, self.nodeData,
|
|
35
|
+
self.centroidData, *self.nodeSets.values(), *self.elementSets.values()
|
|
36
|
+
):
|
|
37
|
+
array.setflags(write=False)
|
|
38
|
+
|
|
39
|
+
def __repr__(self) -> str:
|
|
40
|
+
"""Readable database summary."""
|
|
41
|
+
indent: str = " "*2
|
|
42
|
+
join: Callable[[Collection[str]], str] = lambda items: \
|
|
43
|
+
"\n".join(f"{indent*2}\"{item}\"" for item in items) if len(items) else f"{indent*2}None"
|
|
44
|
+
typeSummary: str = "; ".join(f"{t}: {c}" for t, c in zip(*np.unique(self.types, return_counts=True)))
|
|
45
|
+
timeSummary: str = "\n".join(f"{indent}{i}: {t}" for i, t in enumerate(self.times))
|
|
46
|
+
return f"""\
|
|
47
|
+
{os.path.splitext(self.path)[1][1:].upper()} Database - {self.path}
|
|
48
|
+
Mesh:
|
|
49
|
+
{indent}Number of nodes: {self.nodes.shape[0]}
|
|
50
|
+
{indent}Number of elements: {self.elements.shape[0]} ({typeSummary})
|
|
51
|
+
Sets:
|
|
52
|
+
{indent}Available node sets ({len(self.nodeSets)}):\n{join(self.nodeSets.keys())}
|
|
53
|
+
{indent}Available element sets ({len(self.elementSets)}):\n{join(self.elementSets.keys())}
|
|
54
|
+
Time steps ({self.times.size}):\n{timeSummary}
|
|
55
|
+
Fields:
|
|
56
|
+
{indent}Node fields ({self.nodeHeaders.size}):\n{join(self.nodeHeaders)}
|
|
57
|
+
{indent}Centroid fields ({self.centroidHeaders.size}):\n{join(self.centroidHeaders)}"""
|
|
58
|
+
|
|
59
|
+
def get(
|
|
60
|
+
self,
|
|
61
|
+
position: Literal["nodes", "centroids"],
|
|
62
|
+
fields: Sequence[str],
|
|
63
|
+
subset: str | None = None,
|
|
64
|
+
frame: int | None = None
|
|
65
|
+
) -> tuple[Array, ...]:
|
|
66
|
+
"""
|
|
67
|
+
Retrieve field output data for the specified position, region, and time.
|
|
68
|
+
|
|
69
|
+
Parameters
|
|
70
|
+
----------
|
|
71
|
+
position : {'nodes', 'centroids'}
|
|
72
|
+
The spatial location of the requested data.
|
|
73
|
+
fields : sequence of strings
|
|
74
|
+
The names/headers of the requested fields, e.g., `['U.U1', 'U.U2', 'U.U3']`, `['S.MISES', 'S.TRESCA']`.
|
|
75
|
+
subset : string, optional
|
|
76
|
+
Optional node (if `position='nodes'`) or element (if `position='centroids'`) set name defining the region
|
|
77
|
+
for which the data is to be extracted. If not specified, extracts data for all nodes or centroids.
|
|
78
|
+
frame : integer, optional
|
|
79
|
+
The time frame index for which the data is to be extracted. If not specified, extracts data for all frames.
|
|
80
|
+
|
|
81
|
+
Returns
|
|
82
|
+
-------
|
|
83
|
+
out : tuple of arrays
|
|
84
|
+
Arrays containing the requested field output data. If the data is requested at a specific frame, the
|
|
85
|
+
returned arrays are vectors of size `m`; otherwise, they are matrices of size `m`-by-`n`, where `m` is the
|
|
86
|
+
number of nodes (if `position='nodes'`) or elements (if `position='centroids'`) and `n` is the number of
|
|
87
|
+
available frames.
|
|
88
|
+
"""
|
|
89
|
+
|
|
90
|
+
# get requested position
|
|
91
|
+
targetData: Array; targetSets: dict[str, Array]; targetHeaders: Array
|
|
92
|
+
match position:
|
|
93
|
+
case "nodes":
|
|
94
|
+
targetData = self.nodeData
|
|
95
|
+
targetSets = self.nodeSets
|
|
96
|
+
targetHeaders = self.nodeHeaders
|
|
97
|
+
case "centroids":
|
|
98
|
+
targetData = self.centroidData
|
|
99
|
+
targetSets = self.elementSets
|
|
100
|
+
targetHeaders = self.centroidHeaders
|
|
101
|
+
case _:
|
|
102
|
+
raise ValueError(f"invalid position '{position}'; position must be 'nodes' or 'centroids'")
|
|
103
|
+
|
|
104
|
+
# get j-indexing
|
|
105
|
+
j: slice | Array = slice(None)
|
|
106
|
+
if subset is not None:
|
|
107
|
+
if subset not in targetSets.keys():
|
|
108
|
+
raise ValueError(
|
|
109
|
+
f"set '{subset}' not available for position '{position}'; available sets: " +
|
|
110
|
+
", ".join(f"'{key}'" for key in targetSets.keys())
|
|
111
|
+
)
|
|
112
|
+
j = targetSets[subset]
|
|
113
|
+
|
|
114
|
+
# get k-indexing
|
|
115
|
+
k: slice | int = slice(None) if frame is None else frame
|
|
116
|
+
|
|
117
|
+
# get fields
|
|
118
|
+
out: list[Array] = []
|
|
119
|
+
for header in (fields,) if isinstance(fields, str) else fields:
|
|
120
|
+
found: Array = np.where(targetHeaders == header)[0]
|
|
121
|
+
if found.size == 0:
|
|
122
|
+
raise ValueError(
|
|
123
|
+
f"field '{header}' not available at position '{position}'; available fields: " +
|
|
124
|
+
", ".join(f"'{h}'" for h in targetHeaders)
|
|
125
|
+
)
|
|
126
|
+
i: int = int(found[0])
|
|
127
|
+
out.append(targetData[i, j, k])
|
|
128
|
+
return tuple(out)
|
|
129
|
+
|
|
130
|
+
def add(
|
|
131
|
+
self,
|
|
132
|
+
data: Mapping[str, Array],
|
|
133
|
+
position: Literal["nodes", "centroids"],
|
|
134
|
+
subset: str | None = None,
|
|
135
|
+
frame: int | None = None
|
|
136
|
+
) -> None:
|
|
137
|
+
"""
|
|
138
|
+
Add field output arrays to the database.
|
|
139
|
+
|
|
140
|
+
Parameters
|
|
141
|
+
----------
|
|
142
|
+
data : mapping of strings to arrays
|
|
143
|
+
A dict-like object mapping names/headers to the corresponding data arrays to be inserted in the database.
|
|
144
|
+
The names/headers must be unique, and the arrays must have the correct shape for the position, region, and
|
|
145
|
+
time frame(s).
|
|
146
|
+
position : {'nodes', 'centroids'}
|
|
147
|
+
The spatial location where the new data should be added.
|
|
148
|
+
subset : string, optional
|
|
149
|
+
Optional node (if `position='nodes'`) or element (if `position='centroids'`) set name defining the region
|
|
150
|
+
for which the data is to be added. If not specified, adds data for all nodes or centroids. If specified,
|
|
151
|
+
nodes/centroids outside this subset will be padded with NaN.
|
|
152
|
+
frame : integer, optional
|
|
153
|
+
The time frame index for which the data is to be added. If not specified, adds data for all frames. If
|
|
154
|
+
specified, frames outside this index will be padded with NaN.
|
|
155
|
+
"""
|
|
156
|
+
|
|
157
|
+
# get requested position
|
|
158
|
+
dataAttribute: str; headerAttribute: str
|
|
159
|
+
targetData: Array; targetSets: dict[str, Array]; targetHeaders: Array
|
|
160
|
+
match position:
|
|
161
|
+
case "nodes":
|
|
162
|
+
targetData = self.nodeData
|
|
163
|
+
targetSets = self.nodeSets
|
|
164
|
+
targetHeaders = self.nodeHeaders
|
|
165
|
+
dataAttribute, headerAttribute = "nodeData", "nodeHeaders"
|
|
166
|
+
case "centroids":
|
|
167
|
+
targetData = self.centroidData
|
|
168
|
+
targetSets = self.elementSets
|
|
169
|
+
targetHeaders = self.centroidHeaders
|
|
170
|
+
dataAttribute, headerAttribute = "centroidData", "centroidHeaders"
|
|
171
|
+
case _:
|
|
172
|
+
raise ValueError(f"invalid position '{position}'; position must be 'nodes' or 'centroids'")
|
|
173
|
+
|
|
174
|
+
# get j-indexing
|
|
175
|
+
j: slice | Array = slice(None)
|
|
176
|
+
if subset is not None:
|
|
177
|
+
if subset not in targetSets.keys():
|
|
178
|
+
raise ValueError(
|
|
179
|
+
f"set '{subset}' not available for position '{position}'; available sets: " +
|
|
180
|
+
", ".join(f"'{key}'" for key in targetSets.keys())
|
|
181
|
+
)
|
|
182
|
+
j = targetSets[subset]
|
|
183
|
+
|
|
184
|
+
# get k-indexing
|
|
185
|
+
k: slice | int = slice(None) if frame is None else frame
|
|
186
|
+
|
|
187
|
+
# get expected array shape
|
|
188
|
+
expectedEntityCount: int = int(targetData.shape[1]) if isinstance(j, slice) else j.size
|
|
189
|
+
expectedShape: tuple[int, ...] = \
|
|
190
|
+
(expectedEntityCount, int(targetData.shape[2])) if frame is None else (expectedEntityCount,)
|
|
191
|
+
newArray: Array = np.full(
|
|
192
|
+
shape=(len(data), targetData.shape[1], targetData.shape[2]),
|
|
193
|
+
fill_value=np.nan,
|
|
194
|
+
dtype=targetData.dtype
|
|
195
|
+
)
|
|
196
|
+
|
|
197
|
+
# loop provided data arrays
|
|
198
|
+
for i, (header, array) in enumerate(data.items()):
|
|
199
|
+
if np.where(targetHeaders == header)[0].size > 0:
|
|
200
|
+
raise ValueError(f"header '{header}' already exists at position '{position}'")
|
|
201
|
+
if array.shape != expectedShape:
|
|
202
|
+
raise ValueError(
|
|
203
|
+
f"bad shape for '{header}' field output array at position '{position}'; "
|
|
204
|
+
f"expected shape {expectedShape}, but got {array.shape}"
|
|
205
|
+
)
|
|
206
|
+
newArray[i, j, k] = array
|
|
207
|
+
|
|
208
|
+
# concatenate
|
|
209
|
+
object.__setattr__(self, dataAttribute, np.concatenate((targetData, newArray), axis=0))
|
|
210
|
+
object.__setattr__(self, headerAttribute, np.append(targetHeaders, [*data.keys()]))
|
|
211
|
+
getattr(self, dataAttribute).setflags(write=False)
|
|
212
|
+
getattr(self, headerAttribute).setflags(write=False)
|
|
213
|
+
|
|
214
|
+
def save(self) -> None:
|
|
215
|
+
"""Save the database state to disk."""
|
|
216
|
+
with open(self.path, "wb") as file:
|
|
217
|
+
np.savez(file, allow_pickle=False, **{
|
|
218
|
+
"__nodes__": self.nodes,
|
|
219
|
+
"__types__": self.types,
|
|
220
|
+
"__elements__": np.ma.getdata(self.elements),
|
|
221
|
+
**{f"__node_set__.\"{name}\"": array for name, array in self.nodeSets.items()},
|
|
222
|
+
**{f"__element_set__.\"{name}\"": array for name, array in self.elementSets.items()},
|
|
223
|
+
"__times__": self.times,
|
|
224
|
+
"__node_data__": self.nodeData,
|
|
225
|
+
"__centroid_data__": self.centroidData,
|
|
226
|
+
"__node_headers__": self.nodeHeaders,
|
|
227
|
+
"__centroid_headers__": self.centroidHeaders,
|
|
228
|
+
})
|
odblab/core/load.py
ADDED
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import sys
|
|
2
|
+
import subprocess
|
|
3
|
+
import numpy as np
|
|
4
|
+
from pathlib import Path
|
|
5
|
+
from numpy.ma import MaskedArray
|
|
6
|
+
from numpy import ndarray as Array
|
|
7
|
+
from importlib import resources
|
|
8
|
+
from odblab.core import Database, autoComputeMagnitude, autoComputeInvariants
|
|
9
|
+
|
|
10
|
+
def _loadNpz(npzPath: str | Path, autoComputeAllInvariants: bool = False) -> Database:
|
|
11
|
+
"""Loads the requested *.npz file."""
|
|
12
|
+
if not isinstance(npzPath, Path): npzPath = Path(npzPath)
|
|
13
|
+
npzPath = npzPath.resolve()
|
|
14
|
+
with np.load(npzPath) as data:
|
|
15
|
+
nodes: Array = data["__nodes__"]
|
|
16
|
+
types: Array = data["__types__"]
|
|
17
|
+
elements: MaskedArray = np.ma.array(data=data["__elements__"], mask=data["__elements__"] < 0, fill_value=-1)
|
|
18
|
+
nodeSets: dict[str, Array] = {
|
|
19
|
+
key.removeprefix("__node_set__.")[1:-1]: data[key]
|
|
20
|
+
for key in data.files if key.startswith("__node_set__")
|
|
21
|
+
}
|
|
22
|
+
elementSets: dict[str, Array] = {
|
|
23
|
+
key.removeprefix("__element_set__.")[1:-1]: data[key]
|
|
24
|
+
for key in data.files if key.startswith("__element_set__")
|
|
25
|
+
}
|
|
26
|
+
times: Array = data["__times__"]
|
|
27
|
+
nodeData: Array = data["__node_data__"]
|
|
28
|
+
centroidData: Array = data["__centroid_data__"]
|
|
29
|
+
nodeHeaders: Array = data["__node_headers__"]
|
|
30
|
+
centroidHeaders: Array = data["__centroid_headers__"]
|
|
31
|
+
database: Database = Database(
|
|
32
|
+
nodes, elements, types, nodeSets, elementSets,
|
|
33
|
+
times, nodeHeaders, centroidHeaders, nodeData, centroidData,
|
|
34
|
+
str(npzPath)
|
|
35
|
+
)
|
|
36
|
+
if autoComputeAllInvariants:
|
|
37
|
+
print("Computing invariants...")
|
|
38
|
+
autoComputeMagnitude(database)
|
|
39
|
+
autoComputeInvariants(database)
|
|
40
|
+
database.save()
|
|
41
|
+
print("Database updated with invariants.")
|
|
42
|
+
return database
|
|
43
|
+
|
|
44
|
+
def _loadOdb(odbPath: str | Path) -> Database:
|
|
45
|
+
"""Loads the requested *.odb file."""
|
|
46
|
+
if not isinstance(odbPath, Path): odbPath = Path(odbPath)
|
|
47
|
+
odbPath = odbPath.resolve()
|
|
48
|
+
odbzPath: Path = odbPath.with_suffix(".odbz")
|
|
49
|
+
autoComputeAllInvariants: bool = True
|
|
50
|
+
if odbPath.exists() and odbzPath.exists() and odbzPath.stat().st_mtime > odbPath.stat().st_mtime:
|
|
51
|
+
print("Using cached ODBZ database.")
|
|
52
|
+
autoComputeAllInvariants = False
|
|
53
|
+
else:
|
|
54
|
+
print("ODBZ database not found or outdated. Converting ODB to ODBZ...")
|
|
55
|
+
script: str = str(resources.files("odblab.scripts") / "odb2npz.py")
|
|
56
|
+
if subprocess.run(("abaqus", "python", script, "--odb", str(odbPath)), shell=True, check=True).returncode:
|
|
57
|
+
raise RuntimeError("abaqus command not found; abaqus must be installed on the system")
|
|
58
|
+
with open("odb2npz.log", "r") as log:
|
|
59
|
+
if log.readline().strip() != "EXIT_SUCCESS":
|
|
60
|
+
raise RuntimeError("error in 'odb2npz.py'\n " + log.readline().strip())
|
|
61
|
+
return _loadNpz(odbzPath, autoComputeAllInvariants)
|
|
62
|
+
|
|
63
|
+
def _loadRst(rstPath: str | Path) -> Database:
|
|
64
|
+
"""Loads the requested *.rst file."""
|
|
65
|
+
if not isinstance(rstPath, Path): rstPath = Path(rstPath)
|
|
66
|
+
rstPath = rstPath.resolve()
|
|
67
|
+
rstzPath: Path = rstPath.with_suffix(".rstz")
|
|
68
|
+
autoComputeAllInvariants: bool = True
|
|
69
|
+
if rstPath.exists() and rstzPath.exists() and rstzPath.stat().st_mtime > rstPath.stat().st_mtime:
|
|
70
|
+
print("Using cached RSTZ database.")
|
|
71
|
+
autoComputeAllInvariants = False
|
|
72
|
+
else:
|
|
73
|
+
print("RSTZ database not found or outdated. Converting RST to RSTZ...")
|
|
74
|
+
script: str = str(resources.files("odblab.scripts") / "rst2npz.py")
|
|
75
|
+
subprocess.run((sys.executable, script, "--rst", str(rstPath)), shell=True, check=True)
|
|
76
|
+
return _loadNpz(rstzPath, autoComputeAllInvariants)
|
|
77
|
+
|
|
78
|
+
def load(filePath: str | Path) -> Database:
|
|
79
|
+
"""Loads the requested finite element analysis database file."""
|
|
80
|
+
if not isinstance(filePath, Path): filePath = Path(filePath)
|
|
81
|
+
filePath = filePath.resolve()
|
|
82
|
+
if not filePath.exists(): raise FileNotFoundError(filePath)
|
|
83
|
+
match filePath.suffix.lower():
|
|
84
|
+
case ".odbz" | ".rstz": return _loadNpz(filePath)
|
|
85
|
+
case ".odb": return _loadOdb(filePath)
|
|
86
|
+
case ".rst": return _loadRst(filePath)
|
|
87
|
+
case _: raise ValueError(f"unexpected file extension '{filePath.suffix}': {filePath}")
|
odblab/core/util.py
ADDED
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
import re
|
|
2
|
+
import numpy as np
|
|
3
|
+
from re import Pattern
|
|
4
|
+
from numpy import ndarray as Array
|
|
5
|
+
from odblab.core import Database
|
|
6
|
+
|
|
7
|
+
def _findVectors(database: Database) -> tuple[dict[str, dict[str, str]], dict[str, dict[str, str]]]:
|
|
8
|
+
"""Scan database headers to identify and group vector components."""
|
|
9
|
+
nodeVectors: dict[str, dict[str, str]] = {}
|
|
10
|
+
centroidVectors: dict[str, dict[str, str]] = {}
|
|
11
|
+
pattern: Pattern[str] = re.compile(r"^(.*?)\.[a-zA-Z]*([123])$")
|
|
12
|
+
for vectors, headers in (nodeVectors, database.nodeHeaders), (centroidVectors, database.centroidHeaders):
|
|
13
|
+
for header in headers:
|
|
14
|
+
if match := pattern.match(header := str(header)):
|
|
15
|
+
vectors.setdefault(match.group(1), {})[match.group(2)] = header
|
|
16
|
+
return nodeVectors, centroidVectors
|
|
17
|
+
|
|
18
|
+
def _findTensors(database: Database) -> tuple[dict[str, dict[str, str]], dict[str, dict[str, str]]]:
|
|
19
|
+
"""Scan database headers to identify and group tensor components."""
|
|
20
|
+
nodeTensors: dict[str, dict[str, str]] = {}
|
|
21
|
+
centroidTensors: dict[str, dict[str, str]] = {}
|
|
22
|
+
pattern: Pattern[str] = re.compile(r"^(.*?)\.[a-zA-Z]*([0-9]{2})$")
|
|
23
|
+
for tensors, headers in (nodeTensors, database.nodeHeaders), (centroidTensors, database.centroidHeaders):
|
|
24
|
+
for header in headers:
|
|
25
|
+
if match := pattern.match(header := str(header)):
|
|
26
|
+
tensors.setdefault(match.group(1), {})[match.group(2)] = header
|
|
27
|
+
return nodeTensors, centroidTensors
|
|
28
|
+
|
|
29
|
+
def computeMagnitude(u1: Array, u2: Array, u3: Array | None) -> Array:
|
|
30
|
+
"""Compute the element-wise magnitude of a 2D or 3D vector field."""
|
|
31
|
+
if u3 is None: return np.sqrt(u1*u1 + u2*u2)
|
|
32
|
+
else: return np.sqrt(u1*u1 + u2*u2 + u3*u3)
|
|
33
|
+
|
|
34
|
+
def computePrincipal(*, s11: Array, s22: Array, s33: Array | None, s12: Array, s13: Array | None, s23: Array | None) \
|
|
35
|
+
-> tuple[Array, Array, Array, Array]:
|
|
36
|
+
"""Compute the element-wise max., mid., and min. principal tensor values."""
|
|
37
|
+
tensor: Array = np.zeros(shape=(*s11.shape, 3, 3), dtype=s11.dtype)
|
|
38
|
+
tensor[..., 0, 0] = s11
|
|
39
|
+
tensor[..., 1, 1] = s22
|
|
40
|
+
tensor[..., 0, 1] = tensor[..., 1, 0] = s12
|
|
41
|
+
if s33 is not None: tensor[..., 2, 2] = s33
|
|
42
|
+
if s13 is not None: tensor[..., 0, 2] = tensor[..., 2, 0] = s13
|
|
43
|
+
if s23 is not None: tensor[..., 1, 2] = tensor[..., 2, 1] = s23
|
|
44
|
+
validMask: Array = np.isfinite(tensor).all(axis=(-2, -1))
|
|
45
|
+
eigenvalues: Array = np.full(shape=(*s11.shape, 3), fill_value=np.nan, dtype=s11.dtype)
|
|
46
|
+
eigenvalues[validMask] = np.linalg.eigvalsh(tensor[validMask])
|
|
47
|
+
max: Array = eigenvalues[..., 2]
|
|
48
|
+
mid: Array = eigenvalues[..., 1]
|
|
49
|
+
min: Array = eigenvalues[..., 0]
|
|
50
|
+
major: Array = np.where(np.abs(max) > np.abs(min), max, min)
|
|
51
|
+
return max, mid, min, major
|
|
52
|
+
|
|
53
|
+
def computeEquivalentStress(s1: Array, s2: Array, s3: Array) -> tuple[Array, Array, Array]:
|
|
54
|
+
"""Compute the equivalent von Mises, Tresca, and pressure stress based on the provided principal stresses."""
|
|
55
|
+
mises: Array = np.sqrt(0.5*((s1 - s2)**2 + (s2 - s3)**2 + (s3 - s1)**2))
|
|
56
|
+
tresca: Array = s1 - s3
|
|
57
|
+
pressure: Array = -(s1 + s2 + s3)/3
|
|
58
|
+
return mises, tresca, pressure
|
|
59
|
+
|
|
60
|
+
def autoComputeMagnitude(database: Database) -> None:
|
|
61
|
+
"""
|
|
62
|
+
Auto-discover node and centroid vector fields and compute their element-wise magnitude.
|
|
63
|
+
Results are appended to the database, e.g., "U.MAGNITUDE".
|
|
64
|
+
"""
|
|
65
|
+
for position, currentHeaders, vectors in zip(
|
|
66
|
+
("nodes", "centroids"),
|
|
67
|
+
(database.nodeHeaders, database.centroidHeaders),
|
|
68
|
+
_findVectors(database)
|
|
69
|
+
):
|
|
70
|
+
magnitudes: dict[str, Array] = {}
|
|
71
|
+
for label, components in vectors.items():
|
|
72
|
+
if f"{label}.MAGNITUDE" in currentHeaders: continue
|
|
73
|
+
if "1" not in components or "2" not in components: continue
|
|
74
|
+
u1, u2 = database.get(position, (components["1"], components["2"]))
|
|
75
|
+
u3, = database.get(position, (components["3"],)) if "3" in components else (None,)
|
|
76
|
+
magnitudes[f"{label}.MAGNITUDE"] = computeMagnitude(u1, u2, u3)
|
|
77
|
+
database.add(magnitudes, position)
|
|
78
|
+
|
|
79
|
+
def autoComputeInvariants(database: Database) -> None:
|
|
80
|
+
"""
|
|
81
|
+
Auto-discover node and centroid tensor fields and compute their element-wise invariants.
|
|
82
|
+
Results are appended to the database, e.g., "LE.MAX_PRINCIPAL", "S.MISES".
|
|
83
|
+
"""
|
|
84
|
+
for position, currentHeaders, tensors in zip(
|
|
85
|
+
("nodes", "centroids"),
|
|
86
|
+
(database.nodeHeaders, database.centroidHeaders),
|
|
87
|
+
_findTensors(database)
|
|
88
|
+
):
|
|
89
|
+
invariants: dict[str, Array] = {}
|
|
90
|
+
for label, components in tensors.items():
|
|
91
|
+
if any(f"{label}.{invariant}" in currentHeaders for invariant in (
|
|
92
|
+
"MAX_PRINCIPAL", "MID_PRINCIPAL", "MIN_PRINCIPAL", "MAJOR_PRINCIPAL",
|
|
93
|
+
"MISES", "TRESCA", "PRESSURE"
|
|
94
|
+
)): continue
|
|
95
|
+
if any(ij not in components for ij in ("11", "22", "12")): continue
|
|
96
|
+
s11, s22, s12 = database.get(position, (components["11"], components["22"], components["12"]))
|
|
97
|
+
s33, = database.get(position, (components["33"],)) if "33" in components else (None,)
|
|
98
|
+
s13, = database.get(position, (components["13"],)) if "13" in components else (None,)
|
|
99
|
+
s23, = database.get(position, (components["23"],)) if "23" in components else (None,)
|
|
100
|
+
if label != "S":
|
|
101
|
+
s12 = s12/2
|
|
102
|
+
if s13 is not None: s13 = s13/2
|
|
103
|
+
if s23 is not None: s23 = s23/2
|
|
104
|
+
s1, s2, s3, major = computePrincipal(s11=s11, s22=s22, s33=s33, s12=s12, s13=s13, s23=s23)
|
|
105
|
+
invariants[f"{label}.MAX_PRINCIPAL"] = s1
|
|
106
|
+
invariants[f"{label}.MID_PRINCIPAL"] = s2
|
|
107
|
+
invariants[f"{label}.MIN_PRINCIPAL"] = s3
|
|
108
|
+
invariants[f"{label}.MAJOR_PRINCIPAL"] = major
|
|
109
|
+
if label == "S":
|
|
110
|
+
mises, tresca, pressure = computeEquivalentStress(s1, s2, s3)
|
|
111
|
+
invariants[f"{label}.MISES"] = mises
|
|
112
|
+
invariants[f"{label}.TRESCA"] = tresca
|
|
113
|
+
invariants[f"{label}.PRESSURE"] = pressure
|
|
114
|
+
database.add(invariants, position)
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64"><title>SVG_Artboards</title><polygon points="24.7 16.7 48.02 32.16 24.7 47.63 24.7 39.42 4.29 39.42 4.29 24.92 24.7 24.92 24.7 16.7" style="fill:#a7d28c"/><path d="M24.7,48.76a1.12,1.12,0,0,1-.53-.13,1.14,1.14,0,0,1-.59-1V40.55H4.29a1.13,1.13,0,0,1-1.12-1.13V24.92a1.12,1.12,0,0,1,1.12-1.13H23.58V16.7a1.13,1.13,0,0,1,1.75-.94L48.64,31.22a1.12,1.12,0,0,1,0,1.88L25.33,48.57A1.11,1.11,0,0,1,24.7,48.76ZM5.42,38.29H24.7a1.13,1.13,0,0,1,1.13,1.13v6.11L46,32.16,25.83,18.8v6.12A1.12,1.12,0,0,1,24.7,26H5.42Z" style="fill:#6f6f59"/><path d="M4.29,9.84v6.44H10.9v-5.5H53.07V53.22H10.9V48.31H4.29v5.85A5.72,5.72,0,0,0,10,59.87H54a5.71,5.71,0,0,0,5.71-5.71V9.84A5.71,5.71,0,0,0,54,4.13H10A5.72,5.72,0,0,0,4.29,9.84Z" style="fill:#2896d3"/><path d="M54,61H10a6.85,6.85,0,0,1-6.84-6.84V48.31a1.12,1.12,0,0,1,1.12-1.12H10.9A1.13,1.13,0,0,1,12,48.31V52.1H52V11.9H12v4.38a1.14,1.14,0,0,1-1.13,1.13H4.29a1.13,1.13,0,0,1-1.12-1.13V9.84A6.85,6.85,0,0,1,10,3H54a6.85,6.85,0,0,1,6.85,6.84V54.16A6.85,6.85,0,0,1,54,61ZM5.42,49.44v4.72A4.6,4.6,0,0,0,10,58.75H54a4.59,4.59,0,0,0,4.59-4.59V9.84A4.59,4.59,0,0,0,54,5.25H10A4.6,4.6,0,0,0,5.42,9.84v5.31H9.77V10.78A1.13,1.13,0,0,1,10.9,9.65H53.08a1.12,1.12,0,0,1,1.12,1.13V53.22a1.12,1.12,0,0,1-1.12,1.13H10.9a1.13,1.13,0,0,1-1.13-1.13V49.44Z" style="fill:#6f6f59"/></svg>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64"><rect x="7.61" y="10.75" width="14.66" height="43.05" transform="translate(29.87 64.55) rotate(180)" style="fill:#a7d28c"/><path d="M22.26,54.93H7.61A1.13,1.13,0,0,1,6.48,53.8v-43A1.14,1.14,0,0,1,7.61,9.62H22.26a1.13,1.13,0,0,1,1.13,1.13V53.8A1.12,1.12,0,0,1,22.26,54.93ZM8.73,52.68H21.14V11.88H8.73Z" style="fill:#6f6f59"/><path d="M58.17,53.34V10.66L26,32Z" style="fill:#a7d28c"/><path d="M58.17,54.46a1.17,1.17,0,0,1-.62-.18L25.38,32.93a1.15,1.15,0,0,1-.5-.94,1.14,1.14,0,0,1,.5-.94L57.55,9.72a1.12,1.12,0,0,1,1.16-.05,1.14,1.14,0,0,1,.59,1V53.34a1.11,1.11,0,0,1-1.13,1.12ZM28,32l29,19.25V12.76Z" style="fill:#6f6f59"/></svg>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64"><rect x="41.87" y="10.75" width="14.66" height="43.05" style="fill:#a7d28c"/><path d="M56.53,54.93H41.87a1.12,1.12,0,0,1-1.12-1.13v-43a1.13,1.13,0,0,1,1.12-1.13H56.53a1.14,1.14,0,0,1,1.13,1.13V53.8A1.13,1.13,0,0,1,56.53,54.93ZM43,52.68H55.4V11.88H43Z" style="fill:#6f6f59"/><path d="M6.79,10.66V53.34L39,32Z" style="fill:#a7d28c"/><path d="M6.79,54.46a1.11,1.11,0,0,1-1.13-1.12V10.66a1.14,1.14,0,0,1,.59-1,1.12,1.12,0,0,1,1.16.05L39.58,31.07a1.15,1.15,0,0,1,.5.94,1.14,1.14,0,0,1-.5.94L7.41,54.28A1.17,1.17,0,0,1,6.79,54.46Zm1.12-41.7V51.24L36.92,32Z" style="fill:#6f6f59"/></svg>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64"><rect x="5.81" y="10.75" width="14.66" height="43.05" style="fill:#a7d28c"/><path d="M20.47,54.93H5.81A1.13,1.13,0,0,1,4.68,53.8v-43A1.14,1.14,0,0,1,5.81,9.62H20.47a1.13,1.13,0,0,1,1.12,1.13V53.8A1.12,1.12,0,0,1,20.47,54.93ZM6.94,52.68h12.4V11.88H6.94Z" style="fill:#6f6f59"/><path d="M27.69,10.66V53.34L59.86,32Z" style="fill:#a7d28c"/><path d="M27.69,54.46a1.09,1.09,0,0,1-.53-.13,1.13,1.13,0,0,1-.6-1V10.66a1.13,1.13,0,0,1,.6-1,1.11,1.11,0,0,1,1.15.05L60.48,31.07A1.13,1.13,0,0,1,61,32a1.12,1.12,0,0,1-.51.94L28.31,54.28A1.12,1.12,0,0,1,27.69,54.46Zm1.13-41.7V51.24L57.82,32Z" style="fill:#6f6f59"/></svg>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64"><rect x="12.4" y="9.42" width="15.45" height="45.38" style="fill:#a7d28c"/><path d="M27.85,55.93H12.4a1.13,1.13,0,0,1-1.13-1.13V9.42A1.13,1.13,0,0,1,12.4,8.3H27.85A1.13,1.13,0,0,1,29,9.42V54.8A1.13,1.13,0,0,1,27.85,55.93ZM13.53,53.68H26.72V10.55H13.53Z" style="fill:#6f6f59"/><rect x="36.42" y="9.42" width="15.45" height="45.38" style="fill:#a7d28c"/><path d="M51.87,55.93H36.42a1.13,1.13,0,0,1-1.13-1.13V9.42A1.13,1.13,0,0,1,36.42,8.3H51.87A1.12,1.12,0,0,1,53,9.42V54.8A1.12,1.12,0,0,1,51.87,55.93ZM37.54,53.68h13.2V10.55H37.54Z" style="fill:#6f6f59"/></svg>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64"><path d="M19.9,10.66V53.34L52.07,32Z" style="fill:#a7d28c"/><path d="M19.9,54.47a1.1,1.1,0,0,1-.53-.14,1.12,1.12,0,0,1-.6-1V10.66a1.12,1.12,0,0,1,.6-1,1.11,1.11,0,0,1,1.15.05L52.69,31.07a1.13,1.13,0,0,1,.51.94,1.12,1.12,0,0,1-.51.94L20.52,54.28A1.16,1.16,0,0,1,19.9,54.47ZM21,12.76V51.24L50,32Z" style="fill:#6f6f59"/></svg>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64"><rect x="44.37" y="10.75" width="14.66" height="43.05" transform="translate(103.39 64.55) rotate(180)" style="fill:#a7d28c"/><path d="M59,54.93H44.37a1.13,1.13,0,0,1-1.13-1.13v-43a1.14,1.14,0,0,1,1.13-1.13H59a1.13,1.13,0,0,1,1.12,1.13V53.8A1.12,1.12,0,0,1,59,54.93ZM45.5,52.68H57.9V11.88H45.5Z" style="fill:#6f6f59"/><path d="M37.08,53.34V10.66L4.91,32Z" style="fill:#a7d28c"/><path d="M37.08,54.46a1.17,1.17,0,0,1-.62-.18L4.29,32.93a1.15,1.15,0,0,1-.5-.94,1.14,1.14,0,0,1,.5-.94L36.46,9.72a1.12,1.12,0,0,1,1.16-.05,1.14,1.14,0,0,1,.59,1V53.34a1.11,1.11,0,0,1-1.13,1.12ZM7,32,36,51.24V12.76Z" style="fill:#6f6f59"/></svg>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64"><title>SVG_Artboards</title><rect x="9.45" y="13.18" width="6.18" height="4.54" rx="2.03" style="fill:#787878"/><polygon points="42.09 11.52 26.1 11.52 22.99 16.68 45.2 16.68 42.09 11.52" style="fill:#cdcece"/><path d="M45.2,17.81H23a1.14,1.14,0,0,1-1-1.71l3.12-5.16a1.12,1.12,0,0,1,1-.55h16a1.12,1.12,0,0,1,1,.55l3.11,5.16a1.12,1.12,0,0,1,0,1.13A1.13,1.13,0,0,1,45.2,17.81ZM25,15.55H43.2l-1.75-2.9H26.74Z" style="fill:#787878"/><rect x="6.36" y="16.12" width="51.31" height="36.74" rx="6.96" style="fill:#cdcece"/><path d="M50.71,54H13.33a8.1,8.1,0,0,1-8.09-8.09V23.08A8.1,8.1,0,0,1,13.33,15H50.71a8.1,8.1,0,0,1,8.09,8.09V45.89A8.1,8.1,0,0,1,50.71,54ZM13.33,17.24a5.85,5.85,0,0,0-5.84,5.84V45.89a5.84,5.84,0,0,0,5.84,5.83H50.71a5.84,5.84,0,0,0,5.84-5.83V23.08a5.85,5.85,0,0,0-5.84-5.84Z" style="fill:#787878"/><circle cx="12.55" cy="21.78" r="2.33" style="fill:#de4130"/><circle cx="34.67" cy="34.48" r="13.8" style="fill:#cdcece"/><path d="M34.67,49.41A14.93,14.93,0,1,1,49.59,34.48,15,15,0,0,1,34.67,49.41Zm0-27.6A12.67,12.67,0,1,0,47.34,34.48,12.69,12.69,0,0,0,34.67,21.81Z" style="fill:#787878"/><circle cx="34.67" cy="34.48" r="9.96" style="fill:#d0e5f6"/><path d="M34.67,45.57A11.09,11.09,0,1,1,45.75,34.48,11.11,11.11,0,0,1,34.67,45.57Zm0-19.92a8.83,8.83,0,1,0,8.83,8.83A8.84,8.84,0,0,0,34.67,25.65Z" style="fill:#787878"/><path d="M29.12,35.5a6.65,6.65,0,0,1,11.94-4,6.65,6.65,0,1,0-11.43,6.58A6.61,6.61,0,0,1,29.12,35.5Z" style="fill:#47b1d8"/><path d="M2.81,12.44a1.13,1.13,0,0,1-1.13-1.13V2.69A1.13,1.13,0,0,1,2.81,1.57h8.62a1.13,1.13,0,1,1,0,2.25H3.94v7.49A1.13,1.13,0,0,1,2.81,12.44Z" style="fill:#787878"/><path d="M61.31,12.44a1.12,1.12,0,0,1-1.12-1.13V3.82h-7.5a1.13,1.13,0,0,1,0-2.25h8.62a1.12,1.12,0,0,1,1.13,1.12v8.62A1.12,1.12,0,0,1,61.31,12.44Z" style="fill:#787878"/><path d="M61.31,62.71H52.69a1.13,1.13,0,0,1,0-2.26h7.5V53a1.13,1.13,0,1,1,2.25,0v8.62A1.13,1.13,0,0,1,61.31,62.71Z" style="fill:#787878"/><path d="M11.43,62.71H2.81a1.14,1.14,0,0,1-1.13-1.13V53a1.13,1.13,0,1,1,2.26,0v7.49h7.49a1.13,1.13,0,1,1,0,2.26Z" style="fill:#787878"/></svg>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64"><title>SVG_Artboards</title><rect x="17.52" y="7.45" width="28.97" height="49.1" style="fill:#a7d28c;stroke:#6f6f59;stroke-linecap:round;stroke-linejoin:round;stroke-width:2.2536px"/><rect x="18.62" y="52.47" width="26.71" height="2.96" style="fill:#603c89"/><rect x="18.62" y="49.51" width="26.71" height="2.96" style="fill:#46449b"/><rect x="18.62" y="46.62" width="26.71" height="2.96" style="fill:#2a5aa8"/><rect x="18.62" y="43.66" width="26.71" height="2.96" style="fill:#0c71b8"/><rect x="18.62" y="40.68" width="26.71" height="2.96" style="fill:#0d7fc2"/><rect x="18.62" y="37.72" width="26.71" height="2.96" style="fill:#198ece"/><rect x="18.62" y="34.82" width="26.71" height="2.96" style="fill:#25a1db"/><rect x="18.62" y="31.86" width="26.71" height="2.96" style="fill:#12b2d2"/><rect x="18.62" y="28.85" width="26.71" height="2.96" style="fill:#4bb88e"/><rect x="18.62" y="25.95" width="26.71" height="2.96" style="fill:#98c37e"/><rect x="18.62" y="22.99" width="26.71" height="2.96" style="fill:#a4c661"/><rect x="18.62" y="20.09" width="26.71" height="2.96" style="fill:#c6c835"/><rect x="18.62" y="17.13" width="26.71" height="2.96" style="fill:#e8c61d"/><rect x="18.62" y="14.15" width="26.71" height="2.96" style="fill:#e2ae27"/><rect x="18.62" y="11.19" width="26.71" height="2.96" style="fill:#dc9a2a"/><rect x="18.62" y="8.3" width="26.71" height="2.96" style="fill:#c58338"/></svg>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64"><title>SVG_Artboards</title><rect x="5.57" y="32.13" width="52.28" height="19.82" style="fill:#d4ece6"/><path d="M57.85,53.08H5.57A1.13,1.13,0,0,1,4.45,52V32.13A1.13,1.13,0,0,1,5.57,31H57.85A1.14,1.14,0,0,1,59,32.13V52A1.14,1.14,0,0,1,57.85,53.08ZM6.7,50.82h50V33.25H6.7Z" style="fill:#787878"/><path d="M37.64,13C31.51,29,20.71,31.9,7.06,31.9c-.5,0-1,0-1.49,0V51.93l1.12,0c27.12,0,45.61-14.2,49.65-31.12Z" style="fill:#a7d28c"/><path d="M6.69,53.08l-.75,0H5.56a1.13,1.13,0,0,1-1.11-1.13V31.87a1.15,1.15,0,0,1,.34-.82,1.14,1.14,0,0,1,.83-.31c.48,0,1,0,1.44,0,13.92,0,23.71-3,29.53-18.16A1.14,1.14,0,0,1,37.2,12a1.12,1.12,0,0,1,.88,0l18.7,7.8a1.14,1.14,0,0,1,.66,1.31C53.64,37,36.47,53.08,6.69,53.08Zm0-20V50.82C34.66,50.82,51,36.24,55,21.5l-16.74-7C31.94,29.84,21.2,33,7.06,33Z" style="fill:#6f6f59"/><path d="M51.18,32.13H5.57v19.8l1.12,0C27.45,52,43.15,43.62,51.18,32.13Z" style="fill:#b4cda3"/><path d="M6.69,53.08l-.75,0H5.56a1.13,1.13,0,0,1-1.11-1.13V32.13A1.13,1.13,0,0,1,5.57,31H51.18a1.13,1.13,0,0,1,.93,1.77C43.22,45.49,26.24,53.08,6.69,53.08Zm0-19.83V50.82c17.88,0,33.47-6.53,42.24-17.57Z" style="fill:#a8c396"/><path d="M6.69,53.08l-.75,0H5.56a1.13,1.13,0,0,1-1.11-1.13V31.87a1.15,1.15,0,0,1,.34-.82,1.14,1.14,0,0,1,.83-.31c.48,0,1,0,1.44,0,13.92,0,23.71-3,29.53-18.16A1.14,1.14,0,0,1,37.2,12a1.12,1.12,0,0,1,.88,0l18.7,7.8a1.14,1.14,0,0,1,.66,1.31C53.64,37,36.47,53.08,6.69,53.08Zm0-20V50.82C34.66,50.82,51,36.24,55,21.5l-16.74-7C31.94,29.84,21.2,33,7.06,33Z" style="fill:#6f6f59"/></svg>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64"><path d="M5.28,23.64V50.13l20-13.23Z" style="fill:#a7d28c;stroke:#6f6f59;stroke-linecap:round;stroke-linejoin:round;stroke-width:2.2536px"/><path d="M57.51,50.13V23.64l-20,13.24Z" style="fill:#a7d28c;stroke:#6f6f59;stroke-linecap:round;stroke-linejoin:round;stroke-width:2.2536px"/><line x1="31.46" y1="60.3" x2="31.46" y2="55.9" style="fill:none;stroke:#6f6f59;stroke-linecap:round;stroke-linejoin:round;stroke-width:2.2536px"/><line x1="31.46" y1="49.68" x2="31.46" y2="45.28" style="fill:none;stroke:#6f6f59;stroke-linecap:round;stroke-linejoin:round;stroke-width:2.2536px"/><line x1="31.46" y1="28.44" x2="31.46" y2="24.04" style="fill:none;stroke:#6f6f59;stroke-linecap:round;stroke-linejoin:round;stroke-width:2.2536px"/><line x1="31.46" y1="17.82" x2="31.46" y2="13.42" style="fill:none;stroke:#6f6f59;stroke-linecap:round;stroke-linejoin:round;stroke-width:2.2536px"/><line x1="31.46" y1="39.06" x2="31.46" y2="34.66" style="fill:none;stroke:#6f6f59;stroke-linecap:round;stroke-linejoin:round;stroke-width:2.2536px"/><path d="M53.54,17.8l-.23,0-9.16-1.86a1.12,1.12,0,0,1-.85-.76,1.13,1.13,0,0,1,.25-1.11l1.94-1.94A25.63,25.63,0,0,0,13.3,15.45a2.16,2.16,0,0,1-1.52.63,2.16,2.16,0,0,1-1.53-3.68A30,30,0,0,1,48.59,9l2.3-2.29a1.09,1.09,0,0,1,.79-.33,1.24,1.24,0,0,1,.33,0,1.12,1.12,0,0,1,.78.86l1.85,9.17a1.11,1.11,0,0,1-.31,1A1.13,1.13,0,0,1,53.54,17.8Z" style="fill:#47b1d8"/><path d="M31.46,4.73a28.66,28.66,0,0,1,17.25,5.75l3-3,1.86,9.17-9.17-1.86L47.24,12a26.75,26.75,0,0,0-34.73,2.7,1,1,0,0,1-1.46,0,1,1,0,0,1,0-1.45A28.69,28.69,0,0,1,31.46,4.73m0-2.25a30.93,30.93,0,0,0-22,9.12,3.28,3.28,0,0,0,4.64,4.65,24.46,24.46,0,0,1,29.58-3.93l-.9.9a2.27,2.27,0,0,0-.57,2.24A2.24,2.24,0,0,0,43.92,17l9.17,1.86a2.2,2.2,0,0,0,2-.61,2.27,2.27,0,0,0,.61-2L53.89,7.06a2.23,2.23,0,0,0-1.56-1.71,2.05,2.05,0,0,0-.65-.1,2.24,2.24,0,0,0-1.59.66L48.45,7.55a30.77,30.77,0,0,0-17-5.07Z" style="fill:#6f6f59"/></svg>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64"><title>SVG_Artboards</title><path d="M33.23,33.65a1.13,1.13,0,0,1-1.13-1.13V4.64a1.13,1.13,0,0,1,2.25,0V32.52A1.13,1.13,0,0,1,33.23,33.65Z" style="fill:#6f6f59"/><path d="M58.75,46.24a1.07,1.07,0,0,1-.51-.13L34.11,33.75,5.64,44.56a1.12,1.12,0,1,1-.8-2.1l28.94-11a1.11,1.11,0,0,1,.91.05L59.27,44.11a1.13,1.13,0,0,1,.49,1.51A1.14,1.14,0,0,1,58.75,46.24Z" style="fill:#6f6f59"/><polygon points="37.68 29.53 30.72 24.71 30.72 12.81 37.68 16.39 37.68 29.53" style="fill:#719943"/><polygon points="23.46 11.81 13.08 14.31 13.38 32.6 23.44 29.19 23.46 11.81" style="fill:#a7d28c"/><polygon points="6.62 28.21 13.38 32.45 13.38 15.45 6.62 11.66 6.62 28.21" style="fill:#719943"/><polygon points="17.66 8.59 23.46 11.81 13.54 14.42 6.43 11.26 17.66 8.59" style="fill:#5b8036"/><path d="M26.65,62a1.12,1.12,0,0,1-.71-.25L4.53,44.38a1.12,1.12,0,0,1-.41-.87V10.06a1.13,1.13,0,0,1,.54-1,1.15,1.15,0,0,1,1.11,0l21.4,11.21a1.12,1.12,0,0,1,.61,1V60.88a1.14,1.14,0,0,1-.64,1A1.19,1.19,0,0,1,26.65,62ZM6.37,43,25.53,58.51V22l-19.16-10Z" style="fill:#6f6f59"/><path d="M13.26,33.68,5.49,29.13V9.86L17.36,7.41,24.59,11l0,18.89ZM7.74,27.84l5.77,3.37,8.8-3,0-15.87L17.06,9.77,7.74,11.69Z" style="fill:#6f6f59"/><polygon points="44.42 46.43 44.42 25.58 38.58 26.98 38.58 42.54 44.42 46.43" style="fill:#719943"/><polygon points="44.43 46.43 58.76 39.66 58.76 11.66 37.68 17.03 37.68 29.16 44.43 26.56 44.43 46.43" style="fill:#a7d28c"/><polygon points="48.15 8.16 30.48 12.81 37.49 17.14 58.76 11.66 48.15 8.16" style="fill:#5b8036"/><path d="M26.65,62a1.06,1.06,0,0,1-.59-.17,1.11,1.11,0,0,1-.53-.95V21.27a1.13,1.13,0,0,1,.8-1.08l32.1-9.61a1.12,1.12,0,0,1,1.45,1.08V45.11a1.12,1.12,0,0,1-.63,1L27.15,61.89A1.1,1.1,0,0,1,26.65,62Zm1.13-39.89v37L57.63,44.41V13.17Zm31,23h0Z" style="fill:#6f6f59"/><path d="M44.16,47.73l-6.7-4.91V31.42l-.13,0L29.6,26.11V11.94L48.18,7l11.7,3.86V40.37Zm-4.45-6,4.7,3.44,13.22-6.18V12.47L48.11,9.33,31.85,13.67V24.93l5.85,4,2-.66Z" style="fill:#6f6f59"/><path d="M26.65,22.4a1.06,1.06,0,0,1-.52-.13L4.72,11.05a1.1,1.1,0,0,1-.59-1.13A1.13,1.13,0,0,1,5,9L33.46,2.29a1.06,1.06,0,0,1,.61,0l25,8.27a1.13,1.13,0,0,1,0,2.15L27,22.35A1.26,1.26,0,0,1,26.65,22.4ZM8.45,10.46l18.32,9.6L55,11.61l-21.34-7Z" style="fill:#6f6f59"/></svg>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64"><title>SVG_Artboards</title><rect x="10.56" y="27.68" width="28.2" height="28.2" style="fill:#a7d28c"/><path d="M38.77,57H10.56a1.12,1.12,0,0,1-1.12-1.13V27.68a1.13,1.13,0,0,1,1.12-1.13H38.77a1.14,1.14,0,0,1,1.13,1.13v28.2A1.13,1.13,0,0,1,38.77,57ZM11.69,54.76h26V28.81H11.69Z" style="fill:#6f6f59"/><polygon points="53.44 8.12 30.12 8.12 10.56 27.68 38.77 27.68 53.44 8.12" style="fill:#ffc418"/><path d="M39.33,28.81H7.84L29.65,7h26Zm-26-2.26H38.2l13-17.31H30.59Z" style="fill:#6f6f59"/><polygon points="38.77 55.88 53.44 31.44 53.44 8.12 38.77 27.68 38.77 55.88" style="fill:#ffc418"/><path d="M37.64,60V27.3L54.56,4.74v27ZM39.9,28.06V51.82L52.31,31.13V11.5Z" style="fill:#6f6f59"/><circle cx="53.44" cy="8.12" r="4.38" style="fill:#6f6f59"/><circle cx="53.44" cy="32.97" r="4.38" style="fill:#6f6f59"/><rect x="11.66" y="28.78" width="26.01" height="26.01" style="fill:#ffc418"/><circle cx="30.4" cy="8.12" r="4.38" style="fill:#6f6f59"/><circle cx="10.56" cy="27.68" r="4.38" style="fill:#6f6f59"/><circle cx="10.56" cy="55.88" r="4.38" style="fill:#6f6f59"/><circle cx="38.96" cy="27.68" r="4.38" style="fill:#6f6f59"/><circle cx="38.96" cy="55.88" r="4.38" style="fill:#6f6f59"/></svg>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64"><rect x="28.11" y="8.69" width="4.53" height="51.66" transform="translate(33.31 -11.37) rotate(45)" style="fill:#6f6f59"/><polygon points="42.09 9.88 55.02 22.81 60.1 4.87 42.09 9.88" style="fill:#a7d28c"/><path d="M55,23.94a1.17,1.17,0,0,1-.8-.33L41.29,10.67a1.13,1.13,0,0,1,.5-1.88l18-5a1.13,1.13,0,0,1,1.39,1.39L56.1,23.12a1.11,1.11,0,0,1-.8.78A.86.86,0,0,1,55,23.94ZM44.25,10.45,54.46,20.66l4-14.16Z" style="fill:#6f6f59"/><polygon points="24.18 53.65 11.25 40.72 6.17 58.65 24.18 53.65" style="fill:#a7d28c"/><path d="M6.17,59.78a1.15,1.15,0,0,1-.8-.33,1.11,1.11,0,0,1-.28-1.11l5.08-17.93a1.12,1.12,0,0,1,1.88-.49L25,52.85a1.15,1.15,0,0,1,.29,1.09,1.11,1.11,0,0,1-.79.79l-18,5A1,1,0,0,1,6.17,59.78Zm5.64-16.91L7.8,57l14.22-4Z" style="fill:#6f6f59"/><rect x="28.11" y="3.18" width="4.53" height="51.66" transform="translate(72.36 28.03) rotate(135)" style="fill:#6f6f59"/><polygon points="55.02 40.72 42.09 53.65 60.03 58.73 55.02 40.72" style="fill:#a7d28c"/><path d="M60,59.86a1.06,1.06,0,0,1-.31,0L41.78,54.73a1.13,1.13,0,0,1-.49-1.88L54.22,39.92a1.15,1.15,0,0,1,1.09-.29,1.13,1.13,0,0,1,.8.78l5,18A1.13,1.13,0,0,1,60,59.86ZM44.24,53.09l14.16,4L54.45,42.88Z" style="fill:#6f6f59"/><polygon points="11.25 22.81 24.18 9.88 6.25 4.8 11.25 22.81" style="fill:#a7d28c"/><path d="M11.25,23.94a1.35,1.35,0,0,1-.28,0,1.1,1.1,0,0,1-.8-.79l-5-18A1.13,1.13,0,0,1,6.55,3.71L24.49,8.79a1.12,1.12,0,0,1,.78.8A1.15,1.15,0,0,1,25,10.68L12.05,23.61A1.15,1.15,0,0,1,11.25,23.94ZM7.87,6.43l4,14.22L22,10.44Z" style="fill:#6f6f59"/></svg>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64"><g transform="scale(-1,1) translate(-64,0)"><path d="M24.57,18.2l-9.31-14L5.93,18.2h5V39.46h8.74V18.2Z" style="fill:#a7d28c"/><path d="M19.62,40.58H10.88a1.12,1.12,0,0,1-1.12-1.12V19.33H5.93a1.13,1.13,0,0,1-1-.6A1.11,1.11,0,0,1,5,17.58l9.32-14a1.14,1.14,0,0,1,.94-.5h0a1.15,1.15,0,0,1,.94.5l9.31,14.05a1.13,1.13,0,0,1-.94,1.75H20.75V39.46A1.13,1.13,0,0,1,19.62,40.58ZM12,38.33h6.48V18.2a1.14,1.14,0,0,1,1.13-1.13h2.85L15.26,6.19,8,17.07h2.85A1.14,1.14,0,0,1,12,18.2Z" style="fill:#6f6f59"/><path d="M45.82,58.79l14-9.31-14-9.32V45.1H24.57v8.74H45.82Z" style="fill:#de4130"/><path d="M45.82,59.91a1.13,1.13,0,0,1-1.13-1.12V55H24.57a1.13,1.13,0,0,1-1.13-1.13V45.1A1.12,1.12,0,0,1,24.57,44H44.69V40.16a1.12,1.12,0,0,1,1.75-.94l14.05,9.32a1.11,1.11,0,0,1,.5.94,1.12,1.12,0,0,1-.5.94L46.44,59.73A1.12,1.12,0,0,1,45.82,59.91Zm-20.13-7.2H45.82A1.14,1.14,0,0,1,47,53.84v2.85l10.88-7.21L47,42.26V45.1a1.13,1.13,0,0,1-1.13,1.13H25.69Z" style="fill:#6f6f59"/><rect x="5.93" y="39.46" width="18.46" height="18.46" style="fill:#2896d3"/><path d="M24.39,59.05H5.93A1.14,1.14,0,0,1,4.8,57.92V39.46a1.13,1.13,0,0,1,1.13-1.13H24.39a1.13,1.13,0,0,1,1.13,1.13V57.92A1.14,1.14,0,0,1,24.39,59.05ZM7.06,56.79H23.27V40.58H7.06Z" style="fill:#6f6f59"/></g><g transform="scale(0.9) translate(-15,10)"><path d="M27.88,19l3.47-6.55h4.31L30.18,21.6,36,30.92H31.5l-3.57-6.66-3.57,6.66H20l5.63-9.32-5.49-9.16h4.3Z" style="fill:#787878"/></g><g transform="scale(0.9) translate(-17,-10)"><path d="M50,21h.07l4-8.52H58.2l-6.33,12v6.5H48.16V24.23L41.93,12.44H46Z" style="fill:#787878"/></g></svg>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64"><path d="M24.57,18.2l-9.31-14L5.93,18.2h5V39.46h8.74V18.2Z" style="fill:#2896d3"/><path d="M19.62,40.58H10.88a1.12,1.12,0,0,1-1.12-1.12V19.33H5.93a1.13,1.13,0,0,1-1-.6A1.11,1.11,0,0,1,5,17.58l9.32-14a1.14,1.14,0,0,1,.94-.5h0a1.15,1.15,0,0,1,.94.5l9.31,14.05a1.13,1.13,0,0,1-.94,1.75H20.75V39.46A1.13,1.13,0,0,1,19.62,40.58ZM12,38.33h6.48V18.2a1.14,1.14,0,0,1,1.13-1.13h2.85L15.26,6.19,8,17.07h2.85A1.14,1.14,0,0,1,12,18.2Z" style="fill:#6f6f59"/><path d="M45.82,58.79l14-9.31-14-9.32V45.1H24.57v8.74H45.82Z" style="fill:#de4130"/><path d="M45.82,59.91a1.13,1.13,0,0,1-1.13-1.12V55H24.57a1.13,1.13,0,0,1-1.13-1.13V45.1A1.12,1.12,0,0,1,24.57,44H44.69V40.16a1.12,1.12,0,0,1,1.75-.94l14.05,9.32a1.11,1.11,0,0,1,.5.94,1.12,1.12,0,0,1-.5.94L46.44,59.73A1.12,1.12,0,0,1,45.82,59.91Zm-20.13-7.2H45.82A1.14,1.14,0,0,1,47,53.84v2.85l10.88-7.21L47,42.26V45.1a1.13,1.13,0,0,1-1.13,1.13H25.69Z" style="fill:#6f6f59"/><rect x="5.93" y="39.46" width="18.46" height="18.46" style="fill:#a7d28c"/><path d="M24.39,59.05H5.93A1.14,1.14,0,0,1,4.8,57.92V39.46a1.13,1.13,0,0,1,1.13-1.13H24.39a1.13,1.13,0,0,1,1.13,1.13V57.92A1.14,1.14,0,0,1,24.39,59.05ZM7.06,56.79H23.27V40.58H7.06Z" style="fill:#6f6f59"/><g transform="scale(0.9) translate(30,10)"><path d="M27.88,19l3.47-6.55h4.31L30.18,21.6,36,30.92H31.5l-3.57-6.66-3.57,6.66H20l5.63-9.32-5.49-9.16h4.3Z" style="fill:#787878"/></g><g transform="scale(0.9) translate(11,-10)"><path d="M24.69,28.08h8.48v2.84H20.32V29L28.55,15.3H20.34V12.44H33v1.85Z" style="fill:#787878"/></g></svg>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64"><path d="M24.57,18.2l-9.31-14L5.93,18.2h5V39.46h8.74V18.2Z" style="fill:#a7d28c"/><path d="M19.62,40.58H10.88a1.12,1.12,0,0,1-1.12-1.12V19.33H5.93a1.13,1.13,0,0,1-1-.6A1.11,1.11,0,0,1,5,17.58l9.32-14a1.14,1.14,0,0,1,.94-.5h0a1.15,1.15,0,0,1,.94.5l9.31,14.05a1.13,1.13,0,0,1-.94,1.75H20.75V39.46A1.13,1.13,0,0,1,19.62,40.58ZM12,38.33h6.48V18.2a1.14,1.14,0,0,1,1.13-1.13h2.85L15.26,6.19,8,17.07h2.85A1.14,1.14,0,0,1,12,18.2Z" style="fill:#6f6f59"/><path d="M45.82,58.79l14-9.31-14-9.32V45.1H24.57v8.74H45.82Z" style="fill:#de4130"/><path d="M45.82,59.91a1.13,1.13,0,0,1-1.13-1.12V55H24.57a1.13,1.13,0,0,1-1.13-1.13V45.1A1.12,1.12,0,0,1,24.57,44H44.69V40.16a1.12,1.12,0,0,1,1.75-.94l14.05,9.32a1.11,1.11,0,0,1,.5.94,1.12,1.12,0,0,1-.5.94L46.44,59.73A1.12,1.12,0,0,1,45.82,59.91Zm-20.13-7.2H45.82A1.14,1.14,0,0,1,47,53.84v2.85l10.88-7.21L47,42.26V45.1a1.13,1.13,0,0,1-1.13,1.13H25.69Z" style="fill:#6f6f59"/><rect x="5.93" y="39.46" width="18.46" height="18.46" style="fill:#2896d3"/><path d="M24.39,59.05H5.93A1.14,1.14,0,0,1,4.8,57.92V39.46a1.13,1.13,0,0,1,1.13-1.13H24.39a1.13,1.13,0,0,1,1.13,1.13V57.92A1.14,1.14,0,0,1,24.39,59.05ZM7.06,56.79H23.27V40.58H7.06Z" style="fill:#6f6f59"/><g transform="scale(0.9) translate(30,10)"><path d="M27.88,19l3.47-6.55h4.31L30.18,21.6,36,30.92H31.5l-3.57-6.66-3.57,6.66H20l5.63-9.32-5.49-9.16h4.3Z" style="fill:#787878"/></g><g transform="scale(0.9) translate(-12,-10)"><path d="M50,21h.07l4-8.52H58.2l-6.33,12v6.5H48.16V24.23L41.93,12.44H46Z" style="fill:#787878"/></g></svg>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?><svg id="a" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64"><g transform="translate(0,4)"><g><path d="M41.66,17.69L32.35,3.65l-9.32,14.05h4.95v21.26h8.74V17.69h4.95Z" style="fill:#a7d28c"/><path d="M36.71,40.07h-8.74c-.62,0-1.13-.5-1.13-1.13V18.82h-3.82c-.42,0-.8-.23-.99-.59-.2-.37-.17-.81,.05-1.16L31.41,3.02c.21-.31,.56-.5,.94-.5h0c.38,0,.73,.19,.94,.5l9.31,14.05c.23,.35,.25,.79,.05,1.16-.2,.37-.58,.59-.99,.59h-3.82v20.13c0,.62-.5,1.13-1.13,1.13Zm-7.61-2.25h6.48V17.69c0-.62,.5-1.13,1.13-1.13h2.85l-7.21-10.88-7.22,10.88h2.85c.62,0,1.13,.5,1.13,1.13v20.13Z" style="fill:#6f6f59"/></g><g><path d="M19.19,56.34l-16.8-1.29,7.73-14.98,2.41,4.32,18.57-10.35,4.25,7.63-18.57,10.35,2.41,4.32Z" style="fill:#2896d3"/><path d="M19.19,57.47s-.06,0-.09,0l-16.8-1.29c-.38-.03-.71-.24-.9-.57-.18-.33-.19-.73-.02-1.07l7.73-14.98c.19-.37,.57-.6,.98-.61,.46-.02,.8,.21,1,.58l1.86,3.34,17.58-9.8c.54-.3,1.23-.11,1.53,.44l4.25,7.63c.15,.26,.18,.57,.1,.86-.08,.29-.27,.53-.54,.68l-17.58,9.8c1.71,3.07,1.85,3.31,1.86,3.33,.2,.36,.19,.81-.03,1.16-.21,.33-.57,.52-.95,.52Zm-15.02-3.41l13.01,1c-.34-.61-.79-1.42-1.39-2.49-.3-.54-.11-1.23,.44-1.53l17.58-9.8-3.16-5.66-17.58,9.8c-.26,.14-.57,.18-.86,.1-.29-.08-.53-.27-.68-.54l-1.39-2.49-5.99,11.6Z" style="fill:#6f6f59"/></g><g><path d="M45.02,56.34l16.8-1.29-7.73-14.98-2.41,4.32-18.57-10.35-4.25,7.63,18.57,10.35-2.41,4.32Z" style="fill:#de4130"/><path d="M45.02,57.47c-.38,0-.74-.19-.95-.52-.22-.35-.24-.79-.03-1.16l1.86-3.34-17.58-9.8c-.54-.3-.74-.99-.44-1.53l4.25-7.63c.15-.26,.39-.45,.68-.54,.29-.08,.59-.05,.86,.1l17.58,9.8,1.86-3.34c.2-.36,.59-.59,1-.58,.42,0,.79,.24,.98,.61l7.73,14.98c.17,.34,.17,.74-.02,1.07-.18,.33-.52,.55-.9,.57l-16.8,1.29s-.06,0-.09,0Zm-14.62-16.23l17.58,9.8c.26,.15,.45,.39,.54,.68,.08,.29,.05,.6-.1,.86-.6,1.07-1.05,1.88-1.39,2.49l13.01-1-5.99-11.6-1.39,2.49c-.15,.26-.39,.45-.68,.54-.29,.08-.59,.04-.86-.1l-17.58-9.8-3.16,5.66Z" style="fill:#6f6f59"/></g><g><polygon points="31.88 49.86 21.33 42.7 21.33 29.76 31.88 36.92 31.88 49.86" style="fill:#2896d3"/><path d="M31.88,50.99c-.22,0-.44-.07-.63-.19l-10.55-7.16c-.31-.21-.49-.56-.49-.93v-12.93c0-.42,.23-.8,.6-1,.37-.19,.82-.17,1.16,.06l10.55,7.16c.31,.21,.49,.56,.49,.93v12.93c0,.42-.23,.8-.6,1-.17,.09-.35,.13-.53,.13Zm-9.42-8.89l8.29,5.63v-10.21l-8.29-5.63v10.21Z" style="fill:#6f6f59"/></g><g><polygon points="32.12 49.86 42.67 42.7 42.67 29.76 32.12 36.92 32.12 49.86" style="fill:#de4130"/><path d="M32.12,50.99c-.18,0-.36-.04-.53-.13-.37-.2-.6-.58-.6-1v-12.93c0-.37,.19-.72,.49-.93l10.55-7.16c.35-.23,.79-.26,1.16-.06,.37,.2,.6,.58,.6,1v12.93c0,.37-.19,.72-.49,.93l-10.55,7.16c-.19,.13-.41,.19-.63,.19Zm1.13-13.46v10.21l8.29-5.63v-10.21l-8.29,5.63Z" style="fill:#6f6f59"/></g><g><polygon points="42.27 29.52 31.99 36.61 21.56 29.52 32.02 24.02 42.27 29.52" style="fill:#a7d28c"/><path d="M31.99,37.74c-.22,0-.44-.07-.63-.2l-10.43-7.09c-.33-.22-.51-.6-.49-1,.02-.4,.25-.75,.6-.93l10.47-5.5c.33-.17,.73-.17,1.06,0l10.24,5.5c.35,.19,.57,.54,.59,.93,.02,.39-.16,.77-.49,.99l-10.28,7.09c-.19,.13-.42,.2-.64,.2Zm-8.24-8.09l8.24,5.6,8.13-5.6-8.09-4.35-8.27,4.35Z" style="fill:#6f6f59"/></g></g><g transform="scale(0.8) translate(42,20)"><path d="M27.88,19l3.47-6.55h4.31L30.18,21.6,36,30.92H31.5l-3.57-6.66-3.57,6.66H20l5.63-9.32-5.49-9.16h4.3Z" style="fill:#787878"/></g><g transform="scale(0.8) translate(6,-11)"><path d="M50,21h.07l4-8.52H58.2l-6.33,12v6.5H48.16V24.23L41.93,12.44H46Z" style="fill:#787878"/></g><g transform="scale(0.8) translate(-19,20)"><path d="M24.69,28.08h8.48v2.84H20.32V29L28.55,15.3H20.34V12.44H33v1.85Z" style="fill:#787878"/></g></svg>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64"><path d="M24.57,18.2l-9.31-14L5.93,18.2h5V39.46h8.74V18.2Z" style="fill:#a7d28c"/><path d="M19.62,40.58H10.88a1.12,1.12,0,0,1-1.12-1.12V19.33H5.93a1.13,1.13,0,0,1-1-.6A1.11,1.11,0,0,1,5,17.58l9.32-14a1.14,1.14,0,0,1,.94-.5h0a1.15,1.15,0,0,1,.94.5l9.31,14.05a1.13,1.13,0,0,1-.94,1.75H20.75V39.46A1.13,1.13,0,0,1,19.62,40.58ZM12,38.33h6.48V18.2a1.14,1.14,0,0,1,1.13-1.13h2.85L15.26,6.19,8,17.07h2.85A1.14,1.14,0,0,1,12,18.2Z" style="fill:#6f6f59"/><path d="M45.82,58.79l14-9.31-14-9.32V45.1H24.57v8.74H45.82Z" style="fill:#2896d3"/><path d="M45.82,59.91a1.13,1.13,0,0,1-1.13-1.12V55H24.57a1.13,1.13,0,0,1-1.13-1.13V45.1A1.12,1.12,0,0,1,24.57,44H44.69V40.16a1.12,1.12,0,0,1,1.75-.94l14.05,9.32a1.11,1.11,0,0,1,.5.94,1.12,1.12,0,0,1-.5.94L46.44,59.73A1.12,1.12,0,0,1,45.82,59.91Zm-20.13-7.2H45.82A1.14,1.14,0,0,1,47,53.84v2.85l10.88-7.21L47,42.26V45.1a1.13,1.13,0,0,1-1.13,1.13H25.69Z" style="fill:#6f6f59"/><rect x="5.93" y="39.46" width="18.46" height="18.46" style="fill:#de4130"/><path d="M24.39,59.05H5.93A1.14,1.14,0,0,1,4.8,57.92V39.46a1.13,1.13,0,0,1,1.13-1.13H24.39a1.13,1.13,0,0,1,1.13,1.13V57.92A1.14,1.14,0,0,1,24.39,59.05ZM7.06,56.79H23.27V40.58H7.06Z" style="fill:#6f6f59"/><g transform="scale(0.9) translate(-12,-10)"><path d="M50,21h.07l4-8.52H58.2l-6.33,12v6.5H48.16V24.23L41.93,12.44H46Z" style="fill:#787878"/></g><g transform="scale(0.9) translate(31,10)"><path d="M24.69,28.08h8.48v2.84H20.32V29L28.55,15.3H20.34V12.44H33v1.85Z" style="fill:#787878"/></g></svg>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64"><g transform="scale(-1,1) translate(-64,0)"><path d="M24.57,18.2l-9.31-14L5.93,18.2h5V39.46h8.74V18.2Z" style="fill:#a7d28c"/><path d="M19.62,40.58H10.88a1.12,1.12,0,0,1-1.12-1.12V19.33H5.93a1.13,1.13,0,0,1-1-.6A1.11,1.11,0,0,1,5,17.58l9.32-14a1.14,1.14,0,0,1,.94-.5h0a1.15,1.15,0,0,1,.94.5l9.31,14.05a1.13,1.13,0,0,1-.94,1.75H20.75V39.46A1.13,1.13,0,0,1,19.62,40.58ZM12,38.33h6.48V18.2a1.14,1.14,0,0,1,1.13-1.13h2.85L15.26,6.19,8,17.07h2.85A1.14,1.14,0,0,1,12,18.2Z" style="fill:#6f6f59"/><path d="M45.82,58.79l14-9.31-14-9.32V45.1H24.57v8.74H45.82Z" style="fill:#2896d3"/><path d="M45.82,59.91a1.13,1.13,0,0,1-1.13-1.12V55H24.57a1.13,1.13,0,0,1-1.13-1.13V45.1A1.12,1.12,0,0,1,24.57,44H44.69V40.16a1.12,1.12,0,0,1,1.75-.94l14.05,9.32a1.11,1.11,0,0,1,.5.94,1.12,1.12,0,0,1-.5.94L46.44,59.73A1.12,1.12,0,0,1,45.82,59.91Zm-20.13-7.2H45.82A1.14,1.14,0,0,1,47,53.84v2.85l10.88-7.21L47,42.26V45.1a1.13,1.13,0,0,1-1.13,1.13H25.69Z" style="fill:#6f6f59"/><rect x="5.93" y="39.46" width="18.46" height="18.46" style="fill:#de4130"/><path d="M24.39,59.05H5.93A1.14,1.14,0,0,1,4.8,57.92V39.46a1.13,1.13,0,0,1,1.13-1.13H24.39a1.13,1.13,0,0,1,1.13,1.13V57.92A1.14,1.14,0,0,1,24.39,59.05ZM7.06,56.79H23.27V40.58H7.06Z" style="fill:#6f6f59"/></g><g transform="scale(0.9) translate(-17,-10)"><path d="M50,21h.07l4-8.52H58.2l-6.33,12v6.5H48.16V24.23L41.93,12.44H46Z" style="fill:#787878"/></g><g transform="scale(0.9) translate(-14,10)"><path d="M24.69,28.08h8.48v2.84H20.32V29L28.55,15.3H20.34V12.44H33v1.85Z" style="fill:#787878"/></g></svg>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64"><path d="M10.84,54.67H4.09V52.09h6.75Z" style="fill:#787878"/><path d="M18.74,58.18a2.56,2.56,0,0,0,2-.93,4,4,0,0,0,.79-2.61V53.57a3.72,3.72,0,0,1-3,1.45,4.59,4.59,0,0,1-3.65-1.51,6.05,6.05,0,0,1-1.33-4.12,5.8,5.8,0,0,1,1.57-4.15,5.31,5.31,0,0,1,4-1.65,5.38,5.38,0,0,1,4.12,1.69A6.61,6.61,0,0,1,24.89,50v4.49a5.89,5.89,0,0,1-6.15,6.28A8.59,8.59,0,0,1,17,60.56,9.29,9.29,0,0,1,15.21,60l.56-2.42a8.14,8.14,0,0,0,1.41.44A8.19,8.19,0,0,0,18.74,58.18Zm.4-5.61a3,3,0,0,0,1.43-.33,2.77,2.77,0,0,0,1-.9v-2a3.94,3.94,0,0,0-.64-2.4,2.09,2.09,0,0,0-1.72-.83,1.86,1.86,0,0,0-1.63.94A4.08,4.08,0,0,0,17,49.39a4.25,4.25,0,0,0,.56,2.31A1.83,1.83,0,0,0,19.14,52.57Z" style="fill:#787878"/><path d="M38.51,54.47A6.54,6.54,0,0,1,37,59.08a5.29,5.29,0,0,1-4.08,1.67,5.34,5.34,0,0,1-4.11-1.67,6.5,6.5,0,0,1-1.55-4.61V49.88a6.55,6.55,0,0,1,1.54-4.61,5.29,5.29,0,0,1,4.1-1.68A5.3,5.3,0,0,1,37,45.27a6.51,6.51,0,0,1,1.55,4.61Zm-3.33-4.94a4.27,4.27,0,0,0-.61-2.48,2.08,2.08,0,0,0-3.41,0,4.35,4.35,0,0,0-.6,2.48v5.26a4.47,4.47,0,0,0,.61,2.52,2,2,0,0,0,1.72.87,1.93,1.93,0,0,0,1.69-.87,4.47,4.47,0,0,0,.6-2.52Z" style="fill:#787878"/><path d="M57.16,12.07a18.7,18.7,0,0,0-33.8,6.21h-5l7.8,10.22,7.76-10.23H28.8a13.49,13.49,0,1,1,8.68,17v5.41A18.71,18.71,0,0,0,57.16,12.07Z" style="fill:#a7d28c"/><path d="M41.68,42.31a19.85,19.85,0,0,1-4.45-.5,1.12,1.12,0,0,1-.88-1.09V35.31a1.13,1.13,0,0,1,1.47-1.07,12.36,12.36,0,1,0-3.09-22.05,12,12,0,0,0-4.27,5h3.47a1.13,1.13,0,0,1,.9,1.81L27.06,29.18a1.11,1.11,0,0,1-.89.44h0a1.11,1.11,0,0,1-.9-.44L17.48,19a1.12,1.12,0,0,1-.12-1.18,1.14,1.14,0,0,1,1-.63h4.11A19.84,19.84,0,0,1,58.1,11.44h0A19.84,19.84,0,0,1,52.63,39,19.59,19.59,0,0,1,41.68,42.31Zm-3.07-2.52a17.58,17.58,0,0,0,17.62-27.1h0a17.59,17.59,0,0,0-31.77,5.84,1.12,1.12,0,0,1-1.1.87H20.65l5.51,7.24,5.5-7.24H28.8a1.13,1.13,0,0,1-1.07-1.48,14.48,14.48,0,0,1,5.74-7.61A14.62,14.62,0,1,1,49.72,34.62a14.48,14.48,0,0,1-11.11,2.15Z" style="fill:#6f6f59"/></svg>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64"><path d="M7.12,12.07a18.71,18.71,0,0,1,33.81,6.21h5L38.12,28.5,30.35,18.27h5.14a13.49,13.49,0,1,0-8.68,17v5.41A18.71,18.71,0,0,1,7.12,12.07Z" style="fill:#a7d28c"/><path d="M22.61,42.31a19.84,19.84,0,0,1-19.39-16A19.84,19.84,0,0,1,41.8,17.15h4.12a1.15,1.15,0,0,1,1,.63A1.12,1.12,0,0,1,46.81,19L39,29.18a1.14,1.14,0,0,1-.9.44h0a1.14,1.14,0,0,1-.9-.44L29.46,19a1.1,1.1,0,0,1-.11-1.18,1.11,1.11,0,0,1,1-.63h3.48a12.16,12.16,0,0,0-4.27-5,12.36,12.36,0,1,0-3.1,22.05,1.12,1.12,0,0,1,1.47,1.07v5.41a1.11,1.11,0,0,1-.87,1.09A20,20,0,0,1,22.61,42.31Zm.11-37.44A17.62,17.62,0,0,0,8.06,12.69h0A17.6,17.6,0,0,0,12.91,37.1a17.38,17.38,0,0,0,12.77,2.69v-3A14.63,14.63,0,1,1,36.56,17.92a1.13,1.13,0,0,1-.16,1,1.11,1.11,0,0,1-.91.47H32.63l5.49,7.24,5.52-7.24H40.92a1.12,1.12,0,0,1-1.09-.87A17.58,17.58,0,0,0,22.72,4.87Zm-15.6,7.2h0Z" style="fill:#6f6f59"/><path d="M29.64,51.16h4.1V54h-4.1v4.71H26.49V54H22.37V51.16h4.12V46.67h3.15Z" style="fill:#787878"/><path d="M40.52,58.1a2.53,2.53,0,0,0,2-.92,3.94,3.94,0,0,0,.78-2.6V53.51A3.58,3.58,0,0,1,42,54.59a3.65,3.65,0,0,1-1.64.37,4.56,4.56,0,0,1-3.63-1.51,6,6,0,0,1-1.32-4.09A5.71,5.71,0,0,1,37,45.23a5.25,5.25,0,0,1,4-1.65,5.38,5.38,0,0,1,4.09,1.69,6.59,6.59,0,0,1,1.58,4.67v4.47A6.07,6.07,0,0,1,44.91,59a6,6,0,0,1-4.39,1.69,8.49,8.49,0,0,1-1.78-.19A9.42,9.42,0,0,1,37,59.94l.56-2.41A7.27,7.27,0,0,0,39,58,8.08,8.08,0,0,0,40.52,58.1Zm.4-5.58a3,3,0,0,0,1.42-.33,2.63,2.63,0,0,0,1-.89V49.36A3.86,3.86,0,0,0,42.69,47,2,2,0,0,0,41,46.15a1.87,1.87,0,0,0-1.62.93,4,4,0,0,0-.62,2.28,4.17,4.17,0,0,0,.56,2.29A1.8,1.8,0,0,0,40.92,52.52Z" style="fill:#787878"/><path d="M60.19,54.41A6.5,6.5,0,0,1,58.66,59a5.26,5.26,0,0,1-4.06,1.67A5.32,5.32,0,0,1,50.5,59,6.5,6.5,0,0,1,49,54.41V49.84a6.53,6.53,0,0,1,1.53-4.58,5.78,5.78,0,0,1,8.15,0,6.49,6.49,0,0,1,1.54,4.58ZM56.88,49.5A4.33,4.33,0,0,0,56.27,47a2,2,0,0,0-1.7-.88,1.92,1.92,0,0,0-1.69.88,4.33,4.33,0,0,0-.6,2.47v5.23a4.29,4.29,0,0,0,.61,2.5,2,2,0,0,0,1.71.87,1.93,1.93,0,0,0,1.68-.87,4.38,4.38,0,0,0,.6-2.5Z" style="fill:#787878"/></svg>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64"><g transform="scale(1,-1) translate(0,-64)"><path d="M24.57,18.2l-9.31-14L5.93,18.2h5V39.46h8.74V18.2Z" style="fill:#2896d3"/><path d="M19.62,40.58H10.88a1.12,1.12,0,0,1-1.12-1.12V19.33H5.93a1.13,1.13,0,0,1-1-.6A1.11,1.11,0,0,1,5,17.58l9.32-14a1.14,1.14,0,0,1,.94-.5h0a1.15,1.15,0,0,1,.94.5l9.31,14.05a1.13,1.13,0,0,1-.94,1.75H20.75V39.46A1.13,1.13,0,0,1,19.62,40.58ZM12,38.33h6.48V18.2a1.14,1.14,0,0,1,1.13-1.13h2.85L15.26,6.19,8,17.07h2.85A1.14,1.14,0,0,1,12,18.2Z" style="fill:#6f6f59"/><path d="M45.82,58.79l14-9.31-14-9.32V45.1H24.57v8.74H45.82Z" style="fill:#de4130"/><path d="M45.82,59.91a1.13,1.13,0,0,1-1.13-1.12V55H24.57a1.13,1.13,0,0,1-1.13-1.13V45.1A1.12,1.12,0,0,1,24.57,44H44.69V40.16a1.12,1.12,0,0,1,1.75-.94l14.05,9.32a1.11,1.11,0,0,1,.5.94,1.12,1.12,0,0,1-.5.94L46.44,59.73A1.12,1.12,0,0,1,45.82,59.91Zm-20.13-7.2H45.82A1.14,1.14,0,0,1,47,53.84v2.85l10.88-7.21L47,42.26V45.1a1.13,1.13,0,0,1-1.13,1.13H25.69Z" style="fill:#6f6f59"/><rect x="5.93" y="39.46" width="18.46" height="18.46" style="fill:#a7d28c"/><path d="M24.39,59.05H5.93A1.14,1.14,0,0,1,4.8,57.92V39.46a1.13,1.13,0,0,1,1.13-1.13H24.39a1.13,1.13,0,0,1,1.13,1.13V57.92A1.14,1.14,0,0,1,24.39,59.05ZM7.06,56.79H23.27V40.58H7.06Z" style="fill:#6f6f59"/></g><g transform="scale(0.9) translate(30,18)"><path d="M27.88,19l3.47-6.55h4.31L30.18,21.6,36,30.92H31.5l-3.57-6.66-3.57,6.66H20l5.63-9.32-5.49-9.16h4.3Z" style="fill:#787878"/></g><g transform="scale(0.9) translate(11,38)"><path d="M24.69,28.08h8.48v2.84H20.32V29L28.55,15.3H20.34V12.44H33v1.85Z" style="fill:#787878"/></g></svg>
|