Jump to content

BillW

Member
  • Posts

    74
  • Joined

  • Last visited

Everything posted by BillW

  1. Just when I thought I would have an answer to the problem I am finding the returned Z values differ depending on the type of object and rotations. The 3D locus returns Z height related to the active layer plane while the others are related to world base level (either correct or incorrect values). See attached image for values of rotation ie 0/0/0 and Z values returned (rounded). Something is not quite right. I am trying to align a new object (created at 0/0) ie 3D symbol or plugin with an existing object. I still have to modify the Z height by the layer base height to move new object into the correct location. I added 2D rectangle as the last example for a 2D planar object. Any guidance would be gratefully received. The code for the script is show below procedure test; Var planarset,btest,isMirroredXY : BOOLEAN; v1,rot : VECTOR; x,y,z : REAL; refID : LONGINT; baseElev, thickness : REAL; srcobjH : HANDLE; begin GetLayerElevation(actlayer, baseElev, thickness); srcobjH := fsactlayer; if gettypeN(srcobjH) = 9 then begin {3D locus} getlocus3D(srcobjH,v1.x,v1.y,v1.z); end else if gettypeN(srcobjH) = 3 then begin {2D rectangle} hcenter(srcobjH,x,y); refID := GetPlanarRef(srcobjH); btest := PlanarPtTo3DModelPt(refID,x,y,v1.x,v1.y,v1.z); btest := GetEntityMatrix(srcobjH,x,y,z,rot.x,rot.y,rot.z); {rot Z is the plane rotation not the objects} end else begin planarset := getObjectVariableBoolean(srcobjH,1161); if planarset then begin {2D symbol} getsymloc(srcobjH,x,y); refID := GetPlanarRef(srcobjH); btest := PlanarPtTo3DModelPt(refID,x,y,v1.x,v1.y,v1.z); btest := Get3DOrientation(srcobjH,rot.x,rot.y,rot.z,isMirroredXY); end else begin {3D symbol or plugin} getsymloc3D(srcobjH,v1.x,v1.y,v1.z); getsymloc(srcobjH,v1.x,v1.y); btest := Get3DOrientation(srcobjH,rot.x,rot.y,rot.z,isMirroredXY); end; end; message(planarset,' ',v1,' ',rot,' elev ',baseElev); end; run(test); convertsymleveltest v2.vwx
  2. Thanks. Nice bit of lateral thinking. I also understood the symbol's transformation matrix was used but not the solution. As you say the layer elevation is taken into account which saves a bit of code. Already got the symbol rotations covered as suggested. This is added to the various workarounds in the memory bank.
  3. This is driving me nuts. In the example file I have the following: Layer 0 set to elevation 0mm Layer 6000 set to elevation 6000mm On each layer, I have an extrude which I used to place 3D symbols (each containing a single 3D locus) and 3D plugins via the auto working plane option (\) The script palette has a script which tests the 3D location (ie getsymloc3D) of the selected object. When run on Layer 0 everything works fine. When I run on Layer 6000 I get weird results shown in the message box. I've tested the 3D symbols and plugin to see if they are planar which is not the case. I have tested on VW 2023 sp3, 2022 sp6, 2021 sp4 and 2020 sp6 (the attached file version). I can get a correct result on the 3D symbols via Get3DCentr which is fine for a single 3D locus but not for complex content. I understand if I got a correct result I would have to modify the Z value by the layer elevation base height. Any thoughts and whether I've got something wrong. TIA sympio baselev test.vwx
  4. Following on from my initial post, thought I'd pass on an unencrypted full blown example of a python based menu command "Convert from Faces.." which places a symbol consisting of a 2D locus at locations around/on 2D/3D objects which can take account of adjacent 3D faces to determine direction. There's a lot of work with planar objects and vectors. I include an install file "install convertfromfaces.zip" which you can install in Vectorworks via Tools>Plugins Manager>Third-party Plug-ins>install... You will need to add command to a workspace via Tools>Workspaces...> Menus>WHW 3D modelling>Convert from Faces... The zip file contains the VSM file and supporting python files. As python files can't be uploaded, I include source code text files "convertfrom faces 2020", "convsf_classes" and "convsf_utils". Note, I use class convSF to store operational variables. Classes entmat, vertexdef and multidef are used to store geometry definitions. Displacement Offset works in local axes but Rotation works in world axes. Haven't figured out a local axes rotation yet. Hope this will pass on some inspiration. install convertfromfaces.zip convsf_classes source.txt convsf_utils source.txt convertfromfaces 2020 source.txt
  5. Thanks PatW - duly bookmarked - just whats needed.
  6. Just give some idea on converting a Vectorscript palette script to Python. The code splits a polyline/polygon into seperate line segments or linked curve segments which will give some idea how to traverse polylines/polygons including holes. Hope the code is useful. I did find that the VS call IsPolyClosed(polyH) is unreliable when you have invisible segments other than the last and doesnt handle holes so I wrote my own "IsClosed" I use a lot of STRUCTURE's in vectorscript which I have transposed into classes in python. Similarly there is no "repeat/until" in python which is handled by "while 1:" with a "break" call. Also vectorscript "case of" will have to wait for Python 3.10 version "match case" - use "if elif else" for the time being. Arrays such as "enddefs : array[1..250] of multidef;" are handled by a python class "multidef" and appended to a list via "enddefs.append(multidef(vstart,1))" Also note the use of GetEntityMatrix and SetEntityMatrix to align new content with the existing poly. Find enclosed text content of equivalent Vectorscript/Python code, a VW2020 file I used for testing with a script palette "Palette-1" and scripts "mark verts vs, split poly vs, split poly py" Been scripting for decades mostly in Vectorscript and mainly between my day job of 3D modelling. Lot's of relearning for Python needed. split spline test vw2020.vwx split poly vs.txt split poly py.txt
  7. Has anyone managed to get procedure "ConsolidatePlanar(obj1,obj2) : BOOLEAN" to work. In the attached VW2020 file I have a polygon (named "testpoly") which is rotated in 3D by 45degrees around the X axis. In the script palette I have a script "test consolidateplanar" which when run shows new/old objects are planar but ConsolidatePlanar fails. The new locus is in the correct X/Y position but not aligned with the rotated polygon ie Z direction is vertical. I can do what I want with vector routines but thought ConsolidatePlanar might be easier. I tried reseting the new object, bounding box or 3DOrientation with now luck. As an aside, I noted when I used an oval it wasn't in the correct position when viewed from Top/Plan. Anyone had any luck?? procedure test; Var objH : HANDLE; refID :LONGINT; x1,y1,x2,y2,z2 : REAL; consolidated,planar1,planar2,btest : BOOLEAN; begin objH := getobject('testpoly'); dselectall; setselect(objH); if objH <> NIL then begin refID := GetPlanarRef(objH); GetPolyPt(objH,1,x1,y1); btest := PlanarPtTo3DModelPt(refID,x1,y1,x2,y2,z2); locus(x2,y2); {OvalN(x2,y2, 1, 0, 50, 50);} consolidated := ConsolidatePlanar(objH,LNewobj); {align new object with existing object??} planar1 := getObjectVariableBoolean(objH,1161); planar2 := getObjectVariableBoolean(LNewobj,1161); message(planar1,' ',planar2,' consolidated ',consolidated); end; end; run(test); consolidate planar test VW2020.vwx
  8. As an aside I found some code for handling euler and quaterion rotations which I'm trying to figure out. As far as I can tell 3D rotations in VW code are world based which doesnt help if you want to rotate an object around it's local orientation. Find attached a zip file with the main python code being 'pyrotation.py' which needs numpy loaded. pyrotation.zip
  9. I had a go at converting python code for vectors back in 2016 see attached. I never really used the code as I can't guarantee that the vector python file will exist in all settings. It may be of use. Also units in VW python are not really handled as in Vectorscript ie 20mm in code will be automatically converted to the current units - not so in python. Find attached a go at handling automatic conversion. PS I couldnt upload .py files so I had to rename files below as .txt files. Just rename back to .py vwvector.txt vwunits.txt
  10. Just to say I successfully loaded numpy "1.18.5 cp35" in VW2021 via DomC's node and copied the folder "Python Externals" back to folder ...Appdata/Roaming/Nemetschek/Vectorworks/2020 I also successfully ran script below import numpy as np a = np.asarray((1,0,0,0,1,0,0,0,1)) vs.AlrtDialog(str(a)) I can now learn/try out some open source python code for Euler/Quaterion rotations.
  11. I tried running DomC's node "Install numpy" on it's own and got an error "module numpy cannot be downloaded". Running VW 2020 SP6 on PC I checked the file path from https://pypi.org/project/numpy/1.17.4/#files and copied link to check and it matched the node entry below: numpy = 'https://files.pythonhosted.org/packages/25/71/37628d7654da4a539f33497c9d9d6713d2bb3c9e35638776b3eea38ca04a/numpy-1.17.4-cp35-cp35m-win_amd64.whl' I even tried pasting into a browser which allowed me to download ".whl" file. I tried alternative pre path "https://pypi.python.org/packages" - same error I even tried (as VW2020 uses Python 3.5) https://files.pythonhosted.org/packages/ed/09/ff8f529a5548ff788765f66a81ef751130f26f8c7d517e94d3dbf3ba1ed5/numpy-1.18.5-cp35-cp35m-win_amd64.whl I'm kind of stuck
  12. Thanks to Kostadin Ivanov - "The problem is that at the moment the function ResList_ActFolder and ResList_Filter cannot be used in one script. use only ResList_Filter" The previous reslist version has been modified to be equivalent to the first version "setactivesymbol.txt" and uses the resource browser interface. It refers to symbols in the active document. Alternatively use ResList_ActFolder if you are happy to display symbols in the specified folder and all symbols in any nested symbol folders. The root folder is ResList_ActFolder(fID,'') setactivesymbol_reslist v2.TXT
  13. A follow up. I've got a dialog working using "ResList_" functions/procedures - see attached. The only drawback is the selected folder includes symbols in that folder and all symbols in any nested folders which may be what you want. In the example in the first post I only display symbols in the selected folder and ignore nested folders. I was hoping to use ResList_Filter( uniqueID:STRING; callback:PROCEDURE) ; to show only symbols in the selected folder. I have established that the callback is a function which I thought would be of the form: function chksyms(symH : HANDLE) : BOOLEAN; Var foldH : HANDLE; begin foldH := getobject(foldname); chksyms := (getparent(symH) = foldH); end; ResList_ActFolder(fID,foldname); ResList_Filter(fID,chksyms); Unfortunately this doesnt seem to work. Anyone have any ideas on the form of the callback? Using ResList procedures/functions certainly make the code much simpler. setactivesymbol_reslist.txt
  14. Just a note - I found out how to use uniqueID - see below. I just need to investigate further. procedure test; Var fID : STRING; itemName : STRING; onlyCurrentDocument,searchOnline, skipCurrentDocument : BOOLEAN; begin (* with settings Top level symbols Symbol-1 Symbol-2 Symbol folder Folder-1 Symbol-3 Symbol-4 Symbols in order of creation *) fID := CreateUUID; ResList_Init(fID, 16); ResList_ActFolder(fID,'Folder-1'); {returns Symbol-3 in ResList_SelFAvail} {first available item in the resource popup} ResList_SelFAvail(fID,itemName,onlyCurrentDocument,searchOnline,skipCurrentDocument); message(itemname,' ',onlyCurrentDocument,' ',searchOnline,' ',skipCurrentDocument); end; run(test);
  15. That's what I was trying to establish - that "ResList_" procedures were not applicable to dialog boxes - however see below. So if they relate to the Resource Manager where does the uniqueID:STRING come from - or is the uniqueID set from a call to "ResList_Init" There is a call ResList_DlgInit( uniqueID:STRING; dlgID:INTEGER; ctrlID:INTEGER) ; which says Use this call during dialog initialization to associate a popup control or resource popup and initialized by the ResList_* calls of the uniqueID identifying the resource list data. The problem is there are no examples in the "Script Function Reference" Thanks anyway.
  16. For processing resource lists, has anyone tried using the procedures begining with "ResList_" ie PROCEDURE ResList_Init( uniqueID:STRING; objectType:INTEGER) ; I'm trying to figure out where I can get a control's "UniqueID" say for a reference to a "CreateThumbnailPopup( dialog, ksymbolpop);" in a scripted dialog. Controls are normally referenced by number. I'm wondering if the "ResList_" procedures relate to only controls shown in the object info palette for PIO's. I have a working dialog version using "symID := BuildResourceList(16,0,'',numSyms);" but was wondering if there is a better way. See the old school method shown in a prototype scripted dialog below setactivesymbol.txt
  17. Thanks. Managed to get things working.
  18. Marissa did a quick test. I tried using the #COMMAND line ie using [UsrLib] which failed with message dialog "The referenced file was not found" I then tried the full path to the file - see attached image - got the same message. The file does exist (on PC) - see below Will keep on trying. Could it be a case sensitive issue with .PY instead of .py
  19. Thanks. I did all of the above and have a functioning user library. My question was can I add nodes to the Marionette Default Library node list. If I craft some NURBS nodes for example, I don't want two locations for NURBS nodes (one set in Default library and another set in User library). I suppose I could have my own version of the Default library which would need to be updated at subsequent Vectorworks releases. Will probably just stick with my User library setup. As an aside, for a user library can the code be stored in .py files similar to Default library. Default nodes have a first line in the script: #COMMAND;READONLYREFFILE;[VWLibDef]/Input\Point2.py; Is there an equivalent path to "VWLibDef" for user nodes (for example UserLibDef)
  20. I have a bunch of nodes which I would like to embed in the standard Marionette tool list. I understand the standard nodes are stored in (PC) "Program files/Vectorworks 2018/Libraries/Defaults/Marionette/Marionette Default Library.vwx" I can setup a separate User defined list of nodes by placing my library file in for example "Users/<username>/Appdata/Roaming/Nemetschek/Vectorworks/2018/Libraries/Defaults/Marionette/Marionette User Library.vwx" What do I need to do to embed user nodes in the standard Marionette tool list? I did notice some folders in the user location ie Attributes$ , Math$ , Textures$ and Objects/NURB$ but I am not sure how to use/implement them. Can I create a new category ie Tools$ It's been quite interesting using Marionette as a front end to plugin objects. TIA
  21. Why not use Python equivalent of PointAlongPoly(h: HANDLE; dist: REAL; VAR ptX, ptY, ptZ: REAL; VAR tangentX, tangentY, tangentZ: REAL) : BOOLEAN; Always a good idea to check file "VWPluginLibraryRoutines.p" in user plugins folder for non documented calls.
  22. Still trying to understand Nurbs particularly how knot values work. Still cant figure out the logic for knot values in all cases - see below (might help others understanding). Please comment if the information is incorrect. I have also noticed when I "Export to script" a nurbs curve with more than 1 piece (ie from NurbsCurveGetNumPieces and with different degree values), if imported (via the script) a nurbs curve is created for each piece. There doesn't seem to be a way of creating (via script) a multi piece nurbs curve as far as I can tell. To solve my problem, I think I will have to convert the (mutli piece) nurbs curve to 3D polygons (one for each piece, grouped), create/modify the 3D polygons and convert back to nurbs. I need the nurbs for internal workings of path based plugins.
  23. I am trying to shorten a nurbs curve. There is an "ExtendNurbsCurve" function but no shorten option. I can move the start point of a nurbs curve with the following code curveH := CreateDuplicateObject(srcH,NIL); if (startoffset > 0) then begin curvelen := hlength(srcH); inPercentOfLength := startoffset / curvelen; if GetPointAndParameterOnNurbsCurveAtGivenLength(curveH,inPercentOfLength,px,py,pz,outParam,outIndex) then begin NurbsSetPt3D(curveH,0,outIndex,px,py,pz); resetobject(curveH); end; end; The problem is with getting the curve alignment correct. I assume I have to set the correct knot values for curve vertex points 0 and 1 with NurbsSetKnot(objH,curveH,0,0) and NurbsSetKnot(objH,curveH,0,1). I can get the existing knot values with NurbsKnot(srcH,curveH,0,0) and NurbsKnot(objH,srcH,0,1) . The question is how will the knot values change - what is the relationship? TIA Bill Wood
  24. That's the problem solved. Thanks vey much. Bill Wood
  25. Marissa, I loaded your script into my VW file - see attached. Weird, I still cannot get it to run. The VW file has popups which do run. I am on Windows 7 Professional SP1 and VW 2018 SP1. Previously, I pretty much made the same sort of edits as your version. angle test.vwx
×
×
  • Create New...