Compare commits
21 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 18234800dd | |||
| 2949142140 | |||
| 5c9138238a | |||
| 276c78603b | |||
| 323d23cfaf | |||
| ab8805d5f2 | |||
| 8b0ee41ed7 | |||
| 92ce4c6abb | |||
| 9596e14c2d | |||
| cb5240c4c0 | |||
| edc686526a | |||
| ed97d83468 | |||
| 5b86638749 | |||
| 1e308bf1ab | |||
| 971d71fc7e | |||
| 821acf93d8 | |||
| 0f4494936e | |||
| 5791667bfe | |||
| 364c8fe507 | |||
| 791dd045c3 | |||
| 999c67ea8d |
@@ -34,6 +34,8 @@ jobs:
|
||||
$version = "$($ver).$($env:CIRCLE_BUILD_NUM)"
|
||||
echo $semver
|
||||
python patch_version.py $semver
|
||||
python setup.py sdist bdist_wheel
|
||||
Copy-Item -Path "dist\speckle_toolbox-$($ver)-py3-none-any.whl" -Destination "speckle_arcgis_installer"
|
||||
speckle-sharp-ci-tools\InnoSetup\ISCC.exe speckle-sharp-ci-tools\arcgis.iss
|
||||
- when:
|
||||
condition: << parameters.installer >>
|
||||
|
||||
@@ -74,7 +74,7 @@ Setup is adapted from [this tutorial](https://pro.arcgis.com/en/pro-app/2.8/arcp
|
||||
|
||||
#### Dev Environment
|
||||
|
||||
For a better development experience in your editor, we recommend creating a [virtual environment in ArcGIS](https://pro.arcgis.com/en/pro-app/2.8/arcpy/get-started/work-with-python-environments.htm). In the venv, you'll just need to install `specklepy`.
|
||||
For a better development experience in your editor, we recommend creating a [virtual conda environment in ArcGIS](https://pro.arcgis.com/en/pro-app/2.8/arcpy/get-started/work-with-python-environments.htm). In the new conda environment, you'll just need to install `specklepy` and `panda3d`.
|
||||
|
||||
### Debugging
|
||||
|
||||
|
||||
@@ -16,6 +16,8 @@ def read(fname):
|
||||
setup(name='speckle_toolbox',
|
||||
author='SpeckleSystems',
|
||||
version="2.9.4",
|
||||
author_email="connectors@speckle.systems",
|
||||
url="https://speckle.systems/",
|
||||
description=("Example for extending geoprocessing through Python modules"),
|
||||
long_description=read('Readme.md'),
|
||||
python_requires='~=3.3',
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -9,6 +9,7 @@ from speckle.converter.geometry.polygon import polygonToNative, polygonToSpeckle
|
||||
from speckle.converter.geometry.polyline import arcToNative, ellipseToNative, circleToNative, curveToNative, lineToNative, polycurveToNative, polylineFromVerticesToSpeckle, polylineToNative, polylineToSpeckle
|
||||
from speckle.converter.geometry.point import pointToCoord, pointToNative, pointToSpeckle, multiPointToSpeckle
|
||||
from speckle.converter.geometry.polyline import speckleArcCircleToPoints, specklePolycurveToPoints, multiPolylineToSpeckle
|
||||
from speckle.converter.geometry.mesh import meshToNative
|
||||
import numpy as np
|
||||
|
||||
def convertToSpeckle(feature, layer, geomType, featureType) -> Union[Base, Sequence[Base], None]:
|
||||
|
||||
@@ -1,10 +1,58 @@
|
||||
from typing import List
|
||||
import arcpy
|
||||
|
||||
from specklepy.objects.geometry import Mesh
|
||||
|
||||
import shapefile
|
||||
from shapefile import TRIANGLE_STRIP, TRIANGLE_FAN
|
||||
from speckle.converter.layers.utils import get_scale_factor
|
||||
|
||||
def meshToNative(mesh: Mesh):
|
||||
"""Converts a Speckle Mesh to QgsGeometry. Currently UNSUPPORTED"""
|
||||
return None
|
||||
def meshToNative(meshes: List[Mesh], path: str):
|
||||
"""Converts a Speckle Mesh to MultiPatch"""
|
||||
print("06___________________Mesh to Native")
|
||||
#print(meshes)
|
||||
#print(mesh.units)
|
||||
w = shapefile.Writer(path)
|
||||
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)
|
||||
w.close()
|
||||
return path
|
||||
|
||||
def fill_mesh_parts(w: shapefile.Writer, mesh: Mesh):
|
||||
scale = get_scale_factor(mesh.units)
|
||||
|
||||
parts_list = []
|
||||
types_list = []
|
||||
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:
|
||||
for f in mesh.faces:
|
||||
try:
|
||||
if mesh.faces[count] == 0 or mesh.faces[count] == 3: # only handle triangles
|
||||
f1 = [ scale*mesh.vertices[mesh.faces[count+1]*3], scale*mesh.vertices[mesh.faces[count+1]*3+1], scale*mesh.vertices[mesh.faces[count+1]*3+2] ]
|
||||
f2 = [ scale*mesh.vertices[mesh.faces[(count+2)]*3], scale*mesh.vertices[mesh.faces[(count+2)]*3+1], scale*mesh.vertices[mesh.faces[(count+2)]*3+2] ]
|
||||
f3 = [ scale*mesh.vertices[mesh.faces[(count+3)]*3], scale*mesh.vertices[mesh.faces[(count+3)]*3+1], scale*mesh.vertices[mesh.faces[(count+3)]*3+2] ]
|
||||
parts_list.append([ f1, f2, f3 ])
|
||||
types_list.append(TRIANGLE_FAN)
|
||||
count += 4
|
||||
else:
|
||||
count += mesh.faces[count+1]
|
||||
except: break
|
||||
w.multipatch(parts_list, partTypes=types_list ) # one type for each part
|
||||
w.record('displayMesh')
|
||||
else: print("not triangulated mesh")
|
||||
|
||||
except Exception as e: pass #; print(e)
|
||||
return w
|
||||
|
||||
def rasterToMesh(vertices, faces, colors):
|
||||
mesh = Mesh.create(vertices, faces, colors)
|
||||
mesh.units = "m"
|
||||
|
||||
@@ -7,8 +7,10 @@ from typing import Any, List, Tuple, Union
|
||||
from regex import D
|
||||
from speckle.converter.layers.CRS import CRS
|
||||
from speckle.converter.layers.Layer import Layer, VectorLayer, RasterLayer
|
||||
from speckle.converter.layers.feature import featureToNative, featureToSpeckle, cadFeatureToNative, rasterFeatureToSpeckle
|
||||
from speckle.converter.layers.feature import featureToNative, featureToSpeckle, cadFeatureToNative, bimFeatureToNative, rasterFeatureToSpeckle
|
||||
from specklepy.objects import Base
|
||||
from specklepy.objects.geometry import Mesh
|
||||
from speckle.converter.geometry.mesh import rasterToMesh, meshToNative
|
||||
|
||||
import arcgisscripting
|
||||
import pandas as pd
|
||||
@@ -38,8 +40,8 @@ def convertSelectedLayers(all_layers: List[arcLayer], selected_layers: List[str]
|
||||
#if layerToSend.isFeatureLayer:
|
||||
newBaseLayer = layerToSpeckle(layerToSend, project)
|
||||
if newBaseLayer is not None: result.append(newBaseLayer)
|
||||
|
||||
elif layerToSend.isRasterLayer: pass
|
||||
print(result)
|
||||
|
||||
return result
|
||||
|
||||
@@ -121,6 +123,8 @@ def layerToSpeckle(layer: arcLayer, project: ArcGISProject) -> Union[VectorLayer
|
||||
speckleLayer.features=layerObjs
|
||||
speckleLayer.geomType = data.shapeType
|
||||
|
||||
if len(speckleLayer.features) == 0: return None
|
||||
|
||||
#layerBase.renderer = layerRenderer
|
||||
#layerBase.applicationId = selectedLayer.id()
|
||||
|
||||
@@ -160,7 +164,184 @@ def layerToNative(layer: Union[Layer, VectorLayer, RasterLayer], streamBranch: s
|
||||
return rasterLayerToNative(layer, streamBranch, project)
|
||||
return None
|
||||
|
||||
def cadLayerToNative(layerContentList:Base, layerName: str, streamBranch: str, project: ArcGISProject) :
|
||||
def bimLayerToNative(layerContentList: List[Base], layerName: str, streamBranch: str, project: ArcGISProject) :
|
||||
print("01______BIM layer to native")
|
||||
print(layerName)
|
||||
geom_meshes = []
|
||||
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)
|
||||
|
||||
if len(geom_meshes)>0: layer_meshes = bimVectorLayerToNative(geom_meshes, layerName, "Mesh", streamBranch, project)
|
||||
|
||||
return True
|
||||
|
||||
|
||||
def bimVectorLayerToNative(geomList, layerName: str, geomType: str, streamBranch: str, project: ArcGISProject):
|
||||
# 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
|
||||
#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 + "\\" #
|
||||
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")
|
||||
|
||||
#CREATE A GROUP "received blabla" with sublayers
|
||||
layerGroup = None
|
||||
newGroupName = f'{streamBranch}'
|
||||
#print(newGroupName)
|
||||
for l in active_map.listLayers():
|
||||
if l.longName == newGroupName: layerGroup = l; break
|
||||
|
||||
#find ID of the layer with a matching name in the "latest" group
|
||||
newName = f'{streamBranch.split("_")[len(streamBranch.split("_"))-1]}_{layerName}'
|
||||
print(newName)
|
||||
|
||||
all_layer_names = []
|
||||
layerExists = 0
|
||||
for l in project.activeMap.listLayers():
|
||||
if l.longName.startswith(newGroupName + "\\"):
|
||||
all_layer_names.append(l.longName)
|
||||
#print(all_layer_names)
|
||||
|
||||
longName = streamBranch + "\\" + newName
|
||||
if longName in all_layer_names:
|
||||
for index, letter in enumerate('234567890abcdefghijklmnopqrstuvwxyz'):
|
||||
if (longName + "_" + letter) not in all_layer_names: newName += "_"+letter; layerExists +=1; break
|
||||
|
||||
# particularly if the layer comes from ArcGIS
|
||||
if "mesh" in geomType.lower(): geomType = "Multipatch"
|
||||
|
||||
#print("Create feature class (cad): ")
|
||||
# should be created inside the workspace to be a proper Feature class (not .shp) with Nullable Fields
|
||||
class_name = ("f_class_" + newName)
|
||||
#f_class = CreateFeatureclass(path, class_name, geomType, has_z="ENABLED", spatial_reference = sr)
|
||||
|
||||
|
||||
shp = meshToNative(geomList, path_bim + newName)
|
||||
print("____ meshes saved___")
|
||||
print(shp)
|
||||
#print(path)
|
||||
#print(class_name)
|
||||
validated_class_path = validate_path(class_name)
|
||||
print(validated_class_path)
|
||||
validated_class_name = validated_class_path.split("\\")[len(validated_class_path.split("\\"))-1]
|
||||
print(validated_class_name)
|
||||
f_class = arcpy.conversion.FeatureClassToFeatureClass(shp, path, validated_class_name)
|
||||
# , spatial_reference = sr
|
||||
#arcpy.management.Project(in_dataset, f_class, sr, in_coor_system=sr)
|
||||
|
||||
print(f_class)
|
||||
#print(geomList)
|
||||
|
||||
# get and set Layer attribute fields
|
||||
# example: https://resource.esriuk.com/blog/an-introductory-slice-of-arcpy-in-arcgis-pro/
|
||||
newFields = getLayerAttributes(geomList)
|
||||
|
||||
fields_to_ignore = ["arcgisgeomfromspeckle", "shape", "objectid", "displayMesh"]
|
||||
matrix = []
|
||||
all_keys = []
|
||||
all_key_types = []
|
||||
max_len = 52
|
||||
|
||||
print("___ after layer attributes: ___________")
|
||||
print(newFields.items())
|
||||
#try:
|
||||
for key, value in newFields.items():
|
||||
existingFields = [fl.name for fl in arcpy.ListFields(validated_class_name)]
|
||||
#print(existingFields)
|
||||
if key not in existingFields and key.lower() not in fields_to_ignore: # exclude geometry and default existing fields
|
||||
#print(key)
|
||||
# signs that should not be used as field names and table names: https://support.esri.com/en/technical-article/000005588
|
||||
key = key.replace(" ","_").replace("-","_").replace("(","_").replace(")","_").replace(":","_").replace("\\","_").replace("/","_").replace("\"","_").replace("&","_").replace("@","_").replace("$","_").replace("%","_").replace("^","_")
|
||||
if key[0] in ['0','1','2','3','4','5','6','7','8','9']: key = "_"+key
|
||||
if len(key)>max_len: key = key[:max_len]
|
||||
#print(all_keys)
|
||||
if key in all_keys:
|
||||
for index, letter in enumerate('1234567890abcdefghijklmnopqrstuvwxyz'):
|
||||
if len(key)<max_len and (key+letter) not in all_keys: key+=letter; break
|
||||
if len(key) == max_len and (key[:9] + letter) not in all_keys: key=key[:9] + letter; break
|
||||
if key not in all_keys:
|
||||
all_keys.append(key)
|
||||
all_key_types.append(value)
|
||||
#print(all_keys)
|
||||
matrix.append([key, value, key, 255])
|
||||
print(all_keys)
|
||||
print(len(all_keys))
|
||||
if len(matrix)>0: AddFields(str(f_class), matrix)
|
||||
|
||||
fets = []
|
||||
print("_________BIM FeatureS To Native___________")
|
||||
for f in geomList[:]:
|
||||
new_feat = bimFeatureToNative(f, newFields, sr, path_bim)
|
||||
if new_feat != "" and new_feat != None:
|
||||
fets.append(new_feat)
|
||||
print(len(fets))
|
||||
|
||||
|
||||
if len(fets) == 0: return None
|
||||
count = 0
|
||||
rowValues = []
|
||||
for i, feat in enumerate(fets):
|
||||
|
||||
row = []
|
||||
heads = []
|
||||
for key in all_keys:
|
||||
try:
|
||||
row.append(feat[key])
|
||||
heads.append(key)
|
||||
except Exception as e:
|
||||
row.append(None)
|
||||
heads.append(key)
|
||||
|
||||
rowValues.append(row)
|
||||
count += 1
|
||||
|
||||
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
|
||||
try:
|
||||
for rowShape in cur:
|
||||
for i,r in enumerate(rowShape):
|
||||
rowShape[i] = rowValues[shp_num][i]
|
||||
if isinstance(rowValues[shp_num][i], str): rowShape[i] = rowValues[shp_num][i][:255]
|
||||
|
||||
cur.updateRow(rowShape)
|
||||
shp_num += 1
|
||||
except Exception as e:
|
||||
print(e)
|
||||
print(i)
|
||||
print(shp_num)
|
||||
print(len(rowValues))
|
||||
print(rowValues[i-1])
|
||||
print(len(rowValues[i-1]))
|
||||
del cur
|
||||
|
||||
print("create layer:")
|
||||
vl = MakeFeatureLayer(str(f_class), newName).getOutput(0)
|
||||
|
||||
active_map.addLayerToGroup(layerGroup, vl)
|
||||
print("created2")
|
||||
#os.remove(path_bim)
|
||||
|
||||
return True #last one
|
||||
|
||||
def cadLayerToNative(layerContentList: List[Base], layerName: str, streamBranch: str, project: ArcGISProject) :
|
||||
print("01______Cad vector layer to native")
|
||||
print(layerName)
|
||||
geom_points = []
|
||||
@@ -187,7 +368,7 @@ def cadVectorLayerToNative(geomList, layerName: str, geomType: str, streamBranch
|
||||
layerName = layerName.replace("[","_").replace("]","_").replace(" ","_").replace("-","_").replace("(","_").replace(")","_").replace(":","_").replace("\\","_").replace("/","_").replace("\"","_").replace("&","_").replace("@","_").replace("$","_").replace("%","_").replace("^","_")
|
||||
layerName = layerName + "_" + geomType
|
||||
|
||||
sr = arcpy.SpatialReference(project.activeMap.spatialReference.name)
|
||||
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 + "\\" #
|
||||
|
||||
@@ -231,7 +412,7 @@ def cadVectorLayerToNative(geomList, layerName: str, geomType: str, streamBranch
|
||||
# should be created inside the workspace to be a proper Feature class (not .shp) with Nullable Fields
|
||||
class_name = ("f_class_" + newName)
|
||||
f_class = CreateFeatureclass(path, class_name, geomType, has_z="ENABLED", spatial_reference = sr)
|
||||
#print(f_class)
|
||||
print(f_class)
|
||||
#print(geomList)
|
||||
|
||||
# get and set Layer attribute fields
|
||||
@@ -269,7 +450,7 @@ def cadVectorLayerToNative(geomList, layerName: str, geomType: str, streamBranch
|
||||
if new_feat != "" and new_feat != None:
|
||||
fets.append(new_feat)
|
||||
#print("features created")
|
||||
#print(fets)
|
||||
print(len(fets))
|
||||
|
||||
if len(fets) == 0: return None
|
||||
count = 0
|
||||
@@ -287,19 +468,16 @@ def cadVectorLayerToNative(geomList, layerName: str, geomType: str, streamBranch
|
||||
row.append(value)
|
||||
rowValues.append(row)
|
||||
count += 1
|
||||
#print(heads)
|
||||
cur = arcpy.da.InsertCursor(str(f_class), tuple(heads) )
|
||||
for row in rowValues:
|
||||
#print(tuple(heads))
|
||||
#print(tuple(row))
|
||||
cur.insertRow(tuple(row))
|
||||
del cur
|
||||
#print(f_class)
|
||||
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)
|
||||
print("Layer created")
|
||||
|
||||
return vl
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@ from speckle.converter.layers.utils import (findTransformation, getVariantFromVa
|
||||
traverseDictByKey, hsv_to_rgb)
|
||||
|
||||
from speckle.converter.geometry.point import pointToSpeckle
|
||||
from speckle.converter.geometry.mesh import rasterToMesh
|
||||
from speckle.converter.geometry.mesh import rasterToMesh, meshToNative
|
||||
|
||||
import numpy as np
|
||||
import colorsys
|
||||
@@ -27,10 +27,19 @@ def featureToSpeckle(fieldnames, attr_list, f_shape, projectCRS: arcpy.SpatialRe
|
||||
layer_sr = data.spatialReference # if sr.type == "Projected":
|
||||
geomType = data.shapeType #Polygon, Point, Polyline, Multipoint, MultiPatch
|
||||
featureType = data.featureType # Simple,SimpleJunction,SimpleJunction,ComplexEdge,Annotation,CoverageAnnotation,Dimension,RasterCatalogItem
|
||||
|
||||
print(geomType)
|
||||
print(hasattr(data, "isRevit"))
|
||||
print(hasattr(data, "isIFC"))
|
||||
print(hasattr(data, "bimLevels"))
|
||||
print(hasattr(data, "hasSpatialIndex"))
|
||||
if geomType == "MultiPatch" or hasattr(data, "isRevit") or hasattr(data, "isIFC") or hasattr(data, "bimLevels"):
|
||||
print(f"Layer {selectedLayer.name} has unsupported data type")
|
||||
arcpy.AddWarning(f"Layer {selectedLayer.name} has unsupported data type")
|
||||
return None
|
||||
#print(layer_sr.name)
|
||||
#print(projectCRS.name)
|
||||
f_shape = findTransformation(f_shape, geomType, layer_sr, projectCRS, selectedLayer)
|
||||
if f_shape is None: return None
|
||||
|
||||
######################################### Convert geometry ##########################################
|
||||
try:
|
||||
@@ -82,9 +91,26 @@ def featureToNative(feature: Base, fields: dict, geomType: str, sr: arcpy.Spatia
|
||||
if variant == "LONG": feat.update({key: None})
|
||||
if variant == "SHORT": feat.update({key: None})
|
||||
return feat
|
||||
|
||||
def bimFeatureToNative(feature: Base, fields: dict, sr: arcpy.SpatialReference, path: str):
|
||||
#print("04_________BIM Feature To Native____________")
|
||||
|
||||
feat = {}
|
||||
try: speckle_geom = feature["geometry"] # for created in QGIS Layer type
|
||||
except: speckle_geom = feature # for created in other software
|
||||
|
||||
feat.update({"arcGisGeomFromSpeckle": ""})
|
||||
|
||||
try:
|
||||
if "Speckle_ID" not in fields.keys() and feature["id"]: feat.update("Speckle_ID", "TEXT")
|
||||
except: pass
|
||||
feat_updated = updateFeat(feat, fields, feature)
|
||||
|
||||
return feat_updated
|
||||
|
||||
|
||||
def cadFeatureToNative(feature: Base, fields: dict, sr: arcpy.SpatialReference):
|
||||
print("04_________CAD Feature To Native____________")
|
||||
#print("04_________CAD Feature To Native____________")
|
||||
feat = {}
|
||||
try: speckle_geom = feature["geometry"] # for created in QGIS Layer type
|
||||
except: speckle_geom = feature # for created in other software
|
||||
@@ -94,43 +120,73 @@ def cadFeatureToNative(feature: Base, fields: dict, sr: arcpy.SpatialReference):
|
||||
else: arcGisGeom = convertToNative(speckle_geom[0], sr)
|
||||
else:
|
||||
arcGisGeom = convertToNative(speckle_geom, sr)
|
||||
print(feat)
|
||||
|
||||
if arcGisGeom is not None:
|
||||
feat.update({"arcGisGeomFromSpeckle": arcGisGeom})
|
||||
else: return None
|
||||
print(feat)
|
||||
|
||||
try:
|
||||
if "Speckle_ID" not in fields.keys() and feature["id"]: feat.update("Speckle_ID", "TEXT")
|
||||
except: pass
|
||||
print(feat)
|
||||
#### setting attributes to feature
|
||||
for key, variant in fields.items():
|
||||
#value = feature[key]
|
||||
#print()
|
||||
if key == "Speckle_ID":
|
||||
value = str(feature["id"])
|
||||
feat[key] = value
|
||||
else:
|
||||
try: value = feature[key]
|
||||
except:
|
||||
rootName = key.split("_")[0]
|
||||
newF, newVals = traverseDict({}, {}, rootName, feature[rootName][0])
|
||||
for i, (k,v) in enumerate(newVals.items()):
|
||||
if k == key: value = v; break
|
||||
# for all values:
|
||||
if variant == "TEXT": value = str(value)
|
||||
|
||||
if variant == getVariantFromValue(value) and value != "NULL" and value != "None":
|
||||
feat.update({key: value})
|
||||
else:
|
||||
if variant == "TEXT": feat.update({key: None})
|
||||
if variant == "FLOAT": feat.update({key: None})
|
||||
if variant == "LONG": feat.update({key: None})
|
||||
if variant == "SHORT": feat.update({key: None})
|
||||
|
||||
print(feat)
|
||||
return feat
|
||||
#### setting attributes to feature
|
||||
feat_updated = updateFeat(feat, fields, feature)
|
||||
return feat_updated
|
||||
|
||||
def updateFeat(feat:dict, fields: dict, feature: Base) -> dict[str, Any]:
|
||||
|
||||
for key, variant in fields.items():
|
||||
try:
|
||||
if key == "Speckle_ID":
|
||||
value = str(feature["id"])
|
||||
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})
|
||||
|
||||
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})
|
||||
|
||||
except:
|
||||
value = None
|
||||
rootName = key.split("_")[0]
|
||||
#try: # if the root category exists
|
||||
# if its'a list
|
||||
if isinstance(feature[rootName], list):
|
||||
for i in range(len(feature[rootName])):
|
||||
try:
|
||||
newF, newVals = traverseDict({}, {}, rootName + "_" + str(i), feature[rootName][i])
|
||||
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})
|
||||
except Exception as e: print(e)
|
||||
#except: # if not a list
|
||||
else:
|
||||
try:
|
||||
newF, newVals = traverseDict({}, {}, rootName, feature[rootName])
|
||||
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})
|
||||
except Exception as e: feat.update({key: None})
|
||||
except Exception as e:
|
||||
feat.update({key: None})
|
||||
feat_sorted = {k: v for k, v in sorted(feat.items(), key=lambda item: item[0])}
|
||||
#print("_________________end of updating a feature_________________________")
|
||||
return feat_sorted
|
||||
|
||||
def rasterFeatureToSpeckle(selectedLayer: arcLayer, projectCRS: arcpy.SpatialReference, project: ArcGISProject) -> Base:
|
||||
print("_________ Raster feature to speckle______")
|
||||
# https://pro.arcgis.com/en/pro-app/latest/arcpy/classes/raster-object.htm
|
||||
@@ -181,6 +237,8 @@ def rasterFeatureToSpeckle(selectedLayer: arcLayer, projectCRS: arcpy.SpatialRef
|
||||
reprojectedPt = rasterOriginPoint
|
||||
if my_raster.spatialReference.name != projectCRS.name:
|
||||
reprojectedPt = findTransformation(reprojectedPt, "Point", my_raster.spatialReference, projectCRS, selectedLayer)
|
||||
if reprojectedPt is None:
|
||||
reprojectedPt = rasterOriginPoint
|
||||
geom = pointToSpeckle(reprojectedPt.getPart(), None, None)
|
||||
if (geom != None):
|
||||
b['displayValue'] = [geom]
|
||||
@@ -324,7 +382,7 @@ def rasterFeatureToSpeckle(selectedLayer: arcLayer, projectCRS: arcpy.SpatialRef
|
||||
pt3 = arcpy.PointGeometry(arcpy.Point(extent.XMin+(h+1)*rasterResXY[0], extent.YMax-(v+1)*rasterResXY[1]), my_raster.spatialReference, has_z = True)
|
||||
pt4 = arcpy.PointGeometry(arcpy.Point(extent.XMin+(h+1)*rasterResXY[0], extent.YMax-v*rasterResXY[1]), my_raster.spatialReference, has_z = True)
|
||||
# first, get point coordinates with correct position and resolution, then reproject each:
|
||||
if my_raster.spatialReference.name != projectCRS.name:
|
||||
if my_raster.spatialReference.exportToString() != projectCRS.exportToString():
|
||||
pt1 = findTransformation(pt1, "Point", my_raster.spatialReference, projectCRS, selectedLayer)
|
||||
pt2 = findTransformation(pt2, "Point", my_raster.spatialReference, projectCRS, selectedLayer)
|
||||
pt3 = findTransformation(pt3, "Point", my_raster.spatialReference, projectCRS, selectedLayer)
|
||||
|
||||
@@ -6,8 +6,10 @@ import arcpy
|
||||
from arcpy._mp import ArcGISProject, Map, Layer as arcLayer
|
||||
import os
|
||||
|
||||
ATTRS_REMOVE = ['geometry','applicationId','bbox','displayStyle', 'id', 'renderMaterial', 'displayMesh']
|
||||
|
||||
def getVariantFromValue(value: Any) -> Union[str, None]:
|
||||
#print("_________get variant from value_______")
|
||||
# TODO add Base object
|
||||
pairs = [
|
||||
(str, "TEXT"), # 10
|
||||
@@ -28,73 +30,93 @@ def getVariantFromValue(value: Any) -> Union[str, None]:
|
||||
|
||||
return res
|
||||
|
||||
def getLayerAttributes(features: List[Base], attrsToRemove: List[str] =['geometry','applicationId','bbox','displayStyle', 'id', 'renderMaterial', 'geometry'] ) -> dict:
|
||||
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]
|
||||
else: features = featuresList[:]
|
||||
fields = {}
|
||||
all_props = []
|
||||
for feature in features:
|
||||
#get object properties to add as attributes
|
||||
dynamicProps = feature.get_dynamic_member_names()
|
||||
#attrsToRemove = ['geometry','applicationId','bbox','displayStyle', 'id', 'renderMaterial', 'geometry']
|
||||
for att in attrsToRemove:
|
||||
try: dynamicProps.remove(att)
|
||||
except: pass
|
||||
|
||||
dynamicProps.sort()
|
||||
print(dynamicProps)
|
||||
|
||||
# add field names and variands
|
||||
for name in dynamicProps:
|
||||
if name not in all_props: all_props.append(name)
|
||||
#if name not in all_props: all_props.append(name)
|
||||
|
||||
value = feature[name]
|
||||
variant = getVariantFromValue(value)
|
||||
if not variant: variant = None #LongLong #4
|
||||
|
||||
# go thought the dictionary object
|
||||
print("go thought the dictionary object")
|
||||
if value and isinstance(value, list) and isinstance(value[0], dict) :
|
||||
all_props.remove(name) # remove generic dict name
|
||||
newF, newVals = traverseDict( {}, {}, name, value[0])
|
||||
#print(newF)
|
||||
#print(newF.items())
|
||||
if value and isinstance(value, list):
|
||||
#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)
|
||||
|
||||
# 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()):
|
||||
fields.update({k: v})
|
||||
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:
|
||||
oldVariant = fields[k]
|
||||
# replace if new one is NOT LongLong or IS String
|
||||
if oldVariant != "TEXT" and variant == "TEXT":
|
||||
fields.update({k: variant})
|
||||
#print(fields)
|
||||
|
||||
# add a field if not existing yet AND if variant is known
|
||||
elif variant and (name not in fields.keys()):
|
||||
fields.update({name: variant})
|
||||
|
||||
elif name in fields.keys(): #check if the field was empty previously:
|
||||
oldVariant = fields[name]
|
||||
# replace if new one is NOT LongLong or IS String
|
||||
if oldVariant != "TEXT" and variant == "TEXT":
|
||||
fields.update({name: variant})
|
||||
#print(all_props)
|
||||
|
||||
# replace all empty ones wit String
|
||||
for name in all_props:
|
||||
if name not in fields.keys():
|
||||
fields.update({name: "TEXT"})
|
||||
print(fields)
|
||||
return fields
|
||||
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("Traverse Dict")
|
||||
#print("______05___Traverse Dict")
|
||||
#print(nam)
|
||||
#print(val)
|
||||
|
||||
if isinstance(val, dict):
|
||||
#print("DICT")
|
||||
for i, (k,v) in enumerate(val.items()):
|
||||
traverseDict( newF, newVals, nam+"_"+k, v)
|
||||
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)
|
||||
except: pass
|
||||
dynamicProps.sort()
|
||||
|
||||
item_dict = {}
|
||||
for prop in dynamicProps:
|
||||
item_dict.update({prop: val[prop]})
|
||||
|
||||
for i, (k,v) in enumerate(item_dict.items()):
|
||||
newF, newVals = traverseDict( newF, newVals, nam+"_"+k, v)
|
||||
else:
|
||||
#print("ELSE")
|
||||
var = getVariantFromValue(val)
|
||||
if not var: var = None #LongLong #4
|
||||
else:
|
||||
newF.update({nam: var})
|
||||
newVals.update({nam: val})
|
||||
#print(newF)
|
||||
#print(newVals)
|
||||
#print("traverse end")
|
||||
if var is None:
|
||||
var = 'TEXT'
|
||||
val = str(val)
|
||||
newF.update({nam: var})
|
||||
newVals.update({nam: val})
|
||||
|
||||
return newF, newVals
|
||||
|
||||
def get_scale_factor(units: str) -> float:
|
||||
@@ -123,46 +145,52 @@ def findTransformation(f_shape, geomType, layer_sr: arcpy.SpatialReference, proj
|
||||
#apply transformation if needed
|
||||
if layer_sr.name != projectCRS.name:
|
||||
tr0 = tr1 = tr2 = tr_custom = None
|
||||
transformations = arcpy.ListTransformations(layer_sr, projectCRS)
|
||||
customTransformName = "layer_sr.name"+"_To_"+ projectCRS.name
|
||||
if len(transformations) == 0:
|
||||
midSr = arcpy.SpatialReference("WGS 1984") # GCS_WGS_1984
|
||||
try:
|
||||
tr1 = arcpy.ListTransformations(layer_sr, midSr)[0]
|
||||
tr2 = arcpy.ListTransformations(midSr, projectCRS)[0]
|
||||
except:
|
||||
#customGeoTransfm = "GEOGTRAN[METHOD['Geocentric_Translation'],PARAMETER['X_Axis_Translation',''],PARAMETER['Y_Axis_Translation',''],PARAMETER['Z_Axis_Translation','']]"
|
||||
#CreateCustomGeoTransformation(customTransformName, layer_sr, projectCRS)
|
||||
tr_custom = customTransformName
|
||||
else:
|
||||
#print("else")
|
||||
# choose equation based instead of file-based/grid-based method,
|
||||
# to be consistent with QGIS: https://desktop.arcgis.com/en/arcmap/latest/map/projections/choosing-an-appropriate-transformation.htm
|
||||
selecterTr = {}
|
||||
for tr in transformations:
|
||||
if "NTv2" not in tr and "NADCON" not in tr:
|
||||
set1 = set( layer_sr.name.split("_") + projectCRS.name.split("_") )
|
||||
set2 = set( tr.split("_") )
|
||||
diff = len( set(set1).symmetric_difference(set2) )
|
||||
selecterTr.update({tr: diff})
|
||||
selecterTr = dict(sorted(selecterTr.items(), key=lambda item: item[1]))
|
||||
tr0 = list(selecterTr.keys())[0]
|
||||
print(layer_sr)
|
||||
try:
|
||||
transformations = arcpy.ListTransformations(layer_sr, projectCRS)
|
||||
customTransformName = "layer_sr.name"+"_To_"+ projectCRS.name
|
||||
if len(transformations) == 0:
|
||||
midSr = arcpy.SpatialReference("WGS 1984") # GCS_WGS_1984
|
||||
try:
|
||||
tr1 = arcpy.ListTransformations(layer_sr, midSr)[0]
|
||||
tr2 = arcpy.ListTransformations(midSr, projectCRS)[0]
|
||||
except:
|
||||
#customGeoTransfm = "GEOGTRAN[METHOD['Geocentric_Translation'],PARAMETER['X_Axis_Translation',''],PARAMETER['Y_Axis_Translation',''],PARAMETER['Z_Axis_Translation','']]"
|
||||
#CreateCustomGeoTransformation(customTransformName, layer_sr, projectCRS)
|
||||
tr_custom = customTransformName
|
||||
else:
|
||||
#print("else")
|
||||
# choose equation based instead of file-based/grid-based method,
|
||||
# to be consistent with QGIS: https://desktop.arcgis.com/en/arcmap/latest/map/projections/choosing-an-appropriate-transformation.htm
|
||||
selecterTr = {}
|
||||
for tr in transformations:
|
||||
if "NTv2" not in tr and "NADCON" not in tr:
|
||||
set1 = set( layer_sr.name.split("_") + projectCRS.name.split("_") )
|
||||
set2 = set( tr.split("_") )
|
||||
diff = len( set(set1).symmetric_difference(set2) )
|
||||
selecterTr.update({tr: diff})
|
||||
selecterTr = dict(sorted(selecterTr.items(), key=lambda item: item[1]))
|
||||
tr0 = list(selecterTr.keys())[0]
|
||||
|
||||
if geomType != "Point" and geomType != "Polyline" and geomType != "Polygon" and geomType != "Multipoint":
|
||||
try: arcpy.AddWarning("Unsupported or invalid geometry in layer " + selectedLayer.name)
|
||||
except: arcpy.AddWarning("Unsupported or invalid geometry")
|
||||
if geomType != "Point" and geomType != "Polyline" and geomType != "Polygon" and geomType != "Multipoint":
|
||||
try: arcpy.AddWarning("Unsupported or invalid geometry in layer " + selectedLayer.name)
|
||||
except: arcpy.AddWarning("Unsupported or invalid geometry")
|
||||
|
||||
# reproject geometry using chosen transformstion(s)
|
||||
if tr0 is not None:
|
||||
ptgeo1 = f_shape.projectAs(projectCRS, tr0)
|
||||
f_shape = ptgeo1
|
||||
elif tr1 is not None and tr2 is not None:
|
||||
ptgeo1 = f_shape.projectAs(midSr, tr1)
|
||||
ptgeo2 = ptgeo1.projectAs(projectCRS, tr2)
|
||||
f_shape = ptgeo2
|
||||
else:
|
||||
ptgeo1 = f_shape.projectAs(projectCRS)
|
||||
f_shape = ptgeo1
|
||||
# reproject geometry using chosen transformstion(s)
|
||||
if tr0 is not None:
|
||||
ptgeo1 = f_shape.projectAs(projectCRS, tr0)
|
||||
f_shape = ptgeo1
|
||||
elif tr1 is not None and tr2 is not None:
|
||||
ptgeo1 = f_shape.projectAs(midSr, tr1)
|
||||
ptgeo2 = ptgeo1.projectAs(projectCRS, tr2)
|
||||
f_shape = ptgeo2
|
||||
else:
|
||||
ptgeo1 = f_shape.projectAs(projectCRS)
|
||||
f_shape = ptgeo1
|
||||
|
||||
except:
|
||||
arcpy.AddWarning(f"Spatial Transformation not found for layer {selectedLayer.name}")
|
||||
return None
|
||||
|
||||
return f_shape
|
||||
|
||||
@@ -252,12 +280,12 @@ def curvedFeatureClassToSegments(layer) -> str:
|
||||
print(newPath)
|
||||
return newPath
|
||||
|
||||
def validate_path(path):
|
||||
def validate_path(path: str):
|
||||
# https://github.com/EsriOceans/btm/commit/a9c0529485c9b0baa78c1f094372c0f9d83c0aaf
|
||||
"""If our path contains a DB name, make sure we have a valid DB name and not a standard file name."""
|
||||
dirname, file_name = os.path.split(path)
|
||||
print(dirname)
|
||||
print(file_name)
|
||||
#print(dirname)
|
||||
#print(file_name)
|
||||
file_base = os.path.splitext(file_name)[0]
|
||||
if dirname == '':
|
||||
# a relative path only, relying on the workspace
|
||||
|
||||
@@ -0,0 +1,246 @@
|
||||
from arcpy._mp import ArcGISProject, Map, Layer as arcLayer
|
||||
import arcpy
|
||||
|
||||
from speckle.converter.layers.CRS import CRS
|
||||
from speckle.converter.layers.Layer import Layer, VectorLayer, RasterLayer
|
||||
|
||||
from arcpy._mp import ArcGISProject, Map, Layer as arcLayer
|
||||
from arcpy.management import (CreateFeatureclass, MakeFeatureLayer,
|
||||
AddFields, AlterField, DefineProjection )
|
||||
|
||||
from specklepy.objects import Base
|
||||
|
||||
project = ArcGISProject('CURRENT')
|
||||
active_map = project.activeMap
|
||||
all_layers = []
|
||||
#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 isinstance(layer, arcLayer):
|
||||
|
||||
projectCRS = project.activeMap.spatialReference
|
||||
try: data = arcpy.Describe(layer.dataSource)
|
||||
except OSError as e: print(e)
|
||||
|
||||
layerName = layer.name
|
||||
crs = data.SpatialReference
|
||||
units = "m"
|
||||
layerObjs = []
|
||||
|
||||
# Convert CRS to speckle, use the projectCRS
|
||||
speckleReprojectedCrs = CRS(name = projectCRS.name, wkt = projectCRS.exportToString(), units = units)
|
||||
layerCRS = CRS(name=crs.name, wkt=crs.exportToString(), units = units)
|
||||
|
||||
if layer.isFeatureLayer:
|
||||
print("VECTOR LAYER HERE")
|
||||
|
||||
speckleLayer = VectorLayer(units = "m")
|
||||
speckleLayer.type="VectorLayer"
|
||||
speckleLayer.name = layerName
|
||||
speckleLayer.crs = speckleReprojectedCrs
|
||||
|
||||
if data.datasetType == "FeatureClass": #FeatureClass, ?Table Properties, ?Datasets
|
||||
# write feature attributes
|
||||
fieldnames = [field.name for field in data.fields]
|
||||
rows_shapes = arcpy.da.SearchCursor(layer.longName, "Shape@") # arcpy.da.SearchCursor(in_table, field_names, {where_clause}, {spatial_reference}, {explode_to_points}, {sql_clause})
|
||||
print("__ start iterating features")
|
||||
row_shapes_list = [x for k, x in enumerate(rows_shapes)]
|
||||
for i, features in enumerate(row_shapes_list):
|
||||
|
||||
print("____error Feature # " + str(i+1)) # + " / " + str(sum(1 for _ in enumerate(rows_shapes))))
|
||||
if features[0] is None: continue
|
||||
feat = features[0]
|
||||
|
||||
if feat is not None:
|
||||
print(feat)
|
||||
rows_attributes = arcpy.da.SearchCursor(layer.longName, fieldnames)
|
||||
row_attr = []
|
||||
for k, attrs in enumerate(rows_attributes):
|
||||
if i == k: row_attr = attrs; break
|
||||
if feat.hasCurves: feat = feat.densify("ANGLE", 1000, 0.12)
|
||||
|
||||
print("___________Feature to Speckle____________")
|
||||
|
||||
b = Base(units = "m")
|
||||
data = arcpy.Describe(layer.dataSource)
|
||||
layer_sr = data.spatialReference # if sr.type == "Projected":
|
||||
geomType = data.shapeType #Polygon, Point, Polyline, Multipoint, MultiPatch
|
||||
featureType = data.featureType # Simple,SimpleJunction,SimpleJunction,ComplexEdge,Annotation,CoverageAnnotation,Dimension,RasterCatalogItem
|
||||
print(geomType)
|
||||
print(hasattr(data, "isRevit"))
|
||||
print(hasattr(data, "isIFC"))
|
||||
print(hasattr(data, "bimLevels"))
|
||||
print(hasattr(data, "hasSpatialIndex"))
|
||||
if geomType == "MultiPatch" or hasattr(data, "isRevit") or hasattr(data, "isIFC") or hasattr(data, "bimLevels"):
|
||||
print(f"Layer {layer.name} has unsupported data type")
|
||||
|
||||
print("___convertToSpeckle____________")
|
||||
geom = feat
|
||||
print(geom.isMultipart) # e.g. False
|
||||
print(geom.hasCurves)
|
||||
print(geom.partCount)
|
||||
geomMultiType = geom.isMultipart
|
||||
hasCurves = feat.hasCurves
|
||||
|
||||
geomPart = []
|
||||
for i,x in enumerate(feat): # [[x,x,x]
|
||||
|
||||
if i==0:
|
||||
print("Part # " + str(i+1))
|
||||
print(x)
|
||||
|
||||
inner_arr = []
|
||||
for k,ptn in enumerate(x):
|
||||
if k<10: print(ptn) # e.g. 6.25128173828125 -9.42138671875 22.2768999999971 NaN
|
||||
|
||||
inner_arr.append(ptn)
|
||||
#inner_arr.append(inner_arr[0]) #add first in the end
|
||||
geomPart.append(arcpy.Array(inner_arr))
|
||||
|
||||
geomPartArray = arcpy.Array(inner_arr)
|
||||
sr = project.activeMap.spatialReference
|
||||
|
||||
multipatch = arcpy.Multipatch(arcpy.Array(x), sr, has_z=True) # error
|
||||
print(multipatch)
|
||||
|
||||
else:
|
||||
print("___convertToSpeckle____________")
|
||||
geom = feat
|
||||
print(geom.isMultipart) # e.g. False
|
||||
print(geom.hasCurves)
|
||||
print(geom.partCount)
|
||||
geomMultiType = geom.isMultipart
|
||||
hasCurves = feat.hasCurves
|
||||
|
||||
for i,x in enumerate(feat): # [[x,x,x]
|
||||
print("Part # " + str(i+1))
|
||||
print(x)
|
||||
for k,ptn in enumerate(x):
|
||||
if k<10: print(ptn) # e.g. 6.25128173828125 -9.42138671875 22.2768999999971 NaN
|
||||
|
||||
|
||||
path: str = project.filePath.replace("aprx","gdb")
|
||||
sr = project.activeMap.spatialReference
|
||||
print(sr)
|
||||
f_class = CreateFeatureclass(path, "NewTestLayer", "Multipatch", has_z="ENABLED", spatial_reference = sr)
|
||||
fets = []
|
||||
print("04_____Feature To Native____________")
|
||||
new_feat = {}
|
||||
new_feat.update({"arcGisGeomFromSpeckle": multipatch})
|
||||
fets.append(new_feat)
|
||||
|
||||
vl = MakeFeatureLayer(str(f_class), "NewTestLayer").getOutput(0)
|
||||
|
||||
|
||||
|
||||
############################# write shapefile ##################################
|
||||
|
||||
import shapefile
|
||||
from shapefile import TRIANGLE_STRIP, TRIANGLE_FAN
|
||||
|
||||
from arcpy._mp import ArcGISProject, Map, Layer as arcLayer
|
||||
from arcpy.management import (CreateFeatureclass, MakeFeatureLayer,
|
||||
AddFields, AlterField, DefineProjection )
|
||||
|
||||
from specklepy.objects import Base
|
||||
|
||||
project = ArcGISProject('CURRENT')
|
||||
path: str = project.filePath.replace("aprx","gdb")
|
||||
|
||||
#with shapefile.Writer(path + "\contextwriter") as w:
|
||||
# w.field('field1', 'C')
|
||||
# pass
|
||||
|
||||
w = shapefile.Writer(path + '\\dtype')
|
||||
w.field('TEXT', 'C')
|
||||
w.field('SHORT_TEXT', 'C', size=5)
|
||||
w.field('LONG_TEXT', 'C', size=250)
|
||||
w.null()
|
||||
w.record('Hello', 'World', 'World'*50)
|
||||
w.close()
|
||||
|
||||
r = shapefile.Reader(path + '\\dtype')
|
||||
assert r.record(0) == ['Hello', 'World', 'World'*50]
|
||||
################################################################### WORKS #################################
|
||||
|
||||
w = shapefile.Writer(path + '\\dtype')
|
||||
w.field('INT', 'N')
|
||||
w.field('LOWPREC', 'N', decimal=2)
|
||||
w.field('MEDPREC', 'N', decimal=10)
|
||||
w.field('HIGHPREC', 'N', decimal=30)
|
||||
w.field('FTYPE', 'F', decimal=10)
|
||||
w.field('LARGENR', 'N', 101)
|
||||
w.field('FIRST_FLD','C','40')
|
||||
w.field('SECOND_FLD','C','40')
|
||||
nr = 1.3217328
|
||||
w.null()
|
||||
w.null()
|
||||
w.record(INT=nr, LOWPREC=nr, MEDPREC=nr, HIGHPREC=-3.2302e-25, FTYPE=nr, LARGENR=int(nr)*10**100, FIRST_FLD='First', SECOND_FLD='Line')
|
||||
w.record(None, None, None, None, None, None, '', '')
|
||||
w.close()
|
||||
|
||||
r = shapefile.Reader(path + '\\dtype')
|
||||
assert r.record(0) == [1, 1.32, 1.3217328, -3.2302e-25, 1.3217328, 10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000, 'First', 'Line']
|
||||
assert r.record(1) == [None, None, None, None, None, None, '', '']
|
||||
|
||||
################################################################# Add point ####################
|
||||
|
||||
w = shapefile.Writer(path + '\\dtypeShapes')
|
||||
w.field('name', 'C')
|
||||
|
||||
w.point(122, 37)
|
||||
w.record('point1')
|
||||
|
||||
w.close()
|
||||
|
||||
################################################################# Add Multipatch ####################
|
||||
|
||||
w = shapefile.Writer(path + '\\MultipatchTest2')
|
||||
w.field('name', 'C')
|
||||
|
||||
w.multipatch([
|
||||
[[0,0,0],[0,0,3],[5,0,0],[5,0,3],[5,5,0],[5,5,3],[0,5,0],[0,5,3],[0,0,0],[0,0,3]], # TRIANGLE_STRIP for house walls
|
||||
[[2.5,2.5,5],[0,0,3],[5,0,3],[5,5,3],[0,5,3],[0,0,3]], # TRIANGLE_FAN for pointed house roof
|
||||
],
|
||||
partTypes=[TRIANGLE_STRIP, TRIANGLE_FAN]) # one type for each part
|
||||
|
||||
w.record('house1')
|
||||
w.close()
|
||||
|
||||
r = shapefile.Reader(path + '\\MultipatchTest2')
|
||||
assert r.record(0) == ['house1']
|
||||
|
||||
|
||||
active_map.addDataFromPath(path + '\\MultipatchTest2.shp')
|
||||
|
||||
########################################################################## reader
|
||||
sf = shapefile.Reader(path + '\\MultipatchTest2.shp')
|
||||
sf.shapeType # e.g. 31 - multipatch
|
||||
sf.bbox # e.g. [0.0, 0.0, 5.0, 5.0]
|
||||
shapefile.Shape
|
||||
|
||||
|
||||
##################################################### cerate multipatch layer #################################
|
||||
result = arcpy.management.CreateFeatureclass(arcpy.env.scratchGDB, "test_multipatch", "MULTIPATCH", has_z="ENABLED", spatial_reference=4326)
|
||||
feature_class = result[0]
|
||||
|
||||
|
||||
################################# reading shapefile - works ####################
|
||||
|
||||
fc = r'C:\Users\katri\Documents\ArcGIS\Projects\MyProject\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')
|
||||
|
||||
##################################### update rows in feature class - working #############
|
||||
with arcpy.da.UpdateCursor('f_class_2f8cfa8644___Structural_Framing_Mesh', 'name') as cursor:
|
||||
# For each row, evaluate the WELL_YIELD value (index position
|
||||
# of 0), and update WELL_CLASS (index position of 1)
|
||||
for row in cursor:
|
||||
row[0] = "newName"
|
||||
cursor.updateRow(row)
|
||||
|
||||
@@ -13,7 +13,7 @@ from arcpy import metadata as md
|
||||
from specklepy.api.models import Branch, Stream, Streams
|
||||
from speckle.converter.layers.Layer import Layer, RasterLayer
|
||||
|
||||
from speckle.converter.layers._init_ import convertSelectedLayers, layerToNative, cadLayerToNative
|
||||
from speckle.converter.layers._init_ import convertSelectedLayers, layerToNative, cadLayerToNative, bimLayerToNative
|
||||
from arcgis.features import FeatureLayer
|
||||
import os
|
||||
import os.path
|
||||
@@ -257,7 +257,7 @@ class Speckle:
|
||||
|
||||
msg = arcpy.Parameter(
|
||||
displayName="Message",
|
||||
name="message",
|
||||
name="msg",
|
||||
datatype="GPString",
|
||||
parameterType="Optional",
|
||||
direction="Input",
|
||||
@@ -398,12 +398,12 @@ class Speckle:
|
||||
for p in parameters:
|
||||
if p.name == "lat" and p.valueAsText is not None:
|
||||
# add value from the UI to saved lat
|
||||
lat = p.valueAsText[:].replace(",","").replace(" ","").replace(";","").replace("-","").replace("_","")
|
||||
lat = p.valueAsText[:].replace(",","").replace(" ","").replace(";","").replace("_","")
|
||||
try: lat = float(lat)
|
||||
except: lat = 0; p.value = "0.0"
|
||||
if p.name == "lon" and p.valueAsText is not None:
|
||||
# add value from the UI to saved lat
|
||||
lon = p.valueAsText[:].replace(",","").replace(" ","").replace(";","").replace("-","").replace("_","")
|
||||
lon = p.valueAsText[:].replace(",","").replace(" ","").replace(";","").replace("_","")
|
||||
try: lon = float(lon)
|
||||
except: lon = 0; p.value = "0.0"
|
||||
coords = [lat, lon]
|
||||
@@ -494,6 +494,7 @@ class Speckle:
|
||||
|
||||
if par.name == "msg" and par.altered and par.valueAsText is not None:
|
||||
self.toolboxInputs.messageSpeckle = par.valueAsText
|
||||
print(self.toolboxInputs.messageSpeckle)
|
||||
|
||||
if par.name == "action" and par.altered:
|
||||
#print("action changed")
|
||||
@@ -602,6 +603,9 @@ class Speckle:
|
||||
base_obj = Base(units = "m")
|
||||
base_obj.layers = convertSelectedLayers(self.speckleInputs.all_layers, self.toolboxInputs.selected_layers, self.speckleInputs.project)
|
||||
|
||||
if len(base_obj.layers) == 0:
|
||||
arcpy.AddMessage("No data sent to stream " + streamId)
|
||||
return
|
||||
try:
|
||||
# this serialises the block and sends it to the transport
|
||||
objId = operations.send(base=base_obj, transports=[transport])
|
||||
@@ -614,7 +618,9 @@ class Speckle:
|
||||
|
||||
|
||||
message = self.toolboxInputs.messageSpeckle
|
||||
print(message)
|
||||
if message is None or ( isinstance(message, str) and len(message) == 0): message = "Sent from ArcGIS"
|
||||
print(message)
|
||||
try:
|
||||
# you can now create a commit on your stream with this object
|
||||
client.commit.create(
|
||||
@@ -755,17 +761,27 @@ class Speckle:
|
||||
for item in value:
|
||||
loopVal(item, name)
|
||||
#print(item)
|
||||
pt = None
|
||||
if item.speckle_type and item.speckle_type.startswith("Objects.Geometry."):
|
||||
|
||||
pt, pl = cadLayerToNative(value, name, streamBranch, self.speckleInputs.project)
|
||||
if pt is not None: print("Layer group created: " + pt.name())
|
||||
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."):
|
||||
|
||||
msh_bool = bimLayerToNative(value, name, streamBranch, self.speckleInputs.project)
|
||||
#if msh is not None: print("Layer group created: " + msh.name())
|
||||
break
|
||||
|
||||
traverseObject(commitObj, callback, check)
|
||||
|
||||
except SpeckleException as e:
|
||||
print("Receive failed")
|
||||
except (SpeckleException, GraphQLException) as e:
|
||||
print("Receive failed: " + str(e))
|
||||
arcpy.AddError("Receive failed: " + str(e))
|
||||
return
|
||||
|
||||
print("received")
|
||||
#self.updateParameters(parameters, True)
|
||||
#self.refresh(parameters)
|
||||
|
||||
@@ -28,11 +28,19 @@ class speckleInputsClass:
|
||||
saved_streams: List[Optional[Tuple[StreamWrapper, Stream]]] = []
|
||||
stream_file_path: str = ""
|
||||
all_layers: List[arcLayer] = []
|
||||
clients = []
|
||||
|
||||
for acc in accounts:
|
||||
if acc.isDefault:
|
||||
account = acc
|
||||
break
|
||||
#break
|
||||
new_client = SpeckleClient(
|
||||
acc.serverInfo.url,
|
||||
acc.serverInfo.url.startswith("https")
|
||||
)
|
||||
new_client.authenticate_with_token(token=acc.token)
|
||||
clients.append(new_client)
|
||||
|
||||
speckle_client = None
|
||||
if account:
|
||||
speckle_client = SpeckleClient(
|
||||
@@ -52,8 +60,9 @@ class speckleInputsClass:
|
||||
|
||||
if self.active_map is not None and isinstance(self.active_map, Map): # if project loaded
|
||||
for layer in self.active_map.listLayers():
|
||||
#print(layer)
|
||||
if layer.isFeatureLayer or layer.isRasterLayer: self.all_layers.append(layer) #type: 'arcpy._mp.Layer'
|
||||
try: geomType = arcpy.Describe(layer.dataSource).shapeType.lower()
|
||||
except: geomType = '' #print(arcpy.Describe(layer.dataSource)) #and arcpy.Describe(layer.dataSource).shapeType.lower() != "multipatch")
|
||||
if (layer.isFeatureLayer and geomType != "multipatch") or layer.isRasterLayer: self.all_layers.append(layer) #type: 'arcpy._mp.Layer'
|
||||
self.stream_file_path: str = aprx.filePath.replace("aprx","gdb") + "\\speckle_streams.txt"
|
||||
|
||||
if os.path.exists(self.stream_file_path):
|
||||
@@ -157,7 +166,7 @@ class toolboxInputsClass:
|
||||
try:
|
||||
aprx = ArcGISProject('CURRENT')
|
||||
self.project = aprx
|
||||
except: self.project = None; print("Project not found")
|
||||
except: self.project = None; print("Project not found"); arcpy.AddWarning("Project not found")
|
||||
self.instances.append(self)
|
||||
|
||||
def setProjectStreams(self, wr: StreamWrapper, add = True):
|
||||
@@ -244,15 +253,21 @@ class toolboxInputsClass:
|
||||
newCrsString = "+proj=tmerc +ellps=WGS84 +datum=WGS84 +units=m +no_defs +lon_0=" + str(self.lon) + " lat_0=" + str(self.lat) + " +x_0=0 +y_0=0 +k_0=1"
|
||||
newCrs = osr.SpatialReference()
|
||||
newCrs.ImportFromProj4(newCrsString)
|
||||
print(newCrs.ExportToWkt())
|
||||
newCrs.MorphToESRI() # converts the WKT to an ESRI-compatible format
|
||||
|
||||
|
||||
validate = True if len(newCrs.ExportToWkt())>10 else False
|
||||
|
||||
if validate:
|
||||
newProjSR = arcpy.SpatialReference()
|
||||
newProjSR.loadFromString(newCrs.ExportToWkt())
|
||||
|
||||
#source = osr.SpatialReference()
|
||||
#source.ImportFromWkt(self.project.activeMap.spatialReference.exportToString())
|
||||
#transform = osr.CoordinateTransformation(source, newCrs)
|
||||
|
||||
self.project.activeMap.spatialReference = newProjSR
|
||||
arcpy.AddWarning("Custom project CRS successfully applied")
|
||||
arcpy.AddMessage("Custom project CRS successfully applied")
|
||||
else:
|
||||
arcpy.AddWarning("Custom CRS could not be created")
|
||||
|
||||
|
||||
Reference in New Issue
Block a user