Compare commits

...

20 Commits

Author SHA1 Message Date
KatKatKateryna 772ed3334d Update Readme.md 2022-11-02 02:58:13 +08:00
KatKatKateryna 3b9188dabe Merge pull request #24 from specklesystems/kate/2.9_debugging
Kate/2.9 debugging
2022-11-02 02:46:53 +08:00
KatKatKateryna 895eded593 path to .exe corrected 2022-11-02 02:21:49 +08:00
KatKatKateryna fa4908ed1a fixed bug with dynamically changing received polycurve 2022-11-02 02:11:37 +08:00
KatKatKateryna 3cf079acaf add .pyt after user clicks Install; clone conda env by condition(if exists/if invalid/if doesn't exist); package import directly to new env. clean lists on Refresh; add units on Send; raster stretch-coloring on send 2022-11-01 20:34:12 +08:00
KatKatKateryna 6d6df92d42 Manage conda envs and packages all from 1 file (conda_clone_activate); checked Manual install instructions 2022-11-01 06:29:59 +08:00
KatKatKateryna 4fcd408759 patching file adapted 2022-11-01 02:18:17 +08:00
KatKatKateryna 7bf8957989 Installing dependencies properly; .pyt back to debugging mode; creatingGroupLayer adapted to ArcGIS 3.0 2022-11-01 00:31:04 +08:00
KatKatKateryna e409e6d578 Merge pull request #22 from specklesystems/kate/2.9_debugging
Kate/2.9 debugging
2022-10-25 18:30:24 +01:00
KatKatKateryna 98cfc35cbc add conflicted file 2022-10-25 19:29:58 +02:00
KatKatKateryna 1ba8aaaa15 Revert "add conflicted file"
This reverts commit 1f95fbd169.
2022-10-25 19:29:43 +02:00
KatKatKateryna 1f95fbd169 add conflicted file 2022-10-25 19:26:12 +02:00
KatKatKateryna 42f9f8c815 2.9.3; don't duplicate layers of Refresh 2022-10-25 19:10:20 +02:00
KatKatKateryna 019f67ffbc 2.9.2 naming 2022-10-25 18:50:16 +02:00
KatKatKateryna 3f6a21f65e Toolbox naming 2022-10-25 18:03:00 +02:00
KatKatKateryna 3ce685f77a exception for unrefresed UI; defining types properly 2022-10-25 18:00:17 +02:00
KatKatKateryna be8996ebaa file reading failproof; move plugin to PYT, raster mesh sent correctly 2022-10-25 17:49:24 +02:00
KatKatKateryna 03d8a20a44 patch to update whl version; installer to update specklepy 2022-10-25 16:36:03 +02:00
KatKatKateryna 057cbb8cc5 Raster flipped; extra precautions writing txt file; installer instructions updated 2022-10-25 15:38:12 +02:00
KatKatKateryna a68fdbc999 whl package fix, added missing plugin folder 2022-10-25 14:13:13 +02:00
21 changed files with 323 additions and 185 deletions
+39 -3
View File
@@ -4,16 +4,52 @@ import sys
def patch_installer(tag):
"""Patches the installer with the correct connector version and specklepy version"""
iss_file = "speckle-sharp-ci-tools/arcgis.iss"
setup_whl_file = "setup.py"
conda_file = "speckle_arcgis_installer/conda_clone_activate.py"
toolbox_install_file = "speckle_arcgis_installer/toolbox_install.py"
toolbox_manual_install_file = "speckle_arcgis_installer/toolbox_install_manual.py"
#py_tag = get_specklepy_version()
with open(iss_file, "r") as file:
lines = file.readlines()
lines.insert(12, f'#define AppVersion "{tag.split("-")[0]}"\n')
lines.insert(13, f'#define AppInfoVersion "{tag}"\n')
for i, line in enumerate(lines):
if "#define AppVersion " in line:
lines[i] = f'#define AppVersion "{tag.split("-")[0]}"\n'
if "#define AppInfoVersion " in line:
lines[i] = f'#define AppInfoVersion "{tag}"\n'
with open(iss_file, "w") as file:
file.writelines(lines)
print(f"Patched installer with connector v{tag} and specklepy ")
file.close()
with open(setup_whl_file, "r") as file:
lines = file.readlines()
for i, line in enumerate(lines):
if "version=" in line:
lines[i] = f'\t\t\tversion="{tag.split("-")[0]}",\n'
break
with open(setup_whl_file, "w") as file:
file.writelines(lines)
print(f"Patched whl setup with connector v{tag} and specklepy ")
file.close()
def whlFileRename(fileName: str):
with open(fileName, "r") as file:
lines = file.readlines()
for i, line in enumerate(lines):
if "-py3-none-any.whl" in line:
p1 = line.split("-py3-none-any.whl")[0].split("-")[0]
p2 = f'{tag.split("-")[0]}'
p3 = line.split("-py3-none-any.whl")[1]
lines[i] = p1+"-"+p2+"-py3-none-any.whl"+p3
with open(fileName, "w") as file:
file.writelines(lines)
print(f"Patched toolbox_installer with connector v{tag} and specklepy ")
file.close()
whlFileRename(conda_file)
whlFileRename(toolbox_install_file)
whlFileRename(toolbox_manual_install_file)
def main():
+6 -5
View File
@@ -1,7 +1,7 @@
# to build an installer: run cmd from this folder or use terminal: "%PROGRAMFILES%\\ArcGIS\\Pro\\bin\\Python\\envs\\arcgispro-py3\\python.exe"
#
# 1) python patch_version.py 2.x.x
# 2) (if needed: pip install wheel) python setup.py sdist bdist_wheel #C:\\Users\\username\\Documents\\00_Speckle\\GitHub\\speckle-arcgis\\setup.py sdist bdist_wheel
# 2) python setup.py sdist bdist_wheel #C:\\Users\\username\\Documents\\00_Speckle\\GitHub\\speckle-arcgis\\setup.py sdist bdist_wheel
# copy .whl from "dist" to "speckle_arcgis_installer"
# ref: https://pro.arcgis.com/en/pro-app/2.8/arcpy/geoprocessing_and_python/distributing-python-modules.htm
@@ -14,20 +14,21 @@ def read(fname):
return open(os.path.join(os.path.dirname(__file__), fname)).read()
setup(name='speckle_toolbox',
version='0.1',
author='SpeckleSystems',
version="2.9.4",
description=("Example for extending geoprocessing through Python modules"),
long_description=read('Readme.md'),
python_requires='~=3.3',
setup_requires=['wheel'],
packages=['speckle_toolbox'],
package_data={'speckle_toolbox':['esri/toolboxes/*',
package_data={'speckle_toolbox':[
'esri/arcpy/*',
'esri/help/gp/*', 'esri/help/gp/toolboxes/*', 'esri/help/gp/messages/*',
'esri/toolboxes/*','esri/toolboxes/speckle/*',
'esri/toolboxes/speckle/converter/*', 'esri/toolboxes/speckle/converter/geometry/*', 'esri/toolboxes/speckle/converter/layers/*',
'esri/toolboxes/speckle/plugin_utils/*']
'esri/toolboxes/speckle/plugin_utils/*',
'esri/toolboxes/speckle/ui/*']
},
setup_requires=['wheel'],
)
# then to install in ArcGIS:
+13
View File
@@ -0,0 +1,13 @@
### Manual installation
1. Download present "speckle_arcgis_installer" folder
2. Clone the default ArcGIS Pro conda environment and restart ArcGIS Pro
- for 2.9.0: Project-> Python-> Manage Environments-> Clone Default
- for 3.0.0: Project-> Package Manager-> Active Environment (Environment Manager)-> Clone arcgispro-py3
3. Change the path to your new environemnt Python.exe if necessary (variable "pythonPath" in "toolbox_install_manual.py")
4. Enter the location of 'toolbox_install_manual.py' in the following command and run this command in ArcGIS Python console (View -> Python Window)
```python
import sysconfig; import subprocess; x = sysconfig.get_paths()['data'] + r"\python.exe"; subprocess.run((x, 'C:\\Users\\pathToFolder\\speckle_arcgis_installer\\toolbox_install_manual.py'), capture_output=True, text=True, shell=True, timeout=1000 )
```
+1
View File
@@ -0,0 +1 @@
from speckle.speckle_arcgis import *
@@ -8,50 +8,128 @@ import subprocess
from subprocess import CalledProcessError
from subprocess_call import subprocess_call
from msilib.schema import Error
import sys
import arcpy
def setup():
#print(plugin_dir)
pythonExec = get_python_path() # import numpy; import os; print(os.path.abspath(numpy.__file__))
#print(pythonExec)
if pythonExec is None: # env is default, need to restart ArcGIS
return False
return pythonExec # None if not successful
def get_python_path(): # create a full copy of default env
#print("Get Python path")
# or: import site; site.getsitepackages()[0]
# import specklepy; import os; print(os.path.abspath(specklepy.__file__)) ##currentPythonExec = sysconfig.get_paths()['data'] + r"\python.exe"
pythonExec = os.environ["ProgramFiles"] + r'\ArcGIS\Pro\bin\Python\envs\arcgispro-py3\python.exe' #(r"%PROGRAMFILES%\ArcGIS\Pro\bin\Python\envs\arcgispro-py3\python.exe") #os.path.dirname(sys.executable) + "\\python.exe" # default python.exe
#print(pythonExec)
if not os.path.exists(pythonExec):
pythonExec = os.getenv('APPDATA').replace("Roaming", "Local") + r'\Programs\ArcGIS\Pro\bin\Python\envs\arcgispro-py3\python.exe'
if not os.path.exists(pythonExec): return None
#print(os.getenv('APPDATA') + r'\Programs\ArcGIS\Pro\bin\Python\envs\arcgispro-py3\python.exe')
if sys.platform == "win32":
env_new_name = "arcgispro-py3-speckle"
#clone_env(pythonExec, env_new_name) # only if doesn't exist yet
newExec = clone_env(pythonExec, env_new_name) # only if doesn't exist yet
if not os.path.exists(newExec): return None
activate_env(env_new_name)
return pythonExec
else: pass
return newExec
else: return None
def clone_env(pythonExec_old: str, env_new_name: str):
install_folder = os.getenv('APPDATA').replace("\\Roaming","") + r"\Local\ESRI\conda\envs" #r"%LOCALAPPDATA%\ESRI\conda\envs"
#print("Clone default ArcGIS Pro conda env")
#print(install_folder)
#if not os.path.exists(install_folder): os.makedirs(install_folder)
if not os.path.exists(install_folder): os.makedirs(install_folder)
default_env = pythonExec_old.replace("Pro\\bin\\Python\\envs\\arcgispro-py3\\python.exe","Pro\\bin\\Python\\envs\\arcgispro-py3") # + "\\" + 'arcgispro-py3'
conda_exe = pythonExec_old.replace("Pro\\bin\\Python\\envs\\arcgispro-py3\\python.exe","Pro\\bin\\Python\\Scripts\\conda.exe") #%PROGRAMFILES%\ArcGIS\Pro\bin\Python\Scripts\conda.exe #base: %PROGRAMDATA%\Anaconda3\condabin\conda.bat
new_env = install_folder + "\\" + env_new_name # %LOCALAPPDATA%\ESRI\conda\envs\...
subprocess_call( [ conda_exe, 'create', '--clone', default_env, '-p', new_env] ) # will not execute if already exists
if os.path.exists(conda_exe) and os.path.exists(default_env) and os.path.exists(new_env) and not os.path.exists(new_env + "\\python.exe"):
# conda environment invalid: delete it's folder
print(f"Removing invalid environment {new_env}")
os.remove(new_env)
if os.path.exists(conda_exe) and os.path.exists(default_env) and not os.path.exists(new_env):
print("Wait for the default ArcGIS Pro conda environment to be cloned")
subprocess_call( [ conda_exe, 'config', '--set', 'ssl_verify', 'False'] )
subprocess_call( [ conda_exe, 'create', '--clone', default_env, '-p', new_env] ) # will not execute if already exists
subprocess_call( [ conda_exe, 'config', '--set', 'ssl_verify', 'True'] )
elif os.path.exists(new_env) and os.path.exists(new_env + "\\python.exe"):
print(f"Environment {new_env} already exists, preparing to install packages..")
print(new_env + "\\python.exe")
return new_env + "\\python.exe"
def activate_env(env_new_name: str):
# using Popen, because process does not return result; subprocess.run will hang indefinitely
variable = subprocess.Popen((f'proswap {env_new_name}'),stdout = subprocess.PIPE,stderr = subprocess.PIPE,text = True,shell = True)
#print(variable)
# activate new env : https://support.esri.com/en/technical-article/000024206
setup()
def installToolbox(newExec: str):
print("Installing Speckle Toolbox")
whl_file = os.path.join(os.path.dirname(__file__), "speckle_toolbox-2.9.4-py3-none-any.whl" )
print(whl_file)
subprocess_call([newExec, '-m','pip','install','--upgrade', '--force-reinstall', whl_file])
# to uninstall: cmd.exe "C:\\Users\\username\\AppData\\Local\\ESRI\\conda\\envs\\arcgispro-2.9.4-py3-none-any.whl
return
def installDependencies(pythonExec: str, pkgName: str, pkgVersion: str):
# install pip
print(pythonExec)
try:
import pip
except:
getPipFilePath = os.path.join(os.path.dirname(__file__), "get_pip.py") #TODO: give actual folder path
exec(open(getPipFilePath).read())
# just in case the included version is old
subprocess_call([pythonExec, "-m", "pip", "install", "--upgrade", "pip"])
# install package
try:
#import importlib #importlib.import_module(pkgName)
if pkgName == "specklepy":
import specklepy
if pythonExec.replace("\\python.exe","") not in (os.path.abspath(specklepy.__file__)):
print(f"Installing {pkgName} to {pythonExec}")
#subprocess_call( [pythonExec, "-m", "pip", "uninstall", f"{pkgName}"])
subprocess_call( [pythonExec, "-m", "pip", "install", f"{pkgName}=={pkgVersion}"])
elif pkgName == "panda3d":
import panda3d
if pythonExec.replace("\\python.exe","") not in (os.path.abspath(panda3d.__file__)):
print(f"Installing {pkgName} to {pythonExec}")
subprocess_call( [pythonExec, "-m", "pip", "install", f"{pkgName}=={pkgVersion}"])
except Exception as e:
print(f"{pkgName} not installed")
subprocess_call( [pythonExec, "-m", "pip", "install", f"{pkgName}=={pkgVersion}"])
# Check if package needs updating
r'''
try:
print(f"Attempting to update {pkgName} to {pkgVersion}")
result = subprocess_call(
[
pythonExec,
"-m",
"pip",
"install",
"--upgrade",
f"{pkgName}=={pkgVersion}",
]
)
if result == True:
print(f"{pkgName} upgraded")
return True
else:
return False
except Exception as e:
print(e)
print(e.with_traceback)
'''
return True
pythonPath = setup()
if pythonPath is not None:
installToolbox(pythonPath)
installDependencies(pythonPath, "specklepy", "2.9.0" )
installDependencies(pythonPath, "panda3d", "1.10.11" )
Binary file not shown.
@@ -1,73 +0,0 @@
# MANUAL INSTALLATION:
# 1. enter correct path to Python exe of your new environemnt in line 10
# 2. enter the location of 'manual_toolbox_install.py' in the following command and run this command in ArcGIS Python console (View -> Python Window)
# import sysconfig; import subprocess; x = sysconfig.get_paths()['data'] + r"\python.exe"; subprocess.run((x, 'C:\\...\\manual_toolbox_install.py'), capture_output=True, text=True, shell=True, timeout=1000 )
# then restart
from subprocess_call import subprocess_call
import os
pythonPath = "C:\\ ...\\custom_environment_name\\python.exe"
def installToolbox(newExec: str):
print("Installing Speckle Toolbox")
whl_file = os.path.join(os.path.dirname(__file__), "speckle_toolbox-0.1-py3-none-any.whl" )
subprocess_call([newExec, '-m','pip','install','--upgrade', '--force-reinstall', whl_file])
return
def installDependencies(pythonExec: str):
print("Installing dependencies")
print(pythonExec)
try:
import pip
except:
getPipFilePath = os.path.join(os.path.dirname(__file__), "get_pip.py")
exec(open(getPipFilePath).read())
# just in case the included version is old
subprocess_call([pythonExec, "-m", "pip", "install", "--upgrade", "pip"])
pkgVersion = "2.7.4"
pkgName = "specklepy"
try:
import specklepy
except Exception as e:
subprocess_call([ pythonExec, "-m", "pip", "install", f"{pkgName}=={pkgVersion}"])
pkgVersion = "1.10.11"
pkgName = "panda3d"
try:
import panda3d
except Exception as e:
print("panda3d not installed")
subprocess_call( [pythonExec, "-m", "pip", "install", f"{pkgName}=={pkgVersion}"])
# Check if specklpy needs updating
try:
print(f"Attempting to update specklepy to {pkgVersion}")
# pip.main(['install', "specklepy==2.7.4"])
result = subprocess_call(
[
pythonExec,
"-m",
"pip",
"install",
"--upgrade",
f"{pkgName}=={pkgVersion}",
]
)
if result == True:
print("specklepy upgraded")
return True
else:
return False
except Exception as e:
print(e)
print(e.with_traceback)
return True
installToolbox(pythonPath)
installDependencies(pythonPath)
+3 -3
View File
@@ -14,12 +14,12 @@ def subprocess_call(*args, **kwargs):
startupinfo.dwFlags = subprocess.CREATE_NEW_CONSOLE | subprocess.STARTF_USESHOWWINDOW
startupinfo.wShowWindow = subprocess.SW_HIDE
kwargs['startupinfo'] = startupinfo
print("start")
#print("start")
#print(*args)
try:
# if manually: cmd.exe -> conda activate [env folder] -> pip install specklepy
result = subprocess.run(*args, capture_output=True, text=True, shell=True, timeout=1000)
#print(result)
print(result)
#result = subprocess.Popen( arg, shell=True, stdout=subprocess.PIPE) #, stderr=subprocess.STDOUT)
#retcode = subprocess.check_call(*args, **kwargs) # Creates infinite loop, known issue: https://github.com/python/cpython/issues/87512
except CalledProcessError as e:
@@ -32,7 +32,7 @@ def subprocess_call(*args, **kwargs):
#print(str(e))
return False
except: print("unknown error")
print("end")
#print("end")
return True
+17 -25
View File
@@ -6,43 +6,34 @@ pythonPath = os.getenv('APPDATA').replace("\\Roaming","") + r"\Local\ESRI\conda\
def installToolbox(newExec: str):
print("Installing Speckle Toolbox")
whl_file = os.path.join(os.path.dirname(__file__), "speckle_toolbox-0.1-py3-none-any.whl" )
whl_file = os.path.join(os.path.dirname(__file__), "speckle_toolbox-2.9.4-py3-none-any.whl" )
print(whl_file)
subprocess_call([newExec, '-m','pip','install','--upgrade', '--force-reinstall', whl_file])
# to uninstall: cmd.exe "C:\\Users\\username\\AppData\\Local\\ESRI\\conda\\envs\\arcgispro-py3-speckle\\python.exe" -m pip uninstall C:\\Users\\username\\Downloads\\speckle-arcgis\\foo-0.1-py3-none-any.whl
# to uninstall: cmd.exe "C:\\Users\\username\\AppData\\Local\\ESRI\\conda\\envs\\arcgispro-2.9.4-py3-none-any.whl
return
def installDependencies(pythonExec: str):
#print("Installing dependencies")
def installDependencies(pythonExec: str, pkgName: str, pkgVersion: str):
# install pip
print(pythonExec)
try:
import pip
except:
getPipFilePath = os.path.join(os.path.dirname(__file__), "get_pip.py") #TODO: give actual folder path
exec(open(getPipFilePath).read())
# just in case the included version is old
subprocess_call([pythonExec, "-m", "pip", "install", "--upgrade", "pip"])
pkgVersion = "2.9.0"
pkgName = "specklepy"
# install package
try:
import specklepy # C:\Users\username\AppData\Roaming\Python\Python37\site-packages\specklepy\__init__.py
import importlib
importlib.import_module(pkgName)
except Exception as e:
subprocess_call([ pythonExec, "-m", "pip", "install", f"{pkgName}=={pkgVersion}"])
pkgVersion = "1.10.11"
pkgName = "panda3d"
try:
import panda3d
except Exception as e:
print("panda3d not installed")
print(f"{pkgName} not installed")
subprocess_call( [pythonExec, "-m", "pip", "install", f"{pkgName}=={pkgVersion}"])
# Check if specklpy needs updating
# Check if package needs updating
try:
print(f"Attempting to update specklepy to {pkgVersion}")
# pip.main(['install', "specklepy==2.7.4"])
print(f"Attempting to update {pkgName} to {pkgVersion}")
result = subprocess_call(
[
pythonExec,
@@ -54,16 +45,17 @@ def installDependencies(pythonExec: str):
]
)
if result == True:
print("specklepy upgraded")
print(f"{pkgName} upgraded")
return True
else:
return False
except Exception as e:
print(e)
print(e.with_traceback)
return True
installToolbox(pythonPath)
installDependencies(pythonPath)
installToolbox(pythonPath)
installDependencies(pythonPath, "specklepy", "2.9.0" )
installDependencies(pythonPath, "panda3d", "1.10.11" )
@@ -0,0 +1,57 @@
# MANUAL INSTALLATION:
# 1. Clone the default ArcGIS Pro conda environment
# for 2.9.0: Project-> Python-> Manage Environments-> Clone Default
# for 3.0.0: Project-> Package Manager-> Active Environment (Environment Manager)-> Clone arcgispro-py3
# 2. Change the path to your new environemnt Python.exe if necessary (in variable "pythonPath" below, line 13)
# 3. Enter the location of 'toolbox_install_manual.py' in the following command and run this command in ArcGIS Python console (View -> Python Window)
# import sysconfig; import subprocess; x = sysconfig.get_paths()['data'] + r"\python.exe"; subprocess.run((x, 'C:\\Users\\myusername\\Documents\\manual_toolbox_install.py'), capture_output=True, text=True, shell=True, timeout=1000 )
# 4. Restart ArcGIS Pro
from subprocess_call import subprocess_call
import os
pythonPath = os.getenv('APPDATA').replace("\\Roaming","") + r"\Local\ESRI\conda\envs\arcgispro-py3-speckle\python.exe"
def installToolbox(newExec: str):
print("Installing Speckle Toolbox")
whl_file = os.path.join(os.path.dirname(__file__), "speckle_toolbox-2.9.4-py3-none-any.whl" )
subprocess_call([newExec, '-m','pip','install','--upgrade', '--force-reinstall', whl_file])
return
def installDependencies(pythonExec: str, pkgName: str, pkgVersion: str):
# install package
try:
#import importlib #importlib.import_module(pkgName)
if pkgName == "specklepy": import specklepy
elif pkgName == "panda3d": import panda3d
except Exception as e:
print(f"{pkgName} not installed")
subprocess_call( [pythonExec, "-m", "pip", "install", f"{pkgName}=={pkgVersion}"])
# Check if package needs updating
try:
print(f"Attempting to update {pkgName} to {pkgVersion}")
result = subprocess_call(
[
pythonExec,
"-m",
"pip",
"install",
"--upgrade",
f"{pkgName}=={pkgVersion}",
]
)
if result == True:
print(f"{pkgName} upgraded")
return True
else:
return False
except Exception as e:
print(e)
print(e.with_traceback)
return True
installToolbox(pythonPath)
installDependencies(pythonPath, "specklepy", "2.9.0" )
installDependencies(pythonPath, "panda3d", "1.10.11" )
+1 -1
View File
@@ -1 +1 @@
from speckle.speckle_arcgis import *
from speckle.speckle_arcgis import *
@@ -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>20221024</ModDate><ModTime>110535</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>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
IFhZWiAHzgACAAkABgAxAABhY3NwTVNGVAAAAABJRUMgc1JHQgAAAAAAAAAAAAAAAAAA9tYAAQAA
AADTLUhQICAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABFj
cHJ0AAABUAAAADNkZXNjAAABhAAAAGx3dHB0AAAB8AAAABRia3B0AAACBAAAABRyWFlaAAACGAAA
@@ -55,19 +55,20 @@ def pointToNative(pt: Point, sr: arcpy.SpatialReference) -> arcpy.PointGeometry:
#print(geom)
return geom
def pointToCoord(pt: Point) -> List[float]:
def pointToCoord(point: Point) -> List[float]:
"""Converts a Speckle Point to QgsPoint"""
pt = scalePointToNative(pt, pt.units)
pt = scalePointToNative(point, point.units)
coords = [pt.x, pt.y, pt.z]
#print(coords)
return coords
def scalePointToNative(pt: Point, units: str) -> Point:
def scalePointToNative(point: Point, units: str) -> Point:
"""Scale point coordinates to meters"""
scaleFactor = get_scale_factor(units)
pt.x = pt.x * scaleFactor
pt.y = pt.y * scaleFactor
pt.z = 0 if math.isnan(pt.z) else pt.z * scaleFactor
pt = Point(units = "m")
pt.x = point.x * scaleFactor
pt.y = point.y * scaleFactor
pt.z = 0 if math.isnan(point.z) else point.z * scaleFactor
return pt
def addZtoPoint(coords: List):
@@ -26,6 +26,7 @@ def circleToSpeckle(center, point):
#print(args)
c = Circle.from_list(args)
c.plane.origin.units = "m"
c.units = "m"
#print(c)
return c
@@ -107,6 +108,7 @@ def arc3ptToSpeckle(p0: List, p1: List, p2: List, feature, layer) -> Arc:
arc.plane = Plane() #.from_list(Point(), Vector(Point(0, 0, 1)), Vector(Point(0,1,0)), Vector(Point(-1,0,0)))
arc.plane.origin = Point.from_list(center)
arc.plane.origin.units = "m"
arc.units = "m"
arc.angleRadians, startAngle, endAngle = getArcRadianAngle(arc)
arc.radius = radius
@@ -173,7 +175,7 @@ def curveToSpeckle(geom, geomType, feature, layer) -> Union[Circle, Arc, Polylin
# a - elliptical arc (endPt, centralPt) e.g. for circle: [[[631307.05960000027,5803698.4477999993,0],{"a":[[631307.05960000027,5803698.4477999993,0],[631307.05960000027,5803414.92656173],0,1]}]]
# c - circular arc (endPt, throughPt) e.g. [[[633242.45179999992,5803058.0354999993,0],{"c":[[633718.26040000003,5803496.4210000001,0],[633337.75764975848,5803431.9997026781]]},[633242.45179999992,5803058.0354999993,0]]]
boundary = Polycurve()
boundary = Polycurve(units = "m")
if geomType == "Polyline": boundary.closed = False
else: boundary.closed = True
segments = []
@@ -326,7 +328,7 @@ def lineFrom2pt(pt1: List[float], pt2: List[float]):
dist = math.sqrt( math.pow((pt2[0] - pt1[0]), 2) + math.pow((pt2[1] - pt1[1]), 2) + math.pow((pt2[2] - pt1[2]), 2) )
print(dist)
domain = [0, dist, 0, 0]
line = Line()#.from_list([*pt1, *pt2, *domain])
line = Line(units = "m" )#.from_list([*pt1, *pt2, *domain])
line.start = Point.from_list(pt1)
line.end = Point.from_list(pt2)
line.start.units = line.end.units = "m"
@@ -377,7 +379,7 @@ def ellipseToNative():
def circleToNative(poly: Circle, sr: arcpy.SpatialReference) -> arcpy.Polyline:
"""Converts a Speckle Circle to QgsLineString"""
print("___Convert Circle from Native___")
print("___Convert Circle to Native___")
points = []
angle1 = math.pi/2
@@ -393,7 +395,8 @@ def circleToNative(poly: Circle, sr: arcpy.SpatialReference) -> arcpy.Polyline:
if poly.plane.normal.z == 0: normal = 1
else: normal = poly.plane.normal.z
angle = angle1 + k * math.pi*2 * normal
pt = Point( x = poly.plane.origin.x + radScaled * cos(angle), y = poly.plane.origin.y + radScaled * sin(angle), z = 0)
pt = Point( x = poly.plane.origin.x * get_scale_factor(poly.units) + radScaled * cos(angle), y = poly.plane.origin.y * get_scale_factor(poly.units) + radScaled * sin(angle), z = 0)
print(pt)
pt.units = "m"
points.append(pointToCoord(pt))
points.append(points[0])
@@ -404,10 +407,10 @@ def polycurveToNative(poly: Polycurve, sr: arcpy.SpatialReference) -> arcpy.Poly
points = []
curve = None
print("___Polycurve to native___")
try:
for segm in poly.segments: # Line, Polyline, Curve, Arc, Circle
#print(segm)
try:
for i, segm in enumerate(poly.segments): # Line, Polyline, Curve, Arc, Circle
print("___start segment")
if isinstance(segm,Line): converted = lineToNative(segm, sr) # QgsLineString
elif isinstance(segm,Polyline): converted = polylineToNative(segm, sr) # QgsLineString
elif isinstance(segm,Curve): converted = curveToNative(segm, sr) # QgsLineString
@@ -420,6 +423,7 @@ def polycurveToNative(poly: Polycurve, sr: arcpy.SpatialReference) -> arcpy.Poly
if converted is not None:
#print(converted) # <geoprocessing describe geometry object object at 0x000002B2D3E338D0>
for part in converted:
#print("Part: ")
#print(part) # <geoprocessing array object object at 0x000002B2D2E09530>
for pt in part:
#print(pt) # 64.4584221540162 5.5 NaN NaN
@@ -428,8 +432,7 @@ def polycurveToNative(poly: Polycurve, sr: arcpy.SpatialReference) -> arcpy.Poly
#print(pt_z)
#print(len(points))
if len(points)>0 and pt.X == points[len(points)-1][0] and pt.Y == points[len(points)-1][1] and pt_z == points[len(points)-1][2]: pass
else: points.append(pointToCoord(Point(x=pt.X, y = pt.Y, z = pt_z)))
#print(points)
else: points.append(pointToCoord(Point(x=pt.X, y = pt.Y, z = pt_z, units = "m"))) # e.g. [[64.4584221540162, 5.499999999999999, 0.0], [64.45461685210796, 5.587155742747657, 0.0]]
else:
arcpy.AddWarning(f"Part of the polycurve cannot be converted")
curve = arcpy.Polyline( arcpy.Array([arcpy.Point(*coords) for coords in points]), sr, has_z=True )
@@ -441,7 +444,7 @@ def polycurveToNative(poly: Polycurve, sr: arcpy.SpatialReference) -> arcpy.Poly
return curve
def arcToNativePolyline(poly: Union[Arc, Circle], sr: arcpy.SpatialReference):
print("__Arc/Circle to native__")
print("__Arc/Circle to native polyline__")
pointsSpeckle = speckleArcCircleToPoints(poly)
points = [pointToCoord(p) for p in pointsSpeckle]
curve = arcpy.Polyline( arcpy.Array([arcpy.Point(*coords) for coords in points]), sr, has_z=True )
@@ -454,6 +457,7 @@ def specklePolycurveToPoints(poly: Polycurve) -> List[Point]:
points = []
for segm in poly.segments:
print(segm)
pts = []
if isinstance(segm, Arc) or isinstance(segm, Circle): # or isinstance(segm, Curve):
print("Arc or Curve")
pts: List[Point] = speckleArcCircleToPoints(segm)
@@ -470,8 +474,8 @@ def specklePolycurveToPoints(poly: Polycurve) -> List[Point]:
def speckleArcCircleToPoints(poly: Union[Arc, Circle]) -> List[Point]:
print("__Arc or Circle to Points___")
points = []
print(poly.plane)
print(poly.plane.normal)
#print(poly.plane)
#print(poly.plane.normal)
if poly.plane is None or poly.plane.normal.z == 0: normal = 1
else: normal = poly.plane.normal.z
#print(poly.plane.origin)
@@ -511,7 +515,6 @@ def speckleArcCircleToPoints(poly: Union[Arc, Circle]) -> List[Point]:
pt.units = poly.plane.origin.units
points.append(pt)
if isinstance(poly, Arc): points.append(poly.endPoint)
return points
@@ -161,7 +161,10 @@ def rasterFeatureToSpeckle(selectedLayer: arcLayer, projectCRS: arcpy.SpatialRef
#ds = gdal.Open(selectedLayer.source(), gdal.GA_ReadOnly)
extent = my_raster.extent
rasterOriginPoint = arcpy.PointGeometry(arcpy.Point(extent.XMin, extent.YMin, extent.ZMin), my_raster.spatialReference, has_z = True)
print(extent.XMin)
print(extent.YMin)
rasterOriginPoint = arcpy.PointGeometry(arcpy.Point(extent.XMin, extent.YMax, extent.ZMin), my_raster.spatialReference, has_z = True)
#if extent.YMin>0: rasterOriginPoint = arcpy.PointGeometry(arcpy.Point(extent.XMin, extent.YMax, extent.ZMin), my_raster.spatialReference, has_z = True)
print(rasterOriginPoint)
rasterResXY = [my_raster.meanCellWidth, my_raster.meanCellHeight] #[float(ds.GetGeoTransform()[1]), float(ds.GetGeoTransform()[5])]
rasterBandNoDataVal = [] #list(my_raster.noDataValues)
@@ -192,7 +195,7 @@ def rasterFeatureToSpeckle(selectedLayer: arcLayer, projectCRS: arcpy.SpatialRef
print(np.shape(rb.read()))
valMin = rb.minimum
valMax = rb.maximum
bandVals = np.flip(np.swapaxes(rb.read(), 1, 2), 0).flatten() #.tolist()
bandVals = np.swapaxes(rb.read(), 1, 2).flatten() #.tolist() np.flip( , 0)
bandValsFlat = []
bandValsFlat.extend(bandVals.tolist())
@@ -240,7 +243,7 @@ def rasterFeatureToSpeckle(selectedLayer: arcLayer, projectCRS: arcpy.SpatialRef
b["@(10000)" + item + "_values"] = bandValsFlat #[0:int(max_values/rasterBandCount)]
b["X resolution"] = rasterResXY[0]
b["Y resolution"] = rasterResXY[1]
b["Y resolution"] = -1* rasterResXY[1]
b["X pixels"] = rasterDimensions[0]
b["Y pixels"] = rasterDimensions[1]
b["Band count"] = rasterBandCount
@@ -316,10 +319,10 @@ def rasterFeatureToSpeckle(selectedLayer: arcLayer, projectCRS: arcpy.SpatialRef
# identify symbology type and if Multiband, which band is which color
for v in range(rasterDimensions[1] ): #each row, Y
for h in range(rasterDimensions[0] ): #item in a row, X
pt1 = arcpy.PointGeometry(arcpy.Point(extent.XMin+h*rasterResXY[0],extent.YMin+v*rasterResXY[1]), my_raster.spatialReference, has_z = True)
pt2 = arcpy.PointGeometry(arcpy.Point(extent.XMin+h*rasterResXY[0], extent.YMin+(v+1)*rasterResXY[1]), my_raster.spatialReference, has_z = True)
pt3 = arcpy.PointGeometry(arcpy.Point(extent.XMin+(h+1)*rasterResXY[0], extent.YMin+(v+1)*rasterResXY[1]), my_raster.spatialReference, has_z = True)
pt4 = arcpy.PointGeometry(arcpy.Point(extent.XMin+(h+1)*rasterResXY[0], extent.YMin+v*rasterResXY[1]), my_raster.spatialReference, has_z = True)
pt1 = arcpy.PointGeometry(arcpy.Point(extent.XMin+h*rasterResXY[0],extent.YMax-v*rasterResXY[1]), my_raster.spatialReference, has_z = True)
pt2 = arcpy.PointGeometry(arcpy.Point(extent.XMin+h*rasterResXY[0], extent.YMax-(v+1)*rasterResXY[1]), my_raster.spatialReference, has_z = True)
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:
pt1 = findTransformation(pt1, "Point", my_raster.spatialReference, projectCRS, selectedLayer)
@@ -383,11 +386,17 @@ def rasterFeatureToSpeckle(selectedLayer: arcLayer, projectCRS: arcpy.SpatialRef
if colorizer:
try: bandIndex = int(colorizer.band)
except: pass
if rasterBandVals[bandIndex][int(count/4)] >= float(colorizer.minLabel) and rasterBandVals[bandIndex][int(count/4)] <= float(colorizer.maxLabel) : #rasterBandMinVal[bandIndex]:
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 = 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 )
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
@@ -1,13 +1,13 @@
# -*- coding: utf-8 -*-
r'''
import arcpy
class Toolbox(object):
def __init__(self):
"""Define the toolbox (the name of the toolbox is the name of the
.pyt file)."""
self.label = "Speckle Toolbox"
self.alias = "speckle_toolbox_"
self.label = "Speckle something"
self.alias = "speckle_toolbox"
self.tools = [Speckle]
class Speckle(object):
@@ -45,4 +45,4 @@ class Speckle(object):
def execute(self, parameters):
return
'''
@@ -1,3 +1,4 @@
# -*- coding: utf-8 -*-
from typing import Any, Callable, List, Optional, Tuple
@@ -331,7 +332,7 @@ class Speckle:
saved_streams = self.speckleInputs.getProjectStreams()
self.speckleInputs.saved_streams = saved_streams
p_saved.filter.list = [f"Stream not accessible - {stream[0].stream_id}" if stream[1] is None or isinstance(stream[1], SpeckleException) else f"{stream[1].name} - {stream[1].id}" for i,stream in enumerate(saved_streams)]
p_saved.value = p_saved.filter.list[0]
if len(p_saved.filter.list)>0: print(p_saved.filter.list); p_saved.value = p_saved.filter.list[0]
break
p.value = None
par.value = False
@@ -358,7 +359,7 @@ class Speckle:
saved_streams = self.speckleInputs.getProjectStreams()
self.speckleInputs.saved_streams = saved_streams
p_saved.filter.list = [f"Stream not accessible - {st[0].stream_id}" if st[1] is None or isinstance(st[1], SpeckleException) else f"{st[1].name} - {st[1].id}" for i,st in enumerate(saved_streams)]
p_saved.value = p_saved.filter.list[0]
if len(p_saved.filter.list)>0: print(p_saved.filter.list); p_saved.value = p_saved.filter.list[0]
else: pass
p.value = None
@@ -525,8 +526,8 @@ class Speckle:
if par.name == "streamUrl": par.value = None
if par.name == "streamsDefalut": par.value = None
if par.name == "savedStreams": par.value = None
if par.name == "branch": par.value = ""
if par.name == "commit": par.value = None
if par.name == "branch": par.value = ""; par.filter.list = []
if par.name == "commit": par.value = None; par.filter.list = []
if par.name == "selectedLayers": par.value = None
if par.name == "msg": par.value = ""
if par.name == "action": par.value = "Send"
@@ -681,14 +682,14 @@ class Speckle:
if self.speckleInputs.project.activeMap.spatialReference.type == "Geographic" or self.speckleInputs.project.activeMap.spatialReference is None: #TODO test with invalid CRS
arcpy.AddMessage("It is advisable to set the project Spatial reference to Projected type before receiving CAD geometry (e.g. EPSG:32631), or create a custom one from geographic coordinates")
print("It is advisable to set the project Spatial reference to Projected type before receiving CAD geometry (e.g. EPSG:32631), or create a custom one from geographic coordinates")
print(f"Succesfully received {objId}")
print(f"Successfully received {objId}")
# Clear 'latest' group
streamBranch = streamId + "_" + self.toolboxInputs.active_branch.name + "_" + str(commit.id)
newGroupName = f'{streamBranch}'
groupExists = 0
#print(newGroupName)
print(newGroupName)
for l in self.speckleInputs.project.activeMap.listLayers():
#print(l.longName)
if l.longName.startswith(newGroupName + "\\"):
@@ -697,18 +698,29 @@ class Speckle:
groupExists+=1
elif l.longName == newGroupName:
groupExists+=1
print(newGroupName)
if groupExists == 0:
# create empty group layer file
path = self.speckleInputs.project.filePath.replace("aprx","gdb") #"\\".join(self.toolboxInputs.project.filePath.split("\\")[:-1]) + "\\speckle_layers\\"
#print(path)
f = open(path + "\\" + newGroupName + ".lyrx", "w")
content = createGroupLayer().replace("TestGroupLayer", newGroupName)
f.write(content)
f.close()
smth = arcpy.mp.LayerFile(path + "\\" + newGroupName + ".lyrx")
#print(smth)
layerGroup = self.speckleInputs.project.activeMap.addLayer(smth)[0]
print(path)
try:
f = open(path + "\\" + newGroupName + ".lyrx", "w")
content = createGroupLayer().replace("TestGroupLayer", newGroupName)
f.write(content)
f.close()
newGroupLayer = arcpy.mp.LayerFile(path + "\\" + newGroupName + ".lyrx")
layerGroup = self.speckleInputs.project.activeMap.addLayer(newGroupLayer)[0]
except: # for 3.0.0
if self.speckleInputs.active_map is not None:
layerGroup = self.speckleInputs.active_map.createGroupLayer(newGroupName)
else:
arcpy.AddWarning("The map didn't fully load, try refreshing the plugin.")
return
print(layerGroup)
print("layer added")
layerGroup.name = newGroupName
print(newGroupName)
if app == "QGIS" or app == "ArcGIS": check: Callable[[Base], bool] = lambda base: isinstance(base, Layer) or isinstance(base, VectorLayer) or isinstance(base, RasterLayer)
else: check: Callable[[Base], bool] = lambda base: isinstance(base, Base)
@@ -25,7 +25,7 @@ class speckleInputsClass:
project = None
active_map = None
saved_streams: List[None or Tuple[StreamWrapper, Stream]] = []
saved_streams: List[Optional[Tuple[StreamWrapper, Stream]]] = []
stream_file_path: str = ""
all_layers: List[arcLayer] = []
@@ -44,6 +44,7 @@ class speckleInputsClass:
def __init__(self) -> None:
print("___start speckle inputs________")
self.all_layers = []
try:
aprx = ArcGISProject('CURRENT')
self.project = aprx
@@ -63,7 +64,9 @@ class speckleInputsClass:
f.close()
except: pass
else:
elif len(self.stream_file_path) >10:
f = open(self.stream_file_path, "x")
f.close()
f = open(self.stream_file_path, "w")
content = ""
f.write(content)
@@ -89,6 +92,7 @@ class speckleInputsClass:
streamExists = 0
index = 0
try:
print(url)
sw = StreamWrapper(url)
stream = self.tryGetStream(sw)
@@ -101,7 +105,7 @@ class speckleInputsClass:
streamsTuples.insert(0,(sw, stream))
except SpeckleException as e:
arcpy.AddMessage(str(e.args[0]))
arcpy.AddMessage(str(e.args))
return streamsTuples
else: return []
@@ -126,8 +130,8 @@ class toolboxInputsClass:
instances = []
lat: float = 0.0
lon: float = 0.0
active_stream: None or Stream = None
active_branch: None or Branch = None
active_stream: Optional[Stream] = None
active_branch: Optional[Branch] = None
active_commit = None
selected_layers: List[Any] = []
messageSpeckle: str = ""
@@ -159,7 +163,7 @@ class toolboxInputsClass:
def setProjectStreams(self, wr: StreamWrapper, add = True):
# ERROR 032659 Error queueing metrics request:
# Cannot parse into a stream wrapper class - invalid URL provided.
print("SET proj streamz")
print("SET proj streams")
if os.path.exists(self.stream_file_path):
@@ -180,7 +184,9 @@ class toolboxInputsClass:
f.write(new_content)
f.close()
else:
elif len(self.stream_file_path) >10:
f = open(self.stream_file_path, "x")
f.close()
f = open(self.stream_file_path, "w")
f.write(str(wr.stream_url) + ",")
f.close()
@@ -226,7 +232,9 @@ class toolboxInputsClass:
new_content += pt + "," # add point
f.write(new_content)
f.close()
else:
elif len(self.stream_file_path) >10:
f = open(self.stream_file_path, "x")
f.close()
f = open(self.stream_file_path, "w")
f.write(pt + ",")
f.close()