Jump to content

DomC

Member
  • Posts

    605
  • Joined

  • Last visited

Posts posted by DomC

  1. Tim

    Thanks a lot. Your post brought me to search in the right direction :)

    There seems to be many solutions to convert with python. But after several encoding, decoding tries. I searched again "http://developer.vectorworks.net/" for encoding topics. Lo and behold: There was a vectorscript function to do that job :-)!!!

    vs.StringAnsiToMac(string)

    Nice.

    Thanks again Tim

    Dom

  2. Hi there

    I wonder how to handle special character issues in a smooth way. I use the following commands in my script:

    HSFPath=vs.GetFPathName()
    bool, path=vs.ConvertHSF2PosixPath(HSFPath)

    My File name is äöüéè.vwx. And Vectorscript procudes a file path like "C:\Users\dom\Desktop\‰ˆ¸ÈË.vwx"

    After that I have to replace those "characters" manually by script:
    umlaut={'ä':'‰','ö':'ˆ','ü':'¸','é':'È','è':'Ë','à':'à'} #Python dict with the replace character
    path=path.replace(umlaut.get('ä'),'ä') #umlaut.get(dictkey)
    path=path.replace(umlaut.get('ö'),'ö')
    path=path.replace(umlaut.get('ü'),'ü')
    path=path.replace(umlaut.get('é'),'é')
    path=path.replace(umlaut.get('è'),'è')
    path=path.replace(umlaut.get('à'),'à')

    OK, the path.replace part, maybe could maybe be better programmed. But is there any standard procedure for file-path-character issues like this? Handling pathes is daily business.

    Well, it works on mac platform.

    The complete script:

    HSFPath=vs.GetFPathName()
    bool, path=vs.ConvertHSF2PosixPath(HSFPath)
    umlaut={'ä':'‰','ö':'ˆ','ü':'¸','é':'È','è':'Ë','à':'à'}
    
    path=path.replace(umlaut.get('ä'),'ä')
    path=path.replace(umlaut.get('ö'),'ö')
    path=path.replace(umlaut.get('ü'),'ü')
    path=path.replace(umlaut.get('é'),'é')
    path=path.replace(umlaut.get('è'),'è')
    path=path.replace(umlaut.get('à'),'à')
    
    path=path[:-3]+'txt'
    inPath=path
    skipHeader= False
    asString=True
    delimiter="\t"
    codex='iso8859_2' #'latin_1', 'iso8859_2', 'mac_latin2','utf_8' #https://docs.python.org/3/library/codecs.html
    
    lines=[]
    rows=[]
    import csv
    import os
    if asString==False:
    quote=csv.QUOTE_NONNUMERIC
    else:
    quote=csv.QUOTE_NONE
    
    if os.path.isfile(inPath) == False:
    vs.AlrtDialog('Das Info-File der ERP Software wurde nicht gefunden. Dieses Script liesst eine Textdatei mit gleichem Namen wie die Vectorworks Datei ein. Bitte Erkundigen Sie sich bei Ihrem ERP/PPS Softwarelieferanten über diese Möglichkeit')
    
    
    
    rowNum=10
    lineNum=10
    
    if os.path.isfile(inPath) ==False:
    for x in range(rowNum):
    	rows.append('error Import File')
    for x in range(lineNum):	
    	lines.append('error')
    
    FilePath=('import File missed')
    
    if os.path.isfile(inPath) ==True:
    with open(inPath, encoding=codex) as f:
    	reader= csv.reader(f,dialect='excel',delimiter=delimiter,quoting=quote)
    	if skipHeader==True:
    		next(reader)
    	for line in reader:
    		lines.append(line)
    	lineNum=len(lines)	
    	rowNum=len(line)			
    	for row in range(rowNum):
    		rown=[]
    		for line in range(lineNum):
    			rown.append(lines[line][row])		
    		rows.append(rown)
    
    
    if asString==False:
    	rows = tuple(tuple(x) for x in rows)
    	rows = list(rows)	
    	lines = tuple(tuple(x) for x in lines)
    	lines = list(lines)
    
    erpdict=dict(zip(lines[0], lines[1]))
    plankopf="INSYMBOL & INOBJECT & INVIEWPORT & ('VAA Title Block'.'__Other4'='ERP_Plankopf')"
    #plankopf="INGROUP & INVIEWPORT & (R IN ['VAA Title Block'])"
    
    def PlankopfFelder(h):
    vs.SetRField(h, 'VAA Title Block', '__ProjName', erpdict.get('PRO_STAMM_PROJEKTBEZ'))
    vs.SetRField(h, 'VAA Title Block', '__ClientName', erpdict.get('ADR_NAME_FIRMA'))
    vs.SetRField(h, 'VAA Title Block', '__ProjAddress', erpdict.get('ADR_STRASSE')+', '+erpdict.get('ADR_PLZ')+' '+erpdict.get('ADR_ORT'))
    vs.SetRField(h, 'VAA Title Block', '__ProjNo', erpdict.get('PRO_STAMM_PROJEKTNR'))
    vs.ResetObject(h)
    return()
    
    vs.ForEachObject(PlankopfFelder, plankopf)

  3. In VW I can import the Symbol and convert it to a group which converts it to polygons, then I can extrude it along the path. Will try it in marionette tonight, all the nodes are there.

    How About directly input the symbol in your extrude? You could edit your symbol properties (blue symbol) and insert the symbol directly as a poly (as long as you have not more than one object in the symbol)

    Any-Input-Node, can be handy for testing (even better than connecting many of input nodes to simulate an input :-). At a more final version, we should use dim-inputs for input values (Document Units).

  4. Hi Alan

    Nice, a Cabinet Door with a Handle profile ... :-)

    Path:

    Maybe it is better to use Linear Extrude for this. So you just input start and endpoint and not have to input a path object.

    Profile:

    I would prefer to input this profile as a geometry. You can handle a Geometry by wrapping it to an marionette object and attach profile in the control group box:

    1. Group Polygon

    2. Connect controll geometry node and contend node to get poly

    I think grouping is maybe necessary, to not have your poly as a control path. Or if you want to use different profiles. Also you could get your profile, out of a symbol definition (took a look at my exhibition wall example?).

    For testing your code, Name the group with the poly, name it (info-palette) and input by "name-node"

    If you your are creating our profile with nodes with nodes, maybe use the "any input node" and input

    [(0.0, 0.0),(20.0, 0.0), (20.0, 20.0),(30.0, 60.0),(-50.0, 60.0),(-50.0, 50.0),(-40.0, 50.0),(-40.0, 55.0), (10.0, 55.0),(0.0, 0.0)]

    I also still searching the best practice to input geometries. I hope there is something thereby you can use.

  5. Hi there

    A Marionette Path Object for rectangular exhibition walls. Use second reshape methode to edit path. The objects uses symbols for profiles and walls. So you are able to control wall thickness, classes and material over the symbol definition. Make sure the symbols are content of your document. Offcut or start points of the duplication are controlled inside the marionette script. There are some custom nodes used like: duplicate array between points, insert symbol and change wall length

  6. Hi David

    Hm, I just hav experience by using python moduls for text handling. Because you can get help for this via google for every error message. Also with python you can do so much more (sort, arrange, split, sorting out characters etc).

    An Example. Which Reads a text fila as one single string value. To get File Dialog use vs.GetFile, after that you should convert the path (Which is MacHD:User:Dom:etc:ect) to a Posix Path (MacHD/User/Dom/etc/etc)

    Try this:

    import vs

    fileName = vs.GetFile()

    bool, fileName=vs.ConvertHSF2PosixPath(fileName)

    a=open(fileName).read()

    vs.Message(a)

  7. Hi Alan

    You can check if your value is from 600 to 1200 and returns a "True".

    That can be complicated if you have many if then statements or if maybe a specific combination of true or false should gives other results.

    If you produce many True and False "Answers" and if just one of them would be "False" the whole result is False (if >600 is true and >1200 is false and smartDoor is true etc. etc.) the answer still will be False (just one door as example) and for your example you can do it this way:

  8. This is awesome

    Jared, now things are really heating up!

    @Ilay I did not even got to work ktinker to work. This was just a test and would be not very helpful because ktinker do not much more, than the internal dialog features can do. Even if I am not a fan of using too much third party stuff.

    Thanks

    Dom

  9. Output values are visible, when you click with the second method of the marionette tool on a wire (the "debug" methode). If there is no wire, connect a "Dummy End", which can be found under de "Debug" symbol popup.

  10. Hi

    This Marionette object contains a custom node, which reads a text file. One special application could be to automatically write something like an address or a descreption etc. into the plan.

    Can be very interesting for customers which has to integrate Vectorworks in their software enviroment and rather more pushing data into the document than "self-drawn" content.

    Maybe first read the "instruction.pdf" to see for which special case this example is thought.

  11. If we play around with Record Formats and Lists. It can be useful to access external Lists of Data.

    I Attached a node, which bases on the python csv standard module. It can import lists as strings (text) or as numbers. It can't mix numbers and strings. Except Header (first Line) can be strings during the rest of the lists are numbers.

    It could be used for:

    1. Import csv (or tab) separated text files by using an absolute path.

    2. Import a csv with the same path and name of the Vectorworks file (for Metadata/Project data like Title Blocks etc.)

    3. It puts out rows and lines separately. The used path and rows- and line quantity.

    v03:

    Popup with Text encoding List. Python Standard is 'utf-8'

  12. Check this out:

    A Quick-Modification of the "Get Record Field-Node", which returns a list of Field Names instead the Field Values. So you are able to automatically feed your Field Names.

    I hope this was not already part of the native nodes content.

    Dom

  13. Hallo Michael

    You can just input more than one object or more than one Field Names. This works good, if you know the field names respectively if you always have the same kind of record format.

    If you want to have the field names dynamically (another record with other field names) You need another construct (or node) which generates the field names automatically.

    Dom

  14. Hi

    I just work on a script, that let us jump to the next saved view in alphabetical order. (I know Vectorworks Remote could do that)

    First Problem: Handle the saved views by script (I tried with ID, Parent etc. and failed). Thanks to Pat Standford (My Hero) which found a solution with vs.FIn3D :-)

    https://techboard.vectorworks.net/ubbthreads.php?ubb=showflat&Number=118441

    Second Problem:

    The saved views are stored in the order they was created. Here Python scripting is showing one advantage. We can beatifully sort list with python.

    #Python code to create list
    h=vs.FIn3D(vs.GetObject('Darstellungen'))# International Version "saved views"
    
    views=[]
    
    while h != None:
    name=vs.GetName(h)
    views.append(name)
    h=vs.NextObj(h)	
    views.sort() # Sorts the list alphabetically

    An extended Version. It maintains a Text Block inside the document which acts as a counter in the document. Because after execution the script can't remember the last saved view. Maybe there is a more smarter way by using a hidden record or something like this. I am not familiar with that.

    #Python code to create list, grab and change the named(Info Palette Data field) text block and call up the saved view
    h=vs.FIn3D(vs.GetObject('Darstellungen'))# International Version "saved views"
    
    views=[]
    
    while h != None:
    name=vs.GetName(h)
    views.append(name)
    h=vs.NextObj(h)	
    views.sort() # Sorts the list alphabetically
    
    zähler=vs.GetObject('zähler') #Handle to the text block
    Darstellung=vs.GetText(zähler) #Read Text
    index=views.index(Darstellung) #Check on which index of the list (of the sorted list) this view is stored
    
    if index < len(views)-1:  # -1 it's because len counts from 0 I think
    vs.SetText(zähler, views[index+1]) #Change the Text block to the next saved view
    vs.Message(index)
    
    if index+1 == len(views):
    vs.SetText(zähler, views[0]) #Starts from the beginning
    
    vs.ResetObject(zähler)
    
    vs.VRestore(Darstellung) #call saved View
    

    This hits on an idea to make a slide show, from save views. With an automatically delay. But this is tricky, because it seems to be a feature from scripts, that they do not regenerate views during the script execution. I tried out with a Dialog Box. That seems to work. But who want's to klick a away a Dialoge Box after every Slide.

    I tried to do this this way:

    import time
    h=vs.FIn3D(vs.GetObject('Darstellungen'))
    views=[]
    i=0
    while h != None:
    name=vs.GetName(h)
    views.append(name)
    h=vs.NextObj(h)	
    views.sort()
    
    length=len(views)
    
    def view():
    for i in range(length):
    	#vs.Message(str(views[i]))
    	#time.sleep(0.5)
    	#vs.SetZoom(100)
    	#vs.SetZoom(50)
    	#vs.ReDrawAll
    	vs.VRestore(views[i])
    	#vs.Wait(1)
    return()
    
    view()	

  15. One step nearer to the solution ... anything goes with script, forget crampy worksheet formulas.

    #Formula in Worksheet: =RUNSCRIPT('script-1')

    #python script-1:

    A1=vs.CellValue(1,'A')

    pic=vs.GetObject('pic-1')

    if A1 >= 0:

    pic=vs.GetObject('pic-2')

    vs.WSScript_SetResImage(pic)

    "Just" have to find cell number, the script runs. To read out relative cells to the script cell.

  16. Hi

    Maybe not the right forum for worksheet formula questions.

    I am searching a way to insert an image in a worksheet cell by using a formula. I already searched the forum but could not find any related questions.

    What I am trying to do:

    If want to show an image in cell D1, if the cell A1 has the value greater than "0".

    =if((A1<>0), 'here i want an Image', 'false')

    I tried this:

    =IF((A1<>0), (IMAGE(N='k1')), '') #-> cell is empty

    =IF((A1<>0), D1, '') #D1 is refering to the cell "D1" which shows the image by =IMAGE(N='k1')

    =IF((A1<>0), IMAGE(N='k1'), '') #-> cell is empty

    also tried from other direction:

    =IMAGE((IF((A1<>0), "N='k1'", ''))) #-> error because of the double quote I think

    =IMAGE(E1) #Simple test, if IMAGE() formula can use values from other cells

    I give up... Any tips?

×
×
  • Create New...