Skip to content

Commit

Permalink
Merge pull request #212 from specklesystems/dev
Browse files Browse the repository at this point in the history
Dev
  • Loading branch information
KatKatKateryna authored Sep 8, 2024
2 parents be57c43 + 2096140 commit bdc9d4a
Show file tree
Hide file tree
Showing 9 changed files with 534 additions and 462 deletions.
21 changes: 17 additions & 4 deletions poetry.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ readme = "README.md"
[tool.poetry.dependencies]
python = ">=3.9, <4.0"
numpy = "^1.25.2"
specklepy = "2.18.3"
specklepy = "2.19.3"
pyshp = "2.3.1"
requests = "2.31.0"
requests-toolbelt = "0.10.1"
Expand All @@ -18,6 +18,7 @@ shapely = "2.0.1"
geopandas = "0.13.2"
geovoronoi = "0.4.0"
scipy = "1.9.3"
earcut = "1.1.5"

[tool.poetry.group.dev.dependencies]
pytest = "^7.1.3"
Expand Down
152 changes: 130 additions & 22 deletions speckle/converter/features/feature_conversions.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
)
from speckle.converter.geometry.mesh import constructMeshFromRaster
from speckle.converter.geometry.utils import apply_pt_offsets_rotation_on_send
from speckle.converter.layers.symbology import get_a_r_g_b
from speckle.converter.layers.utils import (
generate_qgis_app_id,
getArrayIndicesFromXY,
Expand Down Expand Up @@ -117,11 +118,11 @@ def featureToSpeckle(
elif isinstance(g, GisPolygonGeometry):
if len(g.displayValue) == 0:
all_errors += (
"Polygon converted, but display mesh not generated"
"Polygon part converted, but display mesh not generated"
+ ", "
)
logToUser(
"Polygon converted, but display mesh not generated",
"Polygon part converted, but display mesh not generated",
level=1,
func=inspect.stack()[0][3],
)
Expand Down Expand Up @@ -307,12 +308,14 @@ def get_raster_colors(
plugin,
):
list_colors = []
have_transparent_cells = False
if rendererType == "multibandcolor":

# mock values for R,G,B channels
vals_red = [0 for _ in rasterBandVals[0]]
vals_green = [0 for _ in rasterBandVals[0]]
vals_blue = [0 for _ in rasterBandVals[0]]
vals_alpha = None

vals_range_red = 1
vals_range_green = 1
Expand All @@ -330,6 +333,7 @@ def get_raster_colors(
bandRed = int(layer.renderer().redBand())
bandGreen = int(layer.renderer().greenBand())
bandBlue = int(layer.renderer().blueBand())
bandAlpha = int(layer.renderer().alphaBand())

# assign correct values to R,G,B channels, where available
for band_index in range(len(rasterBandVals)):
Expand All @@ -355,19 +359,54 @@ def get_raster_colors(
)
val_min_blue = rasterBandMinVal[band_index]
val_na_blue = rasterBandNoDataVal[band_index]
if band_index + 1 == bandAlpha:
vals_range_alpha = (
rasterBandMaxVal[band_index] - rasterBandMinVal[band_index]
)
val_min_alpha = rasterBandMinVal[band_index]
val_na_alpha = rasterBandNoDataVal[band_index]
vals_alpha = rasterBandVals[band_index]

if vals_alpha is not None and 0 in vals_alpha:
have_transparent_cells = True

list_colors = [
(
(255 << 24)
| (int(255 * (vals_red[ind] - val_min_red) / vals_range_red) << 16)
| (int(255 * (vals_green[ind] - val_min_green) / vals_range_green) << 8)
| int(255 * (vals_blue[ind] - val_min_blue) / vals_range_blue)
(
(
255 << 24
if vals_alpha is None or vals_range_alpha == 0
else int(
255 * (vals_alpha[ind] - val_min_alpha) / vals_range_alpha
)
<< 24
)
| (
(
int(255 * (vals_red[ind] - val_min_red) / vals_range_red)
<< 16
)
if vals_range_red != 0
else int(vals_red[ind]) << 16
)
| (
int(255 * (vals_green[ind] - val_min_green) / vals_range_green)
<< 8
if vals_range_green != 0
else int(vals_green[ind]) << 8
)
| (
int(255 * (vals_blue[ind] - val_min_blue) / vals_range_blue)
if vals_range_blue != 0
else int(vals_blue[ind])
)
)
if (
vals_red[ind] != val_na_red
and vals_green[ind] != val_na_green
and vals_blue[ind] != val_na_blue
)
else (0 << 24) + (0 << 16) + (0 << 8) + 0
else (0 << 24) | (0 << 16) | (0 << 8) | 0
)
for ind, _ in enumerate(rasterBandVals[0])
for _ in range(4)
Expand All @@ -384,7 +423,7 @@ def get_raster_colors(

for val in rasterBandVals[bandIndex]:
rgb = None
color = (0 << 24) + (0 << 16) + (0 << 8) + 0
color = (0 << 24) | (0 << 16) | (0 << 8) | 0

for class_ind in range(len(renderer_classes)):
if rasterBandVals[bandIndex] == rasterBandNoDataVal[bandIndex]:
Expand All @@ -400,7 +439,7 @@ def get_raster_colors(
rgb = class_rgbs[class_ind]

if rgb is not None:
color = (255 << 24) + (rgb[0] << 16) + (rgb[1] << 8) + rgb[2]
color = (255 << 24) | (rgb[0] << 16) | (rgb[1] << 8) | rgb[2]

# add color value after looping through classes/categories
list_colors.extend([color, color, color, color])
Expand Down Expand Up @@ -436,7 +475,7 @@ def get_raster_colors(

for val in rasterBandVals[bandIndex]:
rgb = None
color = (0 << 24) + (0 << 16) + (0 << 8) + 0
color = (0 << 24) | (0 << 16) | (0 << 8) | 0

for class_ind in range(len(renderer_classes)):
if rasterBandVals[bandIndex] == rasterBandNoDataVal[bandIndex]:
Expand All @@ -452,7 +491,7 @@ def get_raster_colors(
rgb = class_rgbs[class_ind]

if rgb is not None:
color = (255 << 24) + (rgb[0] << 16) + (rgb[1] << 8) + rgb[2]
color = (255 << 24) | (rgb[0] << 16) | (rgb[1] << 8) | rgb[2]

# add color value after looping through classes/categories
list_colors.extend([color, color, color, color])
Expand Down Expand Up @@ -487,20 +526,38 @@ def get_raster_colors(
pixMax = rasterBandMaxVal[0]
vals_range = pixMax - pixMin

vals_alpha = [
1 if val != rasterBandNoDataVal[0] else 0 for val in rasterBandVals[0]
]
vals_range_alpha = 0
val_min_alpha = 0
try:
val_min_alpha = min(vals_alpha)
vals_range_alpha = max(vals_alpha) - val_min_alpha
if vals_alpha is not None and 0 in vals_alpha:
have_transparent_cells = True
except:
pass

list_colors: List[int] = [
(
(255 << 24)
(
255 << 24
if vals_range_alpha == 0
else int(255 * (vals_alpha[ind] - val_min_alpha) / vals_range_alpha)
<< 24
)
| (int(255 * (rasterBandVals[0][ind] - pixMin) / vals_range) << 16)
| (int(255 * (rasterBandVals[0][ind] - pixMin) / vals_range) << 8)
| int(255 * (rasterBandVals[0][ind] - pixMin) / vals_range)
if rasterBandVals[0][ind] != rasterBandNoDataVal[0]
else (0 << 24) + (0 << 16) + (0 << 8) + 0
else (0 << 24) | (0 << 16) | (0 << 8) | 0
)
for ind, _ in enumerate(rasterBandVals[0])
for _ in range(4)
]

return list_colors
return list_colors, have_transparent_cells


def get_vertices_height(
Expand Down Expand Up @@ -711,7 +768,6 @@ def get_raster_reprojected_stats(
rasterResXY,
rasterDimensions,
dataStorage,

):
# get 4 corners of raster
raster_top_right = QgsPointXY(
Expand All @@ -728,13 +784,12 @@ def get_raster_reprojected_stats(
)
# reproject corners to the project CRS
scale_factor_x = scale_factor_y = 1

reprojected_top_right = raster_top_right
reprojectedOriginPt = rasterOriginPoint
reprojectedMaxPt = rasterMaxPt
reprojected_bottom_left = raster_bottom_left


if selectedLayer.crs() != projectCRS:
reprojected_top_right = transform.transform(
project, raster_top_right, selectedLayer.crs(), projectCRS
Expand Down Expand Up @@ -927,7 +982,6 @@ def rasterFeatureToSpeckle(
reprojectedOriginPt.y(),
)


# fill band values
rasterBandNoDataVal = []
rasterBandMinVal = []
Expand Down Expand Up @@ -1017,7 +1071,6 @@ def rasterFeatureToSpeckle(
elevation_original_ResXY,
elevation_original_dimensions,
dataStorage,

)

(
Expand Down Expand Up @@ -1087,7 +1140,7 @@ def rasterFeatureToSpeckle(
dataStorage,
)
rendererType = selectedLayer.renderer().type()
colors_filtered = get_raster_colors(
colors_filtered, have_transparent_cells = get_raster_colors(
selectedLayer,
rasterBandVals,
rasterBandNoDataVal,
Expand Down Expand Up @@ -1155,7 +1208,7 @@ def rasterFeatureToSpeckle(
] = colors_filtered[colors_list_index + 2] = colors_filtered[
colors_list_index + 3
] = (
(0 << 24) + (0 << 16) + (0 << 8) + 0
(0 << 24) | (0 << 16) | (0 << 8) | 0
)

if terrain_transform is True or texture_transform is True:
Expand Down Expand Up @@ -1208,8 +1261,63 @@ def rasterFeatureToSpeckle(
vertices_filtered, dataStorage
)

# delete faces using invisible vertices
if have_transparent_cells is True:
vertices_filtered_removed = []
colors_filtered_removed = []
deleted_vert = []
vertex_remapping = {}

for i, color in enumerate(colors_filtered):
if i % 4 != 0: # only look a the first vertex of a square
if vertex_remapping[i - 1] is None:
vertex_remapping[i] = None
deleted_vert.append(i)
else:
vertex_remapping[i] = vertex_remapping[i - 1] + 1
continue
a, _, _, _ = get_a_r_g_b(color)
if a != 0:
colors_filtered_removed.extend(colors_filtered[i : i + 4])
vertices_filtered_removed.extend(
vertices_filtered2[3 * i : 3 * i + 12]
)
vertex_remapping[i] = i - len(deleted_vert)
else:
deleted_vert.append(i)
vertex_remapping[i] = None

faces_filtered_removed = []
count = 0
for f in faces_filtered:
if count >= len(faces_filtered):
break
# get first vertex color:
if vertex_remapping[faces_filtered[count + 1]] is not None:
faces_filtered_removed.append(4)
faces_filtered_removed.append(
vertex_remapping[faces_filtered[count + 1]]
)
faces_filtered_removed.append(
vertex_remapping[faces_filtered[count + 2]]
)
faces_filtered_removed.append(
vertex_remapping[faces_filtered[count + 3]]
)
faces_filtered_removed.append(
vertex_remapping[faces_filtered[count + 4]]
)
count += 5
else:
vertices_filtered_removed = vertices_filtered2.copy()
colors_filtered_removed = colors_filtered.copy()
faces_filtered_removed = faces_filtered.copy()

mesh = constructMeshFromRaster(
vertices_filtered2, faces_filtered, colors_filtered, dataStorage
vertices_filtered_removed, # vertices_filtered2,
faces_filtered_removed, # faces_filtered,
colors_filtered_removed, # colors_filtered,
dataStorage,
)
if mesh is not None:
mesh.units = dataStorage.currentUnits
Expand Down
Loading

0 comments on commit bdc9d4a

Please sign in to comment.