Compare commits

...

21 Commits

Author SHA1 Message Date
KatKatKateryna 3131ba8950 Merge pull request #45 from specklesystems/2.11.0-beta
identify large integers, save into "float" type attribute; override "…
2023-01-04 02:43:59 +08:00
KatKatKateryna 9f8637d670 identify large integers, save into "float" type attribute; override "Long" type if already existed 2023-01-04 01:50:01 +08:00
KatKatKateryna f9f2628d3a Merge pull request #42 from specklesystems/kate/2.11
Kate/2.11
2022-12-25 01:35:37 +08:00
KatKatKateryna 22b4672b4a 2.10.3 whl to release 2022-12-25 01:34:27 +08:00
KatKatKateryna b963228da0 Merge pull request #32 from specklesystems/kate/2.10.3
Kate/2.10.2-beta
2022-12-25 01:34:27 +08:00
KatKatKateryna faa8fb9cfa whl file 2.10.2-beta 2022-12-25 01:34:27 +08:00
KatKatKateryna a1de8be5b0 fixing customCRS location (negative values read properly)) 2022-12-25 01:34:26 +08:00
KatKatKateryna bf10c4f00b use custom SR via WKT (not name) 2022-12-25 01:34:05 +08:00
KatKatKateryna f88a9e3966 attach renderers separately for vector/raster layers 2022-12-25 01:24:44 +08:00
KatKatKateryna b4149fa5f7 calculate raster mesh and symbology colors correctly on send; Vector renderer on send 2022-12-25 01:23:57 +08:00
KatKatKateryna 68d8c1f8f3 temporarily removed unhandled specklepy None value exception; 2022-12-23 21:14:12 +08:00
KatKatKateryna 8b4fbe88ef raster renderer on receive and send; mesh coloring on send 2022-12-20 19:35:13 +08:00
KatKatKateryna 67564631d2 fixed SR on receive cad/bim; raster mesh color on send (WIP); raster renderer send (WIP) 2022-12-20 04:28:01 +08:00
KatKatKateryna b3ffdd9d0b receiving vector gis-layer symbology 2022-12-15 23:55:41 +08:00
KatKatKateryna d7f467c6a6 symbology added ()not applied yet) 2022-12-08 01:15:21 +08:00
KatKatKateryna a14550d7ad send/receive from multiple registered accounts 2022-12-07 15:17:10 +08:00
KatKatKateryna 79b8b363f0 Merge pull request #33 from specklesystems/kate/2.11
Kate/2.10.4
2022-12-01 22:45:33 +08:00
KatKatKateryna d9b1b11036 fix 2022-12-01 22:45:10 +08:00
KatKatKateryna e47d89ce57 fix path by removing "/"; add other types than DisplayMesh; 2022-12-01 02:51:02 +08:00
KatKatKateryna 18234800dd 2.10.3 whl to release 2022-11-30 01:27:30 +08:00
KatKatKateryna f0213b7186 stream list with no account 2022-11-30 01:26:50 +08:00
15 changed files with 1098 additions and 164 deletions
@@ -1,5 +1,5 @@
<?xml version="1.0"?>
<metadata xml:lang="en"><Esri><CreaDate>20220718</CreaDate><CreaTime>13500100</CreaTime><ArcGISFormat>1.0</ArcGISFormat><SyncOnce>TRUE</SyncOnce><ModDate>20221031</ModDate><ModTime>212303</ModTime><scaleRange><minScale>150000000</minScale><maxScale>5000</maxScale></scaleRange><ArcGISProfile>ItemDescription</ArcGISProfile></Esri><toolbox name="Speckle" alias="speckle_toolbox_"><arcToolboxHelpPath>c:\program files\arcgis\pro\Resources\Help\gp</arcToolboxHelpPath><toolsets/></toolbox><dataIdInfo><idCitation><resTitle>Speckle</resTitle></idCitation><idPurp>Speckle connector for ArcGIS</idPurp><searchKeys><keyword>speckle3d</keyword></searchKeys></dataIdInfo><distInfo><distributor><distorFormat><formatName>ArcToolbox Toolbox</formatName></distorFormat></distributor></distInfo><mdHrLv><ScopeCd value="005"></ScopeCd></mdHrLv><Binary><Thumbnail><Data EsriPropertyType="PictureX">/9j/4AAQSkZJRgABAQEAYABgAAD/4gxYSUNDX1BST0ZJTEUAAQEAAAxITGlubwIQAABtbnRyUkdC
<metadata xml:lang="en"><Esri><CreaDate>20220718</CreaDate><CreaTime>13500100</CreaTime><ArcGISFormat>1.0</ArcGISFormat><SyncOnce>TRUE</SyncOnce><ModDate>20221207</ModDate><ModTime>175959</ModTime><scaleRange><minScale>150000000</minScale><maxScale>5000</maxScale></scaleRange><ArcGISProfile>ItemDescription</ArcGISProfile></Esri><toolbox name="Speckle" alias="speckle_toolbox_"><arcToolboxHelpPath>c:\program files\arcgis\pro\Resources\Help\gp</arcToolboxHelpPath><toolsets/></toolbox><dataIdInfo><idCitation><resTitle>Speckle</resTitle></idCitation><idPurp>Speckle connector for ArcGIS</idPurp><searchKeys><keyword>speckle3d</keyword></searchKeys></dataIdInfo><distInfo><distributor><distorFormat><formatName>ArcToolbox Toolbox</formatName></distorFormat></distributor></distInfo><mdHrLv><ScopeCd value="005"></ScopeCd></mdHrLv><Binary><Thumbnail><Data EsriPropertyType="PictureX">/9j/4AAQSkZJRgABAQEAYABgAAD/4gxYSUNDX1BST0ZJTEUAAQEAAAxITGlubwIQAABtbnRyUkdC
IFhZWiAHzgACAAkABgAxAABhY3NwTVNGVAAAAABJRUMgc1JHQgAAAAAAAAAAAAAAAAAA9tYAAQAA
AADTLUhQICAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABFj
cHJ0AAABUAAAADNkZXNjAAABhAAAAGx3dHB0AAAB8AAAABRia3B0AAACBAAAABRyWFlaAAACGAAA
@@ -12,7 +12,7 @@ from speckle.converter.geometry.polyline import speckleArcCircleToPoints, speckl
from speckle.converter.geometry.mesh import meshToNative
import numpy as np
def convertToSpeckle(feature, layer, geomType, featureType) -> Union[Base, Sequence[Base], None]:
def convertToSpeckle(feature, index: str, layer, geomType, featureType) -> Union[Base, Sequence[Base], None]:
"""Converts the provided layer feature to Speckle objects"""
print("___convertToSpeckle____________")
geom = feature
@@ -39,8 +39,8 @@ def convertToSpeckle(feature, layer, geomType, featureType) -> Union[Base, Seque
if geom.partCount > 1: return multiPolylineToSpeckle(geom, feature, layer, geomMultiType)
else: return polylineToSpeckle(geom, feature, layer, geomMultiType)
elif geomType == "Polygon":
if geom.partCount > 1: return multiPolygonToSpeckle(geom, feature, layer, geomMultiType)
else: return polygonToSpeckle(geom, feature, layer, geomMultiType)
if geom.partCount > 1: return multiPolygonToSpeckle(geom, feature, index, layer, geomMultiType)
else: return polygonToSpeckle(geom, feature, index, layer, geomMultiType)
elif geomType == "Multipoint":
return multiPointToSpeckle(geom, feature, layer, geomMultiType)
else:
@@ -126,7 +126,7 @@ def multiPolygonToNative(items: List[Base], sr: arcpy.SpatialReference): #TODO f
except: pass # if Line
pts = [pointToCoord(pt) for pt in pointsSpeckle]
print(pts)
#print(pts)
outer_arr = [arcpy.Point(*coords) for coords in pts]
outer_arr.append(outer_arr[0])
@@ -16,12 +16,28 @@ def meshToNative(meshes: List[Mesh], path: str):
w.field('speckleTyp', 'C')
shapes = []
for mesh_full in meshes:
#print(mesh_full)
#print(mesh_full.get_dynamic_member_names())
mesh = mesh_full.displayMesh
#print(mesh)
w = fill_mesh_parts(w, mesh)
for geom in meshes:
try:
if geom.displayValue and isinstance(geom.displayValue, Mesh):
mesh = geom.displayValue
w = fill_mesh_parts(w, mesh)
elif geom.displayValue and isinstance(geom.displayValue, List):
for part in geom.displayValue:
if isinstance(part, Mesh):
mesh = part
w = fill_mesh_parts(w, mesh)
except:
try:
if geom.displayMesh and isinstance(geom.displayMesh, Mesh):
mesh = geom.displayMesh
w = fill_mesh_parts(w, mesh)
elif geom.displayMesh and isinstance(geom.displayMesh, List):
for part in geom.displayMesh:
if isinstance(part, Mesh):
mesh = part
w = fill_mesh_parts(w, mesh)
except: pass
w.close()
return path
@@ -33,7 +49,7 @@ def fill_mesh_parts(w: shapefile.Writer, mesh: Mesh):
count = 0 # sequence of vertex (not of flat coord list)
try:
#print(len(mesh.faces))
if len(mesh.faces) % 4 == 0 and mesh.faces[0] == 0:
if len(mesh.faces) % 4 == 0 and (mesh.faces[0] == 0 or mesh.faces[0] == 3):
for f in mesh.faces:
try:
if mesh.faces[count] == 0 or mesh.faces[count] == 3: # only handle triangles
@@ -17,8 +17,10 @@ from speckle.converter.geometry.polyline import (polylineFromVerticesToSpeckle,
import math
from panda3d.core import Triangulator
from speckle.converter.layers.symbologyTemplates import featureColorfromNativeRenderer
def multiPolygonToSpeckle(geom, feature, layer, multiType: bool):
def multiPolygonToSpeckle(geom, feature, index: str, layer, multiType: bool):
print("___MultiPolygon to Speckle____")
polygon = []
@@ -42,15 +44,15 @@ def multiPolygonToSpeckle(geom, feature, layer, multiType: bool):
arrInnerRings[len(arrInnerRings)-1].append(ptn)
full_arr = [arrBoundary] + arrInnerRings
print(full_arr)
#print(full_arr)
poly = arcpy.Polygon(arcpy.Array(full_arr), arcpy.Describe(layer.dataSource).SpatialReference, has_z = True)
print(poly) #<geoprocessing describe geometry object object at 0x000002B2D3E338D0>
polygon.append(polygonToSpeckle(poly, feature, layer, poly.isMultipart))
#print(poly) #<geoprocessing describe geometry object object at 0x000002B2D3E338D0>
polygon.append(polygonToSpeckle(poly, feature, index, layer, poly.isMultipart))
return polygon
def polygonToSpeckle(geom, feature, layer, multiType: bool):
def polygonToSpeckle(geom, feature, index: int, layer, multiType: bool):
"""Converts a Polygon to Speckle"""
#try:
print("___Polygon to Speckle____")
@@ -202,7 +204,7 @@ def polygonToSpeckle(geom, feature, layer, multiType: bool):
ran = range(0, total_vertices)
#print(polygon)
col = (100<<16) + (100<<8) + 100 #featureColorfromNativeRenderer(feature, layer)
col = featureColorfromNativeRenderer(index, layer)
colors = [col for i in ran] # apply same color for all vertices
mesh = rasterToMesh(vertices, faces, colors)
polygon.displayValue = mesh
@@ -228,7 +230,7 @@ def polygonToNative(poly: Base, sr: arcpy.SpatialReference) -> arcpy.Polygon:
except: pass # if Line
pts = [pointToCoord(pt) for pt in pointsSpeckle]
print(pts)
#print(pts)
outer_arr = [arcpy.Point(*coords) for coords in pts]
outer_arr.append(outer_arr[0])
@@ -456,7 +456,7 @@ def specklePolycurveToPoints(poly: Polycurve) -> List[Point]:
print("_____Speckle Polycurve to points____")
points = []
for segm in poly.segments:
print(segm)
#print(segm)
pts = []
if isinstance(segm, Arc) or isinstance(segm, Circle): # or isinstance(segm, Curve):
print("Arc or Curve")
@@ -23,6 +23,7 @@ from speckle.converter.layers.utils import getLayerAttributes, newLayerGroupAndN
import numpy as np
from speckle.converter.layers.utils import findTransformation
from speckle.converter.layers.symbologyTemplates import vectorRendererToNative, rasterRendererToNative, rendererToSpeckle
def convertSelectedLayers(all_layers: List[arcLayer], selected_layers: List[str], project: ArcGISProject) -> List[Union[VectorLayer,Layer]]:
@@ -39,8 +40,9 @@ def convertSelectedLayers(all_layers: List[arcLayer], selected_layers: List[str]
ds = layerToSend.dataSource #file path
#if layerToSend.isFeatureLayer:
newBaseLayer = layerToSpeckle(layerToSend, project)
if newBaseLayer is not None: result.append(newBaseLayer)
elif layerToSend.isRasterLayer: pass
if newBaseLayer is not None:
result.append(newBaseLayer)
#elif layerToSend.isRasterLayer: pass
print(result)
return result
@@ -74,6 +76,7 @@ def layerToSpeckle(layer: arcLayer, project: ArcGISProject) -> Union[VectorLayer
speckleLayer.type="VectorLayer"
speckleLayer.name = layerName
speckleLayer.crs = speckleReprojectedCrs
speckleLayer.renderer = rendererToSpeckle(project, project.activeMap, layer, None)
#speckleLayer.datum = datum
@@ -114,7 +117,7 @@ def layerToSpeckle(layer: arcLayer, project: ArcGISProject) -> Union[VectorLayer
#print(feat)
b = featureToSpeckle(fieldnames, row_attr, feat, projectCRS, project, layer)
b = featureToSpeckle(fieldnames, row_attr, i, feat, projectCRS, project, layer)
if b is not None: layerObjs.append(b)
print("____End of Feature # " + str(i+1))
@@ -148,6 +151,8 @@ def layerToSpeckle(layer: arcLayer, project: ArcGISProject) -> Union[VectorLayer
#speckleLayer.geomType="Raster"
speckleLayer.features = layerObjs
speckleLayer.renderer = rendererToSpeckle(project, project.activeMap, layer, b)
#speckleLayer.renderer = layerRenderer
#speckleLayer.applicationId = selectedLayer.id()
@@ -171,9 +176,12 @@ def bimLayerToNative(layerContentList: List[Base], layerName: str, streamBranch:
layer_meshes = None
#filter speckle objects by type within each layer, create sub-layer for each type (points, lines, polygons, mesh?)
for geom in layerContentList:
#print(geom)
if geom.displayMesh and isinstance(geom.displayMesh, Mesh):
geom_meshes.append(geom)
try:
if geom.displayMesh: geom_meshes.append(geom)
except:
try:
if geom.displayValue: geom_meshes.append(geom)
except: pass
if len(geom_meshes)>0: layer_meshes = bimVectorLayerToNative(geom_meshes, layerName, "Mesh", streamBranch, project)
@@ -184,19 +192,22 @@ def bimVectorLayerToNative(geomList, layerName: str, geomType: str, streamBranch
# no support for mltipatches, maybe in 3.1: https://community.esri.com/t5/arcgis-pro-ideas/better-support-for-multipatches-in-arcpy/idi-p/953614/page/2#comments
print("02_________BIM vector layer to native_____")
#get Project CRS, use it by default for the new received layer
vl = None
layerName = layerName.replace("[","_").replace("]","_").replace(" ","_").replace("-","_").replace("(","_").replace(")","_").replace(":","_").replace("\\","_").replace("/","_").replace("\"","_").replace("&","_").replace("@","_").replace("$","_").replace("%","_").replace("^","_")
layerName = layerName + "_" + geomType
layerName = layerName.replace("[","_").replace("]","_").replace(" ","_").replace("-","_").replace("(","_").replace(")","_").replace(":","_").replace("\\","_").replace("/","_").replace("\"","_").replace("&","_").replace("@","_").replace("$","_").replace("%","_").replace("^","_")
#if not "__Structural_Foundations_Mesh" in layerName: return None
sr = arcpy.SpatialReference(text = project.activeMap.spatialReference.exportToString())
active_map = project.activeMap
path = project.filePath.replace("aprx","gdb") #
path_bim = "\\".join(project.filePath.split("\\")[:-1]) + "\\BIM_layers_speckle\\" + streamBranch+ "\\" + layerName + "\\" #arcpy.env.workspace + "\\" #
path_bim = "\\".join(project.filePath.split("\\")[:-1]) + "\\Layers_Speckle\\BIM_layers_speckle\\" + streamBranch+ "\\" + layerName + "\\" #arcpy.env.workspace + "\\" #
print(path_bim)
if not os.path.exists(path_bim): os.makedirs(path_bim)
print(path)
if sr.type == "Geographic":
arcpy.AddMessage(f"Project CRS is set to Geographic type, and objects in linear units might not be received correctly")
@@ -283,6 +294,7 @@ def bimVectorLayerToNative(geomList, layerName: str, geomType: str, streamBranch
print(all_keys)
print(len(all_keys))
if len(matrix)>0: AddFields(str(f_class), matrix)
print(matrix)
fets = []
print("_________BIM FeatureS To Native___________")
@@ -310,26 +322,38 @@ def bimVectorLayerToNative(geomList, layerName: str, geomType: str, streamBranch
rowValues.append(row)
count += 1
print(heads)
with arcpy.da.UpdateCursor(f_class, heads) as cur:
# For each row, evaluate the WELL_YIELD value (index position
# of 0), and update WELL_CLASS (index position of 1)
shp_num = 0
#print(heads)
try:
for rowShape in cur:
#print(rowShape)
for i,r in enumerate(rowShape):
#print(heads[i])
#print(matrix[i])
rowShape[i] = rowValues[shp_num][i]
if isinstance(rowValues[shp_num][i], str): rowShape[i] = rowValues[shp_num][i][:255]
#print(type(rowShape[i]))
if matrix[i][1] == 'TEXT' and rowShape[i] is not None: rowShape[i] = str(rowValues[shp_num][i])
#print(type(rowShape[i]))
if isinstance(rowValues[shp_num][i], str): # cut if string is too long
rowShape[i] = rowValues[shp_num][i][:255]
#print(rowShape[i])
#print(rowShape)
cur.updateRow(rowShape)
shp_num += 1
#print(shp_num)
except Exception as e:
print(e)
print(i)
print("Layer attribute error: " + str(e))
#print(i)
print(shp_num)
print(len(rowValues))
print(rowValues[i-1])
print(len(rowValues[i-1]))
#print(rowValues[i])
#print(len(rowValues[i]))
arcpy.AddWarning("Layer attribute error: " + e)
del cur
print("create layer:")
@@ -349,6 +373,7 @@ def cadLayerToNative(layerContentList: List[Base], layerName: str, streamBranch:
geom_polygones = []
geom_meshes = []
#filter speckle objects by type within each layer, create sub-layer for each type (points, lines, polygons, mesh?)
print(layerContentList)
for geom in layerContentList:
#print(geom)
if geom.speckle_type == "Objects.Geometry.Point":
@@ -367,17 +392,21 @@ def cadVectorLayerToNative(geomList, layerName: str, geomType: str, streamBranch
vl = None
layerName = layerName.replace("[","_").replace("]","_").replace(" ","_").replace("-","_").replace("(","_").replace(")","_").replace(":","_").replace("\\","_").replace("/","_").replace("\"","_").replace("&","_").replace("@","_").replace("$","_").replace("%","_").replace("^","_")
layerName = layerName + "_" + geomType
print(layerName)
sr = arcpy.SpatialReference(text = project.activeMap.spatialReference.exportToString())
active_map = project.activeMap
path = project.filePath.replace("aprx","gdb") #"\\".join(project.filePath.split("\\")[:-1]) + "\\speckle_layers\\" #arcpy.env.workspace + "\\" #
print(path)
print(streamBranch)
if sr.type == "Geographic":
arcpy.AddMessage(f"Project CRS is set to Geographic type, and objects in linear units might not be received correctly")
#CREATE A GROUP "received blabla" with sublayers
layerGroup = None
newGroupName = f'{streamBranch}'
print(newGroupName)
#print(newGroupName)
for l in active_map.listLayers():
if l.longName == newGroupName: layerGroup = l; break
@@ -548,7 +577,7 @@ def vectorLayerToNative(layer: Union[Layer, VectorLayer], streamBranch: str, pro
new_feat = featureToNative(f, newFields, geomType, sr)
if new_feat != "" and new_feat!= None: fets.append(new_feat)
print(fets)
#print(fets)
if len(fets) == 0: return None
count = 0
rowValues = []
@@ -569,16 +598,27 @@ def vectorLayerToNative(layer: Union[Layer, VectorLayer], streamBranch: str, pro
count += 1
cur = arcpy.da.InsertCursor(str(f_class), tuple(heads) )
for row in rowValues:
print(tuple(heads))
print(tuple(row))
#print(tuple(heads))
#print(tuple(row))
cur.insertRow(tuple(row))
del cur
vl = MakeFeatureLayer(str(f_class), newName).getOutput(0)
#adding layers from code solved: https://gis.stackexchange.com/questions/344343/arcpy-makefeaturelayer-management-function-not-creating-feature-layer-in-arcgis
#active_map.addLayer(new_layer)
active_map.addLayerToGroup(layerGroup, vl)
vl2 = None
print(newName)
for l in project.activeMap.listLayers():
#print(l.longName)
if l.longName == layerGroup.longName + "\\" + newName:
vl2 = l
break
path_lyr = vectorRendererToNative(project, active_map, layerGroup, layer, vl2, f_class, heads)
#if path_lyr is not None:
# active_map.removeLayer(path_lyr)
r'''
# rename back the layer if was renamed due to existing duplicate
if layerExists:
@@ -622,6 +662,9 @@ def rasterLayerToNative(layer: RasterLayer, streamBranch: str, project: ArcGISPr
rasterHasSr = False
print(path)
path_bands = "\\".join(path.split("\\")[:-1]) + "\\Layers_Speckle\\rasters_Speckle\\" + streamBranch
if not os.path.exists(path_bands): os.makedirs(path_bands)
try:
srRasterWkt = str(layer.rasterCrs.wkt)
print(layer.rasterCrs.wkt)
@@ -667,7 +710,7 @@ def rasterLayerToNative(layer: RasterLayer, streamBranch: str, project: ArcGISPr
for i in range(bandsCount):
print(i)
print(bandNames[i])
rasterbandPath = path + "\\" + newName + "_Band_" + str(i+1) #+ ".tif"
rasterbandPath = path_bands + "\\" + newName + "_Band_" + str(i+1) + ".tif"
bandDatasets += rasterbandPath + ";"
rasterband = np.array(bandValues[i])
rasterband = np.reshape(rasterband,(ysize, xsize))
@@ -701,23 +744,42 @@ def rasterLayerToNative(layer: RasterLayer, streamBranch: str, project: ArcGISPr
#mergedRaster.setProperty("spatialReference", crsRaster)
full_path = validate_path(path + "\\" + newName) #solved file saving issue
print("RASTER FULL PATH")
print(full_path)
if os.path.exists(full_path):
#print(full_path)
for index, letter in enumerate('1234567890abcdefghijklmnopqrstuvwxyz'):
print(full_path + letter)
if os.path.exists(full_path + letter): pass
else: full_path += letter; break
print("RASTER new PATH")
print(full_path)
#mergedRaster = arcpy.ia.Merge(rastersToMerge) # glues all bands together
#mergedRaster.save(full_path) # similar errors: https://community.esri.com/t5/python-questions/error-010240-could-not-save-raster-dataset/td-p/321690
arcpy.management.CompositeBands(rasterPathsToMerge, full_path)
try:
arcpy.management.CompositeBands(rasterPathsToMerge, full_path)
except: # if already exists
full_path += "_"
arcpy.management.CompositeBands(rasterPathsToMerge, full_path)
print(path + "\\" + newName)
arcpy.management.DefineProjection(full_path, srRaster)
rasterLayer = arcpy.management.MakeRasterLayer(full_path, newName + "_").getOutput(0)
rasterLayer = arcpy.management.MakeRasterLayer(full_path, newName).getOutput(0)
print(layerGroup)
active_map.addLayerToGroup(layerGroup, rasterLayer)
rl2 = None
for l in active_map.listLayers():
if l.longName == layerGroup.longName + "\\" + newName:
print(l.longName)
rl2 = l
break
rasterLayer = rasterRendererToNative(project, active_map, layerGroup, layer, rl2, rasterPathsToMerge, newName)
try: os.remove(path_bands)
except: pass
r'''
if arcpy.Exists(fileout):
arcpy.management.Delete(fileout)
@@ -19,8 +19,10 @@ from speckle.converter.geometry.mesh import rasterToMesh, meshToNative
import numpy as np
import colorsys
from speckle.converter.layers.symbologyTemplates import jsonFromLayerStyle
def featureToSpeckle(fieldnames, attr_list, f_shape, projectCRS: arcpy.SpatialReference, project: ArcGISProject, selectedLayer: arcLayer):
def featureToSpeckle(fieldnames, attr_list, index: int, f_shape, projectCRS: arcpy.SpatialReference, project: ArcGISProject, selectedLayer: arcLayer):
print("___________Feature to Speckle____________")
b = Base(units = "m")
data = arcpy.Describe(selectedLayer.dataSource)
@@ -43,7 +45,7 @@ def featureToSpeckle(fieldnames, attr_list, f_shape, projectCRS: arcpy.SpatialRe
######################################### Convert geometry ##########################################
try:
geom = convertToSpeckle(f_shape, selectedLayer, geomType, featureType)
geom = convertToSpeckle(f_shape, index, selectedLayer, geomType, featureType)
if geom is not None: print(geom); b["geometry"] = geom
except Exception as error:
print("Error converting geometry: " + str(error))
@@ -67,7 +69,7 @@ def featureToNative(feature: Base, fields: dict, geomType: str, sr: arcpy.Spatia
feat = {}
try: speckle_geom = feature["geometry"] # for created in QGIS / ArcGIS Layer type
except: speckle_geom = feature # for created in other software
print(speckle_geom)
#print(speckle_geom)
if isinstance(speckle_geom, list):
if len(speckle_geom)>1 or geomType == "Multipoint": arcGisGeom = convertToNativeMulti(speckle_geom, sr)
else: arcGisGeom = convertToNative(speckle_geom[0], sr)
@@ -93,7 +95,7 @@ def featureToNative(feature: Base, fields: dict, geomType: str, sr: arcpy.Spatia
return feat
def bimFeatureToNative(feature: Base, fields: dict, sr: arcpy.SpatialReference, path: str):
#print("04_________BIM Feature To Native____________")
print("04_________BIM Feature To Native____________")
feat = {}
try: speckle_geom = feature["geometry"] # for created in QGIS Layer type
@@ -133,6 +135,16 @@ def cadFeatureToNative(feature: Base, fields: dict, sr: arcpy.SpatialReference):
feat_updated = updateFeat(feat, fields, feature)
return feat_updated
def addFeatVariant(key, variant, value, f):
feat = f
if variant == "TEXT": value = str(value)
if value != "NULL" and value != "None":
if variant == getVariantFromValue(value) or (variant=="FLOAT" and isinstance(value, int)):
feat.update({key: value})
elif variant == "TEXT" or variant == "FLOAT" or variant == "LONG" or variant == "SHORT": feat.update({key: None})
return feat
def updateFeat(feat:dict, fields: dict, feature: Base) -> dict[str, Any]:
for key, variant in fields.items():
@@ -142,17 +154,11 @@ def updateFeat(feat:dict, fields: dict, feature: Base) -> dict[str, Any]:
if key != "parameters": print(value)
feat[key] = value
if variant == "TEXT": value = str(value)
if variant == getVariantFromValue(value) and value != "NULL" and value != "None": feat.update({key: value})
elif variant == "TEXT" or variant == "FLOAT" or variant == "LONG" or variant == "SHORT": feat.update({key: None})
feat = addFeatVariant(key, variant, value, feat)
else:
try:
value = feature[key]
if variant == "TEXT": value = str(value)
if variant == getVariantFromValue(value) and value != "NULL" and value != "None": feat.update({key: value})
elif variant == "TEXT" or variant == "FLOAT" or variant == "LONG" or variant == "SHORT": feat.update({key: None})
feat = addFeatVariant(key, variant, value, feat)
except:
value = None
rootName = key.split("_")[0]
@@ -165,9 +171,7 @@ def updateFeat(feat:dict, fields: dict, feature: Base) -> dict[str, Any]:
for i, (key,value) in enumerate(newVals.items()):
for k, (x,y) in enumerate(newF.items()):
if key == x: variant = y; break
if variant == "TEXT": value = str(value)
if variant == getVariantFromValue(value) and value != "NULL" and value != "None": feat.update({key: value})
elif variant == "TEXT" or variant == "FLOAT" or variant == "LONG" or variant == "SHORT": feat.update({key: None})
feat = addFeatVariant(key, variant, value, feat)
except Exception as e: print(e)
#except: # if not a list
else:
@@ -176,10 +180,7 @@ def updateFeat(feat:dict, fields: dict, feature: Base) -> dict[str, Any]:
for i, (key,value) in enumerate(newVals.items()):
for k, (x,y) in enumerate(newF.items()):
if key == x: variant = y; break
#print(variant)
if variant == "TEXT": value = str(value)
if variant == getVariantFromValue(value) and value != "NULL" and value != "None": feat.update({key: value})
elif variant == "TEXT" or variant == "FLOAT" or variant == "LONG" or variant == "SHORT": feat.update({key: None})
feat = addFeatVariant(key, variant, value, feat)
except Exception as e: feat.update({key: None})
except Exception as e:
feat.update({key: None})
@@ -191,20 +192,6 @@ def rasterFeatureToSpeckle(selectedLayer: arcLayer, projectCRS: arcpy.SpatialRef
print("_________ Raster feature to speckle______")
# https://pro.arcgis.com/en/pro-app/latest/arcpy/classes/raster-object.htm
r'''
# Save layer file to read symbology
# https://pro.arcgis.com/en/pro-app/latest/tool-reference/data-management/save-to-layer-file.htm
layerFile = project.homeFolder + "\\" + selectedLayer.name.split(".")[0]
arcpy.management.SaveToLayerFile(selectedLayer.name, layerFile, "ABSOLUTE")
# read the file and then delete
f = open(layerFile + ".lyrx", "r")
layerFileContent = json.loads(f.read())
print(layerFileContent)
f.close()
os.remove(layerFile + ".lyrx")
'''
# get Raster object of entire raster dataset
my_raster = arcpy.Raster(selectedLayer.dataSource)
print(my_raster.mdinfo) # None
@@ -290,6 +277,8 @@ def rasterFeatureToSpeckle(selectedLayer: arcLayer, projectCRS: arcpy.SpatialRef
else: rasterBandNoDataVal.append(rb.noDataValue)
except: rasterBandNoDataVal.append(rb.noDataValue)
if rasterBandNoDataVal[len(rasterBandNoDataVal)-1] is None:
rasterBandNoDataVal[len(rasterBandNoDataVal)-1] = 'None'
rasterBandVals.append(bandValsFlat)
@@ -313,7 +302,7 @@ def rasterFeatureToSpeckle(selectedLayer: arcLayer, projectCRS: arcpy.SpatialRef
colors = []
count = 0
print(my_raster.variables)
#print(my_raster.variables)
print(selectedLayer.symbology) #None
colorizer = None
#renderer = selectedLayer.symbology.renderer
@@ -322,8 +311,58 @@ def rasterFeatureToSpeckle(selectedLayer: arcLayer, projectCRS: arcpy.SpatialRef
print(colorizer) # <arcpy._colorizer.RasterStretchColorizer object at 0x000001780497FBC8>
print(colorizer.type) # RasterStretchColorizer
else:
#RGB colorizer
root_path = "\\".join(project.filePath.split("\\")[:-1])
if not os.path.exists(root_path + '\\Layers_Speckle\\rasters_Speckle'): os.makedirs(root_path + '\\Layers_Speckle\\rasters_Speckle')
path_style = root_path + '\\Layers_Speckle\\rasters_Speckle\\' + selectedLayer.name + '_temp.lyrx'
symJson = jsonFromLayerStyle(selectedLayer, path_style)
# read from Json
print(symJson["layerDefinitions"][0]["colorizer"])
try: greenBand = symJson["layerDefinitions"][0]["colorizer"]["greenBandIndex"]
except: greenBand = None
try: blueBand = symJson["layerDefinitions"][0]["colorizer"]["blueBandIndex"]
except: blueBand = None
try: redBand = symJson["layerDefinitions"][0]["colorizer"]["redBandIndex"]
except:
if blueBand!=0 and greenBand!=0: redBand= 0
else: redBand = None
print("bands")
print(redBand)
print(greenBand)
print(blueBand)
try:
rbVals = rasterBandVals[redBand] #my_raster.getRasterBands(rasterBandNames[redBand])
rbvalMin = min(rbVals)
rbvalMax = max(rbVals)
rvalRange = float(rbvalMax) - float(rbvalMin)
print(rbvalMin)
print(rbvalMax)
print(rvalRange)
except Exception as e: print(e); rvalRange = None
try:
gbVals = rasterBandVals[greenBand]
gbvalMin = min(gbVals)
gbvalMax = max(gbVals)
gvalRange = float(gbvalMax) - float(gbvalMin)
print(gbvalMin)
print(gbvalMax)
print(gvalRange)
except: gvalRange = None
try:
bbVals = rasterBandVals[blueBand]
bbvalMin = min(bbVals)
bbvalMax = max(bbVals)
bvalRange = float(bbvalMax) - float(bbvalMin)
print(bbvalMin)
print(bbvalMax)
print(bvalRange)
except: bvalRange = None
rendererType = ""
if hasattr(selectedLayer.symbology, 'renderer'): rendererType = selectedLayer.symbology.renderer.type #e.g. SimpleRenderer
#if hasattr(selectedLayer.symbology, 'renderer'): rendererType = selectedLayer.symbology.renderer.type #e.g. SimpleRenderer
# custom color ramp {"type": "algorithmic", "fromColor": [115, 76, 0, 255],"toColor": [255, 25, 86, 255], "algorithm": "esriHSVAlgorithm"}.
# custom color map {'values': [0, 1, 2, 3, 4, 5], 'colors': ['#000000', '#DCFFDF', '#B8FFBE', '#85FF90', '#50FF60','#00AB10']}
@@ -441,34 +480,71 @@ def rasterFeatureToSpeckle(selectedLayer: arcLayer, projectCRS: arcpy.SpatialRef
print(colorizer.groups)
'''
#else:
if colorizer:
try: bandIndex = int(colorizer.band)
except: pass
try:
if rasterBandVals[bandIndex][int(count/4)] >= float(colorizer.minLabel) and rasterBandVals[bandIndex][int(count/4)] <= float(colorizer.maxLabel) : #rasterBandMinVal[bandIndex]:
# REMAP band values to (0,255) range
valRange = float(colorizer.maxLabel) - float(colorizer.minLabel) #(rasterBandMaxVal[bandIndex] - rasterBandMinVal[bandIndex])
colorVal = int( (rasterBandVals[bandIndex][int(count/4)] - float(colorizer.minLabel)) / valRange * 255 )
if colorizer.invertColorRamp is True: colorVal = int( (-rasterBandVals[bandIndex][int(count/4)] + float(colorizer.maxLabel)) / valRange * 255 )
color = (colorVal<<16) + (colorVal<<8) + colorVal
except: # if no Min Max labels:
# REMAP band values to (0,255) range
valRange = max(rasterBandVals[bandIndex]) - min(rasterBandVals[bandIndex]) #(rasterBandMaxVal[bandIndex] - rasterBandMinVal[bandIndex])
colorVal = int( (rasterBandVals[bandIndex][int(count/4)] - min(rasterBandVals[bandIndex])) / valRange * 255 )
color = (colorVal<<16) + (colorVal<<8) + colorVal
else:
# REMAP band values to (0,255) range
rbVals = my_raster.getRasterBands(rasterBandNames[0])
try:
rbvalMin = rbVals.minimum
rbvalMax = rbVals.maximum
except:
rbvalMin = min(rbVals)
rbvalMax = max(rbVals)
if hasattr(selectedLayer.symbology, 'colorizer'): # only 1 band
try: bandIndex = int(colorizer.band) # if stretched
except: pass
if colorizer.type =='RasterUniqueValueColorizer':
# REDO !!!!!!!!!!!!
colorRVal = colorGVal = colorBVal = 0
try:
for br in colorizer.groups:
print(br.heading) #"Value"
# go through all values classified
if br.heading != 'Value': print(int('x')) #call exception
for k, itm in enumerate(br.items):
print(itm.values)
if itm.values[0] == rasterBandVals[bandIndex][int(count/4)]:
print(itm.values[0])
colorRVal, colorGVal, colorBVal = itm.color['RGB'][0], itm.color['RGB'][1], itm.color['RGB'][2]
break
# if string covering float
try:
if float(itm.values[0]) == float(rasterBandVals[bandIndex][int(count/4)]):
print(itm.values[0])
colorRVal, colorGVal, colorBVal = itm.color['RGB'][0], itm.color['RGB'][1], itm.color['RGB'][2]
break
except Exception as e: print(e); pass
valRange = float(rbvalMax) - float(rbvalMin) #(rasterBandMaxVal[bandIndex] - rasterBandMinVal[bandIndex])
colorVal = int( (rasterBandVals[bandIndex][int(count/4)] - float(rbvalMin)) / valRange * 255 )
color = (colorVal<<16) + (colorVal<<8) + colorVal
except Exception as e: # if no Min Max labels:
# REMAP band values to (0,255) range
print(e)
valRange = max(rasterBandVals[bandIndex]) - min(rasterBandVals[bandIndex]) #(rasterBandMaxVal[bandIndex] - rasterBandMinVal[bandIndex])
colorRVal = colorGVal = colorBVal = int( (rasterBandVals[bandIndex][int(count/4)] - min(rasterBandVals[bandIndex])) / valRange * 255 )
print("__pixel color_")
print(colorRVal)
print(colorGVal)
print(colorBVal)
color = (colorRVal<<16) + (colorGVal<<8) + colorBVal
else:
try:
if rasterBandVals[bandIndex][int(count/4)] >= float(colorizer.minLabel) and rasterBandVals[bandIndex][int(count/4)] <= float(colorizer.maxLabel) : #rasterBandMinVal[bandIndex]:
# REMAP band values to (0,255) range
valRange = float(colorizer.maxLabel) - float(colorizer.minLabel) #(rasterBandMaxVal[bandIndex] - rasterBandMinVal[bandIndex])
colorVal = int( (rasterBandVals[bandIndex][int(count/4)] - float(colorizer.minLabel)) / valRange * 255 )
if colorizer.invertColorRamp is True: colorVal = int( (-rasterBandVals[bandIndex][int(count/4)] + float(colorizer.maxLabel)) / valRange * 255 )
color = (colorVal<<16) + (colorVal<<8) + colorVal
except: # if no Min Max labels:
# REMAP band values to (0,255) range
valRange = max(rasterBandVals[bandIndex]) - min(rasterBandVals[bandIndex]) #(rasterBandMaxVal[bandIndex] - rasterBandMinVal[bandIndex])
colorVal = int( (rasterBandVals[bandIndex][int(count/4)] - min(rasterBandVals[bandIndex])) / valRange * 255 )
color = (colorVal<<16) + (colorVal<<8) + colorVal
else: # rgb
# REMAP band values to (0,255) range
if rvalRange is not None and redBand is not None: colorRVal = int( (rasterBandVals[redBand][int(count/4)] - float(rbvalMin)) / rvalRange * 255 )
else: colorRVal = 0
if gvalRange is not None and greenBand is not None: colorGVal = int( (rasterBandVals[greenBand][int(count/4)] - float(gbvalMin)) / gvalRange * 255 )
else: colorGVal = 0
if bvalRange is not None and blueBand is not None: colorBVal = int( (rasterBandVals[blueBand][int(count/4)] - float(bbvalMin)) / bvalRange * 255 )
else: colorBVal = 0
print("__pixel color_")
print(colorRVal)
print(colorGVal)
print(colorBVal)
color = (colorRVal<<16) + (colorGVal<<8) + colorBVal
colors.extend([color,color,color,color])
count += 4
@@ -0,0 +1,601 @@
import json
from typing import Any, List, Union
import copy
import os
import arcpy
from arcpy._mp import ArcGISProject
from specklepy.objects import Base
from speckle.converter.layers.Layer import Layer, VectorLayer, RasterLayer
from arcpy.management import (CreateFeatureclass, MakeFeatureLayer,
AddFields, AlterField, DefineProjection )
def jsonFromLayerStyle(layerArcgis, path_style):
# write updated renderer to file and get layerStyle variable
arcpy.management.SaveToLayerFile(layerArcgis, path_style, False)
f = open(path_style, "r")
layerStyle = json.loads(f.read())
f.close()
os.remove(path_style)
return layerStyle
def symbol_color_to_speckle(color: dict):
newColor = (0<<16) + (0<<8) + 0
try:
r = int(color['RGB'][0])
g = int(color['RGB'][1])
b = int(color['RGB'][2])
newColor = (r<<16) + (g<<8) + b
except: pass
return newColor
def vectorRendererToNative(project: ArcGISProject, active_map, layerGroup, layerSpeckle: Union[Layer, VectorLayer], layerArcgis, f_class, existingAttrs: List) -> Union[None, dict[str, Any]] :
print("___________APPLY VECTOR RENDERER______________")
print(layerArcgis)
print(f_class)
renderer = layerSpeckle.renderer
if renderer and renderer['type']:
print(renderer['type'])
root_path = "\\".join(project.filePath.split("\\")[:-1])
#path_style = root_path + '\\' + str(f_class).split('\\')[-1] + '_old.lyrx'
data = arcpy.Describe(layerArcgis.dataSource)
if layerArcgis.isFeatureLayer:
geomType = data.shapeType
sym = layerArcgis.symbology
if renderer['type'] == 'singleSymbol':
print("RENDERER SINGLE")
print(renderer)
r,g,b = get_rgb_from_speckle(renderer['properties']['symbol']['symbColor'])
#print(r,g,b)
#print(sym.renderer.symbol.color)
sym.renderer.symbol.color = {'RGB': [r, g, b, 100]}
#print(sym.renderer.symbol.color)
layerArcgis.symbology = sym # SimpleRenderer
#print(layerArcgis)
return layerArcgis
elif renderer['type'] == 'categorizedSymbol':
print("RENDERER CATEGORIZED")
print(renderer)
cats = renderer['properties']['categories']
attribute = renderer['properties']['attribute']
if attribute not in existingAttrs: return layerArcgis
#vl2 = active_map.addLayer(layerArcgis)[0]
#sym = layerArcgis.symbology
sym.updateRenderer('UniqueValueRenderer')
print(sym.renderer.type)
print(existingAttrs)
print(attribute)
sym.renderer.fields = [attribute]
for k, grp in enumerate(sym.renderer.groups):
for itm in grp.items:
transVal = itm.values[0][0] #Grab the first "percent" value in the list of potential values
for i in range(len(cats)):
label = cats[i]['value']
if label is None or label=="" or str(label)=="": label = "<Null>"
r,g,b = get_rgb_from_speckle(cats[i]['symbColor'])
if str(transVal) == label:
itm.symbol.color = {'RGB': [r, g, b, 100]}
itm.label = label
break
layerArcgis.symbology = sym
return layerArcgis
elif renderer['type'] == 'graduatedSymbol':
print("RENDERER GRADUATED")
print(renderer)
attribute = renderer['properties']['attribute']
gradMetod = renderer['properties']['gradMethod'] # by color or by size
if gradMetod != 0:
r,g,b = get_rgb_from_speckle(renderer['properties']['sourceSymbColor'] )
sym.renderer.symbol.color = {'RGB': [r, g, b, 100]}
layerArcgis.symbology = sym # SimpleRenderer
return layerArcgis
if attribute not in existingAttrs or gradMetod != 0: return layerArcgis # by color, not line width
sym.updateRenderer('GraduatedColorsRenderer')
print(sym.renderer.type)
r,g,b = get_rgb_from_speckle(renderer['properties']['sourceSymbColor'])
ramp = renderer['properties']['ramp'] # {discrete, rampType, stops}
ranges = renderer['properties']['ranges'] # []
# get all existing values
all_values = []
with arcpy.da.UpdateCursor(f_class, attribute) as cur:
for rowShape in cur:
all_values.append(rowShape[0])
print(all_values)
del cur
print(len(ranges))
sym.renderer.classificationField = attribute
print(sym.renderer.breakCount)
sym.renderer.breakCount = len(ranges)
print(sym.renderer.breakCount)
if len(sym.renderer.classBreaks) > 0:
totalClasses = 0
for k, br in enumerate(ranges):
print(totalClasses)
if sym.renderer.breakCount < len(ranges):
valFits = 0
# check if any existing value fits in this range:
for val in all_values:
if val <= ranges[k]["upper"] and (totalClasses==0 or (totalClasses>0 and sym.renderer.classBreaks[totalClasses-1].upperBound<val)):
valFits+=1
break
if valFits == 0: continue
r,g,b = get_rgb_from_speckle(ranges[k]['symbColor'])
#classBreak.upperBound = ranges[k]["upper"]
sym.renderer.classBreaks[totalClasses].upperBound = ranges[k]["upper"]
sym.renderer.classBreaks[totalClasses].label = ranges[k]["label"]
sym.renderer.classBreaks[totalClasses].symbol.color = {'RGB': [r, g, b, 100]}
totalClasses += 1
#layerArcgis.symbology = sym
print(ranges[k]["label"])
print(ranges[k]["upper"])
sym.renderer.classBreaks[0].upperBound = ranges[0]["upper"] # otherwise its assigned maximum value
layerArcgis.symbology = sym
return layerArcgis
else: return None
def get_rgb_from_speckle(rgb: int) -> tuple[int, int, int]:
r = g = b = 0
try:
r = (rgb & 0xFF0000) >> 16
g = (rgb & 0xFF00) >> 8
b = rgb & 0xFF
except: r = g = b = 0
r,g,b = check_rgb(r,g,b)
return r,g,b
def check_rgb(r:int, g:int, b:int) -> tuple[int, int, int]:
if not isinstance(r, int) or r<0 or r>255: r=g=b=0
if not isinstance(g, int) or g<0 or g>255: r=g=b=0
if not isinstance(b, int) or b<0 or b>255: r=g=b=0
return r,g,b
def rasterRendererToNative(project: ArcGISProject, active_map, layerGroup, layer: RasterLayer, arcLayer, rasterPathsToMerge, newName):
print("_____rasterRenderer ToNative______")
renderer = layer.renderer
rendererNew = None
print(renderer)
feat = layer.features[0]
print(feat)
bandNames = feat["Band names"]
print(bandNames)
sym = arcLayer.symbology
symJson = None
path_style = ""
path_style2 = ""
print(sym)
if renderer and renderer['type']:
if not hasattr(arcLayer.symbology, 'colorizer'):
# multiband raster, CIMRasterRGBColorizer
# arcpy doesnt support multiband raster symbology: https://community.esri.com/t5/arcgis-api-for-python-questions/why-does-arcpy-mp-arcgis-pro-2-6-mosaic-dataset/td-p/1016312
root_path = "\\".join(project.filePath.split("\\")[:-1])
if not os.path.exists(root_path + '\\Layers_Speckle\\rasters_Speckle'): os.makedirs(root_path + '\\Layers_Speckle\\rasters_Speckle')
path_style = root_path + '\\Layers_Speckle\\rasters_Speckle\\' + newName + '_old.lyrx'
path_style2 = root_path + '\\Layers_Speckle\\rasters_Speckle\\' + newName + '_new.lyrx'
symJson = jsonFromLayerStyle(arcLayer, path_style)
if renderer['type'] == 'singlebandgray':
print("Singleband grey")
band_index = renderer['properties']['band']-1
if symJson is None:
sym.updateColorizer('RasterStretchColorizer')
sym.colorizer.band = band_index
arcLayer.symbology = sym
else:
temp = arcpy.management.MakeRasterLayer(rasterPathsToMerge[band_index], newName + "_temp").getOutput(0)
active_map.addLayerToGroup(layerGroup, temp)
temp_layer = None
for l in active_map.listLayers():
if l.longName == layerGroup.longName + "\\" + newName + "_temp":
print(l.longName)
temp_layer = l
break
sym = temp_layer.symbology
sym.updateColorizer('RasterStretchColorizer')
sym.colorizer.band = band_index
arcLayer.symbology = sym
active_map.removeLayer(temp_layer)
elif renderer['type'] == 'multibandcolor':
print("Multiband")
if symJson is None:
sym.updateColorizer('RasterStretchColorizer')
arcLayer.symbology = sym
else:
redSt = copy.deepcopy(symJson["layerDefinitions"][0]["colorizer"]["stretchStatsRed"])
greenSt = copy.deepcopy(symJson["layerDefinitions"][0]["colorizer"]["stretchStatsGreen"])
blueSt = copy.deepcopy(symJson["layerDefinitions"][0]["colorizer"]["stretchStatsBlue"])
redBand = renderer['properties']['redBand']
greenBand = renderer['properties']['greenBand']
blueBand = renderer['properties']['blueBand']
try: symJson["layerDefinitions"][0]["colorizer"]["greenBandIndex"] = greenBand-1
except: symJson["layerDefinitions"][0]["colorizer"]["greenBandIndex"] = 0
try: symJson["layerDefinitions"][0]["colorizer"]["redBandIndex"] = redBand-1
except: symJson["layerDefinitions"][0]["colorizer"]["redBandIndex"] = 0
try: symJson["layerDefinitions"][0]["colorizer"]["blueBandIndex"] = blueBand-1
except: symJson["layerDefinitions"][0]["colorizer"]["blueBandIndex"] = 0
print(symJson)
f = open(path_style2, "w")
f.write(json.dumps(symJson, indent=2))
f.close()
active_map.removeLayer(arcLayer)
lyrFile = arcpy.mp.LayerFile(path_style2)
active_map.addLayerToGroup(layerGroup, lyrFile )
os.remove(path_style2)
elif renderer['type'] == 'paletted':
print("Paletted")
band_index = renderer['properties']['band']-1
if symJson is None:
for br in sym.colorizer.groups:
print(br.heading) #"Value"
# go through all values classified
for k, itm in enumerate(br.items):
if k< len(renderer['properties']['classes']):
#go through saved renderer classes
for n, cl in enumerate(renderer['properties']['classes']):
if k == n:
r,g,b = get_rgb_from_speckle(cl['color'])
itm.color = {'RGB': [r,g,b, 100]}
itm.label = cl['label']
itm.values = cl['value']
else: pass
arcLayer.symbology = sym
else:
sym.updateColorizer('RasterStretchColorizer')
arcLayer.symbology = sym
return arcLayer
def rendererToSpeckle(project: ArcGISProject, active_map, arcLayer, rasterFeat: Base):
print("_____rasterRenderer To Speckle______")
if arcLayer.isRasterLayer:
try:
rType = arcLayer.symbology.colorizer.type # 'singleSymbol','categorizedSymbol','graduatedSymbol',
if rType =='RasterStretchColorizer': rType = 'singlebandgray'
elif rType =='RasterUniqueValueColorizer': rType = 'paletted' # only for 1-band raster
else: rType = 'singlebandgray'
except:
rType = "multibandcolor"
root_path = "\\".join(project.filePath.split("\\")[:-1])
if not os.path.exists(root_path + '\\Layers_Speckle\\rasters_Speckle'): os.makedirs(root_path + '\\Layers_Speckle\\rasters_Speckle')
path_style = root_path + '\\Layers_Speckle\\rasters_Speckle\\' + arcLayer.name + '_temp.lyrx'
#path_style2 = root_path + '\\' + newName + '_new.lyrx'
symJson = jsonFromLayerStyle(arcLayer, path_style)
layerRenderer: dict[str, Any] = {}
layerRenderer['type'] = rType
print(rType)
my_raster = arcpy.Raster(arcLayer.dataSource)
rasterBandNames = my_raster.bandNames
#bandNames = rasterFeat["Band names"]
bandValues = [rasterFeat["@(10000)" + name + "_values"] for name in rasterBandNames]
if rType == "singlebandgray":
try: band = arcLayer.symbology.colorizer.band
except: band = 0
try:
bVals = bandValues[band]
bvalMin = min(bVals)
bvalMax = max(bVals)
except:
bvalMin = 0
bvalMax = 255
layerRenderer.update({'properties': {'max':bvalMax,'min':bvalMin,'band':band+1,'contrast':1}})
elif rType == "multibandcolor":
try: greenBand = symJson["layerDefinitions"][0]["colorizer"]["greenBandIndex"] +1
except: greenBand = None
try: blueBand = symJson["layerDefinitions"][0]["colorizer"]["blueBandIndex"] +1
except: blueBand = None
try: redBand = symJson["layerDefinitions"][0]["colorizer"]["redBandIndex"] +1
except:
print(greenBand)
print(blueBand)
if blueBand!=1 and greenBand!=1: redBand= 1
else: redBand = None
print(redBand)
try:
rbVals = bandValues[redBand-1]
rbvalMin = min(rbVals)
rbvalMax = max(rbVals)
print(rbvalMin)
print(rbvalMax)
except:
rbvalMin = 0
rbvalMax = 255
try:
gbVals = bandValues[greenBand-1]
gbvalMin = min(gbVals)
gbvalMax = max(gbVals)
except:
gbvalMin = 0
gbvalMax = 255
try:
bbVals = bandValues[blueBand-1]
bbvalMin = min(bbVals)
bbvalMax = max(bbVals)
except:
bbvalMin = 0
bbvalMax = 255
layerRenderer.update({'properties': {'greenBand':greenBand,'blueBand':blueBand,'redBand':redBand}})
layerRenderer['properties'].update({'redContrast':1,'redMin':rbvalMin,'redMax':rbvalMax})
layerRenderer['properties'].update({'greenContrast':1,'greenMin':gbvalMin,'greenMax':gbvalMax})
layerRenderer['properties'].update({'blueContrast':1,'blueMin':bbvalMin,'blueMax':bbvalMax})
elif rType == "paletted":
band = 0
rendererClasses = arcLayer.symbology.colorizer.groups
classes = []
sourceRamp = {}
for i, cl in enumerate(rendererClasses):
if cl.heading == 'Value':
for k, itm in enumerate(cl.items):
value = itm.values[0]
label = itm.label
try:
r,g,b = itm.color['RGB'][0], itm.color['RGB'][1], itm.color['RGB'][2]
sColor = (r<<16) + (g<<8) + b
classes.append({'color':sColor,'value':value,'label':label})
except: pass
layerRenderer.update({'properties': {'classes':classes,'ramp':sourceRamp,'band':band+1}})
return layerRenderer
elif arcLayer.isFeatureLayer:
layerRenderer: dict[str, Any] = {}
sym = arcLayer.symbology
print(sym.renderer.type)
if sym.renderer.type == 'SimpleRenderer':
layerRenderer['type'] = 'singleSymbol'
layerRenderer['properties'] = {'symbol':{}, 'symbType':""}
symbolColor = symbol_color_to_speckle(sym.renderer.symbol.color)
layerRenderer['properties'].update({'symbol':{'symbColor': symbolColor}, 'symbType':''})
elif sym.renderer.type == 'UniqueValueRenderer':
layerRenderer['type'] = 'categorizedSymbol'
layerRenderer['properties'] = {'attribute': '', 'symbType': ''} #{'symbol':{}, 'ramp':{}, 'ranges':{}, 'gradMethod':"", 'symbType':"", 'legendClassificationAttribute': ""}
attribute = sym.renderer.fields[0]
layerRenderer['properties']['attribute'] = attribute
sourceSymbColor = symbol_color_to_speckle(sym.renderer.defaultSymbol.color)
layerRenderer['properties'].update( {'sourceSymbColor': sourceSymbColor} )
categories = sym.renderer.groups
layerRenderer['properties']['categories'] = []
for i, grp in enumerate(categories):
for itm in grp.items:
value = itm.values[0][0]
symbColor = symbol_color_to_speckle(itm.symbol.color)
label = itm.label
layerRenderer['properties']['categories'].append({'value':value,'symbColor':symbColor,'symbOpacity':1, 'sourceSymbColor': sourceSymbColor,'label':label})
elif sym.renderer.type == 'GraduatedColorsRenderer' or sym.renderer.type == 'GraduatedSymbolsRenderer':
layerRenderer['type'] = 'graduatedSymbol'
layerRenderer['properties'] = {'symbol':{}, 'ramp':{}, 'ranges':{}, 'gradMethod':"", 'symbType':""}
attribute = sym.renderer.classificationField
sourceSymbColor = (0<<16) + (0<<8) + 0
layerRenderer['properties'].update( {'attribute': attribute, 'symbType': '', 'gradMethod': 0, 'sourceSymbColor': sourceSymbColor} )
rRamp = sym.renderer.colorRamp # QgsGradientColorRamp
layerRenderer['properties']['ramp'] = {} # gradientColorRampToSpeckle(rRamp)
rRanges = sym.renderer.classBreaks
layerRenderer['properties']['ranges'] = []
for itm in rRanges:
try: lower = float(itm.label.split(" - ")[0]) if (" - " in rRanges.label) else float(rRanges.label[0])
except: lower = 0
upper = itm.upperBound
symbColor = symbol_color_to_speckle(itm.symbol.color)
label = itm.label
width = 0.26
# {'label': '1 - 1.4', 'lower': 1.0, 'symbColor': <PyQt5.QtGui.QColor ...BD9B9D4A0>, 'symbOpacity': 1.0, 'upper': 1.4}
layerRenderer['properties']['ranges'].append({'lower':lower,'upper':upper,'symbColor':symbColor,'symbOpacity':1,'label':label,'width':width})
elif sym.renderer.type == 'UnclassedColorsRenderer':
layerRenderer['type'] = 'graduatedSymbol'
layerRenderer['properties'] = {'symbol':{}, 'ramp':{}, 'ranges':{}, 'gradMethod':"", 'symbType':""}
attribute = sym.renderer.field
sourceSymbColor = (0<<16) + (0<<8) + 0
layerRenderer['properties'].update( {'attribute': attribute, 'symbType': '', 'gradMethod': 0, 'sourceSymbColor': sourceSymbColor} )
layerRenderer['properties']['ramp'] = {} # gradientColorRampToSpeckle(rRamp)
lowest = sym.renderer.lowerLabel
highest = sym.renderer.upperLabel
# trick to get colors
rRamp = sym.renderer.colorRamp # QgsGradientColorRamp
arcRamp = project.listColorRamps('White to Black')[0]
sym.updateRenderer('GraduatedColorsRenderer')
sym.renderer.colorRamp = arcRamp
sym.renderer.classificationField = attribute
rows_attributes = arcpy.da.SearchCursor(arcLayer.longName, attribute)
row_attrs = []
row_max = -1000000000
row_min = 1000000000
for k, attrs in enumerate(rows_attributes):
row_attrs.append(attrs[0])
if attrs[0] < row_min: row_min = attrs[0]
if attrs[0] > row_max: row_max = attrs[0]
row_range = row_max - row_min
breakCount = len(list(set(row_attrs))) # only unique values
sym.renderer.breakCount = breakCount
# run as gradient colors
rRanges = sym.renderer.classBreaks
layerRenderer['properties']['ranges'] = []
for itm in rRanges:
try: lower = float(itm.label.split(" - ")[0]) if (" - " in rRanges.label) else float(rRanges.label[0])
except: lower = 0
upper = itm.upperBound
if row_range==0: rgb = 0
else: rgb = 255 - int((itm.upperBound - row_min) / row_range * 255 )
symbColor = (rgb<<16) + (rgb<<8) + rgb
label = itm.label
width = 0.26
# {'label': '1 - 1.4', 'lower': 1.0, 'symbColor': <PyQt5.QtGui.QColor ...BD9B9D4A0>, 'symbOpacity': 1.0, 'upper': 1.4}
layerRenderer['properties']['ranges'].append({'lower':lower,'upper':upper,'symbColor':symbColor,'symbOpacity':1,'label':label,'width':width})
else: return None
return layerRenderer
else: return None
def featureColorfromNativeRenderer(index: int, arcLayer) -> int:
# case with one color for the entire layer
#try:
sym = arcLayer.symbology
color = {'RGB': [100,100,100,100]}
if sym.renderer.type == 'SimpleRenderer':
print('SimpleRenderer')
color = sym.renderer.symbol.color
elif sym.renderer.type == 'UniqueValueRenderer':
print('Unique Value Renderer')
attribute = sym.renderer.fields[0]
color = sym.renderer.defaultSymbol.color
categories = sym.renderer.groups
rows_attributes = arcpy.da.SearchCursor(arcLayer.longName, attribute)
row_shapes_list = [x for k, x in enumerate(rows_attributes)]
color_found = 0
for i, grp in enumerate(categories):
if color_found == 1: break
for n, itm in enumerate(grp.items):
for k, attrs in enumerate(row_shapes_list):
if str(itm.values[0][0]) == "<Null>": itm.values[0][0] = None
if k == index and ( str(attrs[0]) == str(itm.values[0][0]) or (attrs[0] is None and str(itm.values[0][0]) == "<Null>") ):
color = itm.symbol.color
print("symbol color: ")
print(color)
color_found = 1
break
elif sym.renderer.type == 'GraduatedColorsRenderer' or sym.renderer.type == 'GraduatedSymbolsRenderer':
print('Graduated Colors / Sybmols Renderer')
attribute = sym.renderer.classificationField
rows_attributes = arcpy.da.SearchCursor(arcLayer.longName, attribute)
row_shapes_list = [x for k, x in enumerate(rows_attributes)]
rRanges = sym.renderer.classBreaks
upperBounds = [-10000000000000000000]
color_found = 0
for itm in rRanges:
print(itm)
if color_found == 1: break
for k, attrs in enumerate(row_shapes_list):
try:
if k == index and float(attrs[0]) <= float(itm.upperBound) and (k==0 or float(attrs[0]) > float(upperBounds[-1]) ):
color = itm.symbol.color
color_found = 1
break
except: pass
upperBounds.append(itm.upperBound)
elif sym.renderer.type == 'UnclassedColorsRenderer':
print('UnclassedColorsRenderer')
attribute = sym.renderer.field
sym.updateRenderer('GraduatedColorsRenderer')
sym.renderer.classificationField = attribute
rows_attributes = arcpy.da.SearchCursor(arcLayer.longName, attribute)
row_shapes_list = [x for k, x in enumerate(rows_attributes)]
row_attrs = []
row_max = -10000000000000000000
row_min = 10000000000000000000
feat_value = None
for k, attrs in enumerate(row_shapes_list):
row_attrs.append(attrs[0])
if attrs[0] < row_min: row_min = attrs[0]
if attrs[0] > row_max: row_max = attrs[0]
if k == index: feat_value = attrs[0]
row_range = row_max - row_min
breakCount = len(list(set(row_attrs))) # only unique values
sym.renderer.breakCount = breakCount
# run as gradient colors
upperBounds = [-10000000000000000000]
rRanges = sym.renderer.classBreaks
for itm in rRanges:
print(itm)
try:
if row_range!=0 and float(feat_value) <= float(itm.upperBound) and (len(upperBounds)==0 or float(feat_value) > float(upperBounds[-1])):
rgb = 255 - int((itm.upperBound - row_min) / row_range * 255 )
color = {'RGB':[rgb,rgb,rgb,100]}
print(color)
break
except: pass
upperBounds.append(itm.upperBound)
else:
print('Else')
return (100<<16) + (100<<8) + 100
print("final color: ")
print(color)
# construct RGB color
col = symbol_color_to_speckle(color)
print(col)
return col
@@ -6,7 +6,7 @@ import arcpy
from arcpy._mp import ArcGISProject, Map, Layer as arcLayer
import os
ATTRS_REMOVE = ['geometry','applicationId','bbox','displayStyle', 'id', 'renderMaterial', 'displayMesh']
ATTRS_REMOVE = ['geometry','applicationId','bbox','displayStyle', 'id', 'renderMaterial', 'displayMesh', 'displayValue']
def getVariantFromValue(value: Any) -> Union[str, None]:
#print("_________get variant from value_______")
@@ -20,21 +20,23 @@ def getVariantFromValue(value: Any) -> Union[str, None]:
]
res = None
for p in pairs:
if isinstance(value, p[0]): res = p[1]; break
#t = type(value)
#try: res = pairs[t]
#except: pass
#if isinstance(value, str) and "PyQt5.QtCore.QDate(" in value: res = QVariant.Date #14
#elif isinstance(value, str) and "PyQt5.QtCore.QDateTime(" in value: res = QVariant.DateTime #16
if isinstance(value, p[0]):
res = p[1]
try:
if res == "LONG" and (value>= 2147483647 or value<= -2147483647):
#https://pro.arcgis.com/en/pro-app/latest/help/data/geodatabases/overview/arcgis-field-data-types.htm
res = "FLOAT"
except Exception as e: print(e)
break
return res
def getLayerAttributes(featuresList: List[Base], attrsToRemove: List[str] = ATTRS_REMOVE ) -> dict[str, str]:
print("03________ get layer attributes")
#print(featuresList)
if not isinstance(featuresList, List): features = [featuresList]
if not isinstance(featuresList, list): features = [featuresList]
else: features = featuresList[:]
fields = {}
all_props = []
for feature in features:
@@ -58,44 +60,49 @@ def getLayerAttributes(featuresList: List[Base], attrsToRemove: List[str] = ATTR
#all_props.remove(name) # remove generic dict name
for i, val_item in enumerate(value):
newF, newVals = traverseDict( {}, {}, name+"_"+str(i), val_item)
for i, (k,v) in enumerate(newF.items()):
fields.update({k: v})
if k not in all_props: all_props.append(k)
#print(fields)
if k not in fields.keys(): fields.update({k: v})
else: #check if the field was empty previously:
oldVariant = fields[k]
# replace if new one is NOT Float (too large integers)
if oldVariant != "FLOAT" and v == "FLOAT":
fields.update({k: v})
# replace if new one is NOT LongLong or IS String
if oldVariant != "TEXT" and v == "TEXT":
fields.update({k: v})
# add a field if not existing yet
else: # if str, Base, etc
newF, newVals = traverseDict( {}, {}, name, value)
for i, (k,v) in enumerate(newF.items()):
if k not in all_props: all_props.append(k)
if k not in fields.keys(): fields.update({k: v}) #if variant is known
elif k in fields.keys(): #check if the field was empty previously:
else: #check if the field was empty previously:
oldVariant = fields[k]
# replace if new one is NOT Float (too large integers)
if oldVariant != "FLOAT" and v == "FLOAT":
fields.update({k: v})
# replace if new one is NOT LongLong or IS String
if oldVariant != "TEXT" and variant == "TEXT":
fields.update({k: variant})
#print(fields)
if oldVariant != "TEXT" and v == "TEXT":
fields.update({k: v})
# replace all empty ones wit String
for name in all_props:
if name not in fields.keys():
fields.update({name: 'TEXT'})
#print(fields)
fields_sorted = {k: v for k, v in sorted(fields.items(), key=lambda item: item[0])}
return fields_sorted
def traverseDict(newF: dict, newVals: dict, nam: str, val: Any):
#print("______05___Traverse Dict")
#print(nam)
#print(val)
if isinstance(val, dict):
#print("DICT")
for i, (k,v) in enumerate(val.items()):
newF, newVals = traverseDict( newF, newVals, nam+"_"+k, v)
elif isinstance(val, Base):
#print("BASE")
dynamicProps = val.get_dynamic_member_names()
for att in ATTRS_REMOVE:
try: dynamicProps.remove(att)
@@ -109,11 +116,11 @@ def traverseDict(newF: dict, newVals: dict, nam: str, val: Any):
for i, (k,v) in enumerate(item_dict.items()):
newF, newVals = traverseDict( newF, newVals, nam+"_"+k, v)
else:
#print("ELSE")
var = getVariantFromValue(val)
if var is None:
var = 'TEXT'
val = str(val)
#print(var)
newF.update({nam: var})
newVals.update({nam: val})
@@ -1,5 +1,8 @@
from arcpy._mp import ArcGISProject, Map, Layer as arcLayer
import arcpy
import json
import os
from speckle.converter.layers.CRS import CRS
from speckle.converter.layers.Layer import Layer, VectorLayer, RasterLayer
@@ -10,14 +13,85 @@ from arcpy.management import (CreateFeatureclass, MakeFeatureLayer,
from specklepy.objects import Base
##################################################### get example layers from the project #######
project = ArcGISProject('CURRENT')
active_map = project.activeMap
all_layers = []
layerPolygon = None
layerPolyline = None
layerPoint = None
layerMultiPoint = None
layerRaster = None
#get layer of interest
for layer in active_map.listLayers():
if layer.isFeatureLayer or layer.isRasterLayer: all_layers.append(layer)
if layer.name == "ExteriorShell": break
if layer.isFeatureLayer or layer.isRasterLayer:
all_layers.append(layer)
data = arcpy.Describe(layer.dataSource)
if layer.isRasterLayer and layerRaster is None: layerRaster = layer
if layer.isFeatureLayer:
geomType = data.shapeType
if geomType == "Polygon" and layerPolygon is None: layerPolygon = layer
if geomType == "Polyline" and layerPolyline is None: layerPolyline = layer
if geomType == "Point" and layerPoint is None: layerPoint = layer
if geomType == "Multipoint" and layerMultiPoint is None: layerMultiPoint = layer
################## reset symbology if needed:
sym = layerPolygon.symbology
print(sym.renderer.type)
sym.updateRenderer('UniqueValueRenderer')
layerPolygon.symbology = sym
print(sym.updateRenderer('UniqueValueRenderer'))
print(layerPolygon.symbology.renderer.type)
# SimpleRenderer, GraduatedColorsRenderer, GraduatedSymbolsRenderer, UnclassedColorsRenderer, UniqueValueRenderer
######################################### change symbology #################################
for k, grp in enumerate(sym.renderer.groups):
for itm in grp.items:
print(itm)
print(itm.values)
print(itm.symbol.color)
transVal = itm.values[0][0] #Grab the first "percent" value in the list of potential values
print(transVal)
for i in range(len(cats)):
label = cats[i]['value']
print(label)
if label is None or label=="": label = "<Null>"
print(label)
from speckle.converter.layers.symbologyTemplates import get_polygon_simpleRenderer
from arcpy._mp import ArcGISProject
aprx = ArcGISProject('CURRENT')
root_path = "\\".join(aprx.filePath.split("\\")[:-1])
path_style = root_path + '\\layer_speckle_symbology.lyrx'
path_style2 = root_path + '\\layer_speckle_symbology2.lyrx'
#arcpy.management.SaveToLayerFile(layerPolygon, path_style, False)
print(layerPolygon.dataSource)
arcpy.management.ApplySymbologyFromLayer(
in_layer=layerPolygon.dataSource,
in_symbology_layer=path_style2,
update_symbology='UPDATE')
f = open(path_style, "r")
renderer = json.loads(f.read())
renderer["layerDefinitions"][0]["renderer"] = get_polygon_simpleRenderer(1,2,150)
f = open(path_style2, "w")
f.write(json.dumps(renderer, indent=4))
f.close()
arcpy.management.ApplySymbologyFromLayer(str(layerPolygon), path_style2)
os.remove(path_style)
os.remove(path_style2)
###########################################################################
layer = all_layers[0]
if isinstance(layer, arcLayer):
projectCRS = project.activeMap.spatialReference
@@ -229,12 +303,12 @@ feature_class = result[0]
################################# reading shapefile - works ####################
fc = r'C:\Users\katri\Documents\ArcGIS\Projects\MyProject\BIM_layers_speckle\00f70159b9104180f622cca87f5dd2cb.shp'
fc = r'C:\Users\katri\Documents\ArcGIS\Projects\MyProject\Layers_Speckle\BIM_layers_speckle\00f70159b9104180f622cca87f5dd2cb.shp'
rows = arcpy.da.SearchCursor(fc, 'Shape@')
for r in rows:
if r is not None: shape = r
print(shape)
cl = arcpy.conversion.FeatureClassToFeatureClass(r'C:\Users\katri\Documents\ArcGIS\Projects\MyProject\BIM_layers_speckle\16d73b756a_main_2f8cfa8644\__Floors_Mesh\00c7696966e4cfda2bd8c03860a414a6', r'C:\Users\katri\Documents\ArcGIS\tests', 'copyclass')
cl = arcpy.conversion.FeatureClassToFeatureClass(r'C:\Users\katri\Documents\ArcGIS\Projects\MyProject\Layers_Speckle\BIM_layers_speckle\16d73b756a_main_2f8cfa8644\__Floors_Mesh\00c7696966e4cfda2bd8c03860a414a6', r'C:\Users\katri\Documents\ArcGIS\tests', 'copyclass')
##################################### update rows in feature class - working #############
with arcpy.da.UpdateCursor('f_class_2f8cfa8644___Structural_Framing_Mesh', 'name') as cursor:
@@ -0,0 +1,73 @@
#python speckle_toolbox\esri\toolboxes\speckle\plugin_utils\testing_from_file.py
import arcpy
from arcpy._mp import ArcGISProject, Map, Layer as arcLayer
import json
import os
from arcpy._mp import ArcGISProject, Map, Layer as arcLayer
from arcpy.management import (CreateFeatureclass, MakeFeatureLayer,
AddFields, AlterField, DefineProjection )
##################################################### get example layers from the project #######
path = r'C:\Users\katri\Documents\ArcGIS\Projects\MyProject\MyProject.gdb'
arcpy.env.workspace = path
project = ArcGISProject(path.replace("gdb","aprx"))
active_map = project.listMaps()[0] #.activeMap
all_layers = []
layerPolygon = None
layerPolyline = None
layerPoint = None
layerMultiPoint = None
#get layer of interest
for layer in active_map.listLayers():
if layer.isFeatureLayer or layer.isRasterLayer:
all_layers.append(layer)
data = arcpy.Describe(layer.dataSource)
if layer.isFeatureLayer:
geomType = data.shapeType
if geomType == "Polygon" and layerPolygon is None: layerPolygon = layer
if geomType == "Polyline" and layerPolyline is None: layerPolyline = layer
if geomType == "Point" and layerPoint is None: layerPoint = layer
if geomType == "Multipoint" and layerMultiPoint is None: layerMultiPoint = layer
root_path = "\\".join(project.filePath.split("\\")[:-1])
#path_style = root_path + '\\layer_speckle_symbology.lyrx'
path_style2 = root_path + '\\layer_speckle_symbology2.lyrx'
for layer in active_map.listLayers():
if layer.longName == layerPolygon.longName:
layerPolygon = layer
break
print(layerPolygon.dataSource)
r'''
source = str(layerPolygon.dataSource).split('\\')
layerPolygon = arcpy.ApplySymbologyFromLayer_management(
in_layer= str(layerPolygon.dataSource),
in_symbology_layer=path_style2,
update_symbology='UPDATE')[0]
'''
#vl2 = MakeFeatureLayer(layerPolygon.dataSource, 'someName').getOutput(0)
#active_map.addLayer(arcpy.mp.LayerFile(path_style2))
################## reset symbology if needed:
sym = layerPolygon.symbology
print(sym.renderer.type)
sym.updateRenderer('UniqueValueRenderer')
print(sym.renderer.type)
layerPolygon.symbology = sym
print(sym.renderer.type)
r'''
sym = layerPolygon.symbology
print(sym.renderer.type)
sym.updateRenderer('UniqueValueRenderer')
layerPolygon.symbology = sym
print(sym.updateRenderer('UniqueValueRenderer'))
print(layerPolygon.symbology.renderer.type)
# SimpleRenderer, GraduatedColorsRenderer, GraduatedSymbolsRenderer, UnclassedColorsRenderer, UniqueValueRenderer
'''
project.save()
@@ -0,0 +1,13 @@
import arcpy
from arcpy._mp import ArcGISProject, Map, Layer as arcLayer
import json
import os
from arcpy._mp import ArcGISProject, Map, Layer as arcLayer
from arcpy.management import (CreateFeatureclass, MakeFeatureLayer,
AddFields, AlterField, DefineProjection )
import unittest
@@ -83,8 +83,8 @@ class Toolbox:
# https://pro.arcgis.com/en/pro-app/2.8/arcpy/mapping/alphabeticallistofclasses.htm#except: print("something happened")
class Speckle:
def __init__(self):
#print("________________reset_______________")
def __init__(self):
print("__________________INIT SPECKLE TOOL_________")
self.label = "Speckle"
self.description = "Allows you to send and receive your layers " + \
"to/from other software using Speckle server."
@@ -92,39 +92,28 @@ class Speckle:
self.toRefresh = False
self.speckleInputs = None
self.toolboxInputs = None
#print("ping_Speckle1")
#print(speckleInputsClass.instances)
total = len(speckleInputsClass.instances)
#print(total)
print(total)
for i in range(total):
#print(i)
#print(speckleInputsClass.instances[total-i-1])
if speckleInputsClass.instances[total-i-1] is not None:
try:
#print(speckleInputsClass.instances[total-i-1].streams_default)
y = speckleInputsClass.instances[total-i-1].streams_default # in case not initialized properly
y = speckleInputsClass.instances[total-i-1].streams_default
#if not isinstance(speckleInputsClass.instances[total-i-1].streams_default, SpeckleException): # also will throw exception in case not initialized properly
self.speckleInputs = speckleInputsClass.instances[total-i-1] # take latest (first in reverted list)
#print("FOUND INSTANCE")
break
except: pass
#print(self.speckleInputs)
if self.speckleInputs is None: self.speckleInputs = speckleInputsClass()
if self.speckleInputs is None or isinstance(self.speckleInputs.streams_default, SpeckleException): self.speckleInputs = speckleInputsClass()
#print(self.speckleInputs.streams_default)
print(len(speckleInputsClass.instances))
#print(toolboxInputsClass.instances)
#print("TOTAL = ...................")
total = len(toolboxInputsClass.instances)
#print(total)
for i in range(total):
if toolboxInputsClass.instances[total-i-1] is not None:
self.toolboxInputs = toolboxInputsClass.instances[total-i-1] # take latest (first in reverted list)
#print("FOUND INSTANCE")
break
#print(self.toolboxInputs)
if self.toolboxInputs is None: self.toolboxInputs = toolboxInputsClass()
#print("ping_Speckle2")
def getParameterInfo(self):
#data types: https://pro.arcgis.com/en/pro-app/2.8/arcpy/geoprocessing_and_python/defining-parameter-data-types-in-a-python-toolbox.htm
@@ -144,7 +133,11 @@ class Speckle:
category=cat1
)
streamsDefalut.filter.type = 'ValueList'
streamsDefalut.filter.list = [ (st.name + " - " + st.id) for st in self.speckleInputs.streams_default ]
if isinstance(self.speckleInputs.streams_default, SpeckleException):
arcpy.AddError("Speckle account not accessible")
streamsDefalut.filter.list = []
else:
streamsDefalut.filter.list = [ (st.name + " - " + st.id) for st in self.speckleInputs.streams_default ]
addDefStreams = arcpy.Parameter(
displayName="Add",
@@ -418,9 +411,11 @@ class Speckle:
#print("SAVED STREAMS - selection")
selected_stream_name = par.valueAsText[:]
self.toolboxInputs.active_stream = None
self.toolboxInputs.active_stream_wrapper = None
for st in self.speckleInputs.saved_streams:
if st[1].name == selected_stream_name.split(" - ")[0]:
self.toolboxInputs.active_stream = st[1]
self.toolboxInputs.active_stream_wrapper = st[0]
break
# edit branches: globals and UI
@@ -536,7 +531,12 @@ class Speckle:
if par.name == "lat": par.value = str(self.toolboxInputs.get_survey_point()[0])
if par.name == "lon": par.value = str(self.toolboxInputs.get_survey_point()[1])
if par.name == "streamsDefalut": par.filter.list = [ (st.name + " - " + st.id) for st in self.speckleInputs.streams_default ]
if par.name == "streamsDefalut":
if isinstance(self.speckleInputs.streams_default, SpeckleException):
arcpy.AddError("Speckle account not accessible")
par.filter.list = []
else:
par.filter.list = [ (st.name + " - " + st.id) for st in self.speckleInputs.streams_default ]
if par.name == "savedStreams":
#print("par.name")
saved_streams = self.speckleInputs.getProjectStreams()
@@ -584,7 +584,8 @@ class Speckle:
return
streamId = self.toolboxInputs.active_stream.id #stream_id
client = self.speckleInputs.speckle_client # ?
client = self.toolboxInputs.active_stream_wrapper.get_client()
#client = self.speckleInputs.speckle_client # ?
# Get the stream wrapper
#streamWrapper = StreamWrapper(None)
@@ -642,7 +643,8 @@ class Speckle:
try:
streamId = self.toolboxInputs.active_stream.id #stream_id
client = self.speckleInputs.speckle_client #
client = self.toolboxInputs.active_stream_wrapper.get_client()
#client = self.speckleInputs.speckle_client #
except SpeckleWarning as warning:
arcpy.AddWarning(str(warning.args[0]))
@@ -674,11 +676,13 @@ class Speckle:
except:
arcpy.AddError("Make sure your account has access to the chosen stream")
return
try:
#print(commit)
objId = commit.referencedObject
commitDetailed = client.commit.get(streamId, commit.id)
if isinstance(commitDetailed, GraphQLException):
arcpy.AddError("Access error")
return
app = commitDetailed.sourceApplication
if objId is None:
return
@@ -692,6 +696,8 @@ class Speckle:
# Clear 'latest' group
streamBranch = streamId + "_" + self.toolboxInputs.active_branch.name + "_" + str(commit.id)
streamBranch = streamBranch.replace("[","_").replace("]","_").replace(" ","_").replace("-","_").replace("(","_").replace(")","_").replace(":","_").replace("\\","_").replace("/","_").replace("\"","_").replace("&","_").replace("@","_").replace("$","_").replace("%","_").replace("^","_")
newGroupName = f'{streamBranch}'
groupExists = 0
@@ -750,6 +756,8 @@ class Speckle:
except: pass
def loopVal(value: Any, name: str): # "name" is the parent object/property/layer name
if name.endswith('/displayValue'): return
if isinstance(value, Base):
try: # dont go through parts of Speckle Geometry object
print("objects to loop through: " + value.speckle_type)
@@ -760,7 +768,8 @@ class Speckle:
if isinstance(value, List):
for item in value:
loopVal(item, name)
#print(item)
print(item)
pt = None
if item.speckle_type and item.speckle_type.startswith("Objects.Geometry."):
@@ -769,8 +778,8 @@ class Speckle:
if pl is not None: print("Layer group created: " + pl.name())
break
if item.speckle_type and "Revit" in item.speckle_type and item.speckle_type.startswith("Objects.BuiltElements."):
if item.speckle_type and (item.speckle_type.startswith("Objects.BuiltElements.") or item.speckle_type.startswith("Objects.Structural.Geometry")): # and "Revit" in item.speckle_type
print("__receiving structures__")
msh_bool = bimLayerToNative(value, name, streamBranch, self.speckleInputs.project)
#if msh is not None: print("Layer group created: " + msh.name())
break
@@ -101,7 +101,7 @@ class speckleInputsClass:
streamExists = 0
index = 0
try:
print(url)
#print(url)
sw = StreamWrapper(url)
stream = self.tryGetStream(sw)
@@ -140,6 +140,7 @@ class toolboxInputsClass:
lat: float = 0.0
lon: float = 0.0
active_stream: Optional[Stream] = None
active_stream_wrapper: Optional[StreamWrapper] = None
active_branch: Optional[Branch] = None
active_commit = None
selected_layers: List[Any] = []