Jump to content


  • Posts

  • Joined

  • Last visited

Posts posted by relume

  1. Hello Vlado


    Thank you very much for your response.


    That clarifies what I was assuming – but hopped it is not the case.

    But it is the reason why in VW python "sys.excecutable" on the MacOS/darwin plattform is pointing to the VW app, and why "pyhton" and "pip" are not exectuable on the command line inside the darwin VW app package/bundle (error : missing python image).


    It would makes only sens to install an additional python installation inside the VW app/bundle, if this will replace the internal VW python environment to run the scripts. But after some days finally I was able to install 3.5.2 and get it run as standard installation on the MacOS . This 3.5.2 standard system installation is only used to get the rigth modules (like geopandas and some related modules) installed an be used in VW (installed on '~/Library/Application Support/VectorWorks/2020/Python Externals').


    But I have also to say that python 3.5.2 is for lot of modules a critical version. Python 3.5.3 is much less critical - but module versions loaded with 3.5.3, were incompatible with 3.5.2. Thus I would very appreciate, if in VectorWorks a more recent version of python would be embedded - at least the latest version of an allready EOL minor version - for python 3.5 > 3.5.9. But meanwhile python 3.7 is very common, not pointing to python 3.8.


    Many thanks again and best regards,




  2. Hello JBenghiat


    Thank you very much for your message.


    Yes I had allready carried out the same steps as your hints, prior to post the topic.


    Finally I could resolve the problem with the 3.5.2 installer that was broken for a outdated SSL certificate (with pip it was not possible any more to get the python "pypi.python.org" cache for looking about python packages. Neither it was possible to update PIP for the same reason. Updating PIP resolved the problem:


    curl https://bootstrap.pypa.io/get-pip.py | python3.5

    where python3.5 is the python version installed from 3.5.2


    best regards,





  3. VectorWorks : v2020 SP2

    MacOSX       : 10.14.6




    I am facing big troubles to install some modules like "geopandas" to use them with VectorWorks 2020.


    • Actually I can install with an external python installation version 3.5.9 (the latest version in 3.5) all needed modules. Unfortunately there are some incompatibilities (for example for "pandas") while importing against the the internal VectorWorks 2020 python version 3.5.2 and its built-in functions.
    • So I installed a python 3.5.2 version from the official download page, but now it is not possible to locate any external module, that satisfy the requirements of version 3.5.2 and further I am getting errors that says:
    •   1 location(s) to search for versions of rtree:
        * https://pypi.python.org/simple/rtree/
        Getting page https://pypi.python.org/simple/rtree/
        Looking up "https://pypi.python.org/simple/rtree/" in the cache
        Returning cached "301 Moved Permanently" response (ignoring date and etag information)
        Looking up "https://pypi.org/simple/rtree/" in the cache
        Cache entry deserialization failed, entry ignored
        Starting new HTTPS connection (1): pypi.org
        Could not fetch URL https://pypi.python.org/simple/rtree/: There was a problem confirming the ssl certificate: [SSL: TLSV1_ALERT_PROTOCOL_VERSION] tlsv1 alert protocol version (_ssl.c:

    It seems that VW 2020 python version 3.5.2 is really outdated  and thus it would be "best" to update the internal VW version to 3.5.9 at least. Is this feasible and how?


    Many thanks,





  4. Hello Patrick


    I am sorry to respond only today to your posting.


    Many thanks for posting the "Marionette.VerifyOrGetLib()" implementation. I previously searched in vain for the Marionette lib/package inside the VectorWorks 2020.app package (MacOS version). Where did you found the Marionette.py file?


    It is remarkable, that they use for the installation of modules for the MacOS/darwin plattform not the python distro that is installed inside the VectorWorks 2020.app package but the standard python installation :


    sys.executable = '/usr/bin/python'
    ret_code = pip.main(['install', destination,'-q','--target', cmd])
    sys.executable = sys_executable_orig

    On my MacOSX 10.14.6 system "/usr/bin/python" shows version 2.7.16. VectorWorks 2020 has installed version 3.5.2.


    Furthermore now it became clear to me why installing the modul by pip with an subproccess call and using the value of "sys.executable" did not work and opened a new instance of VectorWorks 2020.app. On the MacOS/darwin plattform "sys.executable" does not hold the path of the internal python installation but the VectorWorks 2020.app itself:


    /Applications/Vectorworks 2020/Vectorworks 2020.app/Contents/MacOS/Vectorworks


    For that reason I tried to call directly the internal (VectorWorks 2020.app) python installation to work with it and to have the corresponding python version for installing appropriate modules. But it seems that the internal python installation is not callable and executable:


    dyld: Library not loaded: /Library/Frameworks/Python.framework/Versions/3.5/Python
      Referenced from: /Applications/Vectorworks 2020/Vectorworks 2020.app/Contents/Frameworks/Python.framework/Versions/3.5/bin/python3.5-32
      Reason: image not found

    The call by "subprocess.run('...../bin/python3.5-32', '--version') results for all python bins to "image not found". So I have to assume that for VectorWorks 2020 on the MacOS/darwin plattform the internal python installation and thus the pyhton image (binary) is somewhat "hiden" or maybe compiled into a VectorWorks package (?).


    For that reason I installed finally for MacOS/darwin with homebrew an appropriate python 3.5.X installation which is then linked and callable to:



    thus now I have modified my own modul installation function in order also to use on the MacOS/darwin plattform the now standard subprocess function "subprocess.run" that replace all other previous subprocess functions:


    vVW_AppUserPy_folder =  vs.GetFolderPath(12).replace(':','/') + 'Python Externals'
    vPython_path = '/usr/local/bin/' 
    vPython_pip_path = vPython_path + 'pip3.5'
    vModule_version = '>=2.5.0' # vModule_version can be passed to pip directly behind the module name
    vModule_version = ''
    vCommand = [vPython_pip_path , 'install', '--upgrade', '-v', vModule+vModule_version, '--target', vVW_AppUserPy_folder]
    vPip_proc = subprocess.run(vCommand, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
    vPip_proc_exit_code = vPip_proc.returncode
    vPip_proc_sdtout = vPip_proc.stdout.decode('utf-8')
    vPip_proc_sdterr = vPip_proc.stderr.decode('utf-8')


    best regards



  5. Hello


    in the following there is the VW log output of installing the module "pyspatial" (the same with "rtree") that does not work with the pip.main() approach and starts a setup.py "process" and a second instance of the VectorWorks.app:


      Starting new HTTPS connection (1): pypi.org
      https://pypi.org:443 "GET /simple/pyspatial/ HTTP/1.1" 304 0
      Analyzing links from page https://pypi.org/simple/pyspatial/
        Found link https://files.pythonhosted.org/packages/e2/a4/3d79183abfa1f898cfb48d858c7b31af158c4a8195f4a68acdc7f2262f26/pyspatial-0.1.0.tar.gz#sha256=0a887170be86e6ef6ef6bab8afa416cd876f9e2ddd3bef50f08213074bcf62d3 (from https://pypi.org/simple/pyspatial/), version: 0.1.0
        Found link https://files.pythonhosted.org/packages/4d/4c/389f48ccacbc3914e0f3e4cc33848b090a12917b4dfec9fa6622e9425d7c/pyspatial-0.1.1.tar.gz#sha256=245c2c8d9c5ad436a01d743b7f1b40067aaa5b998178f52284affb1dd269150b (from https://pypi.org/simple/pyspatial/), version: 0.1.1
        Found link https://files.pythonhosted.org/packages/26/93/adc918fa271de29f14b17de01409a29bbeb54e3ee18578ba999809787726/pyspatial-0.1.2.tar.gz#sha256=fbcec18df8d43d870e42a56f83e6286542d1bcf63bfa1e4070cb4d5dfd6a9ce6 (from https://pypi.org/simple/pyspatial/), version: 0.1.2
        Found link https://files.pythonhosted.org/packages/be/8e/38680a60c87da016a67e7674088562e8cfbb1d478ef75759a2963de7fd82/pyspatial-0.1.4.tar.gz#sha256=d97fb8ca47684cd20659785a541f0e32075cdc23e134761d34e199c7aef5711c (from https://pypi.org/simple/pyspatial/), version: 0.1.4
        Found link https://files.pythonhosted.org/packages/b7/9d/694cf404ea5abb10117b0d9aebaf610cddbaaf1bdc3202aa0b730d1e472f/pyspatial-0.2.1.tar.gz#sha256=612e2ee010558d14c8efaa70dad43c7c147e5b6e79eedc6eb965d61c6b568d46 (from https://pypi.org/simple/pyspatial/), version: 0.2.1
        Found link https://files.pythonhosted.org/packages/eb/b3/57d3d0fc106bb1d22a9ca9b6055a2865e2f5ee9c897e3b8eb2ec91cdf23a/pyspatial-0.2.3.tar.gz#sha256=2ea43da81fa2094de99ade462430bff298778be3ca02bfc3eb5dd69e911491fe (from https://pypi.org/simple/pyspatial/), version: 0.2.3
        Found link https://files.pythonhosted.org/packages/27/c8/279807519a8c76115c5bb38a454784b69513c889e50afee874470f884223/pyspatial-0.2.4.tar.gz#sha256=387e26cf08b02504ebec0ec1c137aa4331d4818ae9738210f19d40aa3261e8c9 (from https://pypi.org/simple/pyspatial/), version: 0.2.4
      Using version 0.2.4 (newest of versions: 0.1.0, 0.1.1, 0.1.2, 0.1.4, 0.2.1, 0.2.3, 0.2.4)
      Looking up "https://files.pythonhosted.org/packages/27/c8/279807519a8c76115c5bb38a454784b69513c889e50afee874470f884223/pyspatial-0.2.4.tar.gz" in the cache
      Current age based on date: 152800
      Freshness lifetime from max-age: 365000000
      The response is "fresh", returning cached response
      365000000 > 152800
      Using cached https://files.pythonhosted.org/packages/27/c8/279807519a8c76115c5bb38a454784b69513c889e50afee874470f884223/pyspatial-0.2.4.tar.gz
      Downloading from URL https://files.pythonhosted.org/packages/27/c8/279807519a8c76115c5bb38a454784b69513c889e50afee874470f884223/pyspatial-0.2.4.tar.gz#sha256=387e26cf08b02504ebec0ec1c137aa4331d4818ae9738210f19d40aa3261e8c9 (from https://pypi.org/simple/pyspatial/)
      Running setup.py (path:/private/var/folders/nx/hzd6xdlj62d6xnh9n63x3cwc000mh8/T/pip-build-huwr1_vk/pyspatial/setup.py) egg_info for package pyspatial
        Running command python setup.py egg_info
        2020-03-07 10:22:20.657 Vectorworks[14776:14547727] ApplePersistenceIgnoreState: Existing state will not be touched. New state will be written to (null)
        2020-03-07 10:22:27.183 Vectorworks[14776:14547727] Attempt to load executable of a type that cannot be dynamically loaded for CFBundle 0x7fc97843d520 </Applications/Vectorworks 2020/Plug-Ins/SketchUpWorker.vwlibrary> (executable, not loaded)
        [0307/102229.600319:WARNING:resource_bundle.cc(353)] locale_file_path.empty() for locale de-CH
        [0307/102229.600668:ERROR:main_delegate.cc(671)] Could not load locale pak for de-CH
        [0307/102229.606890:WARNING:resource_bundle.cc(548)] locale resources are not loaded
        [0307/102229.612772:ERROR:proxy_service_factory.cc(116)] Cannot use V8 Proxy resolver in single process mode.
        *   Trying
        * TCP_NODELAY set
        * Connected to vectorworks-hilfe.computerworks.eu ( port 80 (#0)
        > HEAD /2020/index.htm HTTP/1.1
        Host: vectorworks-hilfe.computerworks.eu
        Accept: */*
        < HTTP/1.1 200 OK
        < Date: Sat, 07 Mar 2020 09:22:32 GMT
        < Server: Apache/2.4.41
        < Last-Modified: Tue, 14 Jan 2020 14:51:47 GMT
        < ETag: "6c4a-59c1abb2fc496"
        < Accept-Ranges: bytes
        < Content-Length: 27722
        < Content-Type: text/html
        * Connection #0 to host vectorworks-hilfe.computerworks.eu left intact
        2020-03-07 10:22:36.016 Vectorworks[14776:14547727] Reachability Flag Status: -R ------- networkStatusForFlags
        Application start      : 03/07/20 at 10:22:37


    by this following part of the sequence (snippet from above log) the second VectorWorks.app is started up:


       Running setup.py (path:/private/var/folders/nx/hzd6xdlj62d6xnh9n63x3cwc000mh8/T/pip-build-huwr1_vk/pyspatial/setup.py) egg_info for package pyspatial
        Running command python setup.py egg_info


    Many thanks for any hint,




    P.S. the Marionette.VerifyOrGetLib() approach does not work really, if you do want to install libs/modules in more generalistic way like this e.g. "pip.main(install --upgrade 'dateutil>=2.5.0' and without passing the ressource URL as it is needed in Marionette.VerifyOrGetLib()



  6. Hello


    I am wondering if there is any documentation for the Marionette function "Marionette.VerifyOrGetLib()" with its posssible parameters. I am wondering if it is possible to get an lib/module and a specific Version with "Marionette.VerifyOrGetLib()" as with pip  (e.g. pip.main('install',  '--upgrade', 'dateutil>=2.5.0') thus not passing a specific ressource URL?


    I have the problem that for some python lib/modules (e.g. pyspatial or rtree) the pip.main() approach does not work, as on installing those libs/moduls a setup.py call is started an therefore a new instance of VectorWorks.app is started.


    see my other topic (installing-modules-from-within-a-script) : I am sorry for crosspointing.


    Many thanks,






  7. approachVectorWorks : v2020

    MacOSX        : 10.14.6




    I have used until now sucessfully the following code snippet to install missing modules:


    see also this forum entry:  "PIL python image library for vw 2018"


    vModule = 'mymoduleToimport'
    pip.main(['install', '--upgrade', '-v', vModule])
    # or 
    vVW_AppUserPy_folder = '/Users/myuser/Library/Application\ Support/VectorWorks/2020/PythonExternals'
    pip.main(['install', '--upgrade', '-v', vModule, '--target', vVW_AppUserPy_folder])

    This works for most modules.  For some modules (e.g. pyspatial) this approach is not working and instead a second instance of the VectorWorks.app is started without any error (only verbose console output), but those modules are finally not installed. As far as I can see, those modules that are not working are calling the setup.py script. Is there any way to suppress this behavior?


    While "debugging" I learned, that in PIP > version 10 (actual PIP version is version 20, and in VectorWorks v2020 version 8.1 is installed by default), the pip.main() function is removed and the following construct should be used:


    vPip_proc = subprocess.run([sys.executable, '-m', 'pip', 'install', '--upgrade', '-v', vModule, '--target', vVW_AppUserPy_folder ])
    vPip_proc_exit_code = vPip_proc.returncode
    vPip_proc_sdtout = vPip_proc.stdout
    vPip_proc_sdterr = vPip_proc.stderr


    Unfortunately this approach is not working at all for all python modules. Every time a second instance of the VectorWorks.app is started without any error and output and no module is installed.


    I would appreciate any hint or suggestion how to solve this problem. Many thanks in advance,









    For external geometrical processing in a python script, every VW polygon that has one or more curved vertices has to be converted to an approximated "lines only" polygon. This represents the standard transformation for any curved vortex on exporting VW objects by the export function to the Shape-Geodata format. There is also an VW-menu functionality, that converts a polygon to a multi-line group, where curved vertices were approximated by as many needed short lines.


    At the moment I can not see, how I can get/convert to such a "lines only" polygon by a VS function. The idea is the following:


    1. get the handle of the VW polygon.
    2. test if there is one or more curved vertices by looping through all vertices of the polygon (using vs.GetPolylineVertex).
    3. if there is any curved vertex in the referenced polygon, make a temporal copy of the original polygon and convert this copy to a "lines only" polygon.
    4. process the "lines only" polygon as needed in the python script


    Step 3. is the operation  I am interessted in – a "fast" and VW internal converting operation to a "lines only" polygon or a group of lines.


    Many thanks in advance for any hint, best regards,



  9. Hello


    I am not sure, if have understood correctly your question. However I can say the following:

    • the progress dialog can be displayed without the vs.ProgressDlgStart() and terminated without the vs.ProgressDlgEnd() call.
    • without calling vs.ProgressDlgClose() the dialog window stays open until the script terminates.
    • vs.ProgressYield() has to have a numeric parameter vs.ProgressYield(1), otherwise pyhton errors are thrown.
    • vs.ProgressYield(int) has to be called otherwise the other messages like vs.ProgressDlgSetMeter(message) are not refreshed on the dialog window.
    def messagePtest3():
    	selCount = 10
    	def DoTheWork():
    	#	vs.ProgressDlgStart(100,selCount)
    		for i in range(selCount+1):
    			vs.Wait( 1 )	#well, we work by waiting
    	vs.ProgressDlgOpen( "I'm about to do some work", False )
    	vs.ProgressDlgSetMeter("") # this resets previous values, if vs.ProgressDlgStart is not callded
    	# vs.ProgressDlgEnd()
        # vs.ProgressDlgClose() # if close is not called, the dialog stays open until the script terminates


    best regards,





  10. Hello


    I created for my pyhton script two types of custom dialogs a simple one and a version I can define the custom dialog by an string (multiple strings passed to the same Dialog-ID). I put both dialogs in a function placed in a lib, so I have them "handy" for all scripts:


    simple dialog:


    def dialog_input_simple(vDialog_Titel = '', vDialog_Text = '', vDialog_Text_help = '', vDialog_Text_input = ''):
    	cCancelButton = 2
    	cOKButton = 1
    	cSetupDialog = 12255
    	def setup(vDialog_Titel, vDialog_Text, vDialog_Text_help, vDialog_Text_input):
    		vDialog_ID = vs.CreateLayout(vDialog_Titel,1,'ausführen','abbrechen')
    		vs.SetFirstLayoutItem(vDialog_ID, 100)
    		vs.SetBelowItem (vDialog_ID,100,300,0,0)
    		vs.SetHelpText(vDialog_ID, 300,vDialog_Text_help)
    		return (vDialog_ID)
    	def control(vDialog_Item, vDialog_Data):
    		# do not write any code here, as it is executed on every event cycle, even after the ok-event
    		nonlocal vDialog_Text_input
    		if vDialog_Item == cSetupDialog:
    			vDialog_Text_input = ''
    		elif vDialog_Item == cCancelButton:
    			pass # pass statement is a null operation
    		elif vDialog_Item == cOKButton:
    			vDialog_Text_input = vs.GetItemText(vDialog_ID, 300)
    			# vestB.messageA(vObject_ID)
    		return (vDialog_Item)
    	vDialog_ID = setup(vDialog_Titel, vDialog_Text, vDialog_Text_help, vDialog_Text_input)
    	vDialog_Result = vs.RunLayoutDialog(vDialog_ID, control)
    	return (vDialog_Result, vDialog_Text_input)


    variable custom dialog:


    def dialog_input_multiple(vDialogParameters = ""):
    	cCancelButton = 2
    	cOKButton = 1
    	cSetupDialog = 12255
    	vDialog_Result = cCancelButton
    	def setup(vDialogParameters_list):
    		vDialog_Titel = vDialogParameters_list['title']
    		vDialog_Text = vDialogParameters_list['head']
    		vDialog_Items_search = 'item'
    		vDialog_Items_List = [vKey for vKey,vValue in vDialogParameters_list.items() if (vKey.lower()).startswith(vDialog_Items_search)]
    		vDialog_ID = vs.CreateLayout(vDialog_Titel,1,'ausführen','abbrechen')
    		vDialog_Item_ID_start = 1000
    		vDialog_Item_ID = vDialog_Item_ID_start
    		vs.SetFirstLayoutItem(vDialog_ID, vDialog_Item_ID)
    		vDialog_Items_List.sort() # this sorts only on items key and not on the ID, future sorting should be on ID
    		# messageA(vDialog_Items_List)
    		vDialog_Results = list()
    		for vDialog_Item_key in vDialog_Items_List:
    			vDialog_Item_values = vest.base.vw.lists.keyvalueList_ToList(vest.base.vw.lists.text_ToList_embraced(vDialogParameters_list[vDialog_Item_key]))
    			vDialog_Item_ID_previous = vDialog_Item_ID
    			vDialog_Item_ID_org = vDialog_Item_values['ID']
    			vDialog_Item_ID = int(vDialog_Item_ID_org)+(2*vDialog_Item_ID_start)
    			vDialog_Item_name = vDialog_Item_values['name']
    			vDialog_Item_label = vDialog_Item_values['label']
    			vDialog_Item_input = vDialog_Item_values['input']
    			vDialog_Item_help = vDialog_Item_values['help']
    			# messageA("vDialog_Item_ID_previous | vDialog_Item_ID:" + str(vDialog_Item_ID_previous) + " | " + str(vDialog_Item_ID))
    			vs.SetBelowItem (vDialog_ID,vDialog_Item_ID_previous,vDialog_Item_ID,0,0)
    			vs.SetHelpText(vDialog_ID, vDialog_Item_ID,vDialog_Item_help)
    			vDialog_Results.append({'dialogID': vDialog_Item_ID, 'ID': vDialog_Item_ID_org, 'name': vDialog_Item_name, 'input': vDialog_Item_input})
    		return (vDialog_ID, vDialog_Results)
    	def control(vDialog_Item, vDialog_Data):
    		# do not write any code here, as it is executed on every event cycle, even after the ok-event
    		nonlocal vDialog_Results
    		if vDialog_Item == cSetupDialog:
    			pass # pass statement is a null operation
    		elif vDialog_Item == cCancelButton:
    			pass # pass statement is a null operation
    		elif vDialog_Item == cOKButton:
    			for vDialog_Results_item in vDialog_Results:
    				vDialog_Item_ID = vDialog_Results_item['dialogID']
    				vDialog_Results_item['input'] = vs.GetItemText(vDialog_ID, vDialog_Item_ID)
    		return (vDialog_Item)
    	vDialogParameters_list = vest.base.vw.lists.keyvalue_ToList(vDialogParameters, ';', '+=')
    	if len(vDialogParameters_list)>0:
    		vDialog_ID, vDialog_Results = setup(vDialogParameters_list)
    		vDialog_Result = vs.RunLayoutDialog(vDialog_ID, control)
    	return (vDialog_Result, vDialog_Results)
    # END		:	vest.base.vw.base.dialog_input_multiple


    the variable dialog can by called by these parameters:


    # dialog_input_multiple(vDialogParameters = "") # "title+=Titel;head+=Head;item1+=[ID=100] [name=field 100] [label=label 100] [input=input 100] [help=help 100] [type=text];"


    or as example:


    	vDialog_Parameters = ''
    	vDialog_Parameters += 'title+=Table Export;'
    	vDialog_Parameters += 'head+=Entry of DB-name and list of all DB-field-name;'
    	vDialog_Parameters += 'item1+=[ID=100] [name=db_name] [label=DB name] [input='+ vDB_Name +'] [help=please enter the DB-name] [type=text];'
    	vDialog_Parameters += 'item2+=[ID=110] [name=db_field_list] [label=Feld Namen] [input='+ vDB_Field_Name_TextList +'] [help=please enter all DB-field names as a list : field1, field2 ... oder !ALL! for all DB fields] [type=text];'
    	vDialog_Result, vDialog_Results = vestB.dialog_input_multiple(vDialog_Parameters)


    and here the functions called inside of the dialog_input_multiple(vDialogParameters) function to decode the input string vDialogParameters:


    def keyvalue_ToList(vValues_text, vValues_Entity_Split = ';', vValues_Pair_Split = '='): # 'key1=value1;key2=value2;key3=value3'
    		vEntity_List = text_ToList(vValues_text, vValues_Entity_Split)
    		vValues_list = list()
    		vValues_list = dict(vEntity.split(vValues_Pair_Split) for vEntity in vEntity_List) 
    		return (vValues_list)
    def text_ToList(vValues_text, vValues_Entity_Split = ',' ):
    	import re
    	vValues_list = list()
    	vValues_list = re.split(r"" + vValues_Entity_Split + "\s*", vValues_text)
    	vValues_list = list(filter(None,vValues_list)) # removes void/empty items
    	return (vValues_list)
    def text_ToList_embraced(vValues_text, vValues_Entity_SplitStart = '', vValues_Entity_SplitEnd = ''):
    	import re
    	vValues_list = list()
    	if vValues_Entity_SplitStart != '' and vValues_Entity_SplitEnd != '':
    		vPattern = re.escape(vValues_Entity_SplitStart) +  "[^" + re.escape(vValues_Entity_SplitEnd) + "]*" + re.escape(vValues_Entity_SplitEnd) + "|\S+"
    		vValues_list = re.findall(vPattern, vValues_text)
    		vPatternReplace = "\A" + re.escape(vValues_Entity_SplitStart) + "|" + re.escape(vValues_Entity_SplitEnd )+ "\Z"
    		vValues_list = [re.sub(vPatternReplace, '', item) for item in vValues_list] # to strip leading and trailing embracing strings
    		vValues_list = re.findall('\[[^\]]*\]|\([^\)]*\)|\"[^\"]*\"|\S+',vValues_text)
    		vValues_list = [re.sub('\A\[|\]\Z|\A\(|\)\Z|\A\"|\"\Z', '', item) for item in vValues_list]
    	vValues_list = list(filter(None,vValues_list)) # removes void/empty items
    	return (vValues_list)


    best regards,






    • Like 1
  11. Hello


    For certain reasons I am "misusing" VectorWorks for some GIS related tasks. So I have to find for a hugh number of simple 2D polygons all possible 2D points on a certain layer that are inside each polygon - the so called "point in polygon" or "PIP" problem. My VectorWork python script using the "vs.FindObjAtPt..." functions is good for a small number of polygons and points but frustrating slow for a large number of objects to be matched/tested – I am siting in front of the computer screen now for more than 72 hours, waiting and without any hope and no idea (for that fact that the vs.message fuctions still does not work in VW2020) when the script will terminate. So my idea is to "outsource" the hole PIP processing to adequate python modules like Geopandas, where solving diverse PIP problems are representing standard functions.


    Thus has someone already some experience or best practice how to "poke out" (transfer) most efficiently and fast the geometric VW object data inside of a VW pyhton script to a Geopandas data structure (data frame) in the form of e.g. for a polygon (x0 y0, x1 y1, x2 y2, ... , xn yn). The question is related to VW given functions to access the object geometric informations hopefully a single step (function call)?


    Many thanks in advance for any hint and best regards,





  12. Hello


    please find two scripts that I have created as part of libs:


    # use		:	assigns a new layer to object 
    def object_layer_assign(vObject_Handle, vLayer_Destination_Name):
    	vLayer_Destination_Handle = vs.GetLayerByName(vLayer_Destination_Name)
    	if vLayer_Destination_Handle == None:
    		vLayer_Actual_Handle = vs.ActLayer()
    		vLayer_Actual_Name = vs.GetLName(vLayer_Actual_Handle)
    		vLayer_Destination_Handle = vs.ActLayer()
    	vs.SetParent(vObject_Handle, vLayer_Destination_Handle)


    and :


    # use		:	assigns a new layer to objects selected by criteria
    def object_layer_assign_criteria(vSelection_Criteria, vLayer_Destination_Name):
    	vLayer_Destination_Handle = vs.GetLayerByName(vLayer_Destination_Name)
    	if vLayer_Destination_Handle == None:
    		vLayer_Actual_Handle = vs.ActLayer()
    		vLayer_Actual_Name = vs.GetLName(vLayer_Actual_Handle)
    		vLayer_Destination_Handle = vs.ActLayer()
    	def object_layer_assign_iterator(vObject_Handle):
    		vs.SetParent(vObject_Handle, vLayer_Destination_Handle)
    	vs.ForEachObject(object_layer_assign_iterator, vSelection_Criteria)

    I hope they will be to your help,


    best regards,





  13. Hello


    With VW2019 I came across, that in my example file "viewport.vwx" the Python-Script "with visibility" to generate a ViewPort and to assign to it the layer visibility to active will crash VW2019. If the created ViewPort is manually deleted VW2019 will crash.

    So in the loop to assign the layer's visibility to active a condition has to assure, that the visibility is only set to design layers (many thanks to D. Corpataux from ComputerWorks.ch).


    So in the attachment there is a new stable Script named "with viability stable VW2019".

    best regards




    # python-script : "with visbility stable VW2019"
    import vs
    def createviewport(ModuleLayer, objectHandle):
    	vs.Layer(ModuleLayer) # make sure we are on the correct starting layer
    	# screenName   = objectList[selectedObjects][0] # Gets the Screen Name   - 1st item in t = (screenName,objectHandle)
    	# objectHandle = objectList[selectedObjects][1] # Gets the Object Handle - 2nd item in t = (screenName,objectHandle)
    	# Get the object height, width and bounding box of object
    	p1, p2       = vs.GetBBox(objectHandle)
    	objectWidth  = vs.HWidth(objectHandle)  
    	objectHeight = vs.HHeight(objectHandle) 
    	#Create VP Crop Object
    	vs.Rect(p1, p2, objectWidth, objectHeight)
    	vpCrop = vs.LNewObj()
    	# Create the layer and set the layer name
    	layerHandle = vs.CreateLayer('01', 2)  # using 01 forces the next unused sheet nubmer to be used
    	layerName   = vs.GetLName(layerHandle) # get they layer name. It appears the layer name is the sheet number
    	#vs.SetObjectVariableString(layerHandle, 159,'Module Layout - ' + screenName)
    	vs.SetObjectVariableString(layerHandle, 159,'Module Layout - ' )
    	# vs.Rect(0,0,10,10) # test to see if something draws on the sheet layer
    	#Create the VP and set Crop Object
    	vpHandle = vs.CreateVP(layerHandle)
    	vs.SetVPCropObject(vpHandle, vpCrop)
    	vs.SetObjectVariableReal(vpHandle, 1003, 32) #set scale to a default of 32
    	## set class and layer visibility to viewport object
    	vClassNum = vs.ClassNum()
    	for vClassNumIndex in range(1, vClassNum+1):
    		vs.SetVPClassVisibility(vpHandle, vs.ClassList(vClassNumIndex), 0)
    	vLayer_handle = vs.FLayer()
    	while vLayer_handle != None:
    		vLayer_Type = vs.GetObjectVariableInt(vLayer_handle, 154) #Design Layer or Sheet Layer
    		if vLayer_Type == 1: # Design Layer
    			vs.SetVPLayerVisibility(vpHandle, vLayer_handle, 0)
    		vLayer_handle = vs.NextLayer(vLayer_handle)
    	viewPort_X, viewPort_Y = vs.HCenter(vpHandle)
    	print(viewPort_X, " ", viewPort_Y)
    ModuleLayer = "test"
    vGroup_handle = vs.LSActLayer()
    createviewport(ModuleLayer, vGroup_handle)


  14. Hello


    Thank very much you for your hints and considering my questions.


    • The command vs.CallTool() is not applicable, because I have to use an allready existent polygon as selection perimeter and do not want any user inteaction.
    • Iterating over every point to check by vs.PtInPoly if it is on/witin the actual polygon is some kind of "brute force", as I have to iterated first over every polygon an then itereate over all points to be checked for each polygon. But it seems that there is no other approach to do it. I wondered if there would be any VW criteria to select objects by a x/y range (select all objects where x/y is >= as xTop/yTop AND x/y is <= xBottom/yBottom) in order to optimise somebit the iteration process by reducing the amount of relevant points to check after in detail if they are within a certain polygon. But unfortunately such numerical/grafical criteria search is not available in VW as it is part of every GIS-tool.

    By looking again at the VW search criterias I found the "location" critearia. If an object has a given name, it is possible to formulate a search criteria that looks for points/objects that are within the object with the given name:

    import vs
    vs.SelectObj("(INSYMBOL & INOBJECT & (L='LayerToSearchIn') & (LOC='MySelectionPolygon'))");

    With this search criteria the solution is much easier (I do not know the details about performance differences) but of course for every polygone to test a name (a temporary unique name) has to be given:


    import vs
    def searchPoints_for_MyPolygon(vMyPolygon_handle):
        # the original name of the object to be processed has to be retrieved
    	vMyPolygon_Name_org = vs.GetName(vMyPolygon_handle)
    	vMyPolygon_Name_temp = 'MyPolygon_temp_unique_name'
    	vs.SetName(vMyPolygon_handle, vMyPolygon_Name_temp) # a temp. unique name has to be given for the case the name = "" for correct selection
    	vSelectionCriteria_Points = "(INSYMBOL & INOBJECT & (L='LayerToSearchIn') & (LOC='"+vMyPolygon_Name_temp+"'))"
    	vPointsFound = vs.Count(vSelectionCriteria_Points)
    	vs.AlrtDialog("Points found: " + str(vPointsFound))
    	vs.SetName(vMyPolygon_handle, vMyPolygon_Name_org) # the original object name has to be reassigned
    vSelectionCriteria_MyPolygons = "INSYMBOL & INOBJECT & (L='LayerWithMyPolygons')"


    best regards, relume




  15. Hello


    I am back 😐 to the recurrent problem of finding/selecting points or other 2D objects within an other 2D polygon or polyline.


    • As long the number of points to be selected are small or smaller than the number of the "selecting" 2D polygons, then I can iterate over every point to check if it is inside a "selecting" 2D polygon by "vs.FindObjAtPt_GetObj".
    • But if I have a (very) large number of points and a smaller number of "selecting" 2D polygons the above approach is inappropriate, due to the huge iteration over every point.
    • So I thought I would be possible to use/adopt the polygon selection tool to "embrace" the relevant points (to be found) by a 2D polygon. But actually I can not see any way how to script this – how to get by scripting a given 2D polygon in to the polygon selection tool to "embrace" the relevant points.


    I would appreciate any idea how to get the problem solved, many thanks in advance,




  16. Hello


    I am using my script for producing many small plats in a batch (moving window on every object) to export each to its own pdf for many years - first in VectorScript and now ported to Python. It works without problems. I do not need to ResetObject() nor  ReDrawAll(). In general I do not see any greate difference to your code. The only difference in my script is, that I am using a predefined presentation layer and reusing it for every plat to be drawn and exported. But I do not think that this is the problem.


    I tried and slightly adapted your code (see attachment) and the only proble that I can see is, that vs.CreateVP() creates a ViewPort-Object with no layer and class activation (they are all set to invisible). So running your code I get also this square with the red cross in it. But when I assign class and layer visibility to active for this ViewPort-Object the bounding box of the viewport change to its real dimensions and location. Thus assigning class and layer visibility is "indispensable" to get the correct result, although the square with the red cross seems to be a temporarily "artifact" with a viewport with all classes and layers set to invisible. Finally the new created viewport has to moved to the page center (or any position) - that is default and is corresponding the manual viewport creation.


    best regards


  17. Hello


    perhaps this snippet from a larger script may help:


    # -- create viewport : move viewport object to page center
    vs.Layer(vLayerViewPort_name) # selects layer with ViewPort object
    vViewCenter_x, vViewCenter_y = vs.GetOrigin() # this works as long SheetLayer origin was not altered
    vViewPort_Rect_center_x, vViewPort_Rect_center_y = vs.HCenter(vViewPort_Object_handle)
    vViewCenter_x = vViewCenter_x * -1
    vViewCenter_y = vViewCenter_y * -1
    vDifference_x = (vViewCenter_x-vViewPort_Rect_center_x)
    vDifference_y = (vViewCenter_y-vViewPort_Rect_center_y)
    # message("object_process_item : vViewCenter : " + str(vViewCenter_x) + " / " + str(vViewCenter_y) + " | " + str(vViewPort_Rect_center_x)+ " / " + str(vViewPort_Rect_center_y)  + " | " + str(vDifference_x)+ " / " + str(vDifference_y))
    vObject_type = vs.GetType(vViewPort_Object_handle)
    if ((vObject_type == 122) or (vObject_type == 3)): vs.HMove(vViewPort_Object_handle, vDifference_x, vDifference_y)


    best regards


  • Create New...